diff options
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ifconfig/ifpfsync.c | 3 | ||||
-rw-r--r-- | sbin/pfctl/parse.y | 177 | ||||
-rw-r--r-- | sbin/pfctl/pfctl.c | 39 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_altq.c | 7 | ||||
-rw-r--r-- | sbin/pfctl/pfctl_parser.c | 20 |
5 files changed, 229 insertions, 17 deletions
diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c index 9dbe1d6..4094610 100644 --- a/sbin/ifconfig/ifpfsync.c +++ b/sbin/ifconfig/ifpfsync.c @@ -203,7 +203,8 @@ pfsync_status(int s) if (preq.pfsyncr_syncdev[0] != '\0' || preq.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP) { printf("maxupd: %d ", preq.pfsyncr_maxupdates); - printf("defer: %s\n", preq.pfsyncr_defer ? "on" : "off"); + printf("defer: %s\n", (preq.pfsyncr_defer & PFSYNCF_DEFER) ? "on" : "off"); + printf("\tsyncok: %d\n", (preq.pfsyncr_defer & PFSYNCF_OK) ? 1 : 0); } } diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index e0cfa3d..6e5ef7e 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -217,6 +217,7 @@ struct filter_opts { #define FOM_TOS 0x04 #define FOM_KEEP 0x08 #define FOM_SRCTRACK 0x10 +#define FOM_DSCP 0x20 #define FOM_SETPRIO 0x0400 #define FOM_PRIO 0x2000 struct node_uid *uid; @@ -229,7 +230,9 @@ struct filter_opts { } flags; struct node_icmp *icmpspec; u_int32_t tos; + u_int32_t dscp; u_int32_t prob; + u_int32_t tracker; struct { int action; struct node_state_opt *options; @@ -237,10 +240,14 @@ struct filter_opts { int fragment; int allowopts; char *label; + char *schedule; struct node_qassign queues; char *tag; char *match_tag; u_int8_t match_tag_not; + u_int32_t dnpipe; + u_int32_t pdnpipe; + u_int32_t free_flags; u_int rtableid; u_int8_t prio; u_int8_t set_prio[2]; @@ -252,6 +259,7 @@ struct filter_opts { struct antispoof_opts { char *label; + u_int32_t tracker; u_int rtableid; } antispoof_opts; @@ -344,6 +352,7 @@ int expand_skip_interface(struct node_if *); int check_rulestate(int); int getservice(char *); int rule_label(struct pf_rule *, char *); +int rule_schedule(struct pf_rule *, char *); int rt_tableid_max(void); void mv_rules(struct pf_ruleset *, struct pf_ruleset *); @@ -445,11 +454,11 @@ int parseport(char *, struct range *r, int); %} -%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS +%token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF -%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL -%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE +%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL SCHEDULE +%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DSCP DROP TABLE TRACKER %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID @@ -457,6 +466,7 @@ int parseport(char *, struct range *r, int); %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY %token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME %token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL +%token DNPIPE DNQUEUE %token LOAD RULESET_OPTIMIZATION PRIO %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY @@ -467,7 +477,7 @@ int parseport(char *, struct range *r, int); %token <v.i> PORTBINARY %type <v.interface> interface if_list if_item_not if_item %type <v.number> number icmptype icmp6type uid gid -%type <v.number> tos not yesno +%type <v.number> tos dscp not yesno %type <v.probability> probability %type <v.i> no dir af fragcache optimizer %type <v.i> sourcetrack flush unaryop statelock @@ -492,7 +502,7 @@ int parseport(char *, struct range *r, int); %type <v.gid> gids gid_list gid_item %type <v.route> route %type <v.redirection> redirection redirpool -%type <v.string> label stringall tag anchorname +%type <v.string> label schedule stringall tag anchorname %type <v.string> string varstring numberstring %type <v.keep_state> keep %type <v.state_opt> state_opt_spec state_opt_list state_opt_item @@ -1237,6 +1247,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { if (rule_label(&r, $5.label)) YYERROR; r.rtableid = $5.rtableid; + r.cuid = $5.tracker; j = calloc(1, sizeof(struct node_if)); if (j == NULL) err(1, "antispoof: calloc"); @@ -1286,6 +1297,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { r.logif = $2.logif; r.quick = $2.quick; r.af = $4; + r.cuid = $5.tracker; if (rule_label(&r, $5.label)) YYERROR; r.rtableid = $5.rtableid; @@ -1347,6 +1359,9 @@ antispoof_opt : label { } antispoof_opts.label = $1; } + | TRACKER number { + antispoof_opts.tracker = $2; + } | RTABLE NUMBER { if ($2 < 0 || $2 > rt_tableid_max()) { yyerror("invalid rtable id"); @@ -2061,6 +2076,11 @@ pfrule : action dir logquick interface route af proto fromto if (rule_label(&r, $9.label)) YYERROR; free($9.label); + if (rule_schedule(&r, $9.schedule)) + YYERROR; + free($9.schedule); + if ($9.tracker) + r.cuid = $9.tracker; r.flags = $9.flags.b1; r.flagset = $9.flags.b2; if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { @@ -2092,7 +2112,14 @@ pfrule : action dir logquick interface route af proto fromto #endif } - r.tos = $9.tos; + if ($9.tos) { + r.tos = $9.tos; + r.rule_flag |= PFRULE_TOS; + } + if ($9.dscp) { + r.tos = $9.dscp; + r.rule_flag |= PFRULE_DSCP; + } r.keep_state = $9.keep.action; o = $9.keep.options; @@ -2410,6 +2437,15 @@ pfrule : action dir logquick interface route af proto fromto } #endif + if ($9.dnpipe) { + r.dnpipe = $9.dnpipe; + if ($9.free_flags & PFRULE_DN_IS_PIPE) + r.free_flags |= PFRULE_DN_IS_PIPE; + else + r.free_flags |= PFRULE_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, ""); @@ -2482,6 +2518,14 @@ filter_opt : USER uids { filter_opts.marker |= FOM_TOS; filter_opts.tos = $2; } + | dscp { + if (filter_opts.marker & FOM_DSCP) { + yyerror("dscp cannot be redefined"); + YYERROR; + } + filter_opts.marker |= FOM_DSCP; + filter_opts.dscp = $1; + } | keep { if (filter_opts.marker & FOM_KEEP) { yyerror("modulate or keep cannot be redefined"); @@ -2491,6 +2535,9 @@ filter_opt : USER uids { filter_opts.keep.action = $1.action; filter_opts.keep.options = $1.options; } + | TRACKER number { + filter_opts.tracker = $2; + } | FRAGMENT { filter_opts.fragment = 1; } @@ -2504,6 +2551,13 @@ filter_opt : USER uids { } filter_opts.label = $1; } + | schedule { + if (filter_opts.schedule) { + yyerror("schedule label cannot be redefined"); + YYERROR; + } + filter_opts.schedule = $1; + } | qname { if (filter_opts.queues.qname) { yyerror("queue cannot be redefined"); @@ -2511,6 +2565,32 @@ filter_opt : USER uids { } filter_opts.queues = $1; } + | DNPIPE number { + filter_opts.dnpipe = $2; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNPIPE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNPIPE '(' number comma number ')' { + filter_opts.pdnpipe = $5; + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_PIPE; + } + | DNQUEUE number { + filter_opts.dnpipe = $2; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } + | DNQUEUE '(' number comma number ')' { + filter_opts.pdnpipe = $5; + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } + | DNQUEUE '(' number ')' { + filter_opts.dnpipe = $3; + filter_opts.free_flags |= PFRULE_DN_IS_QUEUE; + } | TAG string { filter_opts.tag = $2; } @@ -2633,6 +2713,7 @@ probability : STRING { action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } + | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; } | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } ; @@ -3610,6 +3691,48 @@ tos : STRING { } ; +dscp : DSCP STRING { + if (!strcmp($2, "EF")) + $$ = DSCP_EF; + else if (!strcmp($2, "VA")) + $$ = DSCP_VA; + else if (!strcmp($2, "af11")) + $$ = DSCP_AF11; + else if (!strcmp($2, "af12")) + $$ = DSCP_AF12; + else if (!strcmp($2, "af13")) + $$ = DSCP_AF13; + else if (!strcmp($2, "af21")) + $$ = DSCP_AF21; + else if (!strcmp($2, "af22")) + $$ = DSCP_AF22; + else if (!strcmp($2, "af23")) + $$ = DSCP_AF23; + else if (!strcmp($2, "af31")) + $$ = DSCP_AF31; + else if (!strcmp($2, "af32")) + $$ = DSCP_AF32; + else if (!strcmp($2, "af33")) + $$ = DSCP_AF33; + else if (!strcmp($2, "af41")) + $$ = DSCP_AF41; + else if (!strcmp($2, "af42")) + $$ = DSCP_AF42; + else if (!strcmp($2, "af43")) + $$ = DSCP_AF43; + else if ($2[0] == '0' && $2[1] == 'x') + $$ = strtoul($2, NULL, 16) * 4; + else + $$ = strtoul($2, NULL, 10) * 4; + if (!$$ || $$ > 255) { + yyerror("illegal dscp value %s", $2); + free($2); + YYERROR; + } + free($2); + } + ; + sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; } | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; } @@ -3816,6 +3939,11 @@ label : LABEL STRING { } ; +schedule : SCHEDULE STRING { + $$ = $2; + } + ; + qname : QUEUE STRING { $$.qname = $2; $$.pqname = NULL; @@ -4652,6 +4780,15 @@ filter_consistent(struct pf_rule *r, int anchor_call) "synproxy state or modulate state"); problems++; } + if ((r->rule_flag & PFRULE_TOS) && (r->rule_flag & PFRULE_DSCP)) { + yyerror("tos and dscp cannot be used together"); + problems++; + } + if (r->dnpipe && r->pdnpipe && !r->direction) { + yyerror("dummynet cannot be specified without direction"); + problems++; + } + return (-problems); } @@ -5197,6 +5334,7 @@ expand_rule(struct pf_rule *r, int added = 0, error = 0; char ifname[IF_NAMESIZE]; char label[PF_RULE_LABEL_SIZE]; + char schedule[PF_RULE_LABEL_SIZE]; char tagname[PF_TAG_NAME_SIZE]; char match_tagname[PF_TAG_NAME_SIZE]; struct pf_pooladdr *pa; @@ -5205,6 +5343,8 @@ expand_rule(struct pf_rule *r, if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) errx(1, "expand_rule: strlcpy"); + if (strlcpy(schedule, r->schedule, sizeof(schedule)) > sizeof(schedule)) + errx(1, "expand_rule: strlcpy"); if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) errx(1, "expand_rule: strlcpy"); if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= @@ -5256,6 +5396,9 @@ expand_rule(struct pf_rule *r, if (strlcpy(r->label, label, sizeof(r->label)) >= sizeof(r->label)) errx(1, "expand_rule: strlcpy"); + if (strlcpy(r->schedule, schedule, sizeof(r->schedule)) >= + sizeof(r->schedule)) + errx(1, "expand_rule: strlcpy"); if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= sizeof(r->tagname)) errx(1, "expand_rule: strlcpy"); @@ -5264,6 +5407,8 @@ expand_rule(struct pf_rule *r, errx(1, "expand_rule: strlcpy"); expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, src_host, src_port, dst_host, dst_port, proto->proto); + expand_label(r->schedule, PF_RULE_LABEL_SIZE, r->ifname, r->af, + src_host, src_port, dst_host, dst_port, proto->proto); expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af, src_host, src_port, dst_host, dst_port, proto->proto); expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname, @@ -5448,8 +5593,11 @@ lookup(char *s) { "debug", DEBUG}, { "divert-reply", DIVERTREPLY}, { "divert-to", DIVERTTO}, + { "dnpipe", DNPIPE}, + { "dnqueue", DNQUEUE}, { "drop", DROP}, { "drop-ovl", FRAGDROP}, + { "dscp", DSCP}, { "dup-to", DUPTO}, { "fairq", FAIRQ}, { "fastroute", FASTROUTE}, @@ -5481,6 +5629,7 @@ lookup(char *s) { "load", LOAD}, { "log", LOG}, { "loginterface", LOGINTERFACE}, + { "match", MATCH}, { "max", MAXIMUM}, { "max-mss", MAXMSS}, { "max-src-conn", MAXSRCCONN}, @@ -5528,6 +5677,7 @@ lookup(char *s) { "rtable", RTABLE}, { "rule", RULE}, { "ruleset-optimization", RULESET_OPTIMIZATION}, + { "schedule", SCHEDULE}, { "scrub", SCRUB}, { "set", SET}, { "set-tos", SETTOS}, @@ -5549,6 +5699,7 @@ lookup(char *s) { "timeout", TIMEOUT}, { "to", TO}, { "tos", TOS}, + { "tracker", TRACKER}, { "ttl", TTL}, { "upperlimit", UPPERLIMIT}, { "urpf-failed", URPFFAILED}, @@ -6160,6 +6311,20 @@ rule_label(struct pf_rule *r, char *s) return (0); } +int +rule_schedule(struct pf_rule *r, char *s) +{ + if (s) { + if (strlcpy(r->schedule, s, sizeof(r->label)) >= + sizeof(r->label)) { + yyerror("rule schedule label too long (max %d chars)", + sizeof(r->label)-1); + return (-1); + } + } + return (0); +} + u_int16_t parseicmpspec(char *w, sa_family_t af) { diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 43d9dc5..c7a7459 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -75,6 +75,7 @@ void pfctl_addrprefix(char *, struct pf_addr *); int pfctl_kill_src_nodes(int, const char *, int); int pfctl_net_kill_states(int, const char *, int); int pfctl_label_kill_states(int, const char *, int); +int pfctl_kill_schedule(int, const char *, int); int pfctl_id_kill_states(int, const char *, int); void pfctl_init_options(struct pfctl *); int pfctl_load_options(struct pfctl *); @@ -114,6 +115,7 @@ const char *optiopt = NULL; char *pf_device = "/dev/pf"; char *ifaceopt; char *tableopt; +char *schedule = NULL; const char *tblcmdopt; int src_node_killers; char *src_node_kill[2]; @@ -649,6 +651,25 @@ pfctl_net_kill_states(int dev, const char *iface, int opts) } int +pfctl_kill_schedule(int dev, const char *sched, int opts) +{ + struct pfioc_schedule_kill psk; + + memset(&psk, 0, sizeof(psk)); + if (sched != NULL && strlcpy(psk.schedule, sched, + sizeof(psk.schedule)) >= sizeof(psk.schedule)) + errx(1, "invalid schedule label: %s", sched); + + if (ioctl(dev, DIOCKILLSCHEDULE, &psk)) + err(1, "DIOCKILLSCHEDULE"); + + if ((opts & PF_OPT_QUIET) == 0) + fprintf(stderr, "killed %d states from %s schedule label\n", + psk.numberkilled, sched); + return (0); +} + +int pfctl_label_kill_states(int dev, const char *iface, int opts) { struct pfioc_state_kill psk; @@ -799,10 +820,17 @@ pfctl_print_rule_counters(struct pf_rule *rule, int opts) (unsigned long long)(rule->bytes[0] + rule->bytes[1]), (uintmax_t)rule->u_states_cur); if (!(opts & PF_OPT_DEBUG)) +#ifdef PF_USER_INFO printf(" [ Inserted: uid %u pid %u " "State Creations: %-6ju]\n", (unsigned)rule->cuid, (unsigned)rule->cpid, (uintmax_t)rule->u_states_tot); +#else + printf(" [ Inserted: pid %u " + "State Creations: %-6ju]\n", + (unsigned)rule->cpid, + (uintmax_t)rule->u_states_tot); +#endif } } @@ -1999,7 +2027,7 @@ main(int argc, char *argv[]) usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) { + "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2113,6 +2141,12 @@ main(int argc, char *argv[]) opts |= PF_OPT_VERBOSE2; opts |= PF_OPT_VERBOSE; break; + case 'y': + if (schedule != NULL && strlen(schedule) > 64) + errx(1, "Schedule label cannot be more than 64 characters\n"); + schedule = optarg; + mode = O_RDWR; + break; case 'x': debugopt = pfctl_lookup_option(optarg, debugopt_list); if (debugopt == NULL) { @@ -2321,6 +2355,9 @@ main(int argc, char *argv[]) if (src_node_killers) pfctl_kill_src_nodes(dev, ifaceopt, opts); + if (schedule) + pfctl_kill_schedule(dev, schedule, opts); + if (tblcmdopt != NULL) { error = pfctl_command_tables(argc, argv, tableopt, tblcmdopt, rulesopt, anchorname, opts); diff --git a/sbin/pfctl/pfctl_altq.c b/sbin/pfctl/pfctl_altq.c index 6b0443a..4c479bc 100644 --- a/sbin/pfctl/pfctl_altq.c +++ b/sbin/pfctl/pfctl_altq.c @@ -735,13 +735,6 @@ eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa) return (-1); } - if ((opts->rtsc_m1 < opts->rtsc_m2 && opts->rtsc_m1 != 0) || - (opts->lssc_m1 < opts->lssc_m2 && opts->lssc_m1 != 0) || - (opts->ulsc_m1 < opts->ulsc_m2 && opts->ulsc_m1 != 0)) { - warnx("m1 must be zero for convex curve: %s", pa->qname); - return (-1); - } - /* * admission control: * for the real-time service curve, the sum of the service curves diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 4bb1477..af1c73e 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -683,8 +683,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) int i, opts; if (verbose) +#ifdef PF_USER_INFO printf("@%d ", r->nr); - if (r->action > PF_NORDR) +#else + printf("@%d(%u) ", r->nr, r->cuid); +#endif + if (r->action == PF_MATCH) + printf("match"); + else if (r->action > PF_NORDR) printf("action(%d)", r->action); else if (anchor_call[0]) { if (anchor_call[0] == '_') { @@ -839,8 +845,10 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) printf(" code %u", r->code-1); } } - if (r->tos) + if (r->tos && (r->rule_flag & PFRULE_TOS)) printf(" tos 0x%2.2x", r->tos); + if (r->tos && (r->rule_flag & PFRULE_DSCP)) + printf(" dscp 0x%2.2x", r->tos & DSCP_MASK); if (r->prio) printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio); if (r->scrub_flags & PFSTATE_SETMASK) { @@ -1001,6 +1009,14 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) } if (r->label[0]) printf(" label \"%s\"", r->label); + if (r->dnpipe && r->pdnpipe) + printf(" %s(%d, %d)", + r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue", + r->dnpipe, r->pdnpipe); + else if (r->dnpipe) + printf(" %s %d", + r->free_flags & PFRULE_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]) |