Date: Sun, 28 Oct 2007 21:11:09 +0100 From: "=?ISO-8859-1?Q?Ermal_Lu=E7i?=" <ermal.luci@gmail.com> To: freebsd-pf@freebsd.org, freebsd-net@freebsd.org Subject: Fwd: [PATCH] PF+dummynet Message-ID: <9a542da30710281311n7f8a6f29me02da90941d96ae5@mail.gmail.com> In-Reply-To: <9a542da30710281013q642b5aa8k33c7836ee064242e@mail.gmail.com> References: <9a542da30710161409o4732a77bybdf4ba35d7491bb@mail.gmail.com> <200710171043.08126.max@love2party.net> <d5992baf0710171324n65c4b171l71db8aeac445b52d@mail.gmail.com> <9a542da30710211232v4d3c930fg8ea778a12f3f16cb@mail.gmail.com> <9a542da30710280617t11e668e2o4d122998192f71c@mail.gmail.com> <20071028095802.A61999@xorpc.icir.org> <9a542da30710281013q642b5aa8k33c7836ee064242e@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --] Ok thanks to remko@ for hosting it! You can find it here: http://people.freebsd.org/~remko/patches/dummynet_pf.tar.gz Please test and give feedback. > > > It gives full dummynet support in pf.conf syntax and removes dummynet > > depndency to ipfw. > > > > You can configure a pipe/queue using the same ipfw syntax the only > > difference is that i call those 'dnpipe'/'dnqueue' respectivley. > > GRED/RED isn't currently finished but that is a pfctl addition so not > > difficult. > > > > For dummynet i preserve ipfw style statistics so tools of ipfw can be > > used here to. > > > > Since this is PF i preserved ALTQ priotitizing of ACK, meaning on ALTQ you do > > pass in quick proto tcp from any to any flags S/SA queue(pri, que) > > > > You can do the same with dummynet queues only, since for pipes it > > doesn't make much sense since they simulate a link. So yuo can do > > > > dnpipe 10 bandwidth 100Kbit > > dnqueue 10 dnpipe 10 queue 100 > > dnqueue 20 dnpipe 10 queue 20 > > > > pass in quick proto tcp from any to any flags S/SA dnqueue(10, 20) > > > > > > Please test and give feedback. > > > _______________________________________________ > > freebsd-net@freebsd.org mailing list > > http://lists.freebsd.org/mailman/listinfo/freebsd-net > > To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org" > [-- Attachment #2 --] Index: contrib/pf/pfctl/parse.y =================================================================== RCS file: /home/eri/repo/contrib/pf/pfctl/parse.y,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 parse.y --- contrib/pf/pfctl/parse.y 21 Oct 2007 13:53:15 -0000 1.1.1.1 +++ contrib/pf/pfctl/parse.y 21 Oct 2007 19:03:49 -0000 @@ -45,6 +45,9 @@ #include <altq/altq_priq.h> #include <altq/altq_hfsc.h> +#include <netinet/ip_fw.h> +#include <netinet/ip_dummynet.h> + #include <stdio.h> #include <stdlib.h> #include <netdb.h> @@ -206,6 +209,9 @@ char *tag; char *match_tag; u_int8_t match_tag_not; + u_int32_t dnpipe; + u_int32_t pdnpipe; + u_int32_t dntype; int rtableid; } filter_opts; @@ -261,6 +267,8 @@ struct node_hfsc_opts hfsc_opts; +struct dn_pipe dnpipe_opts; +struct dn_flow_set dnqueue_opts; int yyerror(const char *, ...); int disallow_table(struct node_host *, const char *); @@ -395,6 +403,8 @@ struct filter_opts filter_opts; struct antispoof_opts antispoof_opts; struct queue_opts queue_opts; + struct dn_pipe dnpipe_opts; + struct dn_flow_set dnqueue_opts; struct scrub_opts scrub_opts; struct table_opts table_opts; struct pool_opts pool_opts; @@ -421,6 +431,8 @@ %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT %token QUEUE PRIORITY QLIMIT RTABLE +%token DNPIPE DNQUEUE GRED RED WEIGHT MASK DELAY BUCKETS PLR +%token SRCIP DSTIP SRCPORT DSTPORT SRCIP6 DSTIP6 FLOWID NOERROR %token LOAD RULESET_OPTIMIZATION %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH @@ -451,7 +463,7 @@ %type <v.gid> gids gid_list gid_item %type <v.route> route %type <v.redirection> redirection redirpool -%type <v.string> label string tag anchorname +%type <v.string> label string tag anchorname %type <v.keep_state> keep %type <v.state_opt> state_opt_spec state_opt_list state_opt_item %type <v.logquick> logquick quick log logopts logopt @@ -462,6 +474,8 @@ %type <v.number> cbqflags_list cbqflags_item %type <v.number> priqflags_list priqflags_item %type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts +%type <v.dnpipe_opts> dnpipe_opts +%type <v.dnqueue_opts> dnqueue_opts mask_specifier %type <v.queue_bwspec> bandwidth %type <v.filter_opts> filter_opts filter_opt filter_opts_l %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l @@ -483,6 +497,8 @@ | ruleset anchorrule '\n' | ruleset loadrule '\n' | ruleset altqif '\n' + | ruleset dummynetif '\n' + | ruleset dnqueuespec '\n' | ruleset queuespec '\n' | ruleset varset '\n' | ruleset antispoof '\n' @@ -1667,6 +1683,222 @@ } ; +dummynetif : DNPIPE number dnpipe_opts dnqueue_opts { + struct dn_pipe p; + + if (check_rulestate(PFCTL_STATE_QUEUE)) + YYERROR; + + memset(&p, 0, sizeof(p)); + + p.bandwidth = $3.bandwidth; + p.delay = $3.delay; + p.pipe_nr = $2; + memcpy(&p.fs, &$4, + sizeof(p.fs)); + + if(pfctl_add_dummynet(pf, &p)) + YYERROR; + } +dnqueuespec : DNQUEUE number DNPIPE number dnqueue_opts { + struct dn_pipe p; + + if (check_rulestate(PFCTL_STATE_QUEUE)) + YYERROR; + + memset(&p, 0, sizeof(p)); + + if ($4 == 0) { + yyerror("pipe must be specified for queue"); + YYERROR; + } + if ($2 == 0) { + yyerror("queue number must be greater than 0"); + YYERROR; + } + + memcpy(&p.fs, &$5, sizeof(p.fs)); + p.fs.fs_nr = $2; + p.fs.parent_nr = $4; + p.pipe_nr = 0; + + if (pfctl_add_dummynet(pf, &p)) { + yyerror("errors in dnqueue definition"); + YYERROR; + } + } + ; + +dnpipe_opts : /* XXX: fix this */ { + bzero(&dnpipe_opts, sizeof dnpipe_opts); + } + dnpipe_opts_l + { $$ = dnpipe_opts; } + | /* empty */ { + bzero(&dnpipe_opts, sizeof dnpipe_opts); + $$ = dnpipe_opts; + } + ; + +dnpipe_opts_l : dnpipe_opts_l dnpipe_opt + | dnpipe_opt + ; + +dnpipe_opt : BANDWIDTH bandwidth { + dnpipe_opts.bandwidth = $2.bw_absolute; + } + | DELAY number { + if ($2 > 0 && $2 < 10001) + dnpipe_opts.delay = $2; + else { + yyerror("delay needs argument 0..10000ms"); + YYERROR; + } + } + ; + +dnqueue_opts : /* XXX: fix this */ { + bzero(&dnqueue_opts, sizeof dnqueue_opts); + } + dnqueue_opts_l + { $$ = dnqueue_opts; } + | /* empty */ { + bzero(&queue_opts, sizeof queue_opts); + $$ = dnqueue_opts; + } + ; + +dnqueue_opts_l : dnqueue_opts_l dnqueue_opt + | dnqueue_opt + ; + +dnqueue_opt : BUCKETS number { + if ($2 < 16 || $2 > 65535) { + yyerror("buckets out of range: [16-65535]"); + YYERROR; + } + /*dnqueue_opts.marker |= DN_BUCKETS;*/ + dnqueue_opts.rq_size = $2; + } + | WEIGHT number { + if ($2 < 0 || $2 > 100) { /* [0..100] is allowed */ + yyerror("weight must be in [0..100] range"); + YYERROR; + } + + dnqueue_opts.weight = $2; + } + | QUEUE STRING { + double bps; + char *cp; + + bps = strtod($2, &cp); + if (bps < 16 || bps > 65535) { + yyerror("qlimit out of range [16..65535]"); + YYERROR; + } + + if (cp != NULL) { + if (!strcmp(cp, "B")) + dnqueue_opts.flags_fs |= + DN_QSIZE_IS_BYTES; + else if (!strcmp(cp, "KB")) { + bps *= 1024; + dnqueue_opts.flags_fs |= + DN_QSIZE_IS_BYTES; + } else if (*cp != '\0') { + yyerror("unknown unit %s", cp); + free($2); + YYERROR; + } + } else + dnqueue_opts.flags_fs &= + ~DN_QSIZE_IS_BYTES; + free($2); + + dnqueue_opts.qsize = (u_int32_t)bps; + } + | PLR number { + dnqueue_opts.plr = (int)$2*0x7fffffff ; + } + | MASK mask_specifier { + memcpy(&dnqueue_opts, &$2, + sizeof(dnqueue_opts)); + } + | RED string '/' number '/' number '/' string { + /* XXX: this not yet finished! */ + char *e; + double p = strtod($2, &e); + + if (*e == '%') { + p *= 0.01; + e++; + } + if (*e) { + yyerror("invalid: %s", $2); + free($2); + YYERROR; + } + p = floor(p * (UINT_MAX+1.0) + 0.5); + if (p < 1.0 || p >= (UINT_MAX+1.0)) { + yyerror("invalid: %s", $2); + free($2); + YYERROR; + } + free($2); + } + ; + +mask_specifier : ALL { + + memset(&$$, 0, sizeof($$)); + + $$.flow_mask.dst_ip = ~0; + $$.flow_mask.src_ip = ~0; + $$.flow_mask.dst_port = ~0; + $$.flow_mask.src_port = ~0; + $$.flow_mask.proto = ~0; + n2mask(&$$.flow_mask.dst_ip6, 128); + n2mask(&$$.flow_mask.src_ip6, 128); + $$.flow_mask.flow_id6 = ~0; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | DSTIP number { + $$.flow_mask.dst_ip = (uint32_t)$2; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | SRCIP number { + $$.flow_mask.src_ip = (uint32_t)$2; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | DSTPORT number { + $$.flow_mask.dst_port = (uint16_t)$2; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | SRCPORT number { + $$.flow_mask.src_port = (uint16_t)$2; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | DSTIP6 '/' number { + n2mask(&$$.flow_mask.dst_ip6, $3); + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | SRCIP6 '/' number { + n2mask(&$$.flow_mask.src_ip6, $3); + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | FLOWID number { + $$.flow_mask.flow_id6 = (uint32_t)$2; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + + } + | PROTO number { + $$.flow_mask.proto = (uint8_t)$2; + $$.flags_fs |= DN_HAVE_FLOW_MASK; + } + | NOERROR { $$.flags_fs |= DN_NOERROR; } + ; + pfrule : action dir logquick interface route af proto fromto filter_opts { @@ -2034,6 +2266,14 @@ free($9.queues.pqname); } + if ($9.dnpipe) { + r.dnpipe = $9.dnpipe; + r.dntype = $9.dntype; + } + if ($9.pdnpipe && r.dntype == DN_IS_QUEUE) { + r.pdnpipe = $9.pdnpipe; + } + expand_rule(&r, $4, $5.host, $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, $9.uid, $9.gid, $9.icmpspec, ""); @@ -2123,6 +2363,27 @@ } filter_opts.queues = $1; } + | DNPIPE number { + filter_opts.dnpipe = $2; + filter_opts.dntype = DN_IS_PIPE; + } + | DNPIPE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.dntype = DN_IS_PIPE; + } + | DNQUEUE number { + filter_opts.dnpipe = $2; + filter_opts.dntype = DN_IS_QUEUE; + } + | DNQUEUE '(' number comma number ')' { + filter_opts.dnpipe = $3; + filter_opts.pdnpipe = $5; + filter_opts.dntype = DN_IS_QUEUE; + } + | DNQUEUE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.dntype = DN_IS_QUEUE; + } | TAG string { filter_opts.tag = $2; } @@ -4110,6 +4371,11 @@ yyerror("keep state on block rules doesn't make sense"); problems++; } + if (r->rt && r->dnpipe) { + yyerror("route-to/dup-to/fastroute/reply-to with dummynet " + "doesn't make sense"); + problems++; + } return (-problems); } @@ -4896,23 +5162,32 @@ { "bitmask", BITMASK}, { "block", BLOCK}, { "block-policy", BLOCKPOLICY}, + { "buckets", BUCKETS}, { "cbq", CBQ}, { "code", CODE}, { "crop", FRAGCROP}, { "debug", DEBUG}, + { "delay", DELAY}, + { "dnpipe", DNPIPE}, + { "dnqueue", DNQUEUE}, { "drop", DROP}, { "drop-ovl", FRAGDROP}, + { "dst-ip", DSTIP}, + { "dst-ip6", DSTIP6}, { "dup-to", DUPTO}, + { "dst-port", DSTPORT}, { "fastroute", FASTROUTE}, { "file", FILENAME}, { "fingerprints", FINGERPRINTS}, { "flags", FLAGS}, { "floating", FLOATING}, + { "flow-id", FLOWID}, { "flush", FLUSH}, { "for", FOR}, { "fragment", FRAGMENT}, { "from", FROM}, { "global", GLOBAL}, + { "gred", GRED}, { "group", GROUP}, { "hfsc", HFSC}, { "hostid", HOSTID}, @@ -4929,6 +5204,7 @@ { "load", LOAD}, { "log", LOG}, { "loginterface", LOGINTERFACE}, + { "mask", MASK}, { "max", MAXIMUM}, { "max-mss", MAXMSS}, { "max-src-conn", MAXSRCCONN}, @@ -4943,12 +5219,14 @@ { "no-df", NODF}, { "no-route", NOROUTE}, { "no-sync", NOSYNC}, + { "noerror", NOERROR}, { "on", ON}, { "optimization", OPTIMIZATION}, { "os", OS}, { "out", OUT}, { "overload", OVERLOAD}, { "pass", PASS}, + { "plr", PLR}, { "port", PORT}, { "priority", PRIORITY}, { "priq", PRIQ}, @@ -4963,6 +5241,7 @@ { "rdr-anchor", RDRANCHOR}, { "realtime", REALTIME}, { "reassemble", REASSEMBLE}, + { "red", RED}, { "reply-to", REPLYTO}, { "require-order", REQUIREORDER}, { "return", RETURN}, @@ -4980,6 +5259,9 @@ { "skip", SKIP}, { "source-hash", SOURCEHASH}, { "source-track", SOURCETRACK}, + { "src-ip", SRCIP}, + { "src-ip6", SRCIP6}, + { "src-port", SRCPORT}, { "state", STATE}, { "state-policy", STATEPOLICY}, { "static-port", STATICPORT}, @@ -4996,6 +5278,7 @@ { "upperlimit", UPPERLIMIT}, { "urpf-failed", URPFFAILED}, { "user", USER}, + { "weight", WEIGHT}, }; const struct keywords *p; @@ -5524,3 +5807,23 @@ return (0); } + +/* n2mask sets n bits of the mask */ +static void +n2mask(struct in6_addr *mask, int n) +{ + static int minimask[9] = + { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + u_char *p; + + memset(mask, 0, sizeof(struct in6_addr)); + p = (u_char *) mask; + for (; n > 0; p++, n -= 8) { + if (n >= 8) + *p = 0xff; + else + *p = minimask[n]; + } + return; +} + Index: contrib/pf/pfctl/pfctl.c =================================================================== RCS file: /home/eri/repo/contrib/pf/pfctl/pfctl.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pfctl.c --- contrib/pf/pfctl/pfctl.c 21 Oct 2007 13:53:15 -0000 1.1.1.1 +++ contrib/pf/pfctl/pfctl.c 21 Oct 2007 19:03:49 -0000 @@ -46,6 +46,9 @@ #include <altq/altq.h> #include <sys/sysctl.h> +#include <netinet/ip_fw.h> +#include <netinet/ip_dummynet.h> + #include <err.h> #include <errno.h> #include <fcntl.h> @@ -71,6 +74,7 @@ int pfctl_clear_rules(int, int, char *); int pfctl_clear_nat(int, int, char *); int pfctl_clear_altq(int, int); +int pfctl_clear_dummynet(int, int); int pfctl_clear_src_nodes(int, int); int pfctl_clear_states(int, const char *, int); void pfctl_addrprefix(char *, struct pf_addr *); @@ -95,6 +99,7 @@ int pfctl_show_limits(int, int); void pfctl_debug(int, u_int32_t, int); int pfctl_test_altqsupport(int, int); +int pfctl_test_dummynetsupport(int, int); int pfctl_show_anchors(int, int, char *); int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *); int pfctl_load_ruleset(struct pfctl *, char *, @@ -122,6 +127,9 @@ int loadopt; int altqsupport; +int dummynetsupport; +int dnsock; + int dev = -1; int first_title = 1; int labels = 0; @@ -207,12 +215,12 @@ }; static const char *clearopt_list[] = { - "nat", "queue", "rules", "Sources", + "nat", "queue", "dummynet", "rules", "Sources", "state", "info", "Tables", "osfp", "all", NULL }; static const char *showopt_list[] = { - "nat", "queue", "rules", "Anchors", "Sources", "state", "info", + "nat", "queue", "dummynet", "rules", "Anchors", "Sources", "state", "info", "Interfaces", "labels", "timeouts", "memory", "Tables", "osfp", "all", NULL }; @@ -367,6 +375,21 @@ } int +pfctl_clear_dummynet(int dnsock, int opts) +{ + if (!dummynetsupport) + return (-1); + if (setsockopt(dnsock, IPPROTO_IP, IP_DUMMYNET_FLUSH, NULL, 0) < 0) { + err(1,"setsockopt(IP_DUMMYNET_FLUSH)"); + return (1); + } + + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "DUMMYNET cleared\n"); + return (0); +} + +int pfctl_clear_src_nodes(int dev, int opts) { if (ioctl(dev, DIOCCLRSRCNODES)) @@ -1348,6 +1371,24 @@ } int +pfctl_add_dummynet(struct pfctl *pf, struct dn_pipe *p) +{ + if (dummynetsupport && + (loadopt & PFCTL_FLAG_DUMMYNET) != 0) { + if ((pf->opts & PF_OPT_NOACTION) == 0) { + if (setsockopt(dnsock, IPPROTO_IP, IP_DUMMYNET_CONFIGURE, + p, sizeof(*p)) < 0) { + errx(1, "DUMMYNET configure"); + } + } + } + if (pf->opts & PF_OPT_VERBOSE) + print_dummynet(p); + + return (0); +} + +int pfctl_rules(int dev, char *filename, FILE *fin, int opts, int optimize, char *anchorname, struct pfr_buffer *trans) { @@ -1914,6 +1955,21 @@ } int +pfctl_test_dummynetsupport(int dnsock, int opts) +{ + struct dn_pipe p; + socklen_t len; + + if (getsockopt(dnsock, IPPROTO_IP, IP_DUMMYNET_GET, &p, + &len) < 0) { + if (!(opts & (PF_OPT_QUIET|PF_OPT_NOACTION))) + fprintf(stderr, "DUMMYNET not loaded\n"); + return (0); + } + return (1); +} + +int pfctl_show_anchors(int dev, int opts, char *anchorname) { struct pfioc_ruleset pr; @@ -1978,7 +2034,7 @@ usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:K:mnNOo::p:rRs:t:T:vx:z")) != -1) { + "a:AdDP:eqf:F:ghi:k:K:mnNOo::p:rRs:t:T:vx:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2050,6 +2106,9 @@ case 'A': loadopt |= PFCTL_FLAG_ALTQ; break; + case 'P': + loadopt |= PFCTL_FLAG_DUMMYNET; + break; case 'R': loadopt |= PFCTL_FLAG_FILTER; break; @@ -2164,6 +2223,11 @@ if (dev == -1) err(1, "%s", pf_device); altqsupport = pfctl_test_altqsupport(dev, opts); + + dnsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + if (dnsock < 0) + err(1, "socket"); + dummynetsupport = pfctl_test_dummynetsupport(dnsock, opts); } else { dev = open(pf_device, O_RDONLY); if (dev >= 0) @@ -2176,6 +2240,10 @@ #else altqsupport = 1; #endif + dnsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + if (dnsock < 0) + err(1, "socket"); + dummynetsupport = pfctl_test_dummynetsupport(dnsock, opts); } if (opts & PF_OPT_DISABLE) @@ -2205,6 +2273,9 @@ pfctl_show_altq(dev, ifaceopt, opts, opts & PF_OPT_VERBOSE2); break; + case 'd': + pfctl_show_dummynet(dnsock, opts); + break; case 's': pfctl_show_states(dev, ifaceopt, opts); break; @@ -2227,6 +2298,7 @@ pfctl_show_nat(dev, opts, anchorname); pfctl_show_rules(dev, path, opts, 0, anchorname, 0); pfctl_show_altq(dev, ifaceopt, opts, 0); + pfctl_show_dummynet(dnsock, opts); pfctl_show_states(dev, ifaceopt, opts); pfctl_show_src_nodes(dev, opts); pfctl_show_status(dev, opts); @@ -2268,6 +2340,9 @@ case 'q': pfctl_clear_altq(dev, opts); break; + case 'd': + pfctl_clear_dummynet(dnsock, opts); + break; case 's': pfctl_clear_states(dev, ifaceopt, opts); break; @@ -2283,6 +2358,7 @@ pfctl_clear_tables(anchorname, opts); if (!*anchorname) { pfctl_clear_altq(dev, opts); + pfctl_clear_dummynet(dnsock, opts); pfctl_clear_states(dev, ifaceopt, opts); pfctl_clear_src_nodes(dev, opts); pfctl_clear_stats(dev, opts); Index: contrib/pf/pfctl/pfctl.h =================================================================== RCS file: /home/eri/repo/contrib/pf/pfctl/pfctl.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pfctl.h --- contrib/pf/pfctl/pfctl.h 21 Oct 2007 13:53:15 -0000 1.1.1.1 +++ contrib/pf/pfctl/pfctl.h 21 Oct 2007 19:03:49 -0000 @@ -85,6 +85,7 @@ int pfctl_command_tables(int, char *[], char *, const char *, char *, const char *, int); int pfctl_show_altq(int, const char *, int, int); +int pfctl_show_dummynet(int, int); void warn_namespace_collision(const char *); int pfctl_show_ifaces(const char *, int); FILE *pfctl_fopen(const char *, const char *); Index: contrib/pf/pfctl/pfctl_dn.c =================================================================== RCS file: contrib/pf/pfctl/pfctl_dn.c diff -N contrib/pf/pfctl/pfctl_dn.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ contrib/pf/pfctl/pfctl_dn.c 21 Oct 2007 19:03:32 -0000 @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2007 Ermal Luçi + * Copyright (c) 2002-2003 Luigi Rizzo + * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp + * Copyright (c) 1994 Ugen J.S.Antsilevich + * + * Idea and grammar partially left from: + * Copyright (c) 1993 Daniel Boulet + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * NEW command line interface for IP firewall facility + * + */ + +/* + * Most of this is derived from ipfw(8) code. + */ + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <net/pfvar.h> + +#include <err.h> +#include <errno.h> +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> + +#include <netinet/ip_fw.h> +#include <netinet/ip_dummynet.h> + +#include "pfctl_parser.h" +#include "pfctl.h" + +static int do_sort, + verbose; + +static int sort_q(const void *, const void *); +static void +list_queues(struct dn_flow_set *, struct dn_flow_queue *); +static void +print_flowset_parms(struct dn_flow_set *, char *); +static void +list_pipes(void *, uint ); + +static int +sort_q(const void *pa, const void *pb) +{ + int rev = (0); + int field = rev ? -do_sort : do_sort; + long long res = 0; + const struct dn_flow_queue *a = pa; + const struct dn_flow_queue *b = pb; + + switch (field) { + case 1: /* pkts */ + res = a->len - b->len; + break; + case 2: /* bytes */ + res = a->len_bytes - b->len_bytes; + break; + + case 3: /* tot pkts */ + res = a->tot_pkts - b->tot_pkts; + break; + + case 4: /* tot bytes */ + res = a->tot_bytes - b->tot_bytes; + break; + } + if (res < 0) + res = -1; + if (res > 0) + res = 1; + return (int)(rev ? res : -res); +} + +static void +list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q) +{ + int l; + int index_printed, indexes = 0; + char buff[255]; + struct protoent *pe; + + if (fs->rq_elements == 0) + return; + + if (do_sort != 0) + heapsort(q, fs->rq_elements, sizeof *q, sort_q); + + /* Print IPv4 flows */ + index_printed = 0; + for (l = 0; l < fs->rq_elements; l++) { + struct in_addr ina; + + /* XXX: Should check for IPv4 flows */ + if (IS_IP6_FLOW_ID(&(q[l].id))) + continue; + + if (!index_printed) { + index_printed = 1; + if (indexes > 0) /* currently a no-op */ + printf("\n"); + indexes++; + printf(" " + "mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n", + fs->flow_mask.proto, + fs->flow_mask.src_ip, fs->flow_mask.src_port, + fs->flow_mask.dst_ip, fs->flow_mask.dst_port); + + printf("BKT Prot ___Source IP/port____ " + "____Dest. IP/port____ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } + + printf("%3d ", q[l].hash_slot); + pe = getprotobynumber(q[l].id.proto); + if (pe) + printf("%-4s ", pe->p_name); + else + printf("%4u ", q[l].id.proto); + ina.s_addr = htonl(q[l].id.src_ip); + printf("%15s/%-5d ", + inet_ntoa(ina), q[l].id.src_port); + ina.s_addr = htonl(q[l].id.dst_ip); + printf("%15s/%-5d ", + inet_ntoa(ina), q[l].id.dst_port); + printf("%4qu %8qu %2u %4u %3u\n", + q[l].tot_pkts, q[l].tot_bytes, + q[l].len, q[l].len_bytes, q[l].drops); + if (verbose) + printf(" S %20qd F %20qd\n", + q[l].S, q[l].F); + } + + /* Print IPv6 flows */ + index_printed = 0; + for (l = 0; l < fs->rq_elements; l++) { + if (!IS_IP6_FLOW_ID(&(q[l].id))) + continue; + + if (!index_printed) { + index_printed = 1; + if (indexes > 0) + printf("\n"); + indexes++; + printf("\n mask: proto: 0x%02x, flow_id: 0x%08x, ", + fs->flow_mask.proto, fs->flow_mask.flow_id6); + inet_ntop(AF_INET6, &(fs->flow_mask.src_ip6), + buff, sizeof(buff)); + printf("%s/0x%04x -> ", buff, fs->flow_mask.src_port); + inet_ntop( AF_INET6, &(fs->flow_mask.dst_ip6), + buff, sizeof(buff) ); + printf("%s/0x%04x\n", buff, fs->flow_mask.dst_port); + + printf("BKT ___Prot___ _flow-id_ " + "______________Source IPv6/port_______________ " + "_______________Dest. IPv6/port_______________ " + "Tot_pkt/bytes Pkt/Byte Drp\n"); + } + printf("%3d ", q[l].hash_slot); + pe = getprotobynumber(q[l].id.proto); + if (pe != NULL) + printf("%9s ", pe->p_name); + else + printf("%9u ", q[l].id.proto); + printf("%7d %39s/%-5d ", q[l].id.flow_id6, + inet_ntop(AF_INET6, &(q[l].id.src_ip6), buff, sizeof(buff)), + q[l].id.src_port); + printf(" %39s/%-5d ", + inet_ntop(AF_INET6, &(q[l].id.dst_ip6), buff, sizeof(buff)), + q[l].id.dst_port); + printf(" %4qu %8qu %2u %4u %3u\n", + q[l].tot_pkts, q[l].tot_bytes, + q[l].len, q[l].len_bytes, q[l].drops); + if (verbose) + printf(" S %20qd F %20qd\n", q[l].S, q[l].F); + } +} + +static void +print_flowset_parms(struct dn_flow_set *fs, char *prefix) +{ + int l; + char qs[30]; + char plr[30]; + char red[90]; /* Display RED parameters */ + + l = fs->qsize; + if (fs->flags_fs & DN_QSIZE_IS_BYTES) { + if (l >= 8192) + sprintf(qs, "%d KB", l / 1024); + else + sprintf(qs, "%d B", l); + } else + sprintf(qs, "%3d sl.", l); + if (fs->plr) + sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff)); + else + plr[0] = '\0'; + if (fs->flags_fs & DN_IS_RED) /* RED parameters */ + sprintf(red, + "\n\t %cRED w_q %f min_th %d max_th %d max_p %f", + (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ', + 1.0 * fs->w_q / (double)(1 << SCALE_RED), + SCALE_VAL(fs->min_th), + SCALE_VAL(fs->max_th), + 1.0 * fs->max_p / (double)(1 << SCALE_RED)); + else + sprintf(red, "droptail"); + + printf("%s %s%s %d queues (%d buckets) %s\n", + prefix, qs, plr, fs->rq_elements, fs->rq_size, red); +} + + +static void +list_pipes(void *data, uint nbytes) +{ + void *next = data; + struct dn_pipe *p = (struct dn_pipe *) data; + struct dn_flow_set *fs; + struct dn_flow_queue *q; + int l; + + for (; nbytes >= sizeof *p; p = (struct dn_pipe *)next) { + double b = p->bandwidth; + char buf[30]; + char prefix[80]; + + if (SLIST_NEXT(p, next) != (struct dn_pipe *)DN_IS_PIPE) + break; /* done with pipes, now queues */ + + /* + * compute length, as pipe have variable size + */ + l = sizeof(*p) + p->fs.rq_elements * sizeof(*q); + next = (char *)p + l; + nbytes -= l; + + /* + * Print rate (or clocking interface) + */ + if (p->if_name[0] != '\0') + sprintf(buf, "%s", p->if_name); + else if (b == 0) + sprintf(buf, "unlimited"); + else if (b >= 1000000) + sprintf(buf, "%7.3f Mbit/s", b/1000000); + else if (b >= 1000) + sprintf(buf, "%7.3f Kbit/s", b/1000); + else + sprintf(buf, "%7.3f bit/s ", b); + + sprintf(prefix, "%05d: %s %4d ms ", + p->pipe_nr, buf, p->delay); + print_flowset_parms(&(p->fs), prefix); + if (verbose) + printf(" V %20qd\n", p->V >> MY_M); + + q = (struct dn_flow_queue *)(p+1); + list_queues(&(p->fs), q); + } + for (fs = next; nbytes >= sizeof *fs; fs = next) { + char prefix[80]; + + if (SLIST_NEXT(fs, next) != (struct dn_flow_set *)DN_IS_QUEUE) + break; + l = sizeof(*fs) + fs->rq_elements * sizeof(*q); + next = (char *)fs + l; + nbytes -= l; +#if 0 + if (rulenum != 0 && ((rulenum != fs->fs_nr && do_pipe == 2) || + (rulenum != fs->parent_nr && do_pipe == 1))) { + continue; + } +#endif + q = (struct dn_flow_queue *)(fs+1); + sprintf(prefix, "q%05d: weight %d pipe %d ", + fs->fs_nr, fs->weight, fs->parent_nr); + print_flowset_parms(fs, prefix); + list_queues(fs, q); + } +} + +void +print_dummynet(struct dn_pipe *p) +{ + char buff[255]; + + if (p->pipe_nr != 0) { /* This is a pipe */ + printf("dnpipe %d", p->pipe_nr); + if (p->bandwidth) + printf(" bandwidth %dMb", p->bandwidth/1000000); + else if (p->bandwidth >= 1000) + printf(" bandwidth %dKb", p->bandwidth/1000); + else + printf(" bandwidth %db ", p->bandwidth); + if (p->delay > 0) + printf(" delay %d", p->delay); + } else { + printf("dnqueue %d dnpipe %d", p->fs.fs_nr, p->fs.parent_nr); + if (p->fs.weight) + printf(" weight %d", p->fs.weight); + } + + if (p->fs.rq_size > 15) + printf(" buckets %d", p->fs.rq_size); + if (p->fs.flags_fs & DN_QSIZE_IS_BYTES) { + if (p->fs.qsize >= 8192) + printf(" queue %dKB", p->fs.qsize / 1024); + else if (p->fs.qsize > 0) + printf(" queue %dB", p->fs.qsize); + } else + if (p->fs.qsize > 0) + printf(" queue %3d", p->fs.qsize); + if (p->fs.plr > 0) + printf(" plr %f", 1.0 * p->fs.plr / (double)(0x7fffffff)); + + if (p->fs.flow_mask.proto && p->fs.flow_mask.dst_ip && + p->fs.flow_mask.src_ip && p->fs.flow_mask.dst_port && + p->fs.flow_mask.src_port && + p->fs.flow_mask.flow_id6) + printf(" mask all"); + else if (p->fs.flow_mask.proto || p->fs.flow_mask.dst_ip || + p->fs.flow_mask.src_ip || p->fs.flow_mask.dst_port || + p->fs.flow_mask.src_port || + p->fs.flow_mask.flow_id6) { + printf("\n\t mask: "); + if (p->fs.flow_mask.proto) + printf(" proto 0x%02x", p->fs.flow_mask.proto); + if (p->fs.flow_mask.src_ip) + printf(" src-ip 0x%08x", p->fs.flow_mask.src_ip); + if (p->fs.flow_mask.src_port) + printf(" src-port 0x%04x", p->fs.flow_mask.src_port); + if (p->fs.flow_mask.dst_ip) + printf(" dst-ip 0x%08x", p->fs.flow_mask.dst_ip); + if (p->fs.flow_mask.dst_port) + printf(" dst-port 0x%04x", p->fs.flow_mask.dst_port); + if (p->fs.flow_mask.flow_id6) + printf(" dst-port 0x%08x", p->fs.flow_mask.flow_id6); + } + if (p->fs.flags_fs & DN_NOERROR) + printf(" noerror"); + + printf("\n"); +} + +int +pfctl_show_dummynet(int dnsock, int opts) +{ + void *data = NULL; + int nbytes, nalloc = 1024; + + if (opts & PF_OPT_VERBOSE) + verbose = 1; + else + verbose = 0; + + nbytes = nalloc; + while (nbytes >= nalloc) { + nalloc = nalloc * 2 + 200; + nbytes = nalloc; + if ((data = realloc(data, nbytes)) == NULL) + err(1, "realloc"); + if (getsockopt(dnsock, IPPROTO_IP, IP_DUMMYNET_GET, data, + (socklen_t *)&nbytes) < 0) { + free(data); + err(1, "getsockopt(IP_DUMMYNET_GET)"); + } + } + + list_pipes(data, nbytes); + + return (0); + +} Index: contrib/pf/pfctl/pfctl_parser.c =================================================================== RCS file: /home/eri/repo/contrib/pf/pfctl/pfctl_parser.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pfctl_parser.c --- contrib/pf/pfctl/pfctl_parser.c 21 Oct 2007 13:53:15 -0000 1.1.1.1 +++ contrib/pf/pfctl/pfctl_parser.c 21 Oct 2007 19:03:49 -0000 @@ -48,6 +48,9 @@ #include <net/pfvar.h> #include <arpa/inet.h> +#include <netinet/ip_fw.h> +#include <netinet/ip_dummynet.h> + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -981,6 +984,12 @@ } if (r->label[0]) printf(" label \"%s\"", r->label); + if (r->dnpipe && r->pdnpipe) + printf(" dnqueue(%d, %d)", r->dnpipe, r->pdnpipe); + else if (r->dnpipe) + printf(" %s %d", + r->dntype == DN_IS_PIPE ? "dnpipe" : "dnqueue", + r->dnpipe); if (r->qname[0] && r->pqname[0]) printf(" queue(%s, %s)", r->qname, r->pqname); else if (r->qname[0]) Index: contrib/pf/pfctl/pfctl_parser.h =================================================================== RCS file: /home/eri/repo/contrib/pf/pfctl/pfctl_parser.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pfctl_parser.h --- contrib/pf/pfctl/pfctl_parser.h 21 Oct 2007 13:53:15 -0000 1.1.1.1 +++ contrib/pf/pfctl/pfctl_parser.h 21 Oct 2007 19:03:49 -0000 @@ -67,6 +67,7 @@ } struct pfr_buffer; /* forward definition */ +struct dn_pipe; struct pfctl { @@ -217,6 +218,7 @@ int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *); int pfctl_add_altq(struct pfctl *, struct pf_altq *); +int pfctl_add_dummynet(struct pfctl *, struct dn_pipe *); int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t); void pfctl_move_pool(struct pf_pool *, struct pf_pool *); void pfctl_clear_pool(struct pf_pool *); @@ -244,6 +246,8 @@ int eval_pfqueue(struct pfctl *, struct pf_altq *, struct node_queue_bw *, struct node_queue_opt *); +void print_dummynet(struct dn_pipe *); + void print_altq(const struct pf_altq *, unsigned, struct node_queue_bw *, struct node_queue_opt *); void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *, @@ -286,6 +290,7 @@ #define PFCTL_FLAG_OPTION 0x08 #define PFCTL_FLAG_ALTQ 0x10 #define PFCTL_FLAG_TABLE 0x20 +#define PFCTL_FLAG_DUMMYNET 0x40 extern const struct pf_timeout pf_timeouts[]; Index: sbin/pfctl/Makefile =================================================================== RCS file: /home/eri/repo/sbin/pfctl/Makefile,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 Makefile --- sbin/pfctl/Makefile 21 Oct 2007 13:54:16 -0000 1.1.1.1 +++ sbin/pfctl/Makefile 21 Oct 2007 19:03:49 -0000 @@ -11,6 +11,7 @@ SRCS+= pfctl_osfp.c pfctl_radix.c pfctl_table.c pfctl_qstats.c SRCS+= pfctl_optimize.c SRCS+= pf_ruleset.c +SRCS+= pfctl_dn.c CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized CFLAGS+= -Wstrict-prototypes -I${.CURDIR}/../../contrib/pf/pfctl Index: sys/contrib/pf/net/pf.c =================================================================== RCS file: /home/eri/repo/sys/contrib/pf/net/pf.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pf.c --- sys/contrib/pf/net/pf.c 21 Oct 2007 13:54:56 -0000 1.1.1.1 +++ sys/contrib/pf/net/pf.c 21 Oct 2007 19:03:49 -0000 @@ -6718,6 +6719,7 @@ int off, dirndx, pqid = 0; #ifdef __FreeBSD__ + struct ip_fw_args dnflow; PF_LOCK(); #endif if (!pf_status.running) @@ -6744,6 +6746,7 @@ PF_UNLOCK(); return (PF_PASS); } + #else if (pd.pf_mtag->flags & PF_TAG_GENERATED) return (PF_PASS); @@ -6827,6 +6830,13 @@ struct tcphdr th; pd.hdr.tcp = &th; + +#ifdef __FreeBSD__ + dnflow.f_id.flags = th.th_flags; + dnflow.f_id.dst_port = th.th_dport; + dnflow.f_id.src_port = th.th_sport; +#endif + if (!pf_pull_hdr(m, off, &th, sizeof(th), &action, &reason, AF_INET)) { log = action != PF_PASS; @@ -6868,6 +6878,12 @@ struct udphdr uh; pd.hdr.udp = &uh; + +#ifdef __FreeBSD__ + dnflow.f_id.dst_port = uh.uh_dport; + dnflow.f_id.src_port = uh.uh_sport; +#endif + if (!pf_pull_hdr(m, off, &uh, sizeof(uh), &action, &reason, AF_INET)) { log = action != PF_PASS; @@ -6909,6 +6925,7 @@ struct icmp ih; pd.hdr.icmp = &ih; + if (!pf_pull_hdr(m, off, &ih, ICMP_MINLEN, &action, &reason, AF_INET)) { log = action != PF_PASS; @@ -7083,6 +7100,33 @@ pf_route(m0, r, dir, ifp, s, &pd); #ifdef __FreeBSD__ + if (r->dnpipe && ip_dn_io_ptr != NULL) { + struct ip_fw dummyrule; + + dummyrule.cmd->opcode = + r->dntype == DN_IS_PIPE ? O_PIPE : O_QUEUE; + dummyrule.act_ofs = 0; + dummyrule.cmd_len = 1; + if (action == PF_PASS && ( + pqid || (pd.tos & IPTOS_LOWDELAY))) + dnflow.cookie = r->pdnpipe; + else + dnflow.cookie = r->dnpipe; + dnflow.rule = &dummyrule; + dnflow.f_id.addr_type = 4; /* IPv4 type */ + dnflow.f_id.proto = pd.proto; + PF_UNLOCK(); + + h = mtod(*m0, struct ip *); + NTOHS(h->ip_len); + NTOHS(h->ip_off); + ip_dn_io_ptr(*m0, + dir == PF_IN ? DN_TO_IP_IN : DN_TO_IP_OUT, + &dnflow); + *m0 = NULL; + return (action); + } + PF_UNLOCK(); #endif @@ -7111,6 +7155,7 @@ int off, terminal = 0, dirndx, rh_cnt = 0; #ifdef __FreeBSD__ + struct ip_fw_args dnflow; PF_LOCK(); #endif @@ -7286,6 +7331,12 @@ struct tcphdr th; pd.hdr.tcp = &th; +#ifdef __FreeBSD__ + dnflow.f_id.flags = th.th_flags; + dnflow.f_id.dst_port = th.th_dport; + dnflow.f_id.src_port = th.th_sport; +#endif + if (!pf_pull_hdr(m, off, &th, sizeof(th), &action, &reason, AF_INET6)) { log = action != PF_PASS; @@ -7326,6 +7377,11 @@ struct udphdr uh; pd.hdr.udp = &uh; +#ifdef __FreeBSD__ + dnflow.f_id.dst_port = uh.uh_dport; + dnflow.f_id.src_port = uh.uh_sport; +#endif + if (!pf_pull_hdr(m, off, &uh, sizeof(uh), &action, &reason, AF_INET6)) { log = action != PF_PASS; @@ -7539,8 +7595,33 @@ pf_route6(m0, r, dir, ifp, s, &pd); #ifdef __FreeBSD__ + if (r->dnpipe && ip_dn_io_ptr != NULL) { + struct ip_fw dummyrule; + + dummyrule.cmd->opcode = + r->dntype == DN_IS_PIPE ? O_PIPE : O_QUEUE; + dummyrule.act_ofs = 0; + dummyrule.cmd_len = 1; + if (action == PF_PASS && ( + pd.tos & IPTOS_LOWDELAY)) + dnflow.cookie = r->pdnpipe; + else + dnflow.cookie = r->dnpipe; + dnflow.rule = &dummyrule; + dnflow.f_id.addr_type = 6; /* IPv4 type */ + dnflow.f_id.proto = pd.proto; + PF_UNLOCK(); + + ip_dn_io_ptr(*m0, + dir == PF_IN ? DN_TO_IP6_IN : DN_TO_IP6_OUT, + &dnflow); + *m0 = NULL; + return (action); + } + PF_UNLOCK(); #endif + return (action); } #endif /* INET6 */ Index: sys/contrib/pf/net/pf_ioctl.c =================================================================== RCS file: /home/eri/repo/sys/contrib/pf/net/pf_ioctl.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pf_ioctl.c --- sys/contrib/pf/net/pf_ioctl.c 21 Oct 2007 13:54:56 -0000 1.1.1.1 +++ sys/contrib/pf/net/pf_ioctl.c 21 Oct 2007 19:03:49 -0000 @@ -3522,8 +3522,16 @@ * byte order. */ struct ip *h = NULL; + struct m_tag *dn_tag; int chk; + dn_tag = m_tag_find(*m, PACKET_TAG_DUMMYNET, NULL); + if (dn_tag != NULL && + ((struct dn_pkt_tag *)(dn_tag+1))->dn_dir == DN_TO_IP_IN) { + m_tag_delete(*m, dn_tag); + return (PF_PASS); + } + if ((*m)->m_pkthdr.len >= (int)sizeof(struct ip)) { /* if m_pkthdr.len is less than ip header, pf will handle. */ h = mtod(*m, struct ip *); @@ -3557,6 +3565,7 @@ * byte order. */ struct ip *h = NULL; + struct m_tag *dn_tag; int chk; /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */ @@ -3564,6 +3573,14 @@ in_delayed_cksum(*m); (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } + + dn_tag = m_tag_find(*m, PACKET_TAG_DUMMYNET, NULL); + if (dn_tag != NULL && + ((struct dn_pkt_tag *)(dn_tag+1))->dn_dir == DN_TO_IP_OUT) { + m_tag_delete(*m, dn_tag); + return (PF_PASS); + } + if ((*m)->m_pkthdr.len >= (int)sizeof(*h)) { /* if m_pkthdr.len is less than ip header, pf will handle. */ h = mtod(*m, struct ip *); @@ -3593,6 +3610,14 @@ * IPv6 is not affected by ip_len/ip_off byte order changes. */ int chk; + struct m_tag *dn_tag; + + dn_tag = m_tag_find(*m, PACKET_TAG_DUMMYNET, NULL); + if (dn_tag != NULL && + ((struct dn_pkt_tag *)(dn_tag+1))->dn_dir == DN_TO_IP6_IN) { + m_tag_delete(*m, dn_tag); + return (PF_PASS); + } /* * In case of loopback traffic IPv6 uses the real interface in @@ -3616,6 +3641,14 @@ * IPv6 does not affected ip_len/ip_off byte order changes. */ int chk; + struct m_tag *dn_tag; + + dn_tag = m_tag_find(*m, PACKET_TAG_DUMMYNET, NULL); + if (dn_tag != NULL && + ((struct dn_pkt_tag *)(dn_tag+1))->dn_dir == DN_TO_IP6_OUT) { + m_tag_delete(*m, dn_tag); + return (PF_PASS); + } /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */ if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { Index: sys/contrib/pf/net/pfvar.h =================================================================== RCS file: /home/eri/repo/sys/contrib/pf/net/pfvar.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 pfvar.h --- sys/contrib/pf/net/pfvar.h 21 Oct 2007 13:54:56 -0000 1.1.1.1 +++ sys/contrib/pf/net/pfvar.h 21 Oct 2007 19:03:49 -0000 @@ -57,6 +57,9 @@ #ifdef __FreeBSD__ #include <netinet/in.h> + +#include <netinet/ip_fw.h> +#include <netinet/ip_dummynet.h> #endif #include <netinet/tcp_fsm.h> @@ -632,6 +635,9 @@ } max_src_conn_rate; u_int32_t qid; u_int32_t pqid; + u_int32_t dnpipe; + u_int32_t pdnpipe; + u_int32_t dntype; u_int32_t rt_listid; u_int32_t nr; u_int32_t prob; Index: sys/netinet/ip_dummynet.c =================================================================== RCS file: /home/eri/repo/sys/netinet/ip_dummynet.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 ip_dummynet.c --- sys/netinet/ip_dummynet.c 21 Oct 2007 13:55:36 -0000 1.1.1.1 +++ sys/netinet/ip_dummynet.c 21 Oct 2007 19:03:49 -0000 @@ -84,6 +84,9 @@ #include <netinet/ip6.h> /* for ip6_input, ip6_output prototypes */ #include <netinet6/ip6_var.h> + +static struct ip_fw default_rule ; + /* * We keep a private variable for the simulation time, but we could * probably use an existing one ("softticks" in sys/kern/kern_timeout.c) @@ -214,7 +217,6 @@ static void dummynet_send(struct mbuf *); void dummynet_drain(void); static ip_dn_io_t dummynet_io; -static void dn_rule_delete(void *); /* * Heap management functions. @@ -1490,7 +1492,6 @@ DUMMYNET_UNLOCK(); } -extern struct ip_fw *ip_fw_default_rule ; static void dn_rule_delete_fs(struct dn_flow_set *fs, void *r) { @@ -1503,7 +1504,7 @@ for (m = q->head ; m ; m = m->m_nextpkt ) { struct dn_pkt_tag *pkt = dn_tag_get(m) ; if (pkt->rule == r) - pkt->rule = ip_fw_default_rule ; + pkt->rule = &default_rule ; } } /* @@ -1536,7 +1537,7 @@ for (m = pipe->head ; m ; m = m->m_nextpkt ) { pkt = dn_tag_get(m); if (pkt->rule == r) - pkt->rule = ip_fw_default_rule; + pkt->rule = &default_rule; } } DUMMYNET_UNLOCK(); @@ -2129,7 +2130,20 @@ ip_dn_ctl_ptr = ip_dn_ctl; ip_dn_io_ptr = dummynet_io; - ip_dn_ruledel_ptr = dn_rule_delete; + + bzero(&default_rule, sizeof default_rule); + + default_rule.act_ofs = 0; + default_rule.rulenum = IPFW_DEFAULT_RULE; + default_rule.cmd_len = 1; + default_rule.set = RESVD_SET; + + default_rule.cmd[0].len = 1; + default_rule.cmd[0].opcode = +#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT + 1 ? O_ACCEPT : +#endif + O_DENY; TASK_INIT(&dn_task, 0, dummynet_task, NULL); dn_tq = taskqueue_create_fast("dummynet", M_NOWAIT, @@ -2149,7 +2163,6 @@ { ip_dn_ctl_ptr = NULL; ip_dn_io_ptr = NULL; - ip_dn_ruledel_ptr = NULL; DUMMYNET_LOCK(); callout_stop(&dn_timeout); @@ -2197,5 +2210,4 @@ NULL }; DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); -MODULE_DEPEND(dummynet, ipfw, 2, 2, 2); MODULE_VERSION(dummynet, 1); Index: sys/netinet/ip_dummynet.h =================================================================== RCS file: /home/eri/repo/sys/netinet/ip_dummynet.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 ip_dummynet.h --- sys/netinet/ip_dummynet.h 21 Oct 2007 13:55:36 -0000 1.1.1.1 +++ sys/netinet/ip_dummynet.h 21 Oct 2007 19:03:49 -0000 @@ -342,13 +342,13 @@ #ifdef _KERNEL typedef int ip_dn_ctl_t(struct sockopt *); /* raw_ip.c */ -typedef void ip_dn_ruledel_t(void *); /* ip_fw.c */ typedef int ip_dn_io_t(struct mbuf *m, int dir, struct ip_fw_args *fwa); extern ip_dn_ctl_t *ip_dn_ctl_ptr; -extern ip_dn_ruledel_t *ip_dn_ruledel_ptr; extern ip_dn_io_t *ip_dn_io_ptr; #define DUMMYNET_LOADED (ip_dn_io_ptr != NULL) +void dn_rule_delete(void *); + /* * Return the IPFW rule associated with the dummynet tag; if any. * Make sure that the dummynet tag is not reused by lower layers. Index: sys/netinet/ip_fw.h =================================================================== RCS file: /home/eri/repo/sys/netinet/ip_fw.h,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 ip_fw.h --- sys/netinet/ip_fw.h 21 Oct 2007 13:55:36 -0000 1.1.1.1 +++ sys/netinet/ip_fw.h 21 Oct 2007 19:03:49 -0000 @@ -615,5 +615,7 @@ extern ip_fw_chk_t *ip_fw_chk_ptr; #define IPFW_LOADED (ip_fw_chk_ptr != NULL) +#define IPFW_DEFAULT_RULE 65535 + #endif /* _KERNEL */ #endif /* _IPFW2_H */ Index: sys/netinet/ip_fw2.c =================================================================== RCS file: /home/eri/repo/sys/netinet/ip_fw2.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 ip_fw2.c --- sys/netinet/ip_fw2.c 21 Oct 2007 13:55:36 -0000 1.1.1.1 +++ sys/netinet/ip_fw2.c 21 Oct 2007 19:03:49 -0000 @@ -122,7 +122,6 @@ static struct callout ipfw_timeout; static uma_zone_t ipfw_dyn_rule_zone; -#define IPFW_DEFAULT_RULE 65535 /* * Data structure to cache our ucred related @@ -3828,7 +3827,7 @@ while ((rule = head) != NULL) { head = head->next; if (DUMMYNET_LOADED) - ip_dn_ruledel_ptr(rule); + dn_rule_delete(rule); free(rule, M_IPFW); } } Index: sys/netinet/ip_fw_pfil.c =================================================================== RCS file: /home/eri/repo/sys/netinet/ip_fw_pfil.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 ip_fw_pfil.c --- sys/netinet/ip_fw_pfil.c 21 Oct 2007 13:55:36 -0000 1.1.1.1 +++ sys/netinet/ip_fw_pfil.c 21 Oct 2007 19:03:49 -0000 @@ -72,9 +72,6 @@ int ipfw_chg_hook(SYSCTL_HANDLER_ARGS); -/* Dummynet hooks. */ -ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL; - /* Divert hooks. */ ip_divert_packet_t *ip_divert_ptr = NULL;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9a542da30710281311n7f8a6f29me02da90941d96ae5>
