Changeset 198
- Timestamp:
- 04/21/05 22:09:50 (4 years ago)
- Files:
-
- manage/branches/python/CLI.py (modified) (20 diffs)
- manage/branches/python/fwc (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
manage/branches/python/CLI.py
r197 r198 5 5 import sys 6 6 import readline 7 import copy 7 8 8 9 # Commands … … 26 27 # of labels, in which case each grammar branch will be a candidate. 27 28 JUMP_TO = 'JUMP_TO' 29 RETURN = 'RETURN' 28 30 # Include this branch only if the given function returns true. 29 31 IF = 'IF' … … 39 41 # Store value of parent with the given identifier 40 42 VAR = 'VAR' 41 # Require between [min , max]43 # Require between [min [, max]] 42 44 RANGE = 'RANGE' 45 # Merge the given target at this location. Target can either be a sub-grammar 46 # or a callable with the signature function(context, grammar), where grammar is 47 # the grammar at the current depth. 48 MERGE = 'MERGE' 43 49 44 50 # Context states … … 63 69 if LABEL in grammar: 64 70 self.context.add_label(grammar[LABEL], {grammar_key : grammar}) 71 elif GLOBAL_LABEL in grammar: 72 self.context.add_label(grammar[GLOBAL_LABEL], {grammar_key : grammar}) 65 73 # Increase reference count 66 74 context.traverse(grammar) … … 103 111 def __init__(self, grammar, tokens, text): 104 112 self.__label = [] 113 self.__mark = [] 105 114 self.__var = {} 106 115 self.__count = {} 116 self.__rangemap = {} 117 self.grammar = self.__copy_grammar(grammar) 107 118 self.text = text 108 self.grammar = grammar109 119 self.tokens = tokens 110 120 self.parsed_tokens = [] … … 112 122 self.result = None 113 123 self.pre_parse(self.grammar) 124 125 def __copy_grammar(self, grammar): 126 out = {} 127 for k, v in grammar.iteritems(): 128 t = type(v) 129 if t is dict: 130 out[k] = self.__copy_grammar(v) 131 else: 132 if t is types.FunctionType: 133 out[k] = v 134 else: 135 out[k] = copy.copy(v) 136 return out 114 137 115 138 def pre_parse(self, grammar, grammar_key = None): … … 124 147 125 148 def traversed(self, node): 126 if RANGE in node: 127 return node[RANGE][2] 128 else: 129 return 0 149 return self.range(node)[2] 130 150 131 151 def traverse(self, node): 132 if RANGE in node: 133 if type(node[RANGE]) is int: 134 node[RANGE] = [ node[RANGE], node[RANGE], 0 ] 135 else: 136 node[RANGE] = [ 0, 9999, 0 ] 152 node[RANGE] = self.range(node) 137 153 node[RANGE][2] += 1 138 154 return node[RANGE][2] … … 140 156 def add_var(self, var, value): 141 157 if var in self.__var: 158 if type(self.__var[var]) is not list: 159 self.__var[var] = [ self.__var[var] ] 142 160 self.__var[var].append(value) 143 161 else: 144 self.__var[var] = [ value ] 162 self.__var[var] = value 163 164 def add_mark(self, grammar): 165 self.__mark.append(grammar) 145 166 146 167 def add_label(self, name, grammar): … … 153 174 self.__label.append([name, grammar]) 154 175 155 def has_ labels(self, seek):176 def has_all_labels(self, seek): 156 177 if type(seek) is str: seek = [ seek ] 157 178 for s in seek: … … 165 186 return True 166 187 167 def has_vars(self, seek): 188 def has_labels(self, seek): 189 """ Return true if any of the sought labels exist. """ 190 if type(seek) is str: seek = [ seek ] 191 for s in seek: 192 for l in self.__label: 193 if l[0] == s: 194 return True 195 return False 196 197 def has_all_vars(self, seek): 198 """ Determine if all of the sought variables are defiend. """ 168 199 if type(seek) is str: seek = [ seek ] 169 200 for var in seek: … … 172 203 return True 173 204 174 def merge_grammars_shallow(self, seek): 205 def has_vars(self, seek): 206 """ Determine if any of the given variables are defined. """ 207 if type(seek) is str: seek = [ seek ] 208 for var in seek: 209 if var in self.__var: 210 return True 211 return False 212 213 def merge_labels_shallow(self, seek): 175 214 out = {} 176 215 for label in self.__label: … … 181 220 return out 182 221 183 def merge_ grammars(self, seek):222 def merge_labels(self, seek): 184 223 out = {} 185 224 for label in self.__label: … … 188 227 out[key] = label[1][key] 189 228 return out 229 230 def range(self, grammar): 231 range = None 232 if RANGE in grammar: 233 range = grammar[RANGE] 234 t = type(range) 235 if t is int: 236 range = [ range, range, 0, id(self) ] 237 elif t is tuple or t is list: 238 range = list(range) 239 if len(range) < 3: range.append(0) 240 if len(range) < 4: range.append(id(self)) 241 if range[3] != id(self): 242 range[2] = 0 243 range[3] = id(self) 244 if len(range) != 4: 245 raise TypeError("RANGE list or tuple must be 1 or 2 elements") 246 else: 247 raise TypeError("RANGE keys must be either an integer count or a (min,max) tuple/list, not %s" % t) 248 else: 249 range = grammar[RANGE] = [ 0, 9999, 0, id(self) ] 250 grammar[RANGE] = range 251 return range 190 252 191 253 def filter_grammar(self, grammar): … … 199 261 (UNLESS in branch and not branch[UNLESS](self) or UNLESS not in branch) \ 200 262 and 201 ( IF_VAR in branch and branch[IF_VAR] in selfor IF_VAR not in branch) \263 ((IF_VAR in branch and self.has_vars(branch[IF_VAR])) or IF_VAR not in branch) \ 202 264 and 203 265 ((UNLESS_VAR in branch and not self.has_vars(branch[UNLESS_VAR])) or UNLESS_VAR not in branch) \ … … 208 270 and 209 271 # If RANGE is exceeded... 210 ( (RANGE in branch and branch[RANGE][2] < branch[RANGE][1]) or not RANGE in branch)272 (self.range(branch)[2] < self.range(branch)[1]) 211 273 ): 212 274 out[key] = branch … … 223 285 224 286 def grammar_branches(self, grammar): 225 new_grammar = {} 226 if JUMP in grammar: 227 if not self.has_labels(grammar[JUMP]): 228 raise NameError("no such label '%s' referenced in JUMP" % grammar[JUMP]) 229 new_grammar.update(self.merge_grammars_shallow(grammar[JUMP])) 230 if JUMP_TO in grammar: 231 if not self.has_labels(grammar[JUMP_TO]): 232 raise NameError("no such label '%s' referenced in JUMP_TO" % grammar[JUMP_TO]) 233 new_grammar.update(self.merge_grammars(grammar[JUMP_TO])) 234 return new_grammar 287 done = {} 288 for i in range(0, 3): 289 if MERGE in grammar and MERGE not in done: 290 done[MERGE] = 1 291 merge = grammar[MERGE] 292 if type(merge) is not list: merge = [ merge ] 293 self.add_mark(grammar) 294 for m in merge: 295 mtype = type(m) 296 if mtype is types.FunctionType: 297 m = m(self, grammar) 298 mtype = type(m) 299 if mtype is not dict: 300 raise TypeError("MERGE target must be a dictionary (or callable that returns a dictionary)") 301 grammar.update(m) 302 if JUMP in grammar and JUMP not in done: 303 done[JUMP] = 1 304 label = grammar[JUMP] 305 if label == RETURN: 306 grammar.update(self.__mark[-1]) 307 else: 308 if not self.has_labels(label): 309 raise NameError("no such label '%s' referenced in JUMP" % grammar[JUMP]) 310 grammar.update(self.merge_labels_shallow(label)) 311 if JUMP_TO in grammar and JUMP_TO not in done: 312 done[JUMP_TO] = 1 313 label = grammar[JUMP_TO] 314 if label == RETURN: 315 grammar.update(self.__mark[-1]) 316 else: 317 if not self.has_labels(label): 318 raise NameError("no such label '%s' referenced in JUMP_TO" % grammar[JUMP_TO]) 319 grammar.update(self.merge_labels(label)) 320 return grammar 235 321 236 322 def parse_help_node(self, key, node): … … 313 399 314 400 def parse_branch(self, source_grammar, tokens, nodes): 315 grammar = self.copy_grammar_shallow(source_grammar) 316 grammar.update(self.grammar_branches(grammar)) 401 grammar = self.grammar_branches(self.copy_grammar_shallow(source_grammar)) 317 402 self.result_grammar = grammar 318 403 # End of command … … 339 424 return self.parse_branch(grammar[match], tokens, nodes) 340 425 341 return Result(Result.NOMATCH, self, grammar, token, message = "Invalid command")426 return Result(Result.NOMATCH, self, grammar, token, message = "Invalid token") 342 427 343 428 def __iter__(self): … … 353 438 self.grammar = grammar 354 439 self.tokenise = re.compile(r'(\'(?:[^\\\']|.)*\'|"(?:[^\\"]|.)*")|(\S+)') 355 356 def init_grammar(self, grammar):357 if type(grammar) is not dict: return358 if RANGE in grammar:359 t = type(grammar[RANGE])360 if t is int:361 grammar[RANGE] = [ grammar[RANGE], grammar[RANGE], 0 ]362 elif (t is tuple or t is list) and len(grammar[RANGE]) == 2:363 grammar[RANGE] = [ grammar[RANGE][0], grammar[RANGE][1], 0 ]364 elif t is list and len(grammar[RANGE]) == 3:365 grammar[RANGE][2] = 0366 else:367 raise TypeError("RANGE keys must be either an integer count or a (min,max) tuple, not %s" % t)368 else:369 grammar[RANGE] = [ 0, 9999, 0 ]370 for key, branch in grammar.iteritems():371 if not _is_command(key):372 self.init_grammar(branch)373 440 374 441 def parse(self, command): … … 379 446 else: 380 447 raise TypeError("CLI.parse() must be passed a string command") 381 self.init_grammar(self.grammar)382 448 context = CLI.Context(self.grammar, tokens, command) 383 449 return context.parse() manage/branches/python/fwc
r197 r198 8 8 import textwrap 9 9 10 CONF_DIR = "/etc/fwcrc" 11 10 12 class Rule: 11 def __init__(self, action = None, source = [], sport = [], destination = [], dport = [], protocol = [], description = None, state = None ):13 def __init__(self, action = None, source = [], sport = [], destination = [], dport = [], protocol = [], description = None, state = None, log = None): 12 14 self.action = action 13 15 self.source = source … … 19 21 self.description = description 20 22 self.state = state 23 self.log = log 21 24 22 25 class Object: … … 31 34 self.description = description 32 35 33 class Ruleset:34 def __init__(self ):36 class Firewall: 37 def __init__(self, name): 35 38 self.rules = [] 39 self.name = name 36 40 self.ip = {} 37 41 self.network = {} … … 42 46 self.add_object(Object(Object.PORT, 'any', '0-65535', 'Any port')) 43 47 48 def resolve_object(self, type, name): 49 map = getattr(self, type) 50 if map and name in map: 51 return map[name] 52 return Object(type, name, name) 53 54 def resolve_network(self, network): 55 return self.resolve_object('network', network) 56 57 def resolve_ip(self, ip): 58 return self.resolve_ip('ip', ip) 59 60 def resolve_port(self, port): 61 return self.resolve_port('port', port) 62 63 def resolve_rule(self, rule): 64 try: 65 rule = int(rule) 66 if rule >= 0 and rule < len(self.rules): 67 return int(rule) 68 except TypeError: 69 return None 70 44 71 def add(self, rule, where, index = None): 45 72 try: 46 73 if where == 'top': 47 74 self.rules.insert(0, rule) 75 return 0 48 76 elif where == 'bottom' : 49 77 self.rules.append(rule) 78 return len(self.rules) - 1 50 79 elif where == 'before': 51 self.rules.insert(int(index), rule) 80 self.rules.insert(index, rule) 81 return index 52 82 elif where == 'after': 53 self.rules.insert(int(index) + 1, rule) 83 self.rules.insert(index + 1, rule) 84 return index + 1 54 85 elif where == 'replace' : 55 self.rules[int(index)] = rule 86 self.rules[index] = rule 87 return index 56 88 else: 57 89 raise IndexError("invalid location '%s' for rule addition" % where) 58 90 except IndexError: 59 91 error("Invalid ruleset index %s" % index) 92 return None 93 94 def move(self, old, new): 95 if old == new: return 96 try: 97 rule = self.rules.pop(old) 98 try: 99 if new > old: 100 self.rules.insert(new - 1, rule) 101 else: 102 self.rules.insert(new, rule) 103 except: 104 self.rules.insert(old, rule) 105 raise 106 except IndexError: 107 error("Invalid ruleset index %s or %s" % (old, new)) 60 108 61 109 def remove(self, index): 110 if type(index) is not list: index = [ index ] 62 111 try: 63 self.rules.pop(index) 112 for i in index: 113 self.rules[i] = None 114 newrules = [] 115 for i in self.rules: 116 if i: newrules.append(i) 117 self.rules = newrules 64 118 except IndexError: 65 119 error("Invalid rule index %s" % index) 66 120 67 121 def add_object(self, object): 68 getattr(self, object.type)[object.name] = object 122 map = getattr(self, object.type) 123 if object.name in map: 124 error("%s object '%s' already exists" % (object.type.title(), object.name)) 125 else: 126 map[object.name] = object 69 127 70 128 def remove_object(self, object): … … 74 132 error("Object '%s' not in ruleset" % object.name) 75 133 76 ruleset = Ruleset() 134 # Globally useful stuff 135 136 firewalls = {} 137 firewall = firewalls['DEFAULT'] = Firewall() 138 139 def to_list(value): 140 if type(value) is not list: return [value] 141 return value 77 142 78 143 def info(message): … … 90 155 91 156 def check_port_protocol(context): 92 return 'protocol' in context and context['protocol'][0] in [ 'tcp', 'udp' ] 93 94 def enumerate_ip(context): 157 return 'protocol' in context and context['protocol'] in [ 'tcp', 'udp' ] 158 159 # Help extractors 160 161 def help_ip(context): 95 162 help = { '<ip>' : 'IP address.'} 96 for o in ruleset.ip.values():97 text = o.description or "IP address object (%s)" % o.name98 help[o.name] = text 163 for o in firewall.ip.values(): 164 text = o.description or "IP address object %s" % o.name 165 help[o.name] = text + " (%s)" % o.value 99 166 return help 100 167 168 def help_network(context): 169 help = { '<network>' : 'Network address.'} 170 for o in firewall.network.values(): 171 text = o.description or "Network object %s" % o.name 172 help[o.name] = text + " (%s)" % o.value 173 return help 174 175 def help_network_ip(context): 176 help = {} 177 help.update(help_ip(context)) 178 help.update(help_network(context)) 179 return help 180 181 def help_port(context): 182 help = { '<port>' : 'Port.'} 183 for o in firewall.port.values(): 184 text = o.description or "Port object %s" % o.name 185 help[o.name] = text + " (%s)" % o.value 186 return help 187 188 def help_firewall(context): 189 help = {} 190 for f in firewalls: 191 help[f] = "Firewall %s" % firewalls[f].name 192 return help 193 194 # Command validators 195 196 def NETWORK(context, str): 197 return re.match(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}', str) \ 198 or str in help_network(context) 199 200 def NETWORK_IP(context, str): 201 return re.match(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:/\d{1,2})?', str) \ 202 or str in help_network(context) \ 203 or str in help_ip(context) 204 101 205 def IP(context, str): 102 206 return re.match(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', str) \ 103 or str in enumerate_ip(context).keys() 104 105 def enumerate_network(context): 106 help = { '<network>' : 'Network address.'} 107 for o in ruleset.network.values(): 108 text = o.description or "Network object (%s)" % o.name 109 help[o.name] = text 110 return help 111 112 def NETWORK(context, str): 113 return re.match(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/\d{1,2}', str) \ 114 or str in enumerate_network(context).keys() 115 116 def NETWORK_IP(context, str): 117 return re.match(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:/\d{1,2})?', str) \ 118 or str in enumerate_network(context).keys() \ 119 or str in enumerate_ip(context).keys() 120 121 def enumerate_port(context): 122 help = { '<port>' : 'Port.'} 123 for o in ruleset.port.values(): 124 text = o.description or "Port object (%s)" % o.name 125 help[o.name] = text 126 return help 207 or str in help_ip(context) 127 208 128 209 def PORT(context, str): 129 210 return re.match(r'\d{1,5}', str) \ 130 or str in enumerate_port(context).keys()211 or str in help_port(context) 131 212 132 213 def PORT_RANGE(context, str): … … 134 215 return PORT(context, range[0]) and (len(range) < 2 or len(range) > 1 and PORT(context, range[1])) 135 216 136 def insert_rule(context, action, source = [], sport = [], destination = [], dport = [], protocol = None, description = None, where = [ 'bottom' ], index = [ None ], state = []): 137 action = action[0] 138 if description: description = description[0] 139 if state: state = state[0] 140 if index: index = index[0] 141 if where: where = where[0] 142 if protocol: protocol = protocol[0] 143 ruleset.add(Rule(action, source, sport, destination, dport, protocol, description, state), where, index) 217 def RULE(context, str): 218 try: 219 return int(str) >= 0 and int(str) < len(firewall.rules) 220 except: 221 return False 222 223 def FIREWALL(context, str): 224 print help_firewall(context) 225 return str in help_firewall(context) 226 227 # Commands 228 229 def insert_rule(context, action, source = [], sport = [], destination = [], dport = [], protocol = None, description = None, where = 'bottom', index = None, state = 'new', log = None): 230 if log: 231 if log == 'log': 232 log = True 233 else: 234 log = log[1] 235 if index != None: index = int(index) 236 firewall.add(Rule(action, to_list(source), to_list(sport), to_list(destination), to_list(dport), protocol, description, state, log), where, index) 144 237 145 238 def remove_rule(context, rules): 146 for r in rules: 147 ruleset.remove(int(r)) 239 firewall.remove(map(int, rules)) 240 241 def move_rule(context, old, where = 'top', index = None): 242 if index and old == index: return 243 try: 244 old = int(old) 245 new = firewall.add(firewall.rules[old], where, index and int(index) or None) 246 if new < old: old += 1 247 firewall.remove(old) 248 except TypeError, IndexError: 249 error("Invalid move") 250 raise 148 251 149 252 def list_ruleset(context): 150 for ruleno, rule in enumerate( ruleset.rules):151 cmd = rule.action152 if rule.state :153 cmd += " " + rule.state253 for ruleno, rule in enumerate(firewall.rules): 254 cmd = "[1m%s[22m" % rule.action 255 if rule.state != 'new': 256 cmd += " state [1m" + rule.state + "[22m" 154 257 if rule.protocol: 155 cmd += " " + rule.protocol258 cmd += " [1m" + rule.protocol + "[22m" 156 259 if rule.source or rule.sport: 157 260 cmd += " from" 158 261 if rule.source: 159 cmd += " " + ' '.join(rule.source)262 cmd += " [1m" + ' '.join(rule.source) + "[22m" 160 263 if rule.sport: 161 cmd += " port " + ' '.join(rule.sport)264 cmd += " port [1m" + ' '.join(rule.sport) + "[22m" 162 265 if rule.destination or rule.dport: 163 266 cmd += " to" 164 267 if rule.destination: 165 cmd += " " + ' '.join(rule.destination)268 cmd += " [1m" + ' '.join(rule.destination) + "[22m" 166 269 if rule.dport: 167 cmd += " port " + ' '.join(rule.dport) 270 cmd += " port [1m" + ' '.join(rule.dport) + "[22m" 271 if rule.log: 272 cmd += " log" 273 if type(rule.log) is str: 274 cmd += " [1m'%s'[22m" % rule.log 168 275 if rule.description: 169 cmd += " description '%s'" % rule.description276 cmd += " description [1m'%s'[22m" % rule.description 170 277 print "[1m%3i:[0m %s" % (ruleno, cmd) 171 #r = [[ruleno], [action_map[rule.action]], rule.source, rule.sport, rule.destination, rule.dport, [rule.protocol], [rule.state], [rule.description]]172 278 173 279 def create_object(context, type, name, value, description = None): 174 if description: description = description[0] 175 ruleset.add_object(Object(type[0], name[0], value[0], description)) 280 firewall.add_object(Object(type, name, value, description)) 176 281 177 282 def list_objects(context, type = ['network', 'ip', 'port']): 178 for t in type: 179 objects = getattr(ruleset, t) 180 keys = objects.keys() 181 keys.sort() 182 for k in keys: 283 for t in to_list(type): 284 objects = getattr(firewall, t) 285 print "[4m[1m%s objects[0m" % t.title() 286 for k in sorted(objects): 183 287 o = objects[k] 184 str = " object create %s %s %s" % (o.name, o.type, o.value)288 str = " %s %s" % (o.name, o.value) 185 289 if o.description: str += " '%s'" % o.description 186 290 print str … … 190 294 sys.exit(0) 191 295 296 # Grammar content 297 298 placement_rules = { 299 'replace' : { 300 GROUP : 'Rule ordering.', 301 UNLESS_VAR : [ 'old', 'where' ], 302 VAR : 'where', 303 HELP : 'Replace an existing rule.', 304 RULE : { 305 HELP : ('<rule>', 'Rule to replace.'), 306 VAR : 'index', 307 JUMP : RETURN, 308 }, 309 }, 310 'top|bottom' : { 311 GROUP : 'Rule ordering.', 312 UNLESS_VAR : 'where', 313 VAR : 'where', 314 HELP : { 315 'top' : 'Insert rule at top of ruleset.', 316 'bottom' : 'Insert rule at bottom of ruleset (default).', 317 }, 318 JUMP : RETURN, 319 }, 320 'before|after' : { 321 GROUP : 'Rule ordering.', 322 UNLESS_VAR : 'where', 323 VAR : 'where', 324 HELP : { 325 'before' : 'Insert rule before another.', 326 'after' : 'Insert rule after another.', 327 }, 328 RULE : { 329 HELP : ('<rule>', 'Rule to insert relative to.'), 330 VAR : 'index', 331 JUMP : RETURN, 332 }, 333 }, 334 } 335 336 protocol_rules = { 337 'tcp|udp|icmp|ah|esp' : { 338 GROUP : 'Packet matching.', 339 UNLESS_VAR : 'protocol', 340 VAR : 'protocol', 341 HELP : { 342 'tcp' : 'Match TCP packets.', 343 'udp' : 'Match UDP packets.', 344 'icmp' : 'Match ICMP packets.', 345 'ah' : 'Match AH packets.', 346 'esp' : 'Match ESP packets.', 347 }, 348 JUMP : RETURN, 349 }, 350 } 351 192 352 # Grammar 193 353 cli = CLI({ 194 'accept|deny|reject' : { 354 'accept|drop|reject' : { 355 GLOBAL_LABEL : 'commands', 195 356 'state' : { 196 357 GROUP : 'Packet matching.', 197 358 RANGE : 1, 198 LABEL : 'state',199 359 HELP : 'Match connections in this state (default: new).', 200 360 'new|established|invalid|related' : { … … 206 366 'related' : 'Match related connections.', 207 367 }, 208 },209 },210 'replace' : {211 GROUP : 'Rule ordering.',212 UNLESS_VAR : 'where',213 VAR : 'where',214 HELP : 'Replace an existing rule.',215 '\d+' : {216 HELP : ('<rule>', 'Rule to replace.'),217 VAR : 'index',218 JUMP : 'commands',219 },220 },221 'top|bottom' : {222 GROUP : 'Rule ordering.',223 UNLESS_VAR : 'where',224 VAR : 'where',225 HELP : {226 'top' : 'Insert rule at top of ruleset (default).',227 'bottom' : 'Insert rule at bottom of ruleset.',228 },229 JUMP : 'commands',230 },231 'before|after' : {232 GROUP : 'Rule ordering.',233 UNLESS_VAR : 'where',234 VAR : 'where',235 HELP : {236 'before' : 'Insert rule before another.',237 'after' : 'Insert rule after another.',238 },239 '\d+' : {240 HELP : ('<rule>', 'Rule to insert relative to.'),241 VAR : 'index',242 368 JUMP : 'commands', 243 369 }, … … 249 375 ACTION : insert_rule, 250 376 }, 377 MERGE : [ placement_rules, protocol_rules ], 251 378 VAR : 'action', 252 GLOBAL_LABEL : 'commands',253 379 HELP : { 254 380 'accept' : 'Add rule accepting matching packets.', 255 'd eny' : 'Add rule denying matching packets.',381 'drop' : 'Add rule dropping matching packets.', 256 382 'reject' : 'Add rule rejecting matching packets.', 257 },258 'tcp|udp|icmp|ah|esp' : {259 GROUP : 'Packet matching.',260 RANGE : 1,261 VAR : 'protocol',262 HELP : {263 'tcp' : 'Match TCP packets.',264 'udp' : 'Match UDP packets.',265 'icmp' : 'Match ICMP packets.',266 'ah' : 'Match AH packets.',267 'esp' : 'Match ESP packets.',268 },269 JUMP : 'commands',270 383 }, 271 384 'from' : { 272 385 GROUP : 'Packet matching.', 273 386 HELP : 'Match source network or port.', 274 IF : lambda ctx: ('protocol' in ctx and ctx['protocol'] [0]in ['tcp', 'udp'] and not 'sport' in ctx) or not 'source' in ctx,387 IF : lambda ctx: ('protocol' in ctx and ctx['protocol'] in ['tcp', 'udp'] and not 'sport' in ctx) or not 'source' in ctx, 275 388 NETWORK_IP : { 276 389 VAR : 'source', … … 281 394 &
