-# $OpenBSD: Makefile,v 1.20 2013/10/12 12:16:10 henning Exp $
+# $OpenBSD: Makefile,v 1.21 2014/04/19 14:22:32 henning Exp $
PROG= pfctl
-SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c pfctl_altq.c
-SRCS+= pfctl_osfp.c pfctl_radix.c pfctl_table.c pfctl_qstats.c
+SRCS= pfctl.c parse.y pfctl_parser.c pf_print_state.c
+SRCS+= pfctl_osfp.c pfctl_radix.c pfctl_table.c
SRCS+= pfctl_optimize.c pf_ruleset.c pfctl_queue.c
CFLAGS+= -Wall -Wmissing-prototypes -Wno-uninitialized
CFLAGS+= -Wstrict-prototypes -I${.CURDIR}
-/* $OpenBSD: parse.y,v 1.631 2014/01/22 00:21:16 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.632 2014/04/19 14:22:32 henning Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
#include <net/pfvar.h>
#include <net/hfsc.h>
#include <arpa/inet.h>
-#include <altq/altq.h>
-#include <altq/altq_cbq.h>
-#include <altq/altq_priq.h>
-#include <altq/altq_hfsc.h>
#include <stdio.h>
#include <unistd.h>
u_int qlimit;
} queue_opts;
-struct oldqueue_opts {
- int marker;
-#define OQOM_BWSPEC 0x01
-#define OQOM_SCHEDULER 0x02
-#define OQOM_PRIORITY 0x04
-#define OQOM_TBRSIZE 0x08
-#define OQOM_QLIMIT 0x10
- struct node_queue_bw queue_bwspec;
- struct node_queue_opt scheduler;
- int priority;
- int tbrsize;
- int qlimit;
-} oldqueue_opts;
-
struct table_opts {
int flags;
int init_addr;
struct node_gid *, struct node_if *, struct node_icmp *,
const char *);
int expand_queue(char *, struct node_if *, struct queue_opts *);
-int expand_altq(struct pf_altq *, struct node_if *,
- struct node_queue *, struct node_queue_bw bwspec,
- struct node_queue_opt *);
-int expand_oldqueue(struct pf_altq *, struct node_if *,
- struct node_queue *, struct node_queue_bw,
- struct node_queue_opt *);
int expand_skip_interface(struct node_if *);
int getservice(char *);
struct filter_opts filter_opts;
struct antispoof_opts antispoof_opts;
struct queue_opts queue_opts;
- struct oldqueue_opts oldqueue_opts;
struct scrub_opts scrub_opts;
struct table_opts table_opts;
struct pool_opts pool_opts;
%token SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
%token ANTISPOOF FOR INCLUDE MATCHES
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN LEASTSTATES STATICPORT PROBABILITY
-%token WEIGHT
-%token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
-%token QUEUE OLDQUEUE PRIORITY QLIMIT RTABLE RDOMAIN MINIMUM BURST PARENT
+%token WEIGHT BANDWIDTH
+%token QUEUE PRIORITY QLIMIT RTABLE RDOMAIN MINIMUM BURST PARENT
%token LOAD RULESET_OPTIMIZATION RTABLE RDOMAIN PRIO ONCE DEFAULT
%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW
%type <v.logquick> logquick quick log logopts logopt
%type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
%type <v.qassign> qname
-%type <v.queue> qassign qassign_list qassign_item
-%type <v.queue_options> scheduler
-%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.queue_bwspec> bandwidth
%type <v.filter_opts> filter_opts filter_opt filter_opts_l
%type <v.filter_opts> filter_sets filter_set filter_sets_l
%type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l
%type <v.queue_opts> queue_opts queue_opt queue_opts_l optscs
%type <v.sc> scspec
-%type <v.oldqueue_opts> oldqueue_opts oldqueue_opt oldqueue_opts_l
%type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
%type <v.table_opts> table_opts table_opt table_opts_l
%type <v.pool_opts> pool_opts pool_opt pool_opts_l
| ruleset anchorrule '\n'
| ruleset loadrule '\n'
| ruleset queuespec '\n'
- | ruleset altqif '\n'
- | ruleset oldqueuespec '\n'
| ruleset varset '\n'
| ruleset antispoof '\n'
| ruleset tabledef '\n'
}
;
-altqif : ALTQ interface oldqueue_opts QUEUE qassign {
- struct pf_altq a;
-
- memset(&a, 0, sizeof(a));
- if ($3.scheduler.qtype == ALTQT_NONE) {
- yyerror("no scheduler specified!");
- YYERROR;
- }
- a.scheduler = $3.scheduler.qtype;
- a.qlimit = $3.qlimit;
- a.tbrsize = $3.tbrsize;
- if ($5 == NULL) {
- yyerror("no child queues specified");
- YYERROR;
- }
- if (expand_altq(&a, $2, $5, $3.queue_bwspec,
- &$3.scheduler))
- YYERROR;
- }
- ;
-
-oldqueuespec : OLDQUEUE STRING interface oldqueue_opts qassign {
- struct pf_altq a;
-
- memset(&a, 0, sizeof(a));
- if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
- sizeof(a.qname)) {
- yyerror("queue name too long (max "
- "%d chars)", PF_QNAME_SIZE-1);
- free($2);
- YYERROR;
- }
- free($2);
- if ($4.tbrsize) {
- yyerror("cannot specify tbrsize for queue");
- YYERROR;
- }
- if ($4.priority > 255) {
- yyerror("priority out of range: max 255");
- YYERROR;
- }
- a.priority = $4.priority;
- a.qlimit = $4.qlimit;
- a.scheduler = $4.scheduler.qtype;
- if (expand_oldqueue(&a, $3, $5, $4.queue_bwspec,
- &$4.scheduler)) {
- yyerror("errors in queue definition");
- YYERROR;
- }
- }
- ;
-
-oldqueue_opts : {
- bzero(&oldqueue_opts, sizeof oldqueue_opts);
- oldqueue_opts.priority = DEFAULT_PRIORITY;
- oldqueue_opts.qlimit = DEFAULT_QLIMIT;
- oldqueue_opts.scheduler.qtype = ALTQT_NONE;
- oldqueue_opts.queue_bwspec.bw_percent = 100;
- }
- oldqueue_opts_l
- { $$ = oldqueue_opts; }
- | /* empty */ {
- bzero(&oldqueue_opts, sizeof oldqueue_opts);
- oldqueue_opts.priority = DEFAULT_PRIORITY;
- oldqueue_opts.qlimit = DEFAULT_QLIMIT;
- oldqueue_opts.scheduler.qtype = ALTQT_NONE;
- oldqueue_opts.queue_bwspec.bw_percent = 100;
- $$ = oldqueue_opts;
- }
- ;
-
-oldqueue_opts_l : oldqueue_opts_l oldqueue_opt
- | oldqueue_opt
- ;
-
-oldqueue_opt : BANDWIDTH bandwidth {
- if (oldqueue_opts.marker & OQOM_BWSPEC) {
- yyerror("bandwidth cannot be respecified");
- YYERROR;
- }
- oldqueue_opts.marker |= OQOM_BWSPEC;
- oldqueue_opts.queue_bwspec = $2;
- }
- | PRIORITY NUMBER {
- if (oldqueue_opts.marker & OQOM_PRIORITY) {
- yyerror("priority cannot be respecified");
- YYERROR;
- }
- if ($2 < 0 || $2 > 255) {
- yyerror("priority out of range: max 255");
- YYERROR;
- }
- oldqueue_opts.marker |= OQOM_PRIORITY;
- oldqueue_opts.priority = $2;
- }
- | QLIMIT NUMBER {
- if (oldqueue_opts.marker & OQOM_QLIMIT) {
- yyerror("qlimit cannot be respecified");
- YYERROR;
- }
- if ($2 < 0 || $2 > 65535) {
- yyerror("qlimit out of range: max 65535");
- YYERROR;
- }
- oldqueue_opts.marker |= OQOM_QLIMIT;
- oldqueue_opts.qlimit = $2;
- }
- | scheduler {
- if (oldqueue_opts.marker & OQOM_SCHEDULER) {
- yyerror("scheduler cannot be respecified");
- YYERROR;
- }
- oldqueue_opts.marker |= OQOM_SCHEDULER;
- oldqueue_opts.scheduler = $1;
- }
- | TBRSIZE NUMBER {
- if (oldqueue_opts.marker & OQOM_TBRSIZE) {
- yyerror("tbrsize cannot be respecified");
- YYERROR;
- }
- if ($2 < 0 || $2 > 65535) {
- yyerror("tbrsize too big: max 65535");
- YYERROR;
- }
- oldqueue_opts.marker |= OQOM_TBRSIZE;
- oldqueue_opts.tbrsize = $2;
- }
- ;
-
bandwidth : STRING {
double bps;
char *cp;
}
;
-scheduler : CBQ {
- $$.qtype = ALTQT_CBQ;
- $$.data.cbq_opts.flags = 0;
- }
- | CBQ '(' cbqflags_list ')' {
- $$.qtype = ALTQT_CBQ;
- $$.data.cbq_opts.flags = $3;
- }
- | PRIQ {
- $$.qtype = ALTQT_PRIQ;
- $$.data.priq_opts.flags = 0;
- }
- | PRIQ '(' priqflags_list ')' {
- $$.qtype = ALTQT_PRIQ;
- $$.data.priq_opts.flags = $3;
- }
- | HFSC {
- $$.qtype = ALTQT_HFSC;
- bzero(&$$.data.hfsc_opts,
- sizeof(struct node_hfsc_opts));
- }
- | HFSC '(' hfsc_opts ')' {
- $$.qtype = ALTQT_HFSC;
- $$.data.hfsc_opts = $3;
- }
- ;
-
-cbqflags_list : cbqflags_item { $$ |= $1; }
- | cbqflags_list comma cbqflags_item { $$ |= $3; }
- ;
-
-cbqflags_item : DEFAULT {
- $$ = CBQCLF_DEFCLASS;
- }
- | STRING {
- if (!strcmp($1, "borrow"))
- $$ = CBQCLF_BORROW;
- else if (!strcmp($1, "red"))
- $$ = CBQCLF_RED;
- else if (!strcmp($1, "ecn"))
- $$ = CBQCLF_RED|CBQCLF_ECN;
- else {
- yyerror("unknown cbq flag \"%s\"", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-
-priqflags_list : priqflags_item { $$ |= $1; }
- | priqflags_list comma priqflags_item { $$ |= $3; }
- ;
-
-priqflags_item : DEFAULT {
- $$ = PRCF_DEFAULTCLASS;
- }
- | STRING {
- if (!strcmp($1, "red"))
- $$ = PRCF_RED;
- else if (!strcmp($1, "ecn"))
- $$ = PRCF_RED|PRCF_ECN;
- else {
- yyerror("unknown priq flag \"%s\"", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-
-hfsc_opts : {
- bzero(&hfsc_opts,
- sizeof(struct node_hfsc_opts));
- }
- hfscopts_list {
- $$ = hfsc_opts;
- }
- ;
-
-hfscopts_list : hfscopts_item
- | hfscopts_list comma hfscopts_item
- ;
-
-hfscopts_item : LINKSHARE bandwidth {
- if (hfsc_opts.linkshare.used) {
- yyerror("linkshare already specified");
- YYERROR;
- }
- hfsc_opts.linkshare.m2 = $2;
- hfsc_opts.linkshare.used = 1;
- }
- | LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')'
- {
- if ($5 < 0 || $5 > INT_MAX) {
- yyerror("timing in curve out of range");
- YYERROR;
- }
- if (hfsc_opts.linkshare.used) {
- yyerror("linkshare already specified");
- YYERROR;
- }
- hfsc_opts.linkshare.m1 = $3;
- hfsc_opts.linkshare.d = $5;
- hfsc_opts.linkshare.m2 = $7;
- hfsc_opts.linkshare.used = 1;
- }
- | REALTIME bandwidth {
- if (hfsc_opts.realtime.used) {
- yyerror("realtime already specified");
- YYERROR;
- }
- hfsc_opts.realtime.m2 = $2;
- hfsc_opts.realtime.used = 1;
- }
- | REALTIME '(' bandwidth comma NUMBER comma bandwidth ')'
- {
- if ($5 < 0 || $5 > INT_MAX) {
- yyerror("timing in curve out of range");
- YYERROR;
- }
- if (hfsc_opts.realtime.used) {
- yyerror("realtime already specified");
- YYERROR;
- }
- hfsc_opts.realtime.m1 = $3;
- hfsc_opts.realtime.d = $5;
- hfsc_opts.realtime.m2 = $7;
- hfsc_opts.realtime.used = 1;
- }
- | UPPERLIMIT bandwidth {
- if (hfsc_opts.upperlimit.used) {
- yyerror("upperlimit already specified");
- YYERROR;
- }
- hfsc_opts.upperlimit.m2 = $2;
- hfsc_opts.upperlimit.used = 1;
- }
- | UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')'
- {
- if ($5 < 0 || $5 > INT_MAX) {
- yyerror("timing in curve out of range");
- YYERROR;
- }
- if (hfsc_opts.upperlimit.used) {
- yyerror("upperlimit already specified");
- YYERROR;
- }
- hfsc_opts.upperlimit.m1 = $3;
- hfsc_opts.upperlimit.d = $5;
- hfsc_opts.upperlimit.m2 = $7;
- hfsc_opts.upperlimit.used = 1;
- }
- | DEFAULT {
- hfsc_opts.flags |= HFCF_DEFAULTCLASS;
- }
- | STRING {
- if (!strcmp($1, "red"))
- hfsc_opts.flags |= HFCF_RED;
- else if (!strcmp($1, "ecn"))
- hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
- else {
- yyerror("unknown hfsc flag \"%s\"", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-
-qassign : /* empty */ { $$ = NULL; }
- | qassign_item { $$ = $1; }
- | '{' optnl qassign_list '}' { $$ = $3; }
- ;
-
-qassign_list : qassign_item optnl { $$ = $1; }
- | qassign_list comma qassign_item optnl {
- $1->tail->next = $3;
- $1->tail = $3;
- $$ = $1;
- }
- ;
-
-qassign_item : STRING {
- $$ = calloc(1, sizeof(struct node_queue));
- if ($$ == NULL)
- err(1, "qassign_item: calloc");
- if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
- sizeof($$->queue)) {
- yyerror("queue name '%s' too long (max "
- "%d chars)", $1, sizeof($$->queue)-1);
- free($1);
- free($$);
- YYERROR;
- }
- free($1);
- $$->next = NULL;
- $$->tail = $$;
- }
- ;
-
pfrule : action dir logquick interface af proto fromto
filter_opts
{
expand_label_nr("$nr", label, len);
}
-int
-expand_altq(struct pf_altq *a, struct node_if *interfaces,
- struct node_queue *nqueues, struct node_queue_bw bwspec,
- struct node_queue_opt *opts)
-{
- struct pf_altq pa, pb;
- char qname[PF_QNAME_SIZE];
- struct node_queue *n;
- struct node_queue_bw bw;
- int errs = 0;
-
- LOOP_THROUGH(struct node_if, interface, interfaces,
- memcpy(&pa, a, sizeof(struct pf_altq));
- if (strlcpy(pa.ifname, interface->ifname,
- sizeof(pa.ifname)) >= sizeof(pa.ifname))
- errx(1, "expand_altq: strlcpy");
-
- if (interface->not) {
- yyerror("altq on ! <interface> is not supported");
- errs++;
- } else if (interface->use_rdomain) {
- yyerror("altq on rdomain <num> is not supported");
- errs++;
- } else {
- if (eval_pfaltq(pf, &pa, &bwspec, opts))
- errs++;
- else
- if (pfctl_add_altq(pf, &pa))
- errs++;
-
- if (pf->opts & PF_OPT_VERBOSE) {
- print_altq(&pf->paltq->altq, 0,
- &bwspec, opts);
- if (nqueues && nqueues->tail) {
- printf("queue { ");
- LOOP_THROUGH(struct node_queue, queue,
- nqueues,
- printf("%s ",
- queue->queue);
- );
- printf("}");
- }
- printf("\n");
- }
-
- if (pa.scheduler == ALTQT_CBQ ||
- pa.scheduler == ALTQT_HFSC) {
- /* now create a root queue */
- memset(&pb, 0, sizeof(struct pf_altq));
- if (strlcpy(qname, "root_", sizeof(qname)) >=
- sizeof(qname))
- errx(1, "expand_altq: strlcpy");
- if (strlcat(qname, interface->ifname,
- sizeof(qname)) >= sizeof(qname))
- errx(1, "expand_altq: strlcat");
- if (strlcpy(pb.qname, qname,
- sizeof(pb.qname)) >= sizeof(pb.qname))
- errx(1, "expand_altq: strlcpy");
- if (strlcpy(pb.ifname, interface->ifname,
- sizeof(pb.ifname)) >= sizeof(pb.ifname))
- errx(1, "expand_altq: strlcpy");
- pb.qlimit = pa.qlimit;
- pb.scheduler = pa.scheduler;
- bw.bw_absolute = pa.ifbandwidth;
- bw.bw_percent = 0;
- if (eval_pfqueue(pf, &pb, &bw, opts))
- errs++;
- else
- if (pfctl_add_altq(pf, &pb))
- errs++;
- }
-
- LOOP_THROUGH(struct node_queue, queue, nqueues,
- n = calloc(1, sizeof(struct node_queue));
- if (n == NULL)
- err(1, "expand_altq: calloc");
- if (pa.scheduler == ALTQT_CBQ ||
- pa.scheduler == ALTQT_HFSC)
- if (strlcpy(n->parent, qname,
- sizeof(n->parent)) >=
- sizeof(n->parent))
- errx(1, "expand_altq: strlcpy");
- if (strlcpy(n->queue, queue->queue,
- sizeof(n->queue)) >= sizeof(n->queue))
- errx(1, "expand_altq: strlcpy");
- if (strlcpy(n->ifname, interface->ifname,
- sizeof(n->ifname)) >= sizeof(n->ifname))
- errx(1, "expand_altq: strlcpy");
- n->scheduler = pa.scheduler;
- n->next = NULL;
- n->tail = n;
- if (oqueues == NULL)
- oqueues = n;
- else {
- oqueues->tail->next = n;
- oqueues->tail = n;
- }
- );
- }
- );
- FREE_LIST(struct node_if, interfaces);
- FREE_LIST(struct node_queue, nqueues);
-
- return (errs);
-}
-
int
expand_queue(char *qname, struct node_if *interfaces, struct queue_opts *opts)
{
return (0);
}
-int
-expand_oldqueue(struct pf_altq *a, struct node_if *interfaces,
- struct node_queue *nqueues, struct node_queue_bw bwspec,
- struct node_queue_opt *opts)
-{
- struct node_queue *n, *nq;
- struct pf_altq pa;
- u_int8_t found = 0;
- u_int8_t errs = 0;
-
- if (oqueues == NULL) {
- yyerror("queue %s has no parent", a->qname);
- FREE_LIST(struct node_queue, nqueues);
- return (1);
- }
-
- LOOP_THROUGH(struct node_if, interface, interfaces,
- LOOP_THROUGH(struct node_queue, tqueue, oqueues,
- if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
- (interface->ifname[0] == 0 ||
- (!interface->not && !strncmp(interface->ifname,
- tqueue->ifname, IFNAMSIZ)) ||
- (interface->not && strncmp(interface->ifname,
- tqueue->ifname, IFNAMSIZ)))) {
- /* found ourself in queues */
- found++;
-
- memcpy(&pa, a, sizeof(struct pf_altq));
-
- if (pa.scheduler != ALTQT_NONE &&
- pa.scheduler != tqueue->scheduler) {
- yyerror("exactly one scheduler type "
- "per interface allowed");
- return (1);
- }
- pa.scheduler = tqueue->scheduler;
-
- /* scheduler dependent error checking */
- switch (pa.scheduler) {
- case ALTQT_PRIQ:
- if (nqueues != NULL) {
- yyerror("priq queues cannot "
- "have child queues");
- return (1);
- }
- if (bwspec.bw_absolute > 0 ||
- bwspec.bw_percent < 100) {
- yyerror("priq doesn't take "
- "bandwidth");
- return (1);
- }
- break;
- default:
- break;
- }
-
- if (strlcpy(pa.ifname, tqueue->ifname,
- sizeof(pa.ifname)) >= sizeof(pa.ifname))
- errx(1, "expand_queue: strlcpy");
- if (strlcpy(pa.parent, tqueue->parent,
- sizeof(pa.parent)) >= sizeof(pa.parent))
- errx(1, "expand_queue: strlcpy");
-
- if (eval_pfqueue(pf, &pa, &bwspec, opts))
- errs++;
- else
- if (pfctl_add_altq(pf, &pa))
- errs++;
-
- for (nq = nqueues; nq != NULL; nq = nq->next) {
- if (!strcmp(a->qname, nq->queue)) {
- yyerror("queue cannot have "
- "itself as child");
- errs++;
- continue;
- }
- n = calloc(1,
- sizeof(struct node_queue));
- if (n == NULL)
- err(1, "expand_queue: calloc");
- if (strlcpy(n->parent, a->qname,
- sizeof(n->parent)) >=
- sizeof(n->parent))
- errx(1, "expand_queue strlcpy");
- if (strlcpy(n->queue, nq->queue,
- sizeof(n->queue)) >=
- sizeof(n->queue))
- errx(1, "expand_queue strlcpy");
- if (strlcpy(n->ifname, tqueue->ifname,
- sizeof(n->ifname)) >=
- sizeof(n->ifname))
- errx(1, "expand_queue strlcpy");
- n->scheduler = tqueue->scheduler;
- n->next = NULL;
- n->tail = n;
- if (oqueues == NULL)
- oqueues = n;
- else {
- oqueues->tail->next = n;
- oqueues->tail = n;
- }
- }
- if ((pf->opts & PF_OPT_VERBOSE) && (
- (found == 1 && interface->ifname[0] == 0) ||
- (found > 0 && interface->ifname[0] != 0))) {
- print_queue(&pf->paltq->altq, 0,
- &bwspec, interface->ifname[0] != 0,
- opts);
- if (nqueues && nqueues->tail) {
- printf("{ ");
- LOOP_THROUGH(struct node_queue,
- queue, nqueues,
- printf("%s ",
- queue->queue);
- );
- printf("}");
- }
- printf("\n");
- }
- }
- );
- );
-
- FREE_LIST(struct node_queue, nqueues);
- FREE_LIST(struct node_if, interfaces);
-
- if (!found) {
- yyerror("queue %s has no parent", a->qname);
- errs++;
- }
-
- if (errs)
- return (1);
- else
- return (0);
-}
-
int
collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r,
struct redirspec *rs, u_int8_t allow_if)
{ "af-to", AFTO},
{ "all", ALL},
{ "allow-opts", ALLOWOPTS},
- { "altq", ALTQ},
{ "anchor", ANCHOR},
{ "antispoof", ANTISPOOF},
{ "any", ANY},
{ "block", BLOCK},
{ "block-policy", BLOCKPOLICY},
{ "burst", BURST},
- { "cbq", CBQ},
{ "code", CODE},
{ "debug", DEBUG},
{ "default", DEFAULT},
{ "from", FROM},
{ "global", GLOBAL},
{ "group", GROUP},
- { "hfsc", HFSC},
{ "hostid", HOSTID},
{ "icmp-type", ICMPTYPE},
{ "icmp6-type", ICMP6TYPE},
{ "label", LABEL},
{ "least-states", LEASTSTATES},
{ "limit", LIMIT},
- { "linkshare", LINKSHARE},
{ "load", LOAD},
{ "log", LOG},
{ "loginterface", LOGINTERFACE},
{ "no-df", NODF},
{ "no-route", NOROUTE},
{ "no-sync", NOSYNC},
- { "oldqueue", OLDQUEUE},
{ "on", ON},
{ "once", ONCE},
{ "optimization", OPTIMIZATION},
{ "pflow", PFLOW},
{ "port", PORT},
{ "prio", PRIO},
- { "priority", PRIORITY},
- { "priq", PRIQ},
{ "probability", PROBABILITY},
{ "proto", PROTO},
{ "qlimit", QLIMIT},
{ "random-id", RANDOMID},
{ "rdomain", RDOMAIN},
{ "rdr-to", RDRTO},
- { "realtime", REALTIME},
{ "reassemble", REASSEMBLE},
{ "received-on", RECEIVEDON},
{ "reply-to", REPLYTO},
{ "table", TABLE},
{ "tag", TAG},
{ "tagged", TAGGED},
- { "tbrsize", TBRSIZE},
{ "timeout", TIMEOUT},
{ "to", TO},
{ "tos", TOS},
{ "ttl", TTL},
- { "upperlimit", UPPERLIMIT},
{ "urpf-failed", URPFFAILED},
{ "user", USER},
{ "weight", WEIGHT},
-.\" $OpenBSD: pfctl.8,v 1.163 2013/07/21 17:22:49 jmc Exp $
+.\" $OpenBSD: pfctl.8,v 1.164 2014/04/19 14:22:32 henning Exp $
.\"
.\" Copyright (c) 2001 Kjell Wooding. All rights reserved.
.\"
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: July 21 2013 $
+.Dd $Mdocdate: April 19 2014 $
.Dt PFCTL 8
.Os
.Sh NAME
(may be abbreviated):
.Pp
.Bl -tag -width xxxxxxxxxxxx -compact
-.It Fl F Cm queue
-Flush the queue rules.
.It Fl F Cm rules
Flush the filter rules.
.It Fl F Cm states
.Pp
.Bl -tag -width xxxxxxxxxxxxxx -compact
.It Fl s Cm queue
-Show the currently loaded queue rules.
+Show the currently loaded queue definitions.
When used together with
.Fl v ,
per-queue statistics are also shown.
-/* $OpenBSD: pfctl.c,v 1.324 2014/04/11 02:56:41 jsg Exp $ */
+/* $OpenBSD: pfctl.c,v 1.325 2014/04/19 14:22:32 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
#include <netinet/in.h>
#include <net/pfvar.h>
#include <arpa/inet.h>
-#include <altq/altq.h>
#include <net/hfsc.h>
#include <sys/sysctl.h>
int pfctl_clear_stats(int, const char *, int);
int pfctl_clear_interface_flags(int, int);
int pfctl_clear_rules(int, int, char *);
-int pfctl_clear_altq(int, int);
int pfctl_clear_src_nodes(int, int);
int pfctl_clear_states(int, const char *, int);
void pfctl_addrprefix(char *, struct pf_addr *);
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, int);
void pfctl_debug(int, u_int32_t, int);
-int pfctl_test_altqsupport(int, int);
int pfctl_show_anchors(int, int, char *);
int pfctl_ruleset_trans(struct pfctl *, char *, struct pf_anchor *);
u_int pfctl_find_childqs(struct pfctl_qsitem *);
char *src_node_kill[2];
int state_killers;
char *state_kill[2];
-int loadaltq = 1;
-int altqsupport;
int dev = -1;
int first_title = 1;
};
static const char *clearopt_list[] = {
- "queue", "rules", "Sources",
- "states", "info", "Tables", "osfp", "all", NULL
+ "rules", "Sources", "states", "info", "Tables", "osfp", "all", NULL
};
static const char *showopt_list[] = {
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf enabled\n");
- if (altqsupport && ioctl(dev, DIOCSTARTALTQ))
- if (errno != EEXIST)
- err(1, "DIOCSTARTALTQ");
-
return (0);
}
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf disabled\n");
- if (altqsupport && ioctl(dev, DIOCSTOPALTQ))
- if (errno != ENOENT)
- err(1, "DIOCSTOPALTQ");
-
return (0);
}
return (0);
}
-int
-pfctl_clear_altq(int dev, int opts)
-{
- struct pfr_buffer t;
- if (!altqsupport)
- return (-1);
- memset(&t, 0, sizeof(t));
- t.pfrb_type = PFRB_TRANS;
- if (pfctl_add_trans(&t, PF_TRANS_ALTQ, "") ||
- pfctl_trans(dev, &t, DIOCXBEGIN, 0) ||
- pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
- err(1, "pfctl_clear_altq");
- if ((opts & PF_OPT_QUIET) == 0)
- fprintf(stderr, "altq cleared\n");
- return (0);
-}
-
int
pfctl_clear_src_nodes(int dev, int opts)
{
{
int osize = pf->trans->pfrb_size;
- if (a == pf->astack[0] && (altqsupport && loadaltq)) {
- if (pfctl_add_trans(pf->trans, PF_TRANS_ALTQ, path))
- return (2);
- }
if (pfctl_add_trans(pf->trans, PF_TRANS_RULESET, path))
return (3);
if (pfctl_add_trans(pf->trans, PF_TRANS_TABLE, path))
return (0);
}
-int
-pfctl_add_altq(struct pfctl *pf, struct pf_altq *a)
-{
- if (altqsupport) {
- memcpy(&pf->paltq->altq, a, sizeof(struct pf_altq));
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCADDALTQ, pf->paltq)) {
- if (errno == ENXIO)
- errx(1, "qtype not configured");
- else if (errno == ENODEV)
- errx(1, "%s: driver does not support "
- "altq", a->ifname);
- else
- err(1, "DIOCADDALTQ");
- }
- }
- pfaltq_store(&pf->paltq->altq);
- }
- return (0);
-}
-
int
pfctl_rules(int dev, char *filename, int opts, int optimize,
char *anchorname, struct pfr_buffer *trans)
#define ERRX(x) do { warnx(x); goto _error; } while(0)
struct pfr_buffer *t, buf;
- struct pfioc_altq pa;
struct pfctl pf;
struct pf_ruleset *rs;
struct pfr_table trs;
osize = t->pfrb_size;
}
- memset(&pa, 0, sizeof(pa));
memset(&pf, 0, sizeof(pf));
memset(&trs, 0, sizeof(trs));
if ((path = calloc(1, MAXPATHLEN)) == NULL)
pf.dev = dev;
pf.opts = opts;
pf.optimize = optimize;
- if (anchorname[0])
- loadaltq = 0;
/* non-brace anchor, create without resolving the path */
if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
pf.astack[0] = pf.anchor;
pf.asd = 0;
- pf.paltq = &pa;
pf.trans = t;
pfctl_init_options(&pf);
*/
if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor))
ERRX("pfctl_rules");
- if (altqsupport && loadaltq)
- pa.ticket =
- pfctl_get_ticket(t, PF_TRANS_ALTQ, anchorname);
pf.astack[0]->ruleset.tticket =
pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname);
}
free(path);
path = NULL;
- if (altqsupport && loadaltq && check_commit_altq(dev, opts) != 0)
- ERRX("errors in altq config");
-
/* process "load anchor" directives */
if (!anchorname[0])
if (pfctl_load_anchors(dev, &pf, t) == -1)
loglevel_to_string(level));
}
-int
-pfctl_test_altqsupport(int dev, int opts)
-{
- struct pfioc_altq pa;
-
- if (ioctl(dev, DIOCGETALTQS, &pa)) {
- if (errno == ENODEV) {
- if (!(opts & PF_OPT_QUIET))
- fprintf(stderr, "No ALTQ support in kernel\n"
- "ALTQ related functions disabled\n");
- return (0);
- } else
- err(1, "DIOCGETALTQS");
- }
- return (1);
-}
-
int
pfctl_show_anchors(int dev, int opts, char *anchorname)
{
dev = open(pf_device, mode);
if (dev == -1)
err(1, "%s", pf_device);
- altqsupport = pfctl_test_altqsupport(dev, opts);
} else {
dev = open(pf_device, O_RDONLY);
if (dev >= 0)
/* turn off options */
opts &= ~ (PF_OPT_DISABLE | PF_OPT_ENABLE);
clearopt = showopt = debugopt = NULL;
- altqsupport = 1;
}
if (opts & PF_OPT_DISABLE)
case 'q':
pfctl_show_queues(dev, ifaceopt, opts,
opts & PF_OPT_VERBOSE2);
- pfctl_show_altq(dev, ifaceopt, opts,
- opts & PF_OPT_VERBOSE2);
break;
case 's':
pfctl_show_states(dev, ifaceopt, opts);
pfctl_show_rules(dev, path, opts, 0, anchorname,
0, 0, -1);
- pfctl_show_altq(dev, ifaceopt, opts, 0);
pfctl_show_states(dev, ifaceopt, opts);
pfctl_show_src_nodes(dev, opts);
pfctl_show_status(dev, opts);
case 'r':
pfctl_clear_rules(dev, opts, anchorname);
break;
- case 'q':
- pfctl_clear_altq(dev, opts);
- break;
case 's':
pfctl_clear_states(dev, ifaceopt, opts);
break;
/* NOTREACHED */
}
if (!*anchorname) {
- pfctl_clear_altq(dev, opts);
pfctl_clear_states(dev, ifaceopt, opts);
pfctl_clear_src_nodes(dev, opts);
pfctl_clear_stats(dev, ifaceopt, opts);
-/* $OpenBSD: pfctl.h,v 1.51 2013/10/12 12:16:11 henning Exp $ */
+/* $OpenBSD: pfctl.h,v 1.52 2014/04/19 14:22:32 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
int pfctl_show_tables(const char *, int);
int pfctl_command_tables(int, char *[], char *, const char *, char *,
const char *, int);
-int pfctl_show_altq(int, const char *, int, int);
void warn_namespace_collision(const char *);
int pfctl_show_ifaces(const char *, int);
FILE *pfctl_fopen(const char *, const char *);
double x, y, d, m;
};
-int check_commit_altq(int, int);
-void pfaltq_store(struct pf_altq *);
-struct pf_altq *pfaltq_lookup(const char *);
-char *rate2str(double);
-
void print_addr(struct pf_addr_wrap *, sa_family_t, int);
void print_host(struct pf_addr *, u_int16_t p, sa_family_t, u_int16_t, const char *, int);
void print_seq(struct pfsync_state_peer *);
+++ /dev/null
-/* $OpenBSD: pfctl_altq.c,v 1.101 2014/01/19 04:14:34 claudio Exp $ */
-
-/*
- * Copyright (c) 2002
- * Sony Computer Science Laboratories Inc.
- * Copyright (c) 2002, 2003 Henning Brauer <henning@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.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 <altq/altq.h>
-#include <altq/altq_cbq.h>
-#include <altq/altq_priq.h>
-#include <altq/altq_hfsc.h>
-
-#include "pfctl_parser.h"
-#include "pfctl.h"
-
-#define is_sc_null(sc) (((sc) == NULL) || ((sc)->m1 == 0 && (sc)->m2 == 0))
-
-TAILQ_HEAD(altqs, pf_altq) altqs = TAILQ_HEAD_INITIALIZER(altqs);
-LIST_HEAD(gen_sc, segment) rtsc, lssc;
-
-struct pf_altq *qname_to_pfaltq(const char *, const char *);
-u_int32_t qname_to_qid(const char *);
-
-static int eval_pfqueue_cbq(struct pfctl *, struct pf_altq *);
-static int cbq_compute_idletime(struct pfctl *, struct pf_altq *);
-static int check_commit_cbq(int, int, struct pf_altq *);
-static int print_cbq_opts(const struct pf_altq *);
-
-static int eval_pfqueue_priq(struct pfctl *, struct pf_altq *);
-static int check_commit_priq(int, int, struct pf_altq *);
-static int print_priq_opts(const struct pf_altq *);
-
-static int eval_pfqueue_hfsc(struct pfctl *, struct pf_altq *);
-static int check_commit_hfsc(int, int, struct pf_altq *);
-static int print_hfsc_opts(const struct pf_altq *,
- const struct node_queue_opt *);
-
-static void gsc_add_sc(struct gen_sc *, struct service_curve *);
-static int is_gsc_under_sc(struct gen_sc *,
- struct service_curve *);
-static void gsc_destroy(struct gen_sc *);
-static struct segment *gsc_getentry(struct gen_sc *, double);
-static int gsc_add_seg(struct gen_sc *, double, double, double,
- double);
-static double sc_x2y(struct service_curve *, double);
-
-u_int32_t getifspeed(char *);
-u_long getifmtu(char *);
-int eval_queue_opts(struct pf_altq *, struct node_queue_opt *,
- u_int32_t);
-u_int32_t eval_bwspec(struct node_queue_bw *, u_int32_t);
-void print_hfsc_sc(const char *, u_int, u_int, u_int,
- const struct node_hfsc_sc *);
-
-void
-pfaltq_store(struct pf_altq *a)
-{
- struct pf_altq *altq;
-
- if ((altq = malloc(sizeof(*altq))) == NULL)
- err(1, "malloc");
- memcpy(altq, a, sizeof(struct pf_altq));
- TAILQ_INSERT_TAIL(&altqs, altq, entries);
-}
-
-struct pf_altq *
-pfaltq_lookup(const char *ifname)
-{
- struct pf_altq *altq;
-
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 &&
- altq->qname[0] == 0)
- return (altq);
- }
- return (NULL);
-}
-
-struct pf_altq *
-qname_to_pfaltq(const char *qname, const char *ifname)
-{
- struct pf_altq *altq;
-
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(ifname, altq->ifname, IFNAMSIZ) == 0 &&
- strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0)
- return (altq);
- }
- return (NULL);
-}
-
-u_int32_t
-qname_to_qid(const char *qname)
-{
- struct pf_altq *altq;
-
- /*
- * We guarantee that same named queues on different interfaces
- * have the same qid, so we do NOT need to limit matching on
- * one interface!
- */
-
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(qname, altq->qname, PF_QNAME_SIZE) == 0)
- return (altq->qid);
- }
- return (0);
-}
-
-void
-print_altq(const struct pf_altq *a, unsigned int level,
- struct node_queue_bw *bw, struct node_queue_opt *qopts)
-{
- if (a->qname[0] != 0) {
- print_queue(a, level, bw, 1, qopts);
- return;
- }
-
- printf("altq on %s ", a->ifname);
-
- switch (a->scheduler) {
- case ALTQT_CBQ:
- if (!print_cbq_opts(a))
- printf("cbq ");
- break;
- case ALTQT_PRIQ:
- if (!print_priq_opts(a))
- printf("priq ");
- break;
- case ALTQT_HFSC:
- if (!print_hfsc_opts(a, qopts))
- printf("hfsc ");
- break;
- }
-
- if (bw != NULL && bw->bw_percent > 0) {
- if (bw->bw_percent < 100)
- printf("bandwidth %u%% ", bw->bw_percent);
- } else
- printf("bandwidth %s ", rate2str((double)a->ifbandwidth));
-
- if (a->qlimit != DEFAULT_QLIMIT)
- printf("qlimit %u ", a->qlimit);
- printf("tbrsize %u ", a->tbrsize);
-}
-
-void
-print_queue(const struct pf_altq *a, unsigned int level,
- struct node_queue_bw *bw, int print_interface,
- struct node_queue_opt *qopts)
-{
- unsigned int i;
-
- printf("oldqueue ");
- for (i = 0; i < level; ++i)
- printf(" ");
- printf("%s ", a->qname);
- if (print_interface)
- printf("on %s ", a->ifname);
- if (a->scheduler == ALTQT_CBQ || a->scheduler == ALTQT_HFSC) {
- if (bw != NULL && bw->bw_percent > 0) {
- if (bw->bw_percent < 100)
- printf("bandwidth %u%% ", bw->bw_percent);
- } else
- printf("bandwidth %s ", rate2str((double)a->bandwidth));
- }
- if (a->priority != DEFAULT_PRIORITY)
- printf("priority %u ", a->priority);
- if (a->qlimit != DEFAULT_QLIMIT)
- printf("qlimit %u ", a->qlimit);
- switch (a->scheduler) {
- case ALTQT_CBQ:
- print_cbq_opts(a);
- break;
- case ALTQT_PRIQ:
- print_priq_opts(a);
- break;
- case ALTQT_HFSC:
- print_hfsc_opts(a, qopts);
- break;
- }
-}
-
-/*
- * eval_pfaltq computes the discipline parameters.
- */
-int
-eval_pfaltq(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
- struct node_queue_opt *opts)
-{
- u_int rate, size, errors = 0;
-
- if (bw->bw_absolute > 0)
- pa->ifbandwidth = bw->bw_absolute;
- else
- if ((rate = getifspeed(pa->ifname)) == 0) {
- fprintf(stderr, "interface %s does not know its bandwidth, "
- "please specify an absolute bandwidth\n",
- pa->ifname);
- errors++;
- } else if ((pa->ifbandwidth = eval_bwspec(bw, rate)) == 0)
- pa->ifbandwidth = rate;
-
- errors += eval_queue_opts(pa, opts, pa->ifbandwidth);
-
- /* if tbrsize is not specified, use heuristics */
- if (pa->tbrsize == 0) {
- rate = pa->ifbandwidth;
- if (rate <= 1 * 1000 * 1000)
- size = 1;
- else if (rate <= 10 * 1000 * 1000)
- size = 4;
- else if (rate <= 200 * 1000 * 1000)
- size = 8;
- else
- size = 24;
-
- if ((pf->opts & PF_OPT_NOACTION) == 0)
- size = size * getifmtu(pa->ifname);
- else
- size = size * 1500;
-
- if (size > 0xffff)
- size = 0xffff;
- pa->tbrsize = size;
- }
- return (errors);
-}
-
-/*
- * check_commit_altq does consistency check for each interface
- */
-int
-check_commit_altq(int dev, int opts)
-{
- struct pf_altq *altq;
- int error = 0;
-
- /* call the discipline check for each interface. */
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (altq->qname[0] == 0) {
- switch (altq->scheduler) {
- case ALTQT_CBQ:
- error = check_commit_cbq(dev, opts, altq);
- break;
- case ALTQT_PRIQ:
- error = check_commit_priq(dev, opts, altq);
- break;
- case ALTQT_HFSC:
- error = check_commit_hfsc(dev, opts, altq);
- break;
- default:
- break;
- }
- }
- }
- return (error);
-}
-
-/*
- * eval_pfqueue computes the queue parameters.
- */
-int
-eval_pfqueue(struct pfctl *pf, struct pf_altq *pa, struct node_queue_bw *bw,
- struct node_queue_opt *opts)
-{
- /* should be merged with expand_queue */
- struct pf_altq *if_pa, *parent, *altq;
- u_int32_t bwsum;
- int error = 0;
-
- /* find the corresponding interface and copy fields used by queues */
- if ((if_pa = pfaltq_lookup(pa->ifname)) == NULL) {
- fprintf(stderr, "altq not defined on %s\n", pa->ifname);
- return (1);
- }
- pa->scheduler = if_pa->scheduler;
- pa->ifbandwidth = if_pa->ifbandwidth;
-
- if (qname_to_pfaltq(pa->qname, pa->ifname) != NULL) {
- fprintf(stderr, "queue %s already exists on interface %s\n",
- pa->qname, pa->ifname);
- return (1);
- }
- pa->qid = qname_to_qid(pa->qname);
-
- parent = NULL;
- if (pa->parent[0] != 0) {
- parent = qname_to_pfaltq(pa->parent, pa->ifname);
- if (parent == NULL) {
- fprintf(stderr, "parent %s not found for %s\n",
- pa->parent, pa->qname);
- return (1);
- }
- pa->parent_qid = parent->qid;
- }
- if (pa->qlimit == 0)
- pa->qlimit = DEFAULT_QLIMIT;
-
- if (pa->scheduler == ALTQT_CBQ || pa->scheduler == ALTQT_HFSC) {
- pa->bandwidth = eval_bwspec(bw,
- parent == NULL ? 0 : parent->bandwidth);
-
- if (pa->bandwidth > pa->ifbandwidth) {
- fprintf(stderr, "bandwidth for %s higher than "
- "interface\n", pa->qname);
- return (1);
- }
- /* check the sum of the child bandwidth is under parent's */
- if (parent != NULL) {
- if (pa->bandwidth > parent->bandwidth) {
- warnx("bandwidth for %s higher than parent",
- pa->qname);
- return (1);
- }
- bwsum = 0;
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname,
- IFNAMSIZ) == 0 &&
- altq->qname[0] != 0 &&
- strncmp(altq->parent, pa->parent,
- PF_QNAME_SIZE) == 0)
- bwsum += altq->bandwidth;
- }
- bwsum += pa->bandwidth;
- if (bwsum > parent->bandwidth) {
- warnx("the sum of the child bandwidth higher"
- " than parent \"%s\"", parent->qname);
- }
- }
- }
-
- if (eval_queue_opts(pa, opts, parent == NULL? 0 : parent->bandwidth))
- return (1);
-
- switch (pa->scheduler) {
- case ALTQT_CBQ:
- error = eval_pfqueue_cbq(pf, pa);
- break;
- case ALTQT_PRIQ:
- error = eval_pfqueue_priq(pf, pa);
- break;
- case ALTQT_HFSC:
- error = eval_pfqueue_hfsc(pf, pa);
- break;
- default:
- break;
- }
- return (error);
-}
-
-/*
- * CBQ support functions
- */
-#define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */
-#define RM_NS_PER_SEC (1000000000)
-
-static int
-eval_pfqueue_cbq(struct pfctl *pf, struct pf_altq *pa)
-{
- struct cbq_opts *opts;
- u_int ifmtu;
-
- if (pa->priority >= CBQ_MAXPRI) {
- warnx("priority out of range: max %d", CBQ_MAXPRI - 1);
- return (-1);
- }
-
- if ((pf->opts & PF_OPT_NOACTION) == 0)
- ifmtu = getifmtu(pa->ifname);
- else
- ifmtu = 1500;
-
- opts = &pa->pq_u.cbq_opts;
-
- if (opts->pktsize == 0) { /* use default */
- opts->pktsize = ifmtu;
- if (opts->pktsize > 2048) /* do what TCP does */
- opts->pktsize &= ~2048;
- } else if (opts->pktsize > ifmtu)
- opts->pktsize = ifmtu;
- if (opts->maxpktsize == 0) /* use default */
- opts->maxpktsize = ifmtu;
- else if (opts->maxpktsize > ifmtu)
- opts->pktsize = ifmtu;
-
- if (opts->pktsize > opts->maxpktsize)
- opts->pktsize = opts->maxpktsize;
-
- if (pa->parent[0] == 0)
- opts->flags |= (CBQCLF_ROOTCLASS | CBQCLF_WRR);
-
- cbq_compute_idletime(pf, pa);
- return (0);
-}
-
-/*
- * compute ns_per_byte, maxidle, minidle, and offtime
- */
-static int
-cbq_compute_idletime(struct pfctl *pf, struct pf_altq *pa)
-{
- struct cbq_opts *opts;
- double maxidle_s, maxidle, minidle;
- double offtime, nsPerByte, ifnsPerByte, ptime, cptime;
- double z, g, f, gton, gtom;
- u_int minburst, maxburst;
-
- opts = &pa->pq_u.cbq_opts;
- ifnsPerByte = (1.0 / (double)pa->ifbandwidth) * RM_NS_PER_SEC * 8;
- minburst = opts->minburst;
- maxburst = opts->maxburst;
-
- if (pa->bandwidth == 0)
- f = 0.0001; /* small enough? */
- else
- f = ((double) pa->bandwidth / (double) pa->ifbandwidth);
-
- nsPerByte = ifnsPerByte / f;
- ptime = (double)opts->pktsize * ifnsPerByte;
- cptime = ptime * (1.0 - f) / f;
-
- if (nsPerByte * (double)opts->maxpktsize > (double)INT_MAX) {
- /*
- * this causes integer overflow in kernel!
- * (bandwidth < 6Kbps when max_pkt_size=1500)
- */
- if (pa->bandwidth != 0 && (pf->opts & PF_OPT_QUIET) == 0)
- warnx("queue bandwidth must be larger than %s",
- rate2str(ifnsPerByte * (double)opts->maxpktsize /
- (double)INT_MAX * (double)pa->ifbandwidth));
- fprintf(stderr, "cbq: queue %s is too slow!\n", pa->qname);
- nsPerByte = (double)(INT_MAX / opts->maxpktsize);
- }
-
- if (maxburst == 0) { /* use default */
- if (cptime > 10.0 * 1000000)
- maxburst = 4;
- else
- maxburst = 16;
- }
- if (minburst == 0) /* use default */
- minburst = 2;
- if (minburst > maxburst)
- minburst = maxburst;
-
- z = (double)(1 << RM_FILTER_GAIN);
- g = (1.0 - 1.0 / z);
- gton = pow(g, (double)maxburst);
- gtom = pow(g, (double)(minburst-1));
- maxidle = ((1.0 / f - 1.0) * ((1.0 - gton) / gton));
- maxidle_s = (1.0 - g);
- if (maxidle > maxidle_s)
- maxidle = ptime * maxidle;
- else
- maxidle = ptime * maxidle_s;
- offtime = cptime * (1.0 + 1.0/(1.0 - g) * (1.0 - gtom) / gtom);
- minidle = -((double)opts->maxpktsize * (double)nsPerByte);
-
- /* scale parameters */
- maxidle = ((maxidle * 8.0) / nsPerByte) *
- pow(2.0, (double)RM_FILTER_GAIN);
- offtime = (offtime * 8.0) / nsPerByte *
- pow(2.0, (double)RM_FILTER_GAIN);
- minidle = ((minidle * 8.0) / nsPerByte) *
- pow(2.0, (double)RM_FILTER_GAIN);
-
- maxidle = maxidle / 1000.0;
- offtime = offtime / 1000.0;
- minidle = minidle / 1000.0;
-
- opts->minburst = minburst;
- opts->maxburst = maxburst;
- opts->ns_per_byte = (u_int)nsPerByte;
- opts->maxidle = (u_int)fabs(maxidle);
- opts->minidle = (int)minidle;
- opts->offtime = (u_int)fabs(offtime);
-
- return (0);
-}
-
-static int
-check_commit_cbq(int dev, int opts, struct pf_altq *pa)
-{
- struct pf_altq *altq;
- int root_class, default_class;
- int error = 0;
-
- /*
- * check if cbq has one root queue and one default queue
- * for this interface
- */
- root_class = default_class = 0;
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0)
- continue;
- if (altq->qname[0] == 0) /* this is for interface */
- continue;
- if (altq->pq_u.cbq_opts.flags & CBQCLF_ROOTCLASS)
- root_class++;
- if (altq->pq_u.cbq_opts.flags & CBQCLF_DEFCLASS)
- default_class++;
- }
- if (root_class != 1) {
- warnx("should have one root queue on %s", pa->ifname);
- error++;
- }
- if (default_class != 1) {
- warnx("should have one default queue on %s", pa->ifname);
- error++;
- }
- return (error);
-}
-
-static int
-print_cbq_opts(const struct pf_altq *a)
-{
- const struct cbq_opts *opts;
-
- opts = &a->pq_u.cbq_opts;
- if (opts->flags) {
- printf("cbq(");
- if (opts->flags & CBQCLF_RED)
- printf(" red");
- if (opts->flags & CBQCLF_ECN)
- printf(" ecn");
- if (opts->flags & CBQCLF_BORROW)
- printf(" borrow");
- if (opts->flags & CBQCLF_WRR)
- printf(" wrr");
- if (opts->flags & CBQCLF_ROOTCLASS)
- printf(" root");
- if (opts->flags & CBQCLF_DEFCLASS)
- printf(" default");
- printf(" ) ");
-
- return (1);
- } else
- return (0);
-}
-
-/*
- * PRIQ support functions
- */
-static int
-eval_pfqueue_priq(struct pfctl *pf, struct pf_altq *pa)
-{
- struct pf_altq *altq;
-
- if (pa->priority >= PRIQ_MAXPRI) {
- warnx("priority out of range: max %d", PRIQ_MAXPRI - 1);
- return (-1);
- }
- /* the priority should be unique for the interface */
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) == 0 &&
- altq->qname[0] != 0 && altq->priority == pa->priority) {
- warnx("%s and %s have the same priority",
- altq->qname, pa->qname);
- return (-1);
- }
- }
-
- return (0);
-}
-
-static int
-check_commit_priq(int dev, int opts, struct pf_altq *pa)
-{
- struct pf_altq *altq;
- int default_class;
- int error = 0;
-
- /*
- * check if priq has one default class for this interface
- */
- default_class = 0;
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0)
- continue;
- if (altq->qname[0] == 0) /* this is for interface */
- continue;
- if (altq->pq_u.priq_opts.flags & PRCF_DEFAULTCLASS)
- default_class++;
- }
- if (default_class != 1) {
- warnx("should have one default queue on %s", pa->ifname);
- error++;
- }
- return (error);
-}
-
-static int
-print_priq_opts(const struct pf_altq *a)
-{
- const struct priq_opts *opts;
-
- opts = &a->pq_u.priq_opts;
-
- if (opts->flags) {
- printf("priq(");
- if (opts->flags & PRCF_RED)
- printf(" red");
- if (opts->flags & PRCF_ECN)
- printf(" ecn");
- if (opts->flags & PRCF_DEFAULTCLASS)
- printf(" default");
- printf(" ) ");
-
- return (1);
- } else
- return (0);
-}
-
-/*
- * HFSC support functions
- */
-static int
-eval_pfqueue_hfsc(struct pfctl *pf, struct pf_altq *pa)
-{
- struct pf_altq *altq, *parent;
- struct hfsc_opts *opts;
- struct service_curve sc;
-
- opts = &pa->pq_u.hfsc_opts;
-
- if (pa->parent[0] == 0) {
- /* root queue */
- opts->lssc_m1 = pa->ifbandwidth;
- opts->lssc_m2 = pa->ifbandwidth;
- opts->lssc_d = 0;
- return (0);
- }
-
- LIST_INIT(&rtsc);
- LIST_INIT(&lssc);
-
- /* if link_share is not specified, use bandwidth */
- if (opts->lssc_m2 == 0)
- opts->lssc_m2 = pa->bandwidth;
-
- if ((opts->rtsc_m1 > 0 && opts->rtsc_m2 == 0) ||
- (opts->lssc_m1 > 0 && opts->lssc_m2 == 0) ||
- (opts->ulsc_m1 > 0 && opts->ulsc_m2 == 0)) {
- warnx("m2 is zero for %s", pa->qname);
- 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
- * should not exceed 80% of the interface bandwidth. 20% is reserved
- * not to over-commit the actual interface bandwidth.
- * for the linkshare service curve, the sum of the child service
- * curve should not exceed the parent service curve.
- * for the upper-limit service curve, the assigned bandwidth should
- * be smaller than the interface bandwidth, and the upper-limit should
- * be larger than the real-time service curve when both are defined.
- */
- parent = qname_to_pfaltq(pa->parent, pa->ifname);
- if (parent == NULL)
- errx(1, "parent %s not found for %s", pa->parent, pa->qname);
-
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0)
- continue;
- if (altq->qname[0] == 0) /* this is for interface */
- continue;
-
- /* if the class has a real-time service curve, add it. */
- if (opts->rtsc_m2 != 0 && altq->pq_u.hfsc_opts.rtsc_m2 != 0) {
- sc.m1 = altq->pq_u.hfsc_opts.rtsc_m1;
- sc.d = altq->pq_u.hfsc_opts.rtsc_d;
- sc.m2 = altq->pq_u.hfsc_opts.rtsc_m2;
- gsc_add_sc(&rtsc, &sc);
- }
-
- if (strncmp(altq->parent, pa->parent, PF_QNAME_SIZE) != 0)
- continue;
-
- /* if the class has a linkshare service curve, add it. */
- if (opts->lssc_m2 != 0 && altq->pq_u.hfsc_opts.lssc_m2 != 0) {
- sc.m1 = altq->pq_u.hfsc_opts.lssc_m1;
- sc.d = altq->pq_u.hfsc_opts.lssc_d;
- sc.m2 = altq->pq_u.hfsc_opts.lssc_m2;
- gsc_add_sc(&lssc, &sc);
- }
- }
-
- /* check the real-time service curve. reserve 20% of interface bw */
- if (opts->rtsc_m2 != 0) {
- /* add this queue to the sum */
- sc.m1 = opts->rtsc_m1;
- sc.d = opts->rtsc_d;
- sc.m2 = opts->rtsc_m2;
- gsc_add_sc(&rtsc, &sc);
- /* compare the sum with 80% of the interface */
- sc.m1 = 0;
- sc.d = 0;
- sc.m2 = pa->ifbandwidth / 100 * 80;
- if (!is_gsc_under_sc(&rtsc, &sc)) {
- warnx("real-time sc exceeds 80%% of the interface "
- "bandwidth (%s)", rate2str((double)sc.m2));
- goto err_ret;
- }
- }
-
- /* check the linkshare service curve. */
- if (opts->lssc_m2 != 0) {
- /* add this queue to the child sum */
- sc.m1 = opts->lssc_m1;
- sc.d = opts->lssc_d;
- sc.m2 = opts->lssc_m2;
- gsc_add_sc(&lssc, &sc);
- /* compare the sum of the children with parent's sc */
- sc.m1 = parent->pq_u.hfsc_opts.lssc_m1;
- sc.d = parent->pq_u.hfsc_opts.lssc_d;
- sc.m2 = parent->pq_u.hfsc_opts.lssc_m2;
- if (!is_gsc_under_sc(&lssc, &sc)) {
- warnx("linkshare sc exceeds parent's sc");
- goto err_ret;
- }
- }
-
- /* check the upper-limit service curve. */
- if (opts->ulsc_m2 != 0) {
- if (opts->ulsc_m1 > pa->ifbandwidth ||
- opts->ulsc_m2 > pa->ifbandwidth) {
- warnx("upper-limit larger than interface bandwidth");
- goto err_ret;
- }
- if (opts->rtsc_m2 != 0 && opts->rtsc_m2 > opts->ulsc_m2) {
- warnx("upper-limit sc smaller than real-time sc");
- goto err_ret;
- }
- }
-
- gsc_destroy(&rtsc);
- gsc_destroy(&lssc);
-
- return (0);
-
-err_ret:
- gsc_destroy(&rtsc);
- gsc_destroy(&lssc);
- return (-1);
-}
-
-static int
-check_commit_hfsc(int dev, int opts, struct pf_altq *pa)
-{
- struct pf_altq *altq, *def = NULL;
- int default_class;
- int error = 0;
-
- /* check if hfsc has one default queue for this interface */
- default_class = 0;
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0)
- continue;
- if (altq->qname[0] == 0) /* this is for interface */
- continue;
- if (altq->parent[0] == 0) /* dummy root */
- continue;
- if (altq->pq_u.hfsc_opts.flags & HFCF_DEFAULTCLASS) {
- default_class++;
- def = altq;
- }
- }
- if (default_class != 1) {
- warnx("should have one default queue on %s", pa->ifname);
- return (1);
- }
- /* make sure the default queue is a leaf */
- TAILQ_FOREACH(altq, &altqs, entries) {
- if (strncmp(altq->ifname, pa->ifname, IFNAMSIZ) != 0)
- continue;
- if (altq->qname[0] == 0) /* this is for interface */
- continue;
- if (strncmp(altq->parent, def->qname, PF_QNAME_SIZE) == 0) {
- warnx("default queue is not a leaf");
- error++;
- }
- }
- return (error);
-}
-
-static int
-print_hfsc_opts(const struct pf_altq *a, const struct node_queue_opt *qopts)
-{
- const struct hfsc_opts *opts;
- const struct node_hfsc_sc *rtsc, *lssc, *ulsc;
-
- opts = &a->pq_u.hfsc_opts;
- if (qopts == NULL)
- rtsc = lssc = ulsc = NULL;
- else {
- rtsc = &qopts->data.hfsc_opts.realtime;
- lssc = &qopts->data.hfsc_opts.linkshare;
- ulsc = &qopts->data.hfsc_opts.upperlimit;
- }
-
- if (opts->flags || opts->rtsc_m2 != 0 || opts->ulsc_m2 != 0 ||
- (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth ||
- opts->lssc_d != 0))) {
- printf("hfsc(");
- if (opts->flags & HFCF_RED)
- printf(" red");
- if (opts->flags & HFCF_ECN)
- printf(" ecn");
- if (opts->flags & HFCF_DEFAULTCLASS)
- printf(" default");
- if (opts->rtsc_m2 != 0)
- print_hfsc_sc("realtime", opts->rtsc_m1, opts->rtsc_d,
- opts->rtsc_m2, rtsc);
- if (opts->lssc_m2 != 0 && (opts->lssc_m2 != a->bandwidth ||
- opts->lssc_d != 0))
- print_hfsc_sc("linkshare", opts->lssc_m1, opts->lssc_d,
- opts->lssc_m2, lssc);
- if (opts->ulsc_m2 != 0)
- print_hfsc_sc("upperlimit", opts->ulsc_m1, opts->ulsc_d,
- opts->ulsc_m2, ulsc);
- printf(" ) ");
-
- return (1);
- } else
- return (0);
-}
-
-/*
- * admission control using generalized service curve
- */
-
-/* add a new service curve to a generalized service curve */
-static void
-gsc_add_sc(struct gen_sc *gsc, struct service_curve *sc)
-{
- if (is_sc_null(sc))
- return;
- if (sc->d != 0)
- gsc_add_seg(gsc, 0.0, 0.0, (double)sc->d, (double)sc->m1);
- gsc_add_seg(gsc, (double)sc->d, 0.0, INFINITY, (double)sc->m2);
-}
-
-/*
- * check whether all points of a generalized service curve have
- * their y-coordinates no larger than a given two-piece linear
- * service curve.
- */
-static int
-is_gsc_under_sc(struct gen_sc *gsc, struct service_curve *sc)
-{
- struct segment *s, *last, *end;
- double y;
-
- if (is_sc_null(sc)) {
- if (LIST_EMPTY(gsc))
- return (1);
- LIST_FOREACH(s, gsc, _next) {
- if (s->m != 0)
- return (0);
- }
- return (1);
- }
- /*
- * gsc has a dummy entry at the end with x = INFINITY.
- * loop through up to this dummy entry.
- */
- end = gsc_getentry(gsc, INFINITY);
- if (end == NULL)
- return (1);
- last = NULL;
- for (s = LIST_FIRST(gsc); s != end; s = LIST_NEXT(s, _next)) {
- if (s->y > sc_x2y(sc, s->x))
- return (0);
- last = s;
- }
- /* last now holds the real last segment */
- if (last == NULL)
- return (1);
- if (last->m > sc->m2)
- return (0);
- if (last->x < sc->d && last->m > sc->m1) {
- y = last->y + (sc->d - last->x) * last->m;
- if (y > sc_x2y(sc, sc->d))
- return (0);
- }
- return (1);
-}
-
-static void
-gsc_destroy(struct gen_sc *gsc)
-{
- struct segment *s;
-
- while ((s = LIST_FIRST(gsc)) != NULL) {
- LIST_REMOVE(s, _next);
- free(s);
- }
-}
-
-/*
- * return a segment entry starting at x.
- * if gsc has no entry starting at x, a new entry is created at x.
- */
-static struct segment *
-gsc_getentry(struct gen_sc *gsc, double x)
-{
- struct segment *new, *prev, *s;
-
- prev = NULL;
- LIST_FOREACH(s, gsc, _next) {
- if (s->x == x)
- return (s); /* matching entry found */
- else if (s->x < x)
- prev = s;
- else
- break;
- }
-
- /* we have to create a new entry */
- if ((new = calloc(1, sizeof(struct segment))) == NULL)
- return (NULL);
-
- new->x = x;
- if (x == INFINITY || s == NULL)
- new->d = 0;
- else if (s->x == INFINITY)
- new->d = INFINITY;
- else
- new->d = s->x - x;
- if (prev == NULL) {
- /* insert the new entry at the head of the list */
- new->y = 0;
- new->m = 0;
- LIST_INSERT_HEAD(gsc, new, _next);
- } else {
- /*
- * the start point intersects with the segment pointed by
- * prev. divide prev into 2 segments
- */
- if (x == INFINITY) {
- prev->d = INFINITY;
- if (prev->m == 0)
- new->y = prev->y;
- else
- new->y = INFINITY;
- } else {
- prev->d = x - prev->x;
- new->y = prev->d * prev->m + prev->y;
- }
- new->m = prev->m;
- LIST_INSERT_AFTER(prev, new, _next);
- }
- return (new);
-}
-
-/* add a segment to a generalized service curve */
-static int
-gsc_add_seg(struct gen_sc *gsc, double x, double y, double d, double m)
-{
- struct segment *start, *end, *s;
- double x2;
-
- if (d == INFINITY)
- x2 = INFINITY;
- else
- x2 = x + d;
- start = gsc_getentry(gsc, x);
- end = gsc_getentry(gsc, x2);
- if (start == NULL || end == NULL)
- return (-1);
-
- for (s = start; s != end; s = LIST_NEXT(s, _next)) {
- s->m += m;
- s->y += y + (s->x - x) * m;
- }
-
- end = gsc_getentry(gsc, INFINITY);
- for (; s != end; s = LIST_NEXT(s, _next)) {
- s->y += m * d;
- }
-
- return (0);
-}
-
-/* get y-projection of a service curve */
-static double
-sc_x2y(struct service_curve *sc, double x)
-{
- double y;
-
- if (x <= (double)sc->d)
- /* y belongs to the 1st segment */
- y = x * (double)sc->m1;
- else
- /* y belongs to the 2nd segment */
- y = (double)sc->d * (double)sc->m1
- + (x - (double)sc->d) * (double)sc->m2;
- return (y);
-}
-
-/*
- * misc utilities
- */
-#define R2S_BUFS 8
-#define RATESTR_MAX 16
-
-char *
-rate2str(double rate)
-{
- char *buf;
- static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */
- static int idx = 0;
- int i;
- static const char unit[] = " KMG";
-
- buf = r2sbuf[idx++];
- if (idx == R2S_BUFS)
- idx = 0;
-
- for (i = 0; rate >= 1000 && i <= 3; i++)
- rate /= 1000;
-
- if ((int)(rate * 100) % 100)
- snprintf(buf, RATESTR_MAX, "%.2f%cb", rate, unit[i]);
- else
- snprintf(buf, RATESTR_MAX, "%d%cb", (int)rate, unit[i]);
-
- return (buf);
-}
-
-u_int32_t
-getifspeed(char *ifname)
-{
- int s;
- struct ifreq ifr;
- struct if_data ifrdat;
-
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- err(1, "socket");
- bzero(&ifr, sizeof(ifr));
- if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
- sizeof(ifr.ifr_name))
- errx(1, "getifspeed: strlcpy");
- ifr.ifr_data = (caddr_t)&ifrdat;
- if (ioctl(s, SIOCGIFDATA, (caddr_t)&ifr) == -1)
- err(1, "SIOCGIFDATA");
- if (close(s))
- err(1, "close");
- return ((u_int32_t)ifrdat.ifi_baudrate);
-}
-
-u_long
-getifmtu(char *ifname)
-{
- int s;
- struct ifreq ifr;
-
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- err(1, "socket");
- bzero(&ifr, sizeof(ifr));
- if (strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)) >=
- sizeof(ifr.ifr_name))
- errx(1, "getifmtu: strlcpy");
- if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == -1)
- err(1, "SIOCGIFMTU");
- if (close(s))
- err(1, "close");
- if (ifr.ifr_mtu > 0)
- return (ifr.ifr_mtu);
- else {
- warnx("could not get mtu for %s, assuming 1500", ifname);
- return (1500);
- }
-}
-
-int
-eval_queue_opts(struct pf_altq *pa, struct node_queue_opt *opts,
- u_int32_t ref_bw)
-{
- int errors = 0;
-
- switch (pa->scheduler) {
- case ALTQT_CBQ:
- pa->pq_u.cbq_opts = opts->data.cbq_opts;
- break;
- case ALTQT_PRIQ:
- pa->pq_u.priq_opts = opts->data.priq_opts;
- break;
- case ALTQT_HFSC:
- pa->pq_u.hfsc_opts.flags = opts->data.hfsc_opts.flags;
- if (opts->data.hfsc_opts.linkshare.used) {
- pa->pq_u.hfsc_opts.lssc_m1 =
- eval_bwspec(&opts->data.hfsc_opts.linkshare.m1,
- ref_bw);
- pa->pq_u.hfsc_opts.lssc_m2 =
- eval_bwspec(&opts->data.hfsc_opts.linkshare.m2,
- ref_bw);
- pa->pq_u.hfsc_opts.lssc_d =
- opts->data.hfsc_opts.linkshare.d;
- }
- if (opts->data.hfsc_opts.realtime.used) {
- pa->pq_u.hfsc_opts.rtsc_m1 =
- eval_bwspec(&opts->data.hfsc_opts.realtime.m1,
- ref_bw);
- pa->pq_u.hfsc_opts.rtsc_m2 =
- eval_bwspec(&opts->data.hfsc_opts.realtime.m2,
- ref_bw);
- pa->pq_u.hfsc_opts.rtsc_d =
- opts->data.hfsc_opts.realtime.d;
- }
- if (opts->data.hfsc_opts.upperlimit.used) {
- pa->pq_u.hfsc_opts.ulsc_m1 =
- eval_bwspec(&opts->data.hfsc_opts.upperlimit.m1,
- ref_bw);
- pa->pq_u.hfsc_opts.ulsc_m2 =
- eval_bwspec(&opts->data.hfsc_opts.upperlimit.m2,
- ref_bw);
- pa->pq_u.hfsc_opts.ulsc_d =
- opts->data.hfsc_opts.upperlimit.d;
- }
- break;
- default:
- warnx("eval_queue_opts: unknown scheduler type %u",
- opts->qtype);
- errors++;
- break;
- }
-
- return (errors);
-}
-
-u_int32_t
-eval_bwspec(struct node_queue_bw *bw, u_int32_t ref_bw)
-{
- if (bw->bw_absolute > 0)
- return (bw->bw_absolute);
-
- if (bw->bw_percent > 0)
- return (ref_bw / 100 * bw->bw_percent);
-
- return (0);
-}
-
-void
-print_hfsc_sc(const char *scname, u_int m1, u_int d, u_int m2,
- const struct node_hfsc_sc *sc)
-{
- printf(" %s", scname);
-
- if (d != 0) {
- printf("(");
- if (sc != NULL && sc->m1.bw_percent > 0)
- printf("%u%%", sc->m1.bw_percent);
- else
- printf("%s", rate2str((double)m1));
- printf(" %u", d);
- }
-
- if (sc != NULL && sc->m2.bw_percent > 0)
- printf(" %u%%", sc->m2.bw_percent);
- else
- printf(" %s", rate2str((double)m2));
-
- if (d != 0)
- printf(")");
-}
-/* $OpenBSD: pfctl_parser.h,v 1.101 2013/10/12 12:16:12 henning Exp $ */
+/* $OpenBSD: pfctl_parser.h,v 1.102 2014/04/19 14:22:32 henning Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
int tdirty; /* kernel dirty */
#define PFCTL_ANCHOR_STACK_DEPTH 64
struct pf_anchor *astack[PFCTL_ANCHOR_STACK_DEPTH];
- struct pfioc_altq *paltq;
struct pfioc_queue *pqueue;
struct pfr_buffer *trans;
struct pf_anchor *anchor, *alast;
struct pf_rule_addr *, char *);
int pfctl_add_rule(struct pfctl *, struct pf_rule *, const char *);
-int pfctl_add_altq(struct pfctl *, struct pf_altq *);
int pfctl_add_pool(struct pfctl *, struct pf_pool *, sa_family_t, int);
void pfctl_move_pool(struct pf_pool *, struct pf_pool *);
void pfctl_clear_pool(struct pf_pool *);
void print_status(struct pf_status *, int);
void print_queuespec(struct pf_queuespec *);
-int eval_pfaltq(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
- struct node_queue_opt *);
-int eval_pfqueue(struct pfctl *, struct pf_altq *, struct node_queue_bw *,
- struct node_queue_opt *);
-
-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 *,
- int, struct node_queue_opt *);
-
int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *,
u_int32_t);
char *pfctl_lookup_fingerprint(pf_osfp_t, char *, size_t);
void pfctl_show_fingerprints(int);
-
struct icmptypeent {
const char *name;
u_int8_t type;
+++ /dev/null
-/* $OpenBSD: pfctl_qstats.c,v 1.33 2013/10/12 12:16:12 henning Exp $ */
-
-/*
- * Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <net/pfvar.h>
-#include <arpa/inet.h>
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <altq/altq.h>
-#include <altq/altq_cbq.h>
-#include <altq/altq_priq.h>
-#include <altq/altq_hfsc.h>
-
-#include "pfctl.h"
-#include "pfctl_parser.h"
-
-union class_stats {
- class_stats_t cbq_stats;
- struct priq_classstats priq_stats;
- struct hfsc_classstats hfsc_stats;
-};
-
-#define AVGN_MAX 8
-#define STAT_INTERVAL 5
-
-struct queue_stats {
- union class_stats data;
- int avgn;
- double avg_bytes;
- double avg_packets;
- u_int64_t prev_bytes;
- u_int64_t prev_packets;
-};
-
-struct pf_altq_node {
- struct pf_altq altq;
- struct pf_altq_node *next;
- struct pf_altq_node *children;
- struct queue_stats qstats;
-};
-
-int pfctl_update_altqstats(int, struct pf_altq_node **);
-void pfctl_insert_altq_node(struct pf_altq_node **,
- const struct pf_altq, const struct queue_stats);
-struct pf_altq_node *pfctl_find_altq_node(struct pf_altq_node *,
- const char *, const char *);
-void pfctl_print_altq_node(int, const struct pf_altq_node *,
- unsigned, int);
-void print_cbqstats(struct queue_stats);
-void print_priqstats(struct queue_stats);
-void print_hfscstats(struct queue_stats);
-void pfctl_free_altq_node(struct pf_altq_node *);
-void pfctl_print_altq_nodestat(int,
- const struct pf_altq_node *);
-
-void altq_update_avg(struct pf_altq_node *);
-
-int
-pfctl_show_altq(int dev, const char *iface, int opts, int verbose2)
-{
- struct pf_altq_node *root = NULL, *node;
- int nodes, dotitle = (opts & PF_OPT_SHOWALL);
-
-
- if ((nodes = pfctl_update_altqstats(dev, &root)) < 0)
- return (-1);
-
- if (nodes == 0)
- printf("No altq queue in use\n");
- for (node = root; node != NULL; node = node->next) {
- if (iface != NULL && strcmp(node->altq.ifname, iface))
- continue;
- if (dotitle) {
- pfctl_print_title("ALTQ:");
- dotitle = 0;
- }
- pfctl_print_altq_node(dev, node, 0, opts);
- }
-
- while (verbose2 && nodes > 0) {
- printf("\n");
- fflush(stdout);
- sleep(STAT_INTERVAL);
- if ((nodes = pfctl_update_altqstats(dev, &root)) == -1)
- return (-1);
- for (node = root; node != NULL; node = node->next) {
- if (iface != NULL && strcmp(node->altq.ifname, iface))
- continue;
- pfctl_print_altq_node(dev, node, 0, opts);
- }
- }
- pfctl_free_altq_node(root);
- return (0);
-}
-
-int
-pfctl_update_altqstats(int dev, struct pf_altq_node **root)
-{
- struct pf_altq_node *node;
- struct pfioc_altq pa;
- struct pfioc_altqstats pq;
- u_int32_t mnr, nr;
- struct queue_stats qstats;
- static u_int32_t last_ticket;
-
- memset(&pa, 0, sizeof(pa));
- memset(&pq, 0, sizeof(pq));
- memset(&qstats, 0, sizeof(qstats));
- if (ioctl(dev, DIOCGETALTQS, &pa)) {
- warn("DIOCGETALTQS");
- return (-1);
- }
-
- /* if a new set is found, start over */
- if (pa.ticket != last_ticket && *root != NULL) {
- pfctl_free_altq_node(*root);
- *root = NULL;
- }
- last_ticket = pa.ticket;
-
- mnr = pa.nr;
- for (nr = 0; nr < mnr; ++nr) {
- pa.nr = nr;
- if (ioctl(dev, DIOCGETALTQ, &pa)) {
- warn("DIOCGETALTQ");
- return (-1);
- }
- if (pa.altq.qid > 0) {
- pq.nr = nr;
- pq.ticket = pa.ticket;
- pq.buf = &qstats.data;
- pq.nbytes = sizeof(qstats.data);
- if (ioctl(dev, DIOCGETALTQSTATS, &pq)) {
- warn("DIOCGETALTQSTATS");
- return (-1);
- }
- if ((node = pfctl_find_altq_node(*root, pa.altq.qname,
- pa.altq.ifname)) != NULL) {
- memcpy(&node->qstats.data, &qstats.data,
- sizeof(qstats.data));
- altq_update_avg(node);
- } else {
- pfctl_insert_altq_node(root, pa.altq, qstats);
- }
- }
- }
- return (mnr);
-}
-
-void
-pfctl_insert_altq_node(struct pf_altq_node **root,
- const struct pf_altq altq, const struct queue_stats qstats)
-{
- struct pf_altq_node *node;
-
- node = calloc(1, sizeof(struct pf_altq_node));
- if (node == NULL)
- err(1, "pfctl_insert_altq_node: calloc");
- memcpy(&node->altq, &altq, sizeof(struct pf_altq));
- memcpy(&node->qstats, &qstats, sizeof(qstats));
- node->next = node->children = NULL;
-
- if (*root == NULL)
- *root = node;
- else if (!altq.parent[0]) {
- struct pf_altq_node *prev = *root;
-
- while (prev->next != NULL)
- prev = prev->next;
- prev->next = node;
- } else {
- struct pf_altq_node *parent;
-
- parent = pfctl_find_altq_node(*root, altq.parent, altq.ifname);
- if (parent == NULL)
- errx(1, "parent %s not found", altq.parent);
- if (parent->children == NULL)
- parent->children = node;
- else {
- struct pf_altq_node *prev = parent->children;
-
- while (prev->next != NULL)
- prev = prev->next;
- prev->next = node;
- }
- }
- altq_update_avg(node);
-}
-
-struct pf_altq_node *
-pfctl_find_altq_node(struct pf_altq_node *root, const char *qname,
- const char *ifname)
-{
- struct pf_altq_node *node, *child;
-
- for (node = root; node != NULL; node = node->next) {
- if (!strcmp(node->altq.qname, qname)
- && !(strcmp(node->altq.ifname, ifname)))
- return (node);
- if (node->children != NULL) {
- child = pfctl_find_altq_node(node->children, qname,
- ifname);
- if (child != NULL)
- return (child);
- }
- }
- return (NULL);
-}
-
-void
-pfctl_print_altq_node(int dev, const struct pf_altq_node *node,
- unsigned int level, int opts)
-{
- const struct pf_altq_node *child;
-
- if (node == NULL)
- return;
-
- print_altq(&node->altq, level, NULL, NULL);
-
- if (node->children != NULL) {
- printf("{");
- for (child = node->children; child != NULL;
- child = child->next) {
- printf("%s", child->altq.qname);
- if (child->next != NULL)
- printf(", ");
- }
- printf("}");
- }
- printf("\n");
-
- if (opts & PF_OPT_VERBOSE)
- pfctl_print_altq_nodestat(dev, node);
-
- if (opts & PF_OPT_DEBUG)
- printf(" [ qid=%u ifname=%s ifbandwidth=%s ]\n",
- node->altq.qid, node->altq.ifname,
- rate2str((double)(node->altq.ifbandwidth)));
-
- for (child = node->children; child != NULL;
- child = child->next)
- pfctl_print_altq_node(dev, child, level + 1, opts);
-}
-
-void
-pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a)
-{
- if (a->altq.qid == 0)
- return;
-
- switch (a->altq.scheduler) {
- case ALTQT_CBQ:
- print_cbqstats(a->qstats);
- break;
- case ALTQT_PRIQ:
- print_priqstats(a->qstats);
- break;
- case ALTQT_HFSC:
- print_hfscstats(a->qstats);
- break;
- }
-}
-
-void
-print_cbqstats(struct queue_stats cur)
-{
- printf(" [ pkts: %10llu bytes: %10llu "
- "dropped pkts: %6llu bytes: %6llu ]\n",
- (unsigned long long)cur.data.cbq_stats.xmit_cnt.packets,
- (unsigned long long)cur.data.cbq_stats.xmit_cnt.bytes,
- (unsigned long long)cur.data.cbq_stats.drop_cnt.packets,
- (unsigned long long)cur.data.cbq_stats.drop_cnt.bytes);
- printf(" [ qlength: %3d/%3d borrows: %6u suspends: %6u ]\n",
- cur.data.cbq_stats.qcnt, cur.data.cbq_stats.qmax,
- cur.data.cbq_stats.borrows, cur.data.cbq_stats.delays);
-
- if (cur.avgn < 2)
- return;
-
- printf(" [ measured: %7.1f packets/s, %s/s ]\n",
- cur.avg_packets / STAT_INTERVAL,
- rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
-}
-
-void
-print_priqstats(struct queue_stats cur)
-{
- printf(" [ pkts: %10llu bytes: %10llu "
- "dropped pkts: %6llu bytes: %6llu ]\n",
- (unsigned long long)cur.data.priq_stats.xmitcnt.packets,
- (unsigned long long)cur.data.priq_stats.xmitcnt.bytes,
- (unsigned long long)cur.data.priq_stats.dropcnt.packets,
- (unsigned long long)cur.data.priq_stats.dropcnt.bytes);
- printf(" [ qlength: %3d/%3d ]\n",
- cur.data.priq_stats.qlength, cur.data.priq_stats.qlimit);
-
- if (cur.avgn < 2)
- return;
-
- printf(" [ measured: %7.1f packets/s, %s/s ]\n",
- cur.avg_packets / STAT_INTERVAL,
- rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
-}
-
-void
-print_hfscstats(struct queue_stats cur)
-{
- printf(" [ pkts: %10llu bytes: %10llu "
- "dropped pkts: %6llu bytes: %6llu ]\n",
- (unsigned long long)cur.data.hfsc_stats.xmit_cnt.packets,
- (unsigned long long)cur.data.hfsc_stats.xmit_cnt.bytes,
- (unsigned long long)cur.data.hfsc_stats.drop_cnt.packets,
- (unsigned long long)cur.data.hfsc_stats.drop_cnt.bytes);
- printf(" [ qlength: %3d/%3d ]\n",
- cur.data.hfsc_stats.qlength, cur.data.hfsc_stats.qlimit);
-
- if (cur.avgn < 2)
- return;
-
- printf(" [ measured: %7.1f packets/s, %s/s ]\n",
- cur.avg_packets / STAT_INTERVAL,
- rate2str((8 * cur.avg_bytes) / STAT_INTERVAL));
-}
-
-void
-pfctl_free_altq_node(struct pf_altq_node *node)
-{
- while (node != NULL) {
- struct pf_altq_node *prev;
-
- if (node->children != NULL)
- pfctl_free_altq_node(node->children);
- prev = node;
- node = node->next;
- free(prev);
- }
-}
-
-void
-altq_update_avg(struct pf_altq_node *a)
-{
- struct queue_stats *qs;
- u_int64_t b, p;
- int n;
-
- if (a->altq.qid == 0)
- return;
-
- qs = &a->qstats;
- n = qs->avgn;
-
- switch (a->altq.scheduler) {
- case ALTQT_CBQ:
- b = qs->data.cbq_stats.xmit_cnt.bytes;
- p = qs->data.cbq_stats.xmit_cnt.packets;
- break;
- case ALTQT_PRIQ:
- b = qs->data.priq_stats.xmitcnt.bytes;
- p = qs->data.priq_stats.xmitcnt.packets;
- break;
- case ALTQT_HFSC:
- b = qs->data.hfsc_stats.xmit_cnt.bytes;
- p = qs->data.hfsc_stats.xmit_cnt.packets;
- break;
- default:
- b = 0;
- p = 0;
- break;
- }
-
- if (n == 0) {
- qs->prev_bytes = b;
- qs->prev_packets = p;
- qs->avgn++;
- return;
- }
-
- if (b >= qs->prev_bytes)
- qs->avg_bytes = ((qs->avg_bytes * (n - 1)) +
- (b - qs->prev_bytes)) / n;
-
- if (p >= qs->prev_packets)
- qs->avg_packets = ((qs->avg_packets * (n - 1)) +
- (p - qs->prev_packets)) / n;
-
- qs->prev_bytes = b;
- qs->prev_packets = p;
- if (n < AVGN_MAX)
- qs->avgn++;
-}
-/* $OpenBSD: pfctl_queue.c,v 1.1 2013/10/12 12:16:12 henning Exp $ */
+/* $OpenBSD: pfctl_queue.c,v 1.2 2014/04/19 14:22:32 henning Exp $ */
/*
* Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org>
void pfctl_print_queue_nodestat(int,
const struct pfctl_queue_node *);
void update_avg(struct queue_stats *);
+char *rate2str(double);
int
pfctl_show_queues(int dev, const char *iface, int opts, int verbose2)
if (s->avgn < AVGN_MAX)
s->avgn++;
}
+
+#define R2S_BUFS 8
+#define RATESTR_MAX 16
+
+char *
+rate2str(double rate)
+{
+ char *buf;
+ static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */
+ static int idx = 0;
+ int i;
+ static const char unit[] = " KMG";
+
+ buf = r2sbuf[idx++];
+ if (idx == R2S_BUFS)
+ idx = 0;
+
+ for (i = 0; rate >= 1000 && i <= 3; i++)
+ rate /= 1000;
+
+ if ((int)(rate * 100) % 100)
+ snprintf(buf, RATESTR_MAX, "%.2f%cb", rate, unit[i]);
+ else
+ snprintf(buf, RATESTR_MAX, "%d%cb", (int)rate, unit[i]);
+
+ return (buf);
+}