Merge lp://staging/~bertrand-goareguer/ufw/ufw-qos into lp://staging/~jdstrand/ufw/trunk
- ufw-qos
- Merge into trunk
Proposed by
Jonathan Davies
Status: | Needs review | ||||
---|---|---|---|---|---|
Proposed branch: | lp://staging/~bertrand-goareguer/ufw/ufw-qos | ||||
Merge into: | lp://staging/~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://staging/~bertrand-goareguer/ufw/ufw-qos | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jamie Strandboge | Pending | ||
Review via email: mp+15907@code.staging.launchpad.net |
Commit message
Description of the change
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
1 | === modified file 'setup.py' |
2 | --- setup.py 2009-11-30 16:03:43 +0000 |
3 | +++ setup.py 2009-12-09 23:28:13 +0000 |
4 | @@ -253,7 +253,7 @@ |
5 | license='GPL-3', |
6 | cmdclass={'install': Install}, |
7 | package_dir={'ufw': 'staging'}, |
8 | - py_modules=['ufw.backend', 'ufw.backend_iptables', 'ufw.common', 'ufw.frontend', 'ufw.util', 'ufw.applications'] |
9 | + py_modules=['ufw.backend', 'ufw.backend_iptables', 'ufw.common', 'ufw.frontend', 'ufw.util', 'ufw.applications', 'ufw.tc_functions'] |
10 | ) |
11 | |
12 | shutil.rmtree('staging') |
13 | |
14 | === modified file 'src/backend_iptables.py' |
15 | --- src/backend_iptables.py 2009-11-11 18:05:16 +0000 |
16 | +++ src/backend_iptables.py 2009-12-09 23:28:13 +0000 |
17 | @@ -20,9 +20,11 @@ |
18 | import re |
19 | import sys |
20 | import tempfile |
21 | +import ufw.tc_functions |
22 | |
23 | from ufw.common import UFWError, UFWRule, config_dir, state_dir, prefix_dir |
24 | from ufw.util import warn, debug, msg, cmd, cmd_pipe |
25 | +from ufw.tc_functions import add_filter, delete_filter |
26 | import ufw.backend |
27 | |
28 | |
29 | @@ -388,6 +390,9 @@ |
30 | (rc, out) = cmd([self.files['init'], 'start']) |
31 | if rc != 0: |
32 | raise UFWError(err_msg + " ufw-init") |
33 | + else: |
34 | + # if firewall has been started successfully, apply the TC rules |
35 | + self._reload_user_filters() |
36 | |
37 | if not self.defaults.has_key('loglevel') or \ |
38 | self.defaults['loglevel'] not in self.loglevels.keys(): |
39 | @@ -454,7 +459,19 @@ |
40 | if rc != 0: |
41 | raise UFWError(err_msg + " ip6tables") |
42 | |
43 | +<<<<<<< TREE |
44 | def _get_rules_from_formatted(self, frule, prefix, suffix): |
45 | +======= |
46 | + def _reload_user_filters(self): |
47 | + '''Reload TC filters''' |
48 | + for rule in self.rules: |
49 | + if rule.rate != "unlimited": |
50 | + if rule.action == "allow": |
51 | + add_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.rate, rule.filter_id) |
52 | + |
53 | + |
54 | + def _get_rules_from_formatted(self, frule, prefix): |
55 | +>>>>>>> MERGE-SOURCE |
56 | '''Return list of iptables rules appropriate for sending''' |
57 | snippets = [] |
58 | |
59 | @@ -558,7 +575,11 @@ |
60 | if pat_tuple.match(line): |
61 | tuple = pat_tuple.sub('', line) |
62 | tmp = re.split(r'\s+', tuple.strip()) |
63 | +<<<<<<< TREE |
64 | if len(tmp) < 6 or len(tmp) > 9: |
65 | +======= |
66 | + if len(tmp) != 8 and len(tmp) != 10: |
67 | +>>>>>>> MERGE-SOURCE |
68 | warn_msg = _("Skipping malformed tuple (bad length): %s") % (tuple) |
69 | warn(warn_msg) |
70 | continue |
71 | @@ -573,12 +594,24 @@ |
72 | else: |
73 | type = tmp[-1] |
74 | try: |
75 | +<<<<<<< TREE |
76 | if len(tmp) < 8: |
77 | +======= |
78 | + if len(tmp) == 8: |
79 | +>>>>>>> MERGE-SOURCE |
80 | rule = UFWRule(tmp[0], tmp[1], tmp[2], tmp[3], |
81 | +<<<<<<< TREE |
82 | tmp[4], tmp[5], type) |
83 | +======= |
84 | + tmp[4], tmp[5], tmp[6], tmp[7]) |
85 | +>>>>>>> MERGE-SOURCE |
86 | else: |
87 | rule = UFWRule(tmp[0], tmp[1], tmp[2], tmp[3], |
88 | +<<<<<<< TREE |
89 | tmp[4], tmp[5], type) |
90 | +======= |
91 | + tmp[4], tmp[5], tmp[8], tmp[9]) |
92 | +>>>>>>> MERGE-SOURCE |
93 | # Removed leading [sd]app_ and unescape spaces |
94 | pat_space = re.compile('%20') |
95 | if tmp[6] != "-": |
96 | @@ -662,6 +695,7 @@ |
97 | action += "_" + r.logtype |
98 | |
99 | if r.dapp == "" and r.sapp == "": |
100 | +<<<<<<< TREE |
101 | tstr = "\n### tuple ### %s %s %s %s %s %s %s" % \ |
102 | (action, r.protocol, r.dport, r.dst, r.sport, r.src, \ |
103 | r.direction) |
104 | @@ -670,6 +704,10 @@ |
105 | if r.interface_out != "": |
106 | tstr += "_%s" % (r.interface_out) |
107 | ufw.util.write_to_file(fd, tstr + "\n") |
108 | +======= |
109 | + os.write(fd, "\n### tuple ### %s %s %s %s %s %s %s %s\n" % \ |
110 | + (r.action, r.protocol, r.dport, r.dst, r.sport, r.src, r.rate, r.filter_id)) |
111 | +>>>>>>> MERGE-SOURCE |
112 | else: |
113 | pat_space = re.compile(' ') |
114 | dapp = "-" |
115 | @@ -678,6 +716,7 @@ |
116 | sapp = "-" |
117 | if r.sapp: |
118 | sapp = pat_space.sub('%20', r.sapp) |
119 | +<<<<<<< TREE |
120 | tstr = "\n### tuple ### %s %s %s %s %s %s %s %s %s" % \ |
121 | (action, r.protocol, r.dport, r.dst, r.sport, r.src, \ |
122 | dapp, sapp, r.direction) |
123 | @@ -697,6 +736,14 @@ |
124 | for s in self._get_rules_from_formatted(rule_str, chain_prefix, \ |
125 | chain_suffix): |
126 | ufw.util.write_to_file(fd, s) |
127 | +======= |
128 | + os.write(fd, "\n### tuple ### %s %s %s %s %s %s %s %s %s %s\n" \ |
129 | + % (r.action, r.protocol, r.dport, r.dst, r.sport, r.src, \ |
130 | + dapp, sapp, r.rate, r.filter_id)) |
131 | + |
132 | + for s in self._get_rules_from_formatted(rule_str, chain_prefix): |
133 | + os.write(fd, s) |
134 | +>>>>>>> MERGE-SOURCE |
135 | |
136 | # Write footer |
137 | ufw.util.write_to_file(fd, "\n### END RULES ###\n") |
138 | @@ -825,9 +872,17 @@ |
139 | # skip it. |
140 | found = True |
141 | if not rule.remove: |
142 | +<<<<<<< TREE |
143 | newrules.append(rule.dup_rule()) |
144 | elif ret < 0 and not rule.remove and not inserted: |
145 | # If only the action is different, replace the rule if it's not |
146 | +======= |
147 | + newrules.append(rule) |
148 | + else: |
149 | + rule.filter_id = r.filter_id |
150 | + elif ret < 0 and not rule.remove: |
151 | + # If only the action or the rate is different, replace the rule if it's not |
152 | +>>>>>>> MERGE-SOURCE |
153 | # to be removed. |
154 | found = True |
155 | modified = True |
156 | @@ -932,13 +987,39 @@ |
157 | msg(out, sys.stderr) |
158 | UFWError(err_msg) |
159 | |
160 | +<<<<<<< TREE |
161 | # delete any lingering RETURN rules (needed for upgrades) |
162 | if flag == "-A" and pat_log.search(" ".join(s)): |
163 | c = pat_log.sub(r'\2', " ".join(s)) |
164 | (rc, out) = cmd([exe, '-D', c, '-j', 'RETURN']) |
165 | +======= |
166 | + # add/remove the TC filter if needed |
167 | + if rule.rate != "unlimited": |
168 | + if not rule.remove: |
169 | + add_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.rate, rule.filter_id) |
170 | + else: |
171 | + delete_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.filter_id) |
172 | + |
173 | + # delete the RETURN rule then add it back, so it is at the |
174 | + # end |
175 | + if flag == "-A": |
176 | + (rc, out) = cmd([exe, '-D', chain, '-j', 'RETURN']) |
177 | +>>>>>>> MERGE-SOURCE |
178 | if rc != 0: |
179 | debug("FAILOK: -D %s -j RETURN" % (c)) |
180 | |
181 | +<<<<<<< TREE |
182 | +======= |
183 | + (rc, out) = cmd([exe, '-A', chain, '-j', 'RETURN']) |
184 | + if rc != 0: |
185 | + msg(out, sys.stderr) |
186 | + |
187 | + else: |
188 | + # the rule has been updated: remove the old filter (an error occurs if there was none) and add the new one (if it exists) |
189 | + delete_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.filter_id) |
190 | + if rule.rate != "unlimited": |
191 | + add_filter(rule.src, rule.dst, rule.sport, rule.dport, rule.rate, rule.filter_id) |
192 | +>>>>>>> MERGE-SOURCE |
193 | return rstr |
194 | |
195 | def get_app_rules_from_system(self, template, v6): |
196 | |
197 | === modified file 'src/common.py' |
198 | --- src/common.py 2009-08-26 20:18:30 +0000 |
199 | +++ src/common.py 2009-12-09 23:28:13 +0000 |
200 | @@ -40,7 +40,11 @@ |
201 | class UFWRule: |
202 | '''This class represents firewall rules''' |
203 | def __init__(self, action, protocol, dport="any", dst="0.0.0.0/0", |
204 | +<<<<<<< TREE |
205 | sport="any", src="0.0.0.0/0", direction="in"): |
206 | +======= |
207 | + sport="any", src="0.0.0.0/0", rate="unlimited", filter_id="0"): |
208 | +>>>>>>> MERGE-SOURCE |
209 | # Be sure to update dup_rule accordingly... |
210 | self.remove = False |
211 | self.updated = False |
212 | @@ -54,10 +58,15 @@ |
213 | self.dapp = "" |
214 | self.sapp = "" |
215 | self.action = "" |
216 | +<<<<<<< TREE |
217 | self.position = 0 |
218 | self.logtype = "" |
219 | self.interface_in = "" |
220 | self.interface_out = "" |
221 | +======= |
222 | + self.rate ="" |
223 | + self.filter_id ="" |
224 | +>>>>>>> MERGE-SOURCE |
225 | try: |
226 | self.set_action(action) |
227 | self.set_protocol(protocol) |
228 | @@ -65,7 +74,12 @@ |
229 | self.set_port(sport, "src") |
230 | self.set_src(src) |
231 | self.set_dst(dst) |
232 | +<<<<<<< TREE |
233 | self.set_direction(direction) |
234 | +======= |
235 | + self.set_rate(rate) |
236 | + self.set_filter_id(filter_id) |
237 | +>>>>>>> MERGE-SOURCE |
238 | except UFWError: |
239 | raise |
240 | |
241 | @@ -85,11 +99,16 @@ |
242 | rule.multi = self.multi |
243 | rule.dapp = self.dapp |
244 | rule.sapp = self.sapp |
245 | +<<<<<<< TREE |
246 | rule.position = self.position |
247 | rule.logtype = self.logtype |
248 | rule.interface_in = self.interface_in |
249 | rule.interface_out = self.interface_out |
250 | rule.direction = self.direction |
251 | +======= |
252 | + rule.rate = self.rate |
253 | + rule.filter_id = self.filter_id |
254 | +>>>>>>> MERGE-SOURCE |
255 | |
256 | return rule |
257 | |
258 | @@ -278,6 +297,7 @@ |
259 | self.dst = tmp |
260 | self._fix_anywhere() |
261 | |
262 | +<<<<<<< TREE |
263 | def set_interface(self, type, name): |
264 | '''Sets an interface for rule''' |
265 | if type != "in" and type != "out": |
266 | @@ -321,6 +341,18 @@ |
267 | err_msg = _("Unsupported direction '%s'") % (direction) |
268 | raise UFWError(err_msg) |
269 | |
270 | +======= |
271 | + def set_rate(self, rate): |
272 | + '''Sets rate for the rule''' |
273 | + self.rate = rate |
274 | + self._fix_anywhere() |
275 | + |
276 | + def set_filter_id(self, filter_id): |
277 | + '''Sets the if of the filter associated to the rule''' |
278 | + self.filter_id = filter_id |
279 | + self._fix_anywhere() |
280 | + |
281 | +>>>>>>> MERGE-SOURCE |
282 | def normalize(self): |
283 | '''Normalize src and dst to standard form''' |
284 | changed = False |
285 | @@ -391,6 +423,7 @@ |
286 | if x.sapp != y.sapp: |
287 | debug(dbg_msg) |
288 | return 1 |
289 | +<<<<<<< TREE |
290 | if x.interface_in != y.interface_in: |
291 | return 1 |
292 | if x.interface_out != y.interface_out: |
293 | @@ -398,13 +431,20 @@ |
294 | if x.direction != y.direction: |
295 | return 1 |
296 | if x.action == y.action and x.logtype == y.logtype: |
297 | +======= |
298 | + if x.action == y.action and x.rate == y.rate: |
299 | +>>>>>>> MERGE-SOURCE |
300 | dbg_msg = _("Found exact match") |
301 | debug(dbg_msg) |
302 | return 0 |
303 | +<<<<<<< TREE |
304 | dbg_msg = _("Found non-action/non-logtype match " \ |
305 | "(%(xa)s/%(ya)s %(xl)s/%(yl)s)") % \ |
306 | ({'xa': x.action, 'ya': y.action, \ |
307 | 'xl': x.logtype, 'yl': y.logtype}) |
308 | +======= |
309 | + dbg_msg = _("Found non-action or non-rate match") |
310 | +>>>>>>> MERGE-SOURCE |
311 | debug(dbg_msg) |
312 | return -1 |
313 | |
314 | |
315 | === modified file 'src/frontend.py' |
316 | --- src/frontend.py 2009-09-21 14:33:28 +0000 |
317 | +++ src/frontend.py 2009-12-09 23:28:13 +0000 |
318 | @@ -25,6 +25,7 @@ |
319 | import ufw.util |
320 | from ufw.util import error, warn |
321 | from ufw.backend_iptables import UFWBackendIptables |
322 | +from ufw.tc_functions import get_next_filter_id |
323 | |
324 | def allowed_command(cmd): |
325 | '''Return command if it is allowed, otherwise raise an exception''' |
326 | @@ -204,6 +205,7 @@ |
327 | direction=rule_direction) |
328 | if remove: |
329 | rule.remove = remove |
330 | +<<<<<<< TREE |
331 | elif insert_pos != "": |
332 | try: |
333 | rule.set_position(insert_pos) |
334 | @@ -211,6 +213,10 @@ |
335 | raise |
336 | if nargs == 3: |
337 | # Short form where only app or port/proto is given |
338 | +======= |
339 | + if nargs == 3 or nargs == 5: |
340 | + # Short form where only app + rate? or port/proto + rate? is given |
341 | +>>>>>>> MERGE-SOURCE |
342 | if ufw.applications.valid_profile_name(argv[2]): |
343 | # Check if name collision with /etc/services. If so, use |
344 | # /etc/services instead of application profile |
345 | @@ -233,9 +239,21 @@ |
346 | raise UFWError(err_msg) |
347 | to_service = port |
348 | |
349 | + if nargs == 5 and argv[3] == "rate" and action == "allow": |
350 | + if not re.match('^\d([0-9]*\d+)*$', argv[4]): |
351 | + err_msg = ("Rates must be numeric") |
352 | + raise UFWError(err_msg) |
353 | + rate = argv[4] |
354 | + filter_id = "undefined" |
355 | + else: |
356 | + rate = "unlimited" |
357 | + filter_id = "0" |
358 | + |
359 | try: |
360 | rule.set_protocol(proto) |
361 | rule.set_port(port, "dst") |
362 | + rule.set_rate(rate) |
363 | + rule.set_filter_id(filter_id) |
364 | type = "both" |
365 | except UFWError: |
366 | err_msg = _("Bad port") |
367 | @@ -249,7 +267,11 @@ |
368 | raise UFWError(err_msg) |
369 | else: |
370 | # Full form with PF-style syntax |
371 | +<<<<<<< TREE |
372 | keys = [ 'proto', 'from', 'to', 'port', 'app', 'in', 'out' ] |
373 | +======= |
374 | + keys = [ 'proto', 'from', 'to', 'port', 'app', 'rate' ] |
375 | +>>>>>>> MERGE-SOURCE |
376 | |
377 | # quick check |
378 | if argv.count("to") > 1 or \ |
379 | @@ -259,7 +281,8 @@ |
380 | argv.count("in") > 1 or \ |
381 | argv.count("out") > 1 or \ |
382 | argv.count("app") > 2 or \ |
383 | - argv.count("app") > 0 and argv.count("proto") > 0: |
384 | + argv.count("app") > 0 and argv.count("proto") > 0 or \ |
385 | + argv.count("rate") > 1: |
386 | err_msg = _("Improper rule syntax") |
387 | raise UFWError(err_msg) |
388 | |
389 | @@ -269,7 +292,26 @@ |
390 | if i % 2 == 0 and argv[i] not in keys: |
391 | err_msg = _("Invalid token '%s'") % (argv[i]) |
392 | raise UFWError(err_msg) |
393 | - if arg == "proto": |
394 | + if arg == "rate": |
395 | + if i+1 < nargs: |
396 | + if action != "allow": |
397 | + err_msg = ("Rates can only be specified with the 'allow' action") |
398 | + raise UFWError(err_msg) |
399 | + try: |
400 | + rate = argv[i+1] |
401 | + if not re.match('^\d([0-9]*\d+)*$', rate): |
402 | + err_msg = _("Rates must be numeric") |
403 | + raise UFWError(err_msg) |
404 | + |
405 | + rule.set_rate(rate) |
406 | + filter_id = "undefined" |
407 | + rule.set_filter_id(filter_id) |
408 | + except Exception: |
409 | + raise |
410 | + else: |
411 | + err_msg = ("Invalid 'rate' clause") |
412 | + raise UFWError(err_msg) |
413 | + elif arg == "proto": |
414 | if i+1 < nargs: |
415 | try: |
416 | rule.set_protocol(argv[i+1]) |
417 | @@ -900,6 +942,7 @@ |
418 | tmp = self.backend.find_application_name(rule.sapp) |
419 | if tmp != rule.sapp: |
420 | rule.sapp = tmp |
421 | +<<<<<<< TREE |
422 | rule.set_port(tmp, "dst") |
423 | except UFWError, e: |
424 | # allow for the profile being deleted (LP: #407810) |
425 | @@ -909,6 +952,13 @@ |
426 | err_msg = _("Invalid profile name") |
427 | raise UFWError(err_msg) |
428 | |
429 | +======= |
430 | + rule.set_port(tmp, "src") |
431 | + if not rule.remove and rule.rate != "undefined": |
432 | + rule.filter_id = get_next_filter_id(self.backend.rules) |
433 | + except UFWError, e: |
434 | + error(e.value) |
435 | +>>>>>>> MERGE-SOURCE |
436 | res = self.set_rule(rule, ip_version) |
437 | else: |
438 | err_msg = _("Unsupported action '%s'") % (action) |
439 | |
440 | === added file 'src/tc_functions.py' |
441 | --- src/tc_functions.py 1970-01-01 00:00:00 +0000 |
442 | +++ src/tc_functions.py 2009-12-09 23:28:13 +0000 |
443 | @@ -0,0 +1,150 @@ |
444 | +# |
445 | +# tc_functions.py: tc related functions for ufw |
446 | +# |
447 | +# Copyright (C) 2008-2009 Canonical Ltd. |
448 | +# |
449 | +# This program is free software: you can redistribute it and/or modify |
450 | +# it under the terms of the GNU General Public License version 3, |
451 | +# as published by the Free Software Foundation. |
452 | +# |
453 | +# This program is distributed in the hope that it will be useful, |
454 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
455 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
456 | +# GNU General Public License for more details. |
457 | +# |
458 | +# You should have received a copy of the GNU General Public License |
459 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
460 | +# |
461 | + |
462 | +import os |
463 | +import re |
464 | +import sys |
465 | +import subprocess |
466 | + |
467 | +from ufw.common import UFWError, UFWRule, config_dir, state_dir, prefix_dir |
468 | +from ufw.util import warn, debug, msg, cmd, cmd_pipe |
469 | + |
470 | +def get_interface_list(): |
471 | + '''Get a list of all the available network interfaces''' |
472 | + list = [] |
473 | + |
474 | + sp1 = subprocess.Popen("/sbin/ifconfig", stdout=subprocess.PIPE) |
475 | + sp2 = subprocess.Popen(["cut", '-d ', "-f1"], stdin=sp1.stdout, stdout=subprocess.PIPE) |
476 | + sp3 = subprocess.Popen(["sort", '-u'], stdin=sp2.stdout, stdout=subprocess.PIPE) |
477 | + sp4 = subprocess.Popen(["grep", '-v', "^$"], stdin=sp3.stdout, stdout=subprocess.PIPE) |
478 | + sp5 = subprocess.Popen("xargs", stdin=sp4.stdout, stdout=subprocess.PIPE) |
479 | + |
480 | + out = sp5.communicate()[0] |
481 | + |
482 | + list = out.split() |
483 | + |
484 | + return list |
485 | + |
486 | + |
487 | +def is_local_ip_address(addr): |
488 | + '''Checks whether the given IP address is a local IP addresse''' |
489 | + sp1 = subprocess.Popen("/sbin/ifconfig", stdout=subprocess.PIPE) |
490 | + sp2 = subprocess.Popen(["grep", addr], stdin=sp1.stdout, stdout=subprocess.PIPE) |
491 | + sp3 = subprocess.Popen(["grep", "-ci", "inet"], stdin=sp2.stdout, stdout=subprocess.PIPE) |
492 | + |
493 | + out = sp3.communicate()[0] |
494 | + |
495 | + return int(out) |
496 | + |
497 | + |
498 | +def add_filter(src, dst, sport, dport, rate, filter_id): |
499 | + interface_list = get_interface_list() |
500 | + |
501 | + # if src and/or dst are IP addresses (instead of network addresses, add the all 1s netmask |
502 | + if not re.match(r'.*/.*', src): |
503 | + tc_src = src + "/32" |
504 | + else: |
505 | + tc_src = src |
506 | + if not re.match(r'.*/.*', dst): |
507 | + tc_dst = dst + "/32" |
508 | + else: |
509 | + tc_dst = dst |
510 | + |
511 | + |
512 | + # build the u32 filter |
513 | + u32_match="match ip src " + tc_src + " match ip dst " + tc_dst |
514 | + if sport != "any": |
515 | + u32_match = u32_match + " match ip sport " + sport + " 0xffff" |
516 | + if dport != "any": |
517 | + u32_match = u32_match + " match ip dport " + dport + " 0xffff" |
518 | + |
519 | + # add the filter to the proper qdiscs (ingress or egress) |
520 | + if is_local_ip_address(src): |
521 | + #msg("add to egress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport+" "+rate) |
522 | + for i in interface_list: |
523 | + 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'] |
524 | + command = ' '.join(command) |
525 | + command = command.split(' ') |
526 | + cmd(command) |
527 | + else: |
528 | + |
529 | + #msg("add to ingress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport+" "+rate) |
530 | + for i in interface_list: |
531 | + 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'] |
532 | + command = ' '.join(command) |
533 | + command = command.split(' ') |
534 | + cmd(command) |
535 | + |
536 | + |
537 | +def delete_filter(src, dst, sport, dport, filter_id): |
538 | + interface_list = get_interface_list() |
539 | + |
540 | + # if src and/or dst are IP addresses (instead of network addresses, add the all 1s netmask |
541 | + if not re.match(r'.*/.*', src): |
542 | + tc_src = src + "/32" |
543 | + else: |
544 | + tc_src = src |
545 | + if not re.match(r'.*/.*', dst): |
546 | + tc_dst = dst + "/32" |
547 | + else: |
548 | + tc_dst = dst |
549 | + |
550 | + # remove the filter from the proper qdiscs (ingres or egress) |
551 | + if is_local_ip_address(src): |
552 | + #msg("delete from egress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport) |
553 | + for i in interface_list: |
554 | + command=["/sbin/tc", "filter", "del", "dev", i, "parent", "1:", "protocol", "ip", "prio", "1", "handle", "::"+str(filter_id), "u32"] |
555 | + command = ' '.join(command) |
556 | + command = command.split(' ') |
557 | + cmd(command) |
558 | + else: |
559 | + #msg("delete from ingress qdisc: "+tc_src+" "+tc_dst+" "+sport+" "+dport) |
560 | + for i in interface_list: |
561 | + command=["/sbin/tc", "filter", "del", "dev", i, "parent", "ffff:", "protocol", "ip", "prio", "1", "handle", "800::"+str(filter_id), "u32"] |
562 | + command = ' '.join(command) |
563 | + command = command.split(' ') |
564 | + cmd(command) |
565 | + |
566 | + |
567 | +def get_next_filter_id(rules): |
568 | + id_list = [] |
569 | + for r in rules: |
570 | + id_list.append(r.filter_id) |
571 | + |
572 | + id_list.sort() |
573 | + |
574 | + idx = 1 |
575 | + for id in id_list: |
576 | + if(int(id) != idx): |
577 | + return idx |
578 | + idx = idx + 1 |
579 | + |
580 | + return idx |
581 | + |
582 | +def my_main(): |
583 | + msg("hello") |
584 | + list = get_interface_list() |
585 | + msg("Found interfaces : %s" % list) |
586 | + |
587 | + if is_local_ip_address("127.0.0.1"): |
588 | + msg("OK") |
589 | + else: |
590 | + msg("KO") |
591 | + |
592 | + |
593 | + |
594 | |
595 | === modified file 'src/ufw-init-functions' |
596 | --- src/ufw-init-functions 2009-08-24 15:09:18 +0000 |
597 | +++ src/ufw-init-functions 2009-12-09 23:28:13 +0000 |
598 | @@ -122,6 +122,18 @@ |
599 | flush_builtins |
600 | fi |
601 | |
602 | + |
603 | + interface_list=`/sbin/ifconfig | cut -d' ' -f 1 | sort -u | grep -v "^$" | xargs` |
604 | + |
605 | + for i in $interface_list |
606 | + do |
607 | + # create incoming qdiscs |
608 | + /sbin/tc qdisc add dev $i handle ffff: ingress |
609 | + /sbin/tc qdisc add dev $i parent root handle 1: prio bands 3 |
610 | + done |
611 | + |
612 | + |
613 | + |
614 | execs="iptables" |
615 | |
616 | # IPv6 setup |
617 | @@ -347,6 +359,17 @@ |
618 | return 0 |
619 | fi |
620 | |
621 | + |
622 | + interface_list=`/sbin/ifconfig | cut -d' ' -f 1 | sort -u | grep -v "^$" | xargs` |
623 | + |
624 | + for i in $interface_list |
625 | + do |
626 | + # delete incoming qdiscs |
627 | + /sbin/tc qdisc del dev $i ingress |
628 | + /sbin/tc qdisc del dev $i parent root |
629 | + done |
630 | + |
631 | + |
632 | error="" |
633 | execs="iptables" |
634 | if ip6tables -L INPUT -n >/dev/null 2>&1; then |