ufw

Merge lp:~bertrand-goareguer/ufw/ufw-qos into lp:~jdstrand/ufw/trunk

Proposed by Jonathan Davies
Status: Rejected
Rejected by: Jamie Strandboge
Proposed branch: lp:~bertrand-goareguer/ufw/ufw-qos
Merge into: lp:~jdstrand/ufw/trunk
Diff against target: 634 lines (+347/-3)
6 files modified
setup.py (+1/-1)
src/backend_iptables.py (+81/-0)
src/common.py (+40/-0)
src/frontend.py (+52/-2)
src/tc_functions.py (+150/-0)
src/ufw-init-functions (+23/-0)
To merge this branch: bzr merge lp:~bertrand-goareguer/ufw/ufw-qos
Reviewer Review Type Date Requested Status
Jamie Strandboge Pending
Review via email: mp+15907@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

371. By Bertrand Goareguer <beber@beber-laptop>

added creation of the TC filters when firewall is enabled

370. By Bertrand Goareguer <beber@beber-laptop>

implemented the deletion of the tc filters (when deleting the rule)

369. By Bertrand Goareguer <beber@beber-laptop>

added creation of tc filters (deletion is not implemente yet)

368. By Bertrand Goareguer <beber@beber-laptop>

added creation/deletion of tc qdiscs on firewall startup/shutdown

367. By Bertrand Goareguer <beber@beber-laptop>

- rules now have a rate clause
- the rate is expressed in kbps (kilo bits per second)
- the rate can only be specified with the "allow" action
- if no rate is specified or if action != "allow", the rate is set to "unlimited"
- writing the 2 same rules with different rates updates the rule (similar to writing same rules with different actions)
- both short and full rule formats are supported
- rate must be the last parameter for short rule format

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'setup.py'
--- setup.py 2009-11-30 16:03:43 +0000
+++ setup.py 2009-12-09 23:28:13 +0000
@@ -253,7 +253,7 @@
253 license='GPL-3',253 license='GPL-3',
254 cmdclass={'install': Install},254 cmdclass={'install': Install},
255 package_dir={'ufw': 'staging'},255 package_dir={'ufw': 'staging'},
256 py_modules=['ufw.backend', 'ufw.backend_iptables', 'ufw.common', 'ufw.frontend', 'ufw.util', 'ufw.applications']256 py_modules=['ufw.backend', 'ufw.backend_iptables', 'ufw.common', 'ufw.frontend', 'ufw.util', 'ufw.applications', 'ufw.tc_functions']
257)257)
258258
259shutil.rmtree('staging')259shutil.rmtree('staging')
260260
=== modified file 'src/backend_iptables.py'
--- src/backend_iptables.py 2009-11-11 18:05:16 +0000
+++ src/backend_iptables.py 2009-12-09 23:28:13 +0000
@@ -20,9 +20,11 @@
20import re20import re
21import sys21import sys
22import tempfile22import tempfile
23import ufw.tc_functions
2324
24from ufw.common import UFWError, UFWRule, config_dir, state_dir, prefix_dir25from ufw.common import UFWError, UFWRule, config_dir, state_dir, prefix_dir
25from ufw.util import warn, debug, msg, cmd, cmd_pipe26from ufw.util import warn, debug, msg, cmd, cmd_pipe
27from ufw.tc_functions import add_filter, delete_filter
26import ufw.backend28import ufw.backend
2729
2830
@@ -388,6 +390,9 @@
388 (rc, out) = cmd([self.files['init'], 'start'])390 (rc, out) = cmd([self.files['init'], 'start'])
389 if rc != 0:391 if rc != 0:
390 raise UFWError(err_msg + " ufw-init")392 raise UFWError(err_msg + " ufw-init")
393 else:
394 # if firewall has been started successfully, apply the TC rules
395 self._reload_user_filters()
391396
392 if not self.defaults.has_key('loglevel') or \397 if not self.defaults.has_key('loglevel') or \
393 self.defaults['loglevel'] not in self.loglevels.keys():398 self.defaults['loglevel'] not in self.loglevels.keys():
@@ -454,7 +459,19 @@
454 if rc != 0:459 if rc != 0:
455 raise UFWError(err_msg + " ip6tables")460 raise UFWError(err_msg + " ip6tables")
456461
462<<<<<<< TREE
457 def _get_rules_from_formatted(self, frule, prefix, suffix):463 def _get_rules_from_formatted(self, frule, prefix, suffix):
464=======
465 def _reload_user_filters(self):
466 '''Reload TC filters'''
467 for rule in self.rules:
468 if rule.rate != "unlimited":
469 if rule.action == "allow":
470 add_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.rate, rule.filter_id)
471
472
473 def _get_rules_from_formatted(self, frule, prefix):
474>>>>>>> MERGE-SOURCE
458 '''Return list of iptables rules appropriate for sending'''475 '''Return list of iptables rules appropriate for sending'''
459 snippets = []476 snippets = []
460477
@@ -558,7 +575,11 @@
558 if pat_tuple.match(line):575 if pat_tuple.match(line):
559 tuple = pat_tuple.sub('', line)576 tuple = pat_tuple.sub('', line)
560 tmp = re.split(r'\s+', tuple.strip())577 tmp = re.split(r'\s+', tuple.strip())
578<<<<<<< TREE
561 if len(tmp) < 6 or len(tmp) > 9:579 if len(tmp) < 6 or len(tmp) > 9:
580=======
581 if len(tmp) != 8 and len(tmp) != 10:
582>>>>>>> MERGE-SOURCE
562 warn_msg = _("Skipping malformed tuple (bad length): %s") % (tuple)583 warn_msg = _("Skipping malformed tuple (bad length): %s") % (tuple)
563 warn(warn_msg)584 warn(warn_msg)
564 continue585 continue
@@ -573,12 +594,24 @@
573 else:594 else:
574 type = tmp[-1]595 type = tmp[-1]
575 try:596 try:
597<<<<<<< TREE
576 if len(tmp) < 8:598 if len(tmp) < 8:
599=======
600 if len(tmp) == 8:
601>>>>>>> MERGE-SOURCE
577 rule = UFWRule(tmp[0], tmp[1], tmp[2], tmp[3],602 rule = UFWRule(tmp[0], tmp[1], tmp[2], tmp[3],
603<<<<<<< TREE
578 tmp[4], tmp[5], type)604 tmp[4], tmp[5], type)
605=======
606 tmp[4], tmp[5], tmp[6], tmp[7])
607>>>>>>> MERGE-SOURCE
579 else:608 else:
580 rule = UFWRule(tmp[0], tmp[1], tmp[2], tmp[3],609 rule = UFWRule(tmp[0], tmp[1], tmp[2], tmp[3],
610<<<<<<< TREE
581 tmp[4], tmp[5], type)611 tmp[4], tmp[5], type)
612=======
613 tmp[4], tmp[5], tmp[8], tmp[9])
614>>>>>>> MERGE-SOURCE
582 # Removed leading [sd]app_ and unescape spaces615 # Removed leading [sd]app_ and unescape spaces
583 pat_space = re.compile('%20')616 pat_space = re.compile('%20')
584 if tmp[6] != "-":617 if tmp[6] != "-":
@@ -662,6 +695,7 @@
662 action += "_" + r.logtype695 action += "_" + r.logtype
663696
664 if r.dapp == "" and r.sapp == "":697 if r.dapp == "" and r.sapp == "":
698<<<<<<< TREE
665 tstr = "\n### tuple ### %s %s %s %s %s %s %s" % \699 tstr = "\n### tuple ### %s %s %s %s %s %s %s" % \
666 (action, r.protocol, r.dport, r.dst, r.sport, r.src, \700 (action, r.protocol, r.dport, r.dst, r.sport, r.src, \
667 r.direction)701 r.direction)
@@ -670,6 +704,10 @@
670 if r.interface_out != "":704 if r.interface_out != "":
671 tstr += "_%s" % (r.interface_out)705 tstr += "_%s" % (r.interface_out)
672 ufw.util.write_to_file(fd, tstr + "\n")706 ufw.util.write_to_file(fd, tstr + "\n")
707=======
708 os.write(fd, "\n### tuple ### %s %s %s %s %s %s %s %s\n" % \
709 (r.action, r.protocol, r.dport, r.dst, r.sport, r.src, r.rate, r.filter_id))
710>>>>>>> MERGE-SOURCE
673 else:711 else:
674 pat_space = re.compile(' ')712 pat_space = re.compile(' ')
675 dapp = "-"713 dapp = "-"
@@ -678,6 +716,7 @@
678 sapp = "-"716 sapp = "-"
679 if r.sapp:717 if r.sapp:
680 sapp = pat_space.sub('%20', r.sapp)718 sapp = pat_space.sub('%20', r.sapp)
719<<<<<<< TREE
681 tstr = "\n### tuple ### %s %s %s %s %s %s %s %s %s" % \720 tstr = "\n### tuple ### %s %s %s %s %s %s %s %s %s" % \
682 (action, r.protocol, r.dport, r.dst, r.sport, r.src, \721 (action, r.protocol, r.dport, r.dst, r.sport, r.src, \
683 dapp, sapp, r.direction)722 dapp, sapp, r.direction)
@@ -697,6 +736,14 @@
697 for s in self._get_rules_from_formatted(rule_str, chain_prefix, \736 for s in self._get_rules_from_formatted(rule_str, chain_prefix, \
698 chain_suffix):737 chain_suffix):
699 ufw.util.write_to_file(fd, s)738 ufw.util.write_to_file(fd, s)
739=======
740 os.write(fd, "\n### tuple ### %s %s %s %s %s %s %s %s %s %s\n" \
741 % (r.action, r.protocol, r.dport, r.dst, r.sport, r.src, \
742 dapp, sapp, r.rate, r.filter_id))
743
744 for s in self._get_rules_from_formatted(rule_str, chain_prefix):
745 os.write(fd, s)
746>>>>>>> MERGE-SOURCE
700747
701 # Write footer748 # Write footer
702 ufw.util.write_to_file(fd, "\n### END RULES ###\n")749 ufw.util.write_to_file(fd, "\n### END RULES ###\n")
@@ -825,9 +872,17 @@
825 # skip it.872 # skip it.
826 found = True873 found = True
827 if not rule.remove:874 if not rule.remove:
875<<<<<<< TREE
828 newrules.append(rule.dup_rule())876 newrules.append(rule.dup_rule())
829 elif ret < 0 and not rule.remove and not inserted:877 elif ret < 0 and not rule.remove and not inserted:
830 # If only the action is different, replace the rule if it's not878 # If only the action is different, replace the rule if it's not
879=======
880 newrules.append(rule)
881 else:
882 rule.filter_id = r.filter_id
883 elif ret < 0 and not rule.remove:
884 # If only the action or the rate is different, replace the rule if it's not
885>>>>>>> MERGE-SOURCE
831 # to be removed.886 # to be removed.
832 found = True887 found = True
833 modified = True888 modified = True
@@ -932,13 +987,39 @@
932 msg(out, sys.stderr)987 msg(out, sys.stderr)
933 UFWError(err_msg)988 UFWError(err_msg)
934989
990<<<<<<< TREE
935 # delete any lingering RETURN rules (needed for upgrades)991 # delete any lingering RETURN rules (needed for upgrades)
936 if flag == "-A" and pat_log.search(" ".join(s)):992 if flag == "-A" and pat_log.search(" ".join(s)):
937 c = pat_log.sub(r'\2', " ".join(s))993 c = pat_log.sub(r'\2', " ".join(s))
938 (rc, out) = cmd([exe, '-D', c, '-j', 'RETURN'])994 (rc, out) = cmd([exe, '-D', c, '-j', 'RETURN'])
995=======
996 # add/remove the TC filter if needed
997 if rule.rate != "unlimited":
998 if not rule.remove:
999 add_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.rate, rule.filter_id)
1000 else:
1001 delete_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.filter_id)
1002
1003 # delete the RETURN rule then add it back, so it is at the
1004 # end
1005 if flag == "-A":
1006 (rc, out) = cmd([exe, '-D', chain, '-j', 'RETURN'])
1007>>>>>>> MERGE-SOURCE
939 if rc != 0:1008 if rc != 0:
940 debug("FAILOK: -D %s -j RETURN" % (c))1009 debug("FAILOK: -D %s -j RETURN" % (c))
9411010
1011<<<<<<< TREE
1012=======
1013 (rc, out) = cmd([exe, '-A', chain, '-j', 'RETURN'])
1014 if rc != 0:
1015 msg(out, sys.stderr)
1016
1017 else:
1018 # the rule has been updated: remove the old filter (an error occurs if there was none) and add the new one (if it exists)
1019 delete_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.filter_id)
1020 if rule.rate != "unlimited":
1021 add_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.rate, rule.filter_id)
1022>>>>>>> MERGE-SOURCE
942 return rstr1023 return rstr
9431024
944 def get_app_rules_from_system(self, template, v6):1025 def get_app_rules_from_system(self, template, v6):
9451026
=== modified file 'src/common.py'
--- src/common.py 2009-08-26 20:18:30 +0000
+++ src/common.py 2009-12-09 23:28:13 +0000
@@ -40,7 +40,11 @@
40class UFWRule:40class UFWRule:
41 '''This class represents firewall rules'''41 '''This class represents firewall rules'''
42 def __init__(self, action, protocol, dport="any", dst="0.0.0.0/0",42 def __init__(self, action, protocol, dport="any", dst="0.0.0.0/0",
43<<<<<<< TREE
43 sport="any", src="0.0.0.0/0", direction="in"):44 sport="any", src="0.0.0.0/0", direction="in"):
45=======
46 sport="any", src="0.0.0.0/0", rate="unlimited", filter_id="0"):
47>>>>>>> MERGE-SOURCE
44 # Be sure to update dup_rule accordingly...48 # Be sure to update dup_rule accordingly...
45 self.remove = False49 self.remove = False
46 self.updated = False50 self.updated = False
@@ -54,10 +58,15 @@
54 self.dapp = ""58 self.dapp = ""
55 self.sapp = ""59 self.sapp = ""
56 self.action = ""60 self.action = ""
61<<<<<<< TREE
57 self.position = 062 self.position = 0
58 self.logtype = ""63 self.logtype = ""
59 self.interface_in = ""64 self.interface_in = ""
60 self.interface_out = ""65 self.interface_out = ""
66=======
67 self.rate =""
68 self.filter_id =""
69>>>>>>> MERGE-SOURCE
61 try:70 try:
62 self.set_action(action)71 self.set_action(action)
63 self.set_protocol(protocol)72 self.set_protocol(protocol)
@@ -65,7 +74,12 @@
65 self.set_port(sport, "src")74 self.set_port(sport, "src")
66 self.set_src(src)75 self.set_src(src)
67 self.set_dst(dst)76 self.set_dst(dst)
77<<<<<<< TREE
68 self.set_direction(direction)78 self.set_direction(direction)
79=======
80 self.set_rate(rate)
81 self.set_filter_id(filter_id)
82>>>>>>> MERGE-SOURCE
69 except UFWError:83 except UFWError:
70 raise84 raise
7185
@@ -85,11 +99,16 @@
85 rule.multi = self.multi99 rule.multi = self.multi
86 rule.dapp = self.dapp100 rule.dapp = self.dapp
87 rule.sapp = self.sapp101 rule.sapp = self.sapp
102<<<<<<< TREE
88 rule.position = self.position103 rule.position = self.position
89 rule.logtype = self.logtype104 rule.logtype = self.logtype
90 rule.interface_in = self.interface_in105 rule.interface_in = self.interface_in
91 rule.interface_out = self.interface_out106 rule.interface_out = self.interface_out
92 rule.direction = self.direction107 rule.direction = self.direction
108=======
109 rule.rate = self.rate
110 rule.filter_id = self.filter_id
111>>>>>>> MERGE-SOURCE
93112
94 return rule113 return rule
95114
@@ -278,6 +297,7 @@
278 self.dst = tmp297 self.dst = tmp
279 self._fix_anywhere()298 self._fix_anywhere()
280299
300<<<<<<< TREE
281 def set_interface(self, type, name):301 def set_interface(self, type, name):
282 '''Sets an interface for rule'''302 '''Sets an interface for rule'''
283 if type != "in" and type != "out":303 if type != "in" and type != "out":
@@ -321,6 +341,18 @@
321 err_msg = _("Unsupported direction '%s'") % (direction)341 err_msg = _("Unsupported direction '%s'") % (direction)
322 raise UFWError(err_msg)342 raise UFWError(err_msg)
323343
344=======
345 def set_rate(self, rate):
346 '''Sets rate for the rule'''
347 self.rate = rate
348 self._fix_anywhere()
349
350 def set_filter_id(self, filter_id):
351 '''Sets the if of the filter associated to the rule'''
352 self.filter_id = filter_id
353 self._fix_anywhere()
354
355>>>>>>> MERGE-SOURCE
324 def normalize(self):356 def normalize(self):
325 '''Normalize src and dst to standard form'''357 '''Normalize src and dst to standard form'''
326 changed = False358 changed = False
@@ -391,6 +423,7 @@
391 if x.sapp != y.sapp:423 if x.sapp != y.sapp:
392 debug(dbg_msg)424 debug(dbg_msg)
393 return 1425 return 1
426<<<<<<< TREE
394 if x.interface_in != y.interface_in:427 if x.interface_in != y.interface_in:
395 return 1428 return 1
396 if x.interface_out != y.interface_out:429 if x.interface_out != y.interface_out:
@@ -398,13 +431,20 @@
398 if x.direction != y.direction:431 if x.direction != y.direction:
399 return 1432 return 1
400 if x.action == y.action and x.logtype == y.logtype:433 if x.action == y.action and x.logtype == y.logtype:
434=======
435 if x.action == y.action and x.rate == y.rate:
436>>>>>>> MERGE-SOURCE
401 dbg_msg = _("Found exact match")437 dbg_msg = _("Found exact match")
402 debug(dbg_msg)438 debug(dbg_msg)
403 return 0439 return 0
440<<<<<<< TREE
404 dbg_msg = _("Found non-action/non-logtype match " \441 dbg_msg = _("Found non-action/non-logtype match " \
405 "(%(xa)s/%(ya)s %(xl)s/%(yl)s)") % \442 "(%(xa)s/%(ya)s %(xl)s/%(yl)s)") % \
406 ({'xa': x.action, 'ya': y.action, \443 ({'xa': x.action, 'ya': y.action, \
407 'xl': x.logtype, 'yl': y.logtype})444 'xl': x.logtype, 'yl': y.logtype})
445=======
446 dbg_msg = _("Found non-action or non-rate match")
447>>>>>>> MERGE-SOURCE
408 debug(dbg_msg)448 debug(dbg_msg)
409 return -1449 return -1
410450
411451
=== modified file 'src/frontend.py'
--- src/frontend.py 2009-09-21 14:33:28 +0000
+++ src/frontend.py 2009-12-09 23:28:13 +0000
@@ -25,6 +25,7 @@
25import ufw.util25import ufw.util
26from ufw.util import error, warn26from ufw.util import error, warn
27from ufw.backend_iptables import UFWBackendIptables27from ufw.backend_iptables import UFWBackendIptables
28from ufw.tc_functions import get_next_filter_id
2829
29def allowed_command(cmd):30def allowed_command(cmd):
30 '''Return command if it is allowed, otherwise raise an exception'''31 '''Return command if it is allowed, otherwise raise an exception'''
@@ -204,6 +205,7 @@
204 direction=rule_direction)205 direction=rule_direction)
205 if remove:206 if remove:
206 rule.remove = remove207 rule.remove = remove
208<<<<<<< TREE
207 elif insert_pos != "":209 elif insert_pos != "":
208 try:210 try:
209 rule.set_position(insert_pos)211 rule.set_position(insert_pos)
@@ -211,6 +213,10 @@
211 raise213 raise
212 if nargs == 3:214 if nargs == 3:
213 # Short form where only app or port/proto is given215 # Short form where only app or port/proto is given
216=======
217 if nargs == 3 or nargs == 5:
218 # Short form where only app + rate? or port/proto + rate? is given
219>>>>>>> MERGE-SOURCE
214 if ufw.applications.valid_profile_name(argv[2]):220 if ufw.applications.valid_profile_name(argv[2]):
215 # Check if name collision with /etc/services. If so, use221 # Check if name collision with /etc/services. If so, use
216 # /etc/services instead of application profile222 # /etc/services instead of application profile
@@ -233,9 +239,21 @@
233 raise UFWError(err_msg)239 raise UFWError(err_msg)
234 to_service = port240 to_service = port
235241
242 if nargs == 5 and argv[3] == "rate" and action == "allow":
243 if not re.match('^\d([0-9]*\d+)*$', argv[4]):
244 err_msg = ("Rates must be numeric")
245 raise UFWError(err_msg)
246 rate = argv[4]
247 filter_id = "undefined"
248 else:
249 rate = "unlimited"
250 filter_id = "0"
251
236 try:252 try:
237 rule.set_protocol(proto)253 rule.set_protocol(proto)
238 rule.set_port(port, "dst")254 rule.set_port(port, "dst")
255 rule.set_rate(rate)
256 rule.set_filter_id(filter_id)
239 type = "both"257 type = "both"
240 except UFWError:258 except UFWError:
241 err_msg = _("Bad port")259 err_msg = _("Bad port")
@@ -249,7 +267,11 @@
249 raise UFWError(err_msg)267 raise UFWError(err_msg)
250 else:268 else:
251 # Full form with PF-style syntax269 # Full form with PF-style syntax
270<<<<<<< TREE
252 keys = [ 'proto', 'from', 'to', 'port', 'app', 'in', 'out' ]271 keys = [ 'proto', 'from', 'to', 'port', 'app', 'in', 'out' ]
272=======
273 keys = [ 'proto', 'from', 'to', 'port', 'app', 'rate' ]
274>>>>>>> MERGE-SOURCE
253275
254 # quick check276 # quick check
255 if argv.count("to") > 1 or \277 if argv.count("to") > 1 or \
@@ -259,7 +281,8 @@
259 argv.count("in") > 1 or \281 argv.count("in") > 1 or \
260 argv.count("out") > 1 or \282 argv.count("out") > 1 or \
261 argv.count("app") > 2 or \283 argv.count("app") > 2 or \
262 argv.count("app") > 0 and argv.count("proto") > 0:284 argv.count("app") > 0 and argv.count("proto") > 0 or \
285 argv.count("rate") > 1:
263 err_msg = _("Improper rule syntax")286 err_msg = _("Improper rule syntax")
264 raise UFWError(err_msg)287 raise UFWError(err_msg)
265288
@@ -269,7 +292,26 @@
269 if i % 2 == 0 and argv[i] not in keys:292 if i % 2 == 0 and argv[i] not in keys:
270 err_msg = _("Invalid token '%s'") % (argv[i])293 err_msg = _("Invalid token '%s'") % (argv[i])
271 raise UFWError(err_msg)294 raise UFWError(err_msg)
272 if arg == "proto":295 if arg == "rate":
296 if i+1 < nargs:
297 if action != "allow":
298 err_msg = ("Rates can only be specified with the 'allow' action")
299 raise UFWError(err_msg)
300 try:
301 rate = argv[i+1]
302 if not re.match('^\d([0-9]*\d+)*$', rate):
303 err_msg = _("Rates must be numeric")
304 raise UFWError(err_msg)
305
306 rule.set_rate(rate)
307 filter_id = "undefined"
308 rule.set_filter_id(filter_id)
309 except Exception:
310 raise
311 else:
312 err_msg = ("Invalid 'rate' clause")
313 raise UFWError(err_msg)
314 elif arg == "proto":
273 if i+1 < nargs:315 if i+1 < nargs:
274 try:316 try:
275 rule.set_protocol(argv[i+1])317 rule.set_protocol(argv[i+1])
@@ -900,6 +942,7 @@
900 tmp = self.backend.find_application_name(rule.sapp)942 tmp = self.backend.find_application_name(rule.sapp)
901 if tmp != rule.sapp:943 if tmp != rule.sapp:
902 rule.sapp = tmp944 rule.sapp = tmp
945<<<<<<< TREE
903 rule.set_port(tmp, "dst")946 rule.set_port(tmp, "dst")
904 except UFWError, e:947 except UFWError, e:
905 # allow for the profile being deleted (LP: #407810)948 # allow for the profile being deleted (LP: #407810)
@@ -909,6 +952,13 @@
909 err_msg = _("Invalid profile name")952 err_msg = _("Invalid profile name")
910 raise UFWError(err_msg)953 raise UFWError(err_msg)
911954
955=======
956 rule.set_port(tmp, "src")
957 if not rule.remove and rule.rate != "undefined":
958 rule.filter_id = get_next_filter_id(self.backend.rules)
959 except UFWError, e:
960 error(e.value)
961>>>>>>> MERGE-SOURCE
912 res = self.set_rule(rule, ip_version)962 res = self.set_rule(rule, ip_version)
913 else:963 else:
914 err_msg = _("Unsupported action '%s'") % (action)964 err_msg = _("Unsupported action '%s'") % (action)
915965
=== added file 'src/tc_functions.py'
--- src/tc_functions.py 1970-01-01 00:00:00 +0000
+++ src/tc_functions.py 2009-12-09 23:28:13 +0000
@@ -0,0 +1,150 @@
1#
2# tc_functions.py: tc related functions for ufw
3#
4# Copyright (C) 2008-2009 Canonical Ltd.
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License version 3,
8# as published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17#
18
19import os
20import re
21import sys
22import subprocess
23
24from ufw.common import UFWError, UFWRule, config_dir, state_dir, prefix_dir
25from ufw.util import warn, debug, msg, cmd, cmd_pipe
26
27def get_interface_list():
28 '''Get a list of all the available network interfaces'''
29 list = []
30
31 sp1 = subprocess.Popen("/sbin/ifconfig", stdout=subprocess.PIPE)
32 sp2 = subprocess.Popen(["cut", '-d ', "-f1"], stdin=sp1.stdout, stdout=subprocess.PIPE)
33 sp3 = subprocess.Popen(["sort", '-u'], stdin=sp2.stdout, stdout=subprocess.PIPE)
34 sp4 = subprocess.Popen(["grep", '-v', "^$"], stdin=sp3.stdout, stdout=subprocess.PIPE)
35 sp5 = subprocess.Popen("xargs", stdin=sp4.stdout, stdout=subprocess.PIPE)
36
37 out = sp5.communicate()[0]
38
39 list = out.split()
40
41 return list
42
43
44def is_local_ip_address(addr):
45 '''Checks whether the given IP address is a local IP addresse'''
46 sp1 = subprocess.Popen("/sbin/ifconfig", stdout=subprocess.PIPE)
47 sp2 = subprocess.Popen(["grep", addr], stdin=sp1.stdout, stdout=subprocess.PIPE)
48 sp3 = subprocess.Popen(["grep", "-ci", "inet"], stdin=sp2.stdout, stdout=subprocess.PIPE)
49
50 out = sp3.communicate()[0]
51
52 return int(out)
53
54
55def add_filter(src, dst, sport, dport, rate, filter_id):
56 interface_list = get_interface_list()
57
58 # if src and/or dst are IP addresses (instead of network addresses, add the all 1s netmask
59 if not re.match(r'.*/.*', src):
60 tc_src = src + "/32"
61 else:
62 tc_src = src
63 if not re.match(r'.*/.*', dst):
64 tc_dst = dst + "/32"
65 else:
66 tc_dst = dst
67
68
69 # build the u32 filter
70 u32_match="match ip src " + tc_src + " match ip dst " + tc_dst
71 if sport != "any":
72 u32_match = u32_match + " match ip sport " + sport + " 0xffff"
73 if dport != "any":
74 u32_match = u32_match + " match ip dport " + dport + " 0xffff"
75
76 # add the filter to the proper qdiscs (ingress or egress)
77 if is_local_ip_address(src):
78 #msg("add to egress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport+" "+rate)
79 for i in interface_list:
80 command = ["/sbin/tc", "filter", "add", "dev", i, "parent", "1:", "protocol", "ip", "prio", "1", "handle", "::"+str(filter_id), "u32", u32_match, "police", "rate", rate + "kbit", "burst", "100kbit", "drop", "flowid", ':1']
81 command = ' '.join(command)
82 command = command.split(' ')
83 cmd(command)
84 else:
85
86 #msg("add to ingress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport+" "+rate)
87 for i in interface_list:
88 command=["/sbin/tc", "filter", "add", "dev", i, "parent", "ffff:", "protocol", "ip", "prio", "1", "handle", "::"+str(filter_id), "u32", u32_match, "police", "rate", rate + "kbit", "burst", "100kbit", "drop", "flowid", ':1']
89 command = ' '.join(command)
90 command = command.split(' ')
91 cmd(command)
92
93
94def delete_filter(src, dst, sport, dport, filter_id):
95 interface_list = get_interface_list()
96
97 # if src and/or dst are IP addresses (instead of network addresses, add the all 1s netmask
98 if not re.match(r'.*/.*', src):
99 tc_src = src + "/32"
100 else:
101 tc_src = src
102 if not re.match(r'.*/.*', dst):
103 tc_dst = dst + "/32"
104 else:
105 tc_dst = dst
106
107 # remove the filter from the proper qdiscs (ingres or egress)
108 if is_local_ip_address(src):
109 #msg("delete from egress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport)
110 for i in interface_list:
111 command=["/sbin/tc", "filter", "del", "dev", i, "parent", "1:", "protocol", "ip", "prio", "1", "handle", "::"+str(filter_id), "u32"]
112 command = ' '.join(command)
113 command = command.split(' ')
114 cmd(command)
115 else:
116 #msg("delete from ingress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport)
117 for i in interface_list:
118 command=["/sbin/tc", "filter", "del", "dev", i, "parent", "ffff:", "protocol", "ip", "prio", "1", "handle", "800::"+str(filter_id), "u32"]
119 command = ' '.join(command)
120 command = command.split(' ')
121 cmd(command)
122
123
124def get_next_filter_id(rules):
125 id_list = []
126 for r in rules:
127 id_list.append(r.filter_id)
128
129 id_list.sort()
130
131 idx = 1
132 for id in id_list:
133 if(int(id) != idx):
134 return idx
135 idx = idx + 1
136
137 return idx
138
139def my_main():
140 msg("hello")
141 list = get_interface_list()
142 msg("Found interfaces : %s" % list)
143
144 if is_local_ip_address("127.0.0.1"):
145 msg("OK")
146 else:
147 msg("KO")
148
149
150
0151
=== modified file 'src/ufw-init-functions'
--- src/ufw-init-functions 2009-08-24 15:09:18 +0000
+++ src/ufw-init-functions 2009-12-09 23:28:13 +0000
@@ -122,6 +122,18 @@
122 flush_builtins122 flush_builtins
123 fi123 fi
124124
125
126 interface_list=`/sbin/ifconfig | cut -d' ' -f 1 | sort -u | grep -v "^$" | xargs`
127
128 for i in $interface_list
129 do
130 # create incoming qdiscs
131 /sbin/tc qdisc add dev $i handle ffff: ingress
132 /sbin/tc qdisc add dev $i parent root handle 1: prio bands 3
133 done
134
135
136
125 execs="iptables"137 execs="iptables"
126138
127 # IPv6 setup139 # IPv6 setup
@@ -347,6 +359,17 @@
347 return 0359 return 0
348 fi360 fi
349361
362
363 interface_list=`/sbin/ifconfig | cut -d' ' -f 1 | sort -u | grep -v "^$" | xargs`
364
365 for i in $interface_list
366 do
367 # delete incoming qdiscs
368 /sbin/tc qdisc del dev $i ingress
369 /sbin/tc qdisc del dev $i parent root
370 done
371
372
350 error=""373 error=""
351 execs="iptables"374 execs="iptables"
352 if ip6tables -L INPUT -n >/dev/null 2>&1; then375 if ip6tables -L INPUT -n >/dev/null 2>&1; then

Subscribers

People subscribed via source and target branches

to all changes:
to status/vote changes: