Fwd: [PATCH] PF+dummynet



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@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscribe@xxxxxxxxxxx"

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;

_______________________________________________
freebsd-net@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscribe@xxxxxxxxxxx"

Relevant Pages

  • Re: Whats the point of __KERNEL_SYSCALLS__?
    ... retrieving revision 1.4 ... diff -u -p -r1.4 process.c ... -static int errno; ... * calls - which means inline code for fork too, ...
    (Linux-Kernel)
  • Re: Sequence of packet processing with ipfw, pf, ipfilter ?
    ... retrieving revision 1.21 ... diff -u -r1.93.2.1 bridge.c ... -static __inline int ... pfil_run_hooksruns the specified packet filter hooks. ...
    (freebsd-stable)
  • Linux compatible setaffinity.
    ... int sched_setaffinity; ... diff -u -r1.2.10.2 kern_resource.c ... retrieving revision 1.1 ... Please copy any additions and changes to the following compatability tables: ...
    (freebsd-arch)
  • Re: VPD in sysfs
    ... - Write code for devices with PCI 2.1 VPD ... retrieving revision 1.7 ... diff -N vpd-2.6/drivers/pci/vpd.c ... +static int vpd_create_name ...
    (Linux-Kernel)
  • Fwd: [PATCH] PF+dummynet
    ... retrieving revision 1.1.1.1 ... diff -u -r1.1.1.1 parse.y ... +n2mask(struct in6_addr *mask, int n) ... +pfctl_clear_dummynet(int dnsock, int opts) ...
    (freebsd-net)