(no commit message)
[sfa.git] / sfatables / sfatables
1 #!/usr/bin/python 
2 # SFAtables is a tool for restricting access to an SFA aggregate in a generic
3 # and extensible way. 
4
5 # It is modeled using abstractions in iptables. Specifically, 'matches' specify
6 # criteria for matching certain requests, 'targets' specify actions that treat
7 # requests in a certain way, and 'chains' are used to group related
8 # match-action pairs.
9
10 import sys
11 import os
12 import pdb
13 import libxml2
14 from optparse import OptionParser
15
16 from sfatables import commands, matches, targets
17 from sfatables import Xmlextension
18
19 def load_commands(module, list):
20     ext_dict={}
21
22     for command_name in list:
23         command_module = __import__(".".join([module,command_name]),fromlist=[module])
24         command = getattr(command_module, command_name)
25         command_dict[command_name]=command()
26
27     return ext_dict
28
29 def load_xml_extensions(module, list):
30     ext_dict={}
31
32     for ext_name in list:
33         module = Xmlextension(ext_name)
34         ext_dict[ext_name]=module
35
36     return ext_dict
37
38
39 def create_parser(command_dict):
40     parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
41                              description='See "man sfatables" for more detail.')
42     
43     for k in command_dict.keys():
44         command = command_dict[k]
45         for (short_option,long_option) in command.options:
46             parser.add_option(short_option,long_option,dest=command.type,action=command.action,const=k,help=command.help,metavar="CHAIN")
47
48     return parser
49
50 def xml_ext_create_parser(ext_dict):
51     parser = OptionParser(usage="sfatables [command] [chain] [match] [target]",
52                              description='See "man sfatables" for more detail.')
53     
54     for k in command_dict.keys():
55         command = command_dict[k]
56         for arg in command.arguments:
57             parser.add_option(None,"--"+arg,dest=arg,help=command.help,metavar=command.operand)
58
59     return parser
60
61
62 def partition(sep, lst):
63     ret = []
64     curpart = []
65     for item in lst:
66         if (item==sep):
67             ret.append(curpart)
68             curpart=[]
69         else:
70             curpart.append(item)
71     ret.append(curpart)
72
73     return ret
74
75
76 def main():
77     # Segment command line into three blobs, one each for the command, match and target respectively.
78     
79     pargs = partition('--', sys.argv[1:])
80
81     command_dict = load_commands("sfatables.commands",commands.all)
82     command_parser = create_parser(command_dict)
83     (options, args) = command_parser.parse_args()
84
85     command = command_dict[options.command]
86
87     if (command.matches):
88         if (len(pargs)<2):
89             raise Exception("Must specify match for this command")
90         match_dict = load_xml_extensions("sfatables.matches",matches.all)
91         match_parser = create_parser(match_dict)
92         (match_options, args) = match_parser.parse_args(pargs[1])
93     else:
94         match_options=None
95
96     if (command.targets):
97         if (len(pargs)<3):
98             raise Exception("Must specify a target for this command")
99         match_dict = load_xml_extensions("sfatables.targets",targets.all)
100         target_parser = create_parser(match_dict)
101         (target_options, args) = target_parser.parse_args(pargs[2])
102     else:
103         target_options = None
104
105     command(options, match_options, target_options)
106
107 if __name__=='__main__':
108     main()