#!/usr/bin/python
-# SFAtables is a tool for restricting access to an SFA aggregate in a generic
-# and extensible way.
-# It is modeled using abstractions in iptables. Specifically, 'matches' specify
-# criteria for matching certain requests, 'targets' specify actions that treat
-# requests in a certain way, and 'chains' are used to group related
-# match-action pairs.
+# This file parses an sfatables command and generates XML files that parameterize
+# matches and targets. Each such XML file defines a rule. Rules are dropped in directories
+# that represent 'chains.' SFA loads rules from various chains and invokes them at certain
+# 'hook points.' For example, it invokes rules in the 'OUTGOING' chain before returning
+# the output of 'get_resources.'
import sys
import os
import pdb
-from optparse import OptionParser
+import glob
+import libxml2
-from sfatables import commands, matches, targets
+from optparse import OptionParser
+from sfatables import commands
+from sfatables.xmlextension import Xmlextension
+from sfatables.globals import *
-def load_extensions(module, list):
+def load_commands(module, list):
command_dict={}
for command_name in list:
return command_dict
+def load_xml_extensions(module, ext_dir):
+ ext_dict={}
+
+ exts = glob.glob(ext_dir + os.path.sep + "*")
+ for ext in exts:
+ module = Xmlextension(ext)
+ # get the filename and get rid of the ".xml" extension
+ ext_name = os.path.extsep.join(os.path.splitext(os.path.basename(ext))[:-1])
+ ext_dict[ext_name]=module
+
+ return ext_dict
+
+
def create_parser(command_dict):
parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
description='See "man sfatables" for more detail.')
return parser
+def create_parser_xml_ext(ext_dict):
+ parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
+ description='See "man sfatables" for more detail.')
+
+ for k in ext_dict.keys():
+ command = ext_dict[k]
+ for arg in command.arguments:
+ parser.add_option('',"--"+arg['name'],dest=arg['name'],help=arg['help'],metavar=arg['target'])
+
+ return parser
+
def partition(sep, lst):
ret = []
def main():
- # Segment command line into three blobs, one each for the command, match and target respectively.
-
+ # sfatables <command> -- <match> -- <target>
pargs = partition('--', sys.argv[1:])
- command_dict = load_extensions("sfatables.commands",commands.all)
+ command_dict = load_commands("sfatables.commands",commands.all)
command_parser = create_parser(command_dict)
- (options, args) = command_parser.parse_args()
+ (options, args) = command_parser.parse_args(pargs[0])
+ setattr(options, 'args', args)
command = command_dict[options.command]
if (command.matches):
if (len(pargs)<2):
raise Exception("Must specify match for this command")
- match_dict = load_extensions("sfatables.matches",matches.all)
- match_parser = create_parser(match_dict)
+ match_dict = load_xml_extensions("sfatables.matches",match_dir)
+ match_parser = create_parser_xml_ext(match_dict)
+ matches_str = ",".join(match_dict.keys())
+ match_parser.add_option('-m','--match',dest='name',help='Match name (one of %s)'%matches_str, metavar = 'MATCH')
+ match_parser.add_option('-n','--negate',dest='negate',help='Negate result',action='store_true')
(match_options, args) = match_parser.parse_args(pargs[1])
+ try:
+ name = match_options.name
+ except Exception:
+ print "Must specify match name with -m"
+
+ if (match_dict.has_key(name)):
+ setattr(match_options, 'arguments', match_dict[name].arguments)
+ else:
+ raise Exception('Match %s not found'%name)
+
else:
match_options=None
if (command.targets):
if (len(pargs)<3):
raise Exception("Must specify a target for this command")
- match_dict = load_extensions("sfatables.targets",targets.all)
- target_parser = create_parser(match_dict)
+ target_dict = load_xml_extensions("sfatables.targets",target_dir)
+ target_parser = create_parser_xml_ext(target_dict)
+ targets_str = ",".join(target_dict.keys())
+ target_parser.add_option('-j','--jump',dest='name',help='Target name (one of %s)'%targets_str, metavar = 'TARGET')
+ target_parser.add_option('-e','--element',dest='element',help='Element name', metavar = 'ELEMENT')
(target_options, args) = target_parser.parse_args(pargs[2])
+ try:
+ name = target_options.name
+ except Exception:
+ print "Must specify target name with -j"
+
+ if (target_dict.has_key(name)):
+ setattr(target_options, 'arguments', target_dict[name].arguments)
+ else:
+ raise Exception('Target %s not found'%name)
+
else:
target_options = None