summaryrefslogtreecommitdiffstats
path: root/sbin/ipfw/ipfw2.c
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2009-01-27 11:06:59 +0000
committerluigi <luigi@FreeBSD.org>2009-01-27 11:06:59 +0000
commit5153c1f1c42195d9130f83a12b751e798054a287 (patch)
tree0d3c467c28f04b0d33e0bd81c4bea3613bf6f537 /sbin/ipfw/ipfw2.c
parent836697aeba957b721bd91451fd66c5b8d13f2a03 (diff)
downloadFreeBSD-src-5153c1f1c42195d9130f83a12b751e798054a287.zip
FreeBSD-src-5153c1f1c42195d9130f83a12b751e798054a287.tar.gz
Put dummynet-related code in a separate file.
To this purpose, add prototypes for global functions in ipfw2.h and move there also the list of tokens used in various places in the code.
Diffstat (limited to 'sbin/ipfw/ipfw2.c')
-rw-r--r--sbin/ipfw/ipfw2.c796
1 files changed, 11 insertions, 785 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index e457328..5d73567 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -54,7 +54,6 @@
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
#include <netinet/ip_fw.h>
-#include <netinet/ip_dummynet.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <alias.h>
@@ -192,150 +191,8 @@ static struct _s_x ether_types[] = {
{ NULL, 0 }
};
-enum tokens {
- TOK_NULL=0,
-
- TOK_OR,
- TOK_NOT,
- TOK_STARTBRACE,
- TOK_ENDBRACE,
-
- TOK_ACCEPT,
- TOK_COUNT,
- TOK_PIPE,
- TOK_QUEUE,
- TOK_DIVERT,
- TOK_TEE,
- TOK_NETGRAPH,
- TOK_NGTEE,
- TOK_FORWARD,
- TOK_SKIPTO,
- TOK_DENY,
- TOK_REJECT,
- TOK_RESET,
- TOK_UNREACH,
- TOK_CHECKSTATE,
- TOK_NAT,
-
- TOK_ALTQ,
- TOK_LOG,
- TOK_TAG,
- TOK_UNTAG,
-
- TOK_TAGGED,
- TOK_UID,
- TOK_GID,
- TOK_JAIL,
- TOK_IN,
- TOK_LIMIT,
- TOK_KEEPSTATE,
- TOK_LAYER2,
- TOK_OUT,
- TOK_DIVERTED,
- TOK_DIVERTEDLOOPBACK,
- TOK_DIVERTEDOUTPUT,
- TOK_XMIT,
- TOK_RECV,
- TOK_VIA,
- TOK_FRAG,
- TOK_IPOPTS,
- TOK_IPLEN,
- TOK_IPID,
- TOK_IPPRECEDENCE,
- TOK_IPTOS,
- TOK_IPTTL,
- TOK_IPVER,
- TOK_ESTAB,
- TOK_SETUP,
- TOK_TCPDATALEN,
- TOK_TCPFLAGS,
- TOK_TCPOPTS,
- TOK_TCPSEQ,
- TOK_TCPACK,
- TOK_TCPWIN,
- TOK_ICMPTYPES,
- TOK_MAC,
- TOK_MACTYPE,
- TOK_VERREVPATH,
- TOK_VERSRCREACH,
- TOK_ANTISPOOF,
- TOK_IPSEC,
- TOK_COMMENT,
-
- TOK_PLR,
- TOK_NOERROR,
- TOK_BUCKETS,
- TOK_DSTIP,
- TOK_SRCIP,
- TOK_DSTPORT,
- TOK_SRCPORT,
- TOK_ALL,
- TOK_MASK,
- TOK_BW,
- TOK_DELAY,
- TOK_RED,
- TOK_GRED,
- TOK_DROPTAIL,
- TOK_PROTO,
- TOK_WEIGHT,
- TOK_IP,
- TOK_IF,
- TOK_ALOG,
- TOK_DENY_INC,
- TOK_SAME_PORTS,
- TOK_UNREG_ONLY,
- TOK_RESET_ADDR,
- TOK_ALIAS_REV,
- TOK_PROXY_ONLY,
- TOK_REDIR_ADDR,
- TOK_REDIR_PORT,
- TOK_REDIR_PROTO,
-
- TOK_IPV6,
- TOK_FLOWID,
- TOK_ICMP6TYPES,
- TOK_EXT6HDR,
- TOK_DSTIP6,
- TOK_SRCIP6,
-
- TOK_IPV4,
- TOK_UNREACH6,
- TOK_RESET6,
-
- TOK_FIB,
- TOK_SETFIB,
-};
-struct _s_x dummynet_params[] = {
- { "plr", TOK_PLR },
- { "noerror", TOK_NOERROR },
- { "buckets", TOK_BUCKETS },
- { "dst-ip", TOK_DSTIP },
- { "src-ip", TOK_SRCIP },
- { "dst-port", TOK_DSTPORT },
- { "src-port", TOK_SRCPORT },
- { "proto", TOK_PROTO },
- { "weight", TOK_WEIGHT },
- { "all", TOK_ALL },
- { "mask", TOK_MASK },
- { "droptail", TOK_DROPTAIL },
- { "red", TOK_RED },
- { "gred", TOK_GRED },
- { "bw", TOK_BW },
- { "bandwidth", TOK_BW },
- { "delay", TOK_DELAY },
- { "pipe", TOK_PIPE },
- { "queue", TOK_QUEUE },
- { "flow-id", TOK_FLOWID},
- { "dst-ipv6", TOK_DSTIP6},
- { "dst-ip6", TOK_DSTIP6},
- { "src-ipv6", TOK_SRCIP6},
- { "src-ip6", TOK_SRCIP6},
- { "dummynet-params", TOK_NULL },
- { NULL, 0 } /* terminator */
-};
-
-struct _s_x nat_params[] = {
+static struct _s_x nat_params[] = {
{ "ip", TOK_IP },
{ "if", TOK_IF },
{ "log", TOK_ALOG },
@@ -351,7 +208,7 @@ struct _s_x nat_params[] = {
{ NULL, 0 } /* terminator */
};
-struct _s_x rule_actions[] = {
+static struct _s_x rule_actions[] = {
{ "accept", TOK_ACCEPT },
{ "pass", TOK_ACCEPT },
{ "allow", TOK_ACCEPT },
@@ -380,7 +237,7 @@ struct _s_x rule_actions[] = {
{ NULL, 0 } /* terminator */
};
-struct _s_x rule_action_params[] = {
+static struct _s_x rule_action_params[] = {
{ "altq", TOK_ALTQ },
{ "log", TOK_LOG },
{ "tag", TOK_TAG },
@@ -388,7 +245,7 @@ struct _s_x rule_action_params[] = {
{ NULL, 0 } /* terminator */
};
-struct _s_x rule_options[] = {
+static struct _s_x rule_options[] = {
{ "tagged", TOK_TAGGED },
{ "uid", TOK_UID },
{ "gid", TOK_GID },
@@ -498,7 +355,7 @@ safe_realloc(void *ptr, size_t size)
/*
* conditionally runs the command.
*/
-static int
+int
do_cmd(int optname, void *optval, uintptr_t optlen)
{
static int s = -1; /* the socket */
@@ -528,7 +385,7 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
* match_token takes a table and a string, returns the value associated
* with the string (-1 in case of failure).
*/
-static int
+int
match_token(struct _s_x *table, char *string)
{
struct _s_x *pt;
@@ -590,7 +447,7 @@ _substrcmp(const char *str1, const char* str2)
* This function will be removed in the future through the usual
* deprecation process.
*/
-static int
+int
_substrcmp2(const char *str1, const char* str2, const char* str3)
{
@@ -631,7 +488,7 @@ print_port(int proto, uint16_t port)
}
}
-struct _s_x _port_name[] = {
+static struct _s_x _port_name[] = {
{"dst-port", O_IP_DSTPORT},
{"src-port", O_IP_SRCPORT},
{"ipid", O_IPID},
@@ -2088,254 +1945,6 @@ show_dyn_ipfw(ipfw_dyn_rule *d, int pcwidth, int bcwidth)
printf("\n");
}
-static int
-sort_q(const void *pa, const void *pb)
-{
- int rev = (co.do_sort < 0);
- int field = rev ? -co.do_sort : co.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 (co.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 (co.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 (co.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, int ac, char *av[])
-{
- int rulenum;
- void *next = data;
- struct dn_pipe *p = (struct dn_pipe *) data;
- struct dn_flow_set *fs;
- struct dn_flow_queue *q;
- int l;
-
- if (ac > 0)
- rulenum = strtoul(*av++, NULL, 10);
- else
- rulenum = 0;
- 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;
-
- if ((rulenum != 0 && rulenum != p->pipe_nr) || co.do_pipe == 2)
- continue;
-
- /*
- * 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 (co.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 (rulenum != 0 && ((rulenum != fs->fs_nr && co.do_pipe == 2) ||
- (rulenum != fs->parent_nr && co.do_pipe == 1))) {
- continue;
- }
-
- 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);
- }
-}
-
/*
* This one handles all set-related commands
* ipfw set { show | enable | disable }
@@ -2517,7 +2126,7 @@ ipfw_list(int ac, char *av[], int show_counters)
}
if (co.do_pipe) {
- list_pipes(data, nbytes, ac, av);
+ ipfw_list_pipes(data, nbytes, ac, av);
goto done;
}
@@ -2897,7 +2506,7 @@ lookup_host6 (char *host, struct in6_addr *ip6addr)
/* n2mask sets n bits of the mask */
-static void
+void
n2mask(struct in6_addr *mask, int n)
{
static int minimask[9] =
@@ -3145,12 +2754,10 @@ void
ipfw_delete(int ac, char *av[])
{
uint32_t rulenum;
- struct dn_pipe p;
int i;
int exitval = EX_OK;
int do_set = 0;
- memset(&p, 0, sizeof p);
av++; ac--;
NEED1("missing rule specification");
@@ -3174,16 +2781,7 @@ ipfw_delete(int ac, char *av[])
warn("rule %u not available", i);
}
} else if (co.do_pipe) {
- if (co.do_pipe == 1)
- p.pipe_nr = i;
- else
- p.fs.fs_nr = i;
- i = do_cmd(IP_DUMMYNET_DEL, &p, sizeof p);
- if (i) {
- exitval = 1;
- warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
- co.do_pipe == 1 ? p.pipe_nr : p.fs.fs_nr);
- }
+ exitval = ipfw_delete_pipe(co.do_pipe, i);
} else {
if (co.use_set)
rulenum = (i & 0xffff) | (5 << 24) |
@@ -3989,378 +3587,6 @@ ipfw_config_nat(int ac, char **av)
}
}
-void
-ipfw_config_pipe(int ac, char **av)
-{
- struct dn_pipe p;
- int i;
- char *end;
- void *par = NULL;
-
- memset(&p, 0, sizeof p);
-
- av++; ac--;
- /* Pipe number */
- if (ac && isdigit(**av)) {
- i = atoi(*av); av++; ac--;
- if (co.do_pipe == 1)
- p.pipe_nr = i;
- else
- p.fs.fs_nr = i;
- }
- while (ac > 0) {
- double d;
- int tok = match_token(dummynet_params, *av);
- ac--; av++;
-
- switch(tok) {
- case TOK_NOERROR:
- p.fs.flags_fs |= DN_NOERROR;
- break;
-
- case TOK_PLR:
- NEED1("plr needs argument 0..1\n");
- d = strtod(av[0], NULL);
- if (d > 1)
- d = 1;
- else if (d < 0)
- d = 0;
- p.fs.plr = (int)(d*0x7fffffff);
- ac--; av++;
- break;
-
- case TOK_QUEUE:
- NEED1("queue needs queue size\n");
- end = NULL;
- p.fs.qsize = strtoul(av[0], &end, 0);
- if (*end == 'K' || *end == 'k') {
- p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
- p.fs.qsize *= 1024;
- } else if (*end == 'B' ||
- _substrcmp2(end, "by", "bytes") == 0) {
- p.fs.flags_fs |= DN_QSIZE_IS_BYTES;
- }
- ac--; av++;
- break;
-
- case TOK_BUCKETS:
- NEED1("buckets needs argument\n");
- p.fs.rq_size = strtoul(av[0], NULL, 0);
- ac--; av++;
- break;
-
- case TOK_MASK:
- NEED1("mask needs mask specifier\n");
- /*
- * per-flow queue, mask is dst_ip, dst_port,
- * src_ip, src_port, proto measured in bits
- */
- par = NULL;
-
- bzero(&p.fs.flow_mask, sizeof(p.fs.flow_mask));
- end = NULL;
-
- while (ac >= 1) {
- uint32_t *p32 = NULL;
- uint16_t *p16 = NULL;
- uint32_t *p20 = NULL;
- struct in6_addr *pa6 = NULL;
- uint32_t a;
-
- tok = match_token(dummynet_params, *av);
- ac--; av++;
- switch(tok) {
- case TOK_ALL:
- /*
- * special case, all bits significant
- */
- p.fs.flow_mask.dst_ip = ~0;
- p.fs.flow_mask.src_ip = ~0;
- p.fs.flow_mask.dst_port = ~0;
- p.fs.flow_mask.src_port = ~0;
- p.fs.flow_mask.proto = ~0;
- n2mask(&(p.fs.flow_mask.dst_ip6), 128);
- n2mask(&(p.fs.flow_mask.src_ip6), 128);
- p.fs.flow_mask.flow_id6 = ~0;
- p.fs.flags_fs |= DN_HAVE_FLOW_MASK;
- goto end_mask;
-
- case TOK_DSTIP:
- p32 = &p.fs.flow_mask.dst_ip;
- break;
-
- case TOK_SRCIP:
- p32 = &p.fs.flow_mask.src_ip;
- break;
-
- case TOK_DSTIP6:
- pa6 = &(p.fs.flow_mask.dst_ip6);
- break;
-
- case TOK_SRCIP6:
- pa6 = &(p.fs.flow_mask.src_ip6);
- break;
-
- case TOK_FLOWID:
- p20 = &p.fs.flow_mask.flow_id6;
- break;
-
- case TOK_DSTPORT:
- p16 = &p.fs.flow_mask.dst_port;
- break;
-
- case TOK_SRCPORT:
- p16 = &p.fs.flow_mask.src_port;
- break;
-
- case TOK_PROTO:
- break;
-
- default:
- ac++; av--; /* backtrack */
- goto end_mask;
- }
- if (ac < 1)
- errx(EX_USAGE, "mask: value missing");
- if (*av[0] == '/') {
- a = strtoul(av[0]+1, &end, 0);
- if (pa6 == NULL)
- a = (a == 32) ? ~0 : (1 << a) - 1;
- } else
- a = strtoul(av[0], &end, 0);
- if (p32 != NULL)
- *p32 = a;
- else if (p16 != NULL) {
- if (a > 0xFFFF)
- errx(EX_DATAERR,
- "port mask must be 16 bit");
- *p16 = (uint16_t)a;
- } else if (p20 != NULL) {
- if (a > 0xfffff)
- errx(EX_DATAERR,
- "flow_id mask must be 20 bit");
- *p20 = (uint32_t)a;
- } else if (pa6 != NULL) {
- if (a > 128)
- errx(EX_DATAERR,
- "in6addr invalid mask len");
- else
- n2mask(pa6, a);
- } else {
- if (a > 0xFF)
- errx(EX_DATAERR,
- "proto mask must be 8 bit");
- p.fs.flow_mask.proto = (uint8_t)a;
- }
- if (a != 0)
- p.fs.flags_fs |= DN_HAVE_FLOW_MASK;
- ac--; av++;
- } /* end while, config masks */
-end_mask:
- break;
-
- case TOK_RED:
- case TOK_GRED:
- NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
- p.fs.flags_fs |= DN_IS_RED;
- if (tok == TOK_GRED)
- p.fs.flags_fs |= DN_IS_GENTLE_RED;
- /*
- * the format for parameters is w_q/min_th/max_th/max_p
- */
- if ((end = strsep(&av[0], "/"))) {
- double w_q = strtod(end, NULL);
- if (w_q > 1 || w_q <= 0)
- errx(EX_DATAERR, "0 < w_q <= 1");
- p.fs.w_q = (int) (w_q * (1 << SCALE_RED));
- }
- if ((end = strsep(&av[0], "/"))) {
- p.fs.min_th = strtoul(end, &end, 0);
- if (*end == 'K' || *end == 'k')
- p.fs.min_th *= 1024;
- }
- if ((end = strsep(&av[0], "/"))) {
- p.fs.max_th = strtoul(end, &end, 0);
- if (*end == 'K' || *end == 'k')
- p.fs.max_th *= 1024;
- }
- if ((end = strsep(&av[0], "/"))) {
- double max_p = strtod(end, NULL);
- if (max_p > 1 || max_p <= 0)
- errx(EX_DATAERR, "0 < max_p <= 1");
- p.fs.max_p = (int)(max_p * (1 << SCALE_RED));
- }
- ac--; av++;
- break;
-
- case TOK_DROPTAIL:
- p.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
- break;
-
- case TOK_BW:
- NEED1("bw needs bandwidth or interface\n");
- if (co.do_pipe != 1)
- errx(EX_DATAERR, "bandwidth only valid for pipes");
- /*
- * set clocking interface or bandwidth value
- */
- if (av[0][0] >= 'a' && av[0][0] <= 'z') {
- int l = sizeof(p.if_name)-1;
- /* interface name */
- strncpy(p.if_name, av[0], l);
- p.if_name[l] = '\0';
- p.bandwidth = 0;
- } else {
- p.if_name[0] = '\0';
- p.bandwidth = strtoul(av[0], &end, 0);
- if (*end == 'K' || *end == 'k') {
- end++;
- p.bandwidth *= 1000;
- } else if (*end == 'M') {
- end++;
- p.bandwidth *= 1000000;
- }
- if ((*end == 'B' &&
- _substrcmp2(end, "Bi", "Bit/s") != 0) ||
- _substrcmp2(end, "by", "bytes") == 0)
- p.bandwidth *= 8;
- if (p.bandwidth < 0)
- errx(EX_DATAERR, "bandwidth too large");
- }
- ac--; av++;
- break;
-
- case TOK_DELAY:
- if (co.do_pipe != 1)
- errx(EX_DATAERR, "delay only valid for pipes");
- NEED1("delay needs argument 0..10000ms\n");
- p.delay = strtoul(av[0], NULL, 0);
- ac--; av++;
- break;
-
- case TOK_WEIGHT:
- if (co.do_pipe == 1)
- errx(EX_DATAERR,"weight only valid for queues");
- NEED1("weight needs argument 0..100\n");
- p.fs.weight = strtoul(av[0], &end, 0);
- ac--; av++;
- break;
-
- case TOK_PIPE:
- if (co.do_pipe == 1)
- errx(EX_DATAERR,"pipe only valid for queues");
- NEED1("pipe needs pipe_number\n");
- p.fs.parent_nr = strtoul(av[0], &end, 0);
- ac--; av++;
- break;
-
- default:
- errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
- }
- }
- if (co.do_pipe == 1) {
- if (p.pipe_nr == 0)
- errx(EX_DATAERR, "pipe_nr must be > 0");
- if (p.delay > 10000)
- errx(EX_DATAERR, "delay must be < 10000");
- } else { /* co.do_pipe == 2, queue */
- if (p.fs.parent_nr == 0)
- errx(EX_DATAERR, "pipe must be > 0");
- if (p.fs.weight >100)
- errx(EX_DATAERR, "weight must be <= 100");
- }
- if (p.fs.flags_fs & DN_QSIZE_IS_BYTES) {
- size_t len;
- long limit;
-
- len = sizeof(limit);
- if (sysctlbyname("net.inet.ip.dummynet.pipe_byte_limit",
- &limit, &len, NULL, 0) == -1)
- limit = 1024*1024;
- if (p.fs.qsize > limit)
- errx(EX_DATAERR, "queue size must be < %ldB", limit);
- } else {
- size_t len;
- long limit;
-
- len = sizeof(limit);
- if (sysctlbyname("net.inet.ip.dummynet.pipe_slot_limit",
- &limit, &len, NULL, 0) == -1)
- limit = 100;
- if (p.fs.qsize > limit)
- errx(EX_DATAERR, "2 <= queue size <= %ld", limit);
- }
- if (p.fs.flags_fs & DN_IS_RED) {
- size_t len;
- int lookup_depth, avg_pkt_size;
- double s, idle, weight, w_q;
- struct clockinfo ck;
- int t;
-
- if (p.fs.min_th >= p.fs.max_th)
- errx(EX_DATAERR, "min_th %d must be < than max_th %d",
- p.fs.min_th, p.fs.max_th);
- if (p.fs.max_th == 0)
- errx(EX_DATAERR, "max_th must be > 0");
-
- len = sizeof(int);
- if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
- &lookup_depth, &len, NULL, 0) == -1)
- errx(1, "sysctlbyname(\"%s\")",
- "net.inet.ip.dummynet.red_lookup_depth");
- if (lookup_depth == 0)
- errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
- " must be greater than zero");
-
- len = sizeof(int);
- if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
- &avg_pkt_size, &len, NULL, 0) == -1)
-
- errx(1, "sysctlbyname(\"%s\")",
- "net.inet.ip.dummynet.red_avg_pkt_size");
- if (avg_pkt_size == 0)
- errx(EX_DATAERR,
- "net.inet.ip.dummynet.red_avg_pkt_size must"
- " be greater than zero");
-
- len = sizeof(struct clockinfo);
- if (sysctlbyname("kern.clockrate", &ck, &len, NULL, 0) == -1)
- errx(1, "sysctlbyname(\"%s\")", "kern.clockrate");
-
- /*
- * Ticks needed for sending a medium-sized packet.
- * Unfortunately, when we are configuring a WF2Q+ queue, we
- * do not have bandwidth information, because that is stored
- * in the parent pipe, and also we have multiple queues
- * competing for it. So we set s=0, which is not very
- * correct. But on the other hand, why do we want RED with
- * WF2Q+ ?
- */
- if (p.bandwidth==0) /* this is a WF2Q+ queue */
- s = 0;
- else
- s = (double)ck.hz * avg_pkt_size * 8 / p.bandwidth;
-
- /*
- * max idle time (in ticks) before avg queue size becomes 0.
- * NOTA: (3/w_q) is approx the value x so that
- * (1-w_q)^x < 10^-3.
- */
- w_q = ((double)p.fs.w_q) / (1 << SCALE_RED);
- idle = s * 3. / w_q;
- p.fs.lookup_step = (int)idle / lookup_depth;
- if (!p.fs.lookup_step)
- p.fs.lookup_step = 1;
- weight = 1 - w_q;
- for (t = p.fs.lookup_step; t > 1; --t)
- weight *= 1 - w_q;
- p.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
- }
- i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p);
- if (i)
- err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
-}
-
static void
get_mac_addr_mask(const char *p, uint8_t *addr, uint8_t *mask)
{
OpenPOWER on IntegriCloud