ipfw2.c revision 101628
1/*
2 * Copyright (c) 2002 Luigi Rizzo
3 * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
4 * Copyright (c) 1994 Ugen J.S.Antsilevich
5 *
6 * Idea and grammar partially left from:
7 * Copyright (c) 1993 Daniel Boulet
8 *
9 * Redistribution and use in source forms, with and without modification,
10 * are permitted provided that this entire comment appears intact.
11 *
12 * Redistribution in binary form may occur without any restrictions.
13 * Obviously, it would be nice if you gave credit where credit is due
14 * but requiring it would be too onerous.
15 *
16 * This software is provided ``AS IS'' without any warranties of any kind.
17 *
18 * NEW command line interface for IP firewall facility
19 *
20 * $FreeBSD: head/sbin/ipfw/ipfw2.c 101628 2002-08-10 04:37:32Z luigi $
21 */
22
23#include <sys/param.h>
24#include <sys/mbuf.h>
25#include <sys/socket.h>
26#include <sys/sockio.h>
27#include <sys/sysctl.h>
28#include <sys/time.h>
29#include <sys/wait.h>
30
31#include <ctype.h>
32#include <err.h>
33#include <errno.h>
34#include <grp.h>
35#include <limits.h>
36#include <netdb.h>
37#include <pwd.h>
38#include <signal.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <stdarg.h>
42#include <string.h>
43#include <timeconv.h>
44#include <unistd.h>
45#include <sysexits.h>
46
47#include <net/if.h>
48#include <netinet/in.h>
49#include <netinet/in_systm.h>
50#include <netinet/ip.h>
51#include <netinet/ip_icmp.h>
52#include <netinet/ip_fw.h>
53#include <net/route.h> /* def. of struct route */
54#include <netinet/ip_dummynet.h>
55#include <netinet/tcp.h>
56#include <arpa/inet.h>
57
58int		s,			/* main RAW socket */
59		do_resolv,		/* Would try to resolve all */
60		do_acct,		/* Show packet/byte count */
61		do_time,		/* Show time stamps */
62		do_quiet,		/* Be quiet in add and flush */
63		do_force,		/* Don't ask for confirmation */
64		do_pipe,		/* this cmd refers to a pipe */
65		do_sort,		/* field to sort results (0 = no) */
66		do_dynamic,		/* display dynamic rules */
67		do_expired,		/* display expired dynamic rules */
68		show_sets,		/* display rule sets */
69		verbose;
70
71#define	IP_MASK_ALL	0xffffffff
72
73/*
74 * structure to hold flag names and associated values to be
75 * set in the appropriate masks.
76 * A NULL string terminates the array.
77 * Often, an element with 0 value contains an error string.
78 *
79 */
80struct _s_x {
81	char *s;
82	int x;
83};
84
85static struct _s_x f_tcpflags[] = {
86	{ "syn", TH_SYN },
87	{ "fin", TH_FIN },
88	{ "ack", TH_ACK },
89	{ "psh", TH_PUSH },
90	{ "rst", TH_RST },
91	{ "urg", TH_URG },
92	{ "tcp flag", 0 },
93	{ NULL,	0 }
94};
95
96static struct _s_x f_tcpopts[] = {
97	{ "mss",	IP_FW_TCPOPT_MSS },
98	{ "maxseg",	IP_FW_TCPOPT_MSS },
99	{ "window",	IP_FW_TCPOPT_WINDOW },
100	{ "sack",	IP_FW_TCPOPT_SACK },
101	{ "ts",		IP_FW_TCPOPT_TS },
102	{ "timestamp",	IP_FW_TCPOPT_TS },
103	{ "cc",		IP_FW_TCPOPT_CC },
104	{ "tcp option",	0 },
105	{ NULL,	0 }
106};
107
108/*
109 * IP options span the range 0 to 255 so we need to remap them
110 * (though in fact only the low 5 bits are significant).
111 */
112static struct _s_x f_ipopts[] = {
113	{ "ssrr",	IP_FW_IPOPT_SSRR},
114	{ "lsrr",	IP_FW_IPOPT_LSRR},
115	{ "rr",		IP_FW_IPOPT_RR},
116	{ "ts",		IP_FW_IPOPT_TS},
117	{ "ip option",	0 },
118	{ NULL,	0 }
119};
120
121static struct _s_x f_iptos[] = {
122	{ "lowdelay",	IPTOS_LOWDELAY},
123	{ "throughput",	IPTOS_THROUGHPUT},
124	{ "reliability", IPTOS_RELIABILITY},
125	{ "mincost",	IPTOS_MINCOST},
126	{ "congestion",	IPTOS_CE},
127	{ "ecntransport", IPTOS_ECT},
128	{ "ip tos option", 0},
129	{ NULL,	0 }
130};
131
132static struct _s_x limit_masks[] = {
133	{"all",		DYN_SRC_ADDR|DYN_SRC_PORT|DYN_DST_ADDR|DYN_DST_PORT},
134	{"src-addr",	DYN_SRC_ADDR},
135	{"src-port",	DYN_SRC_PORT},
136	{"dst-addr",	DYN_DST_ADDR},
137	{"dst-port",	DYN_DST_PORT},
138	{NULL,		0}
139};
140
141/*
142 * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
143 * This is only used in this code.
144 */
145#define IPPROTO_ETHERTYPE	0x1000
146static struct _s_x ether_types[] = {
147    /*
148     * Note, we cannot use "-:&/" in the names because they are field
149     * separators in the type specifications. Also, we use s = NULL as
150     * end-delimiter, because a type of 0 can be legal.
151     */
152	{ "ip",		0x0800 },
153	{ "ipv4",	0x0800 },
154	{ "ipv6",	0x86dd },
155	{ "arp",	0x0806 },
156	{ "rarp",	0x8035 },
157	{ "vlan",	0x8100 },
158	{ "loop",	0x9000 },
159	{ "trail",	0x1000 },
160	{ "at",		0x809b },
161	{ "atalk",	0x809b },
162	{ "aarp",	0x80f3 },
163	{ "pppoe_disc",	0x8863 },
164	{ "pppoe_sess",	0x8864 },
165	{ "ipx_8022",	0x00E0 },
166	{ "ipx_8023",	0x0000 },
167	{ "ipx_ii",	0x8137 },
168	{ "ipx_snap",	0x8137 },
169	{ "ipx",	0x8137 },
170	{ "ns",		0x0600 },
171	{ NULL,		0 }
172};
173
174static void show_usage(void);
175
176enum tokens {
177	TOK_NULL=0,
178
179	TOK_OR,
180	TOK_NOT,
181
182	TOK_ACCEPT,
183	TOK_COUNT,
184	TOK_PIPE,
185	TOK_QUEUE,
186	TOK_DIVERT,
187	TOK_TEE,
188	TOK_FORWARD,
189	TOK_SKIPTO,
190	TOK_DENY,
191	TOK_REJECT,
192	TOK_RESET,
193	TOK_UNREACH,
194	TOK_CHECKSTATE,
195
196	TOK_UID,
197	TOK_GID,
198	TOK_IN,
199	TOK_LIMIT,
200	TOK_KEEPSTATE,
201	TOK_LAYER2,
202	TOK_OUT,
203	TOK_XMIT,
204	TOK_RECV,
205	TOK_VIA,
206	TOK_FRAG,
207	TOK_IPOPTS,
208	TOK_IPLEN,
209	TOK_IPID,
210	TOK_IPPRECEDENCE,
211	TOK_IPTOS,
212	TOK_IPTTL,
213	TOK_IPVER,
214	TOK_ESTAB,
215	TOK_SETUP,
216	TOK_TCPFLAGS,
217	TOK_TCPOPTS,
218	TOK_TCPSEQ,
219	TOK_TCPACK,
220	TOK_TCPWIN,
221	TOK_ICMPTYPES,
222
223	TOK_PLR,
224	TOK_BUCKETS,
225	TOK_DSTIP,
226	TOK_SRCIP,
227	TOK_DSTPORT,
228	TOK_SRCPORT,
229	TOK_ALL,
230	TOK_MASK,
231	TOK_BW,
232	TOK_DELAY,
233	TOK_RED,
234	TOK_GRED,
235	TOK_DROPTAIL,
236	TOK_PROTO,
237	TOK_WEIGHT,
238};
239
240struct _s_x dummynet_params[] = {
241	{ "plr",		TOK_PLR },
242	{ "buckets",		TOK_BUCKETS },
243	{ "dst-ip",		TOK_DSTIP },
244	{ "src-ip",		TOK_SRCIP },
245	{ "dst-port",		TOK_DSTPORT },
246	{ "src-port",		TOK_SRCPORT },
247	{ "proto",		TOK_PROTO },
248	{ "weight",		TOK_WEIGHT },
249	{ "all",		TOK_ALL },
250	{ "mask",		TOK_MASK },
251	{ "droptail",		TOK_DROPTAIL },
252	{ "red",		TOK_RED },
253	{ "gred",		TOK_GRED },
254	{ "bw",			TOK_BW },
255	{ "bandwidth",		TOK_BW },
256	{ "delay",		TOK_DELAY },
257	{ "pipe",		TOK_PIPE },
258	{ "queue",		TOK_QUEUE },
259	{ "dummynet-params",	TOK_NULL },
260	{ NULL, 0 }
261};
262
263struct _s_x rule_actions[] = {
264	{ "accept",		TOK_ACCEPT },
265	{ "pass",		TOK_ACCEPT },
266	{ "allow",		TOK_ACCEPT },
267	{ "permit",		TOK_ACCEPT },
268	{ "count",		TOK_COUNT },
269	{ "pipe",		TOK_PIPE },
270	{ "queue",		TOK_QUEUE },
271	{ "divert",		TOK_DIVERT },
272	{ "tee",		TOK_TEE },
273	{ "fwd",		TOK_FORWARD },
274	{ "forward",		TOK_FORWARD },
275	{ "skipto",		TOK_SKIPTO },
276	{ "deny",		TOK_DENY },
277	{ "drop",		TOK_DENY },
278	{ "reject",		TOK_REJECT },
279	{ "reset",		TOK_RESET },
280	{ "unreach",		TOK_UNREACH },
281	{ "check-state",	TOK_CHECKSTATE },
282	{ NULL,			TOK_NULL },
283	{ NULL, 0 }
284};
285
286struct _s_x rule_options[] = {
287	{ "uid",		TOK_UID },
288	{ "gid",		TOK_GID },
289	{ "in",			TOK_IN },
290	{ "limit",		TOK_LIMIT },
291	{ "keep-state",		TOK_KEEPSTATE },
292	{ "bridged",		TOK_LAYER2 },
293	{ "layer2",		TOK_LAYER2 },
294	{ "out",		TOK_OUT },
295	{ "xmit",		TOK_XMIT },
296	{ "recv",		TOK_RECV },
297	{ "via",		TOK_VIA },
298	{ "fragment",		TOK_FRAG },
299	{ "frag",		TOK_FRAG },
300	{ "ipoptions",		TOK_IPOPTS },
301	{ "ipopts",		TOK_IPOPTS },
302	{ "iplen",		TOK_IPLEN },
303	{ "ipid",		TOK_IPID },
304	{ "ipprecedence",	TOK_IPPRECEDENCE },
305	{ "iptos",		TOK_IPTOS },
306	{ "ipttl",		TOK_IPTTL },
307	{ "ipversion",		TOK_IPVER },
308	{ "ipver",		TOK_IPVER },
309	{ "estab",		TOK_ESTAB },
310	{ "established",	TOK_ESTAB },
311	{ "setup",		TOK_SETUP },
312	{ "tcpflags",		TOK_TCPFLAGS },
313	{ "tcpflgs",		TOK_TCPFLAGS },
314	{ "tcpoptions",		TOK_TCPOPTS },
315	{ "tcpopts",		TOK_TCPOPTS },
316	{ "tcpseq",		TOK_TCPSEQ },
317	{ "tcpack",		TOK_TCPACK },
318	{ "tcpwin",		TOK_TCPWIN },
319	{ "icmptype",		TOK_ICMPTYPES },
320	{ "icmptypes",		TOK_ICMPTYPES },
321
322	{ "not",		TOK_NOT },		/* pseudo option */
323	{ "!", /* escape ? */	TOK_NOT },		/* pseudo option */
324	{ "or",			TOK_OR },		/* pseudo option */
325	{ "|", /* escape */	TOK_OR },		/* pseudo option */
326	{ NULL,			TOK_NULL },
327	{ NULL, 0 }
328};
329
330/**
331 * match_token takes a table and a string, returns the value associated
332 * with the string (0 meaning an error in most cases)
333 */
334static int
335match_token(struct _s_x *table, char *string)
336{
337	struct _s_x *pt;
338	int i = strlen(string);
339
340	for (pt = table ; i && pt->s != NULL ; pt++)
341		if (strlen(pt->s) == i && !bcmp(string, pt->s, i))
342			return pt->x;
343	return -1;
344};
345
346static char *
347match_value(struct _s_x *p, u_int32_t value)
348{
349	for (; p->s != NULL; p++)
350		if (p->x == value)
351			return p->s;
352	return NULL;
353}
354
355/*
356 * prints one port, symbolic or numeric
357 */
358static void
359print_port(int proto, u_int16_t port)
360{
361
362	if (proto == IPPROTO_ETHERTYPE) {
363		char *s;
364
365		if (do_resolv && (s = match_value(ether_types, port)) )
366			printf("%s", s);
367		else
368			printf("0x%04x", port);
369	} else {
370		struct servent *se = NULL;
371		if (do_resolv) {
372			struct protoent *pe = getprotobynumber(proto);
373
374			se = getservbyport(htons(port), pe ? pe->p_name : NULL);
375		}
376		if (se)
377			printf("%s", se->s_name);
378		else
379			printf("%d", port);
380	}
381}
382
383/*
384 * print the values in a list of ports
385 * XXX todo: add support for mask.
386 */
387static void
388print_newports(ipfw_insn_u16 *cmd, int proto)
389{
390	u_int16_t *p = cmd->ports;
391	int i;
392	char *sep= " ";
393
394	if (cmd->o.len & F_NOT)
395		printf(" not");
396	for (i = F_LEN((ipfw_insn *)cmd) - 1; i > 0; i--, p += 2) {
397		printf(sep);
398		print_port(proto, p[0]);
399		if (p[0] != p[1]) {
400			printf("-");
401			print_port(proto, p[1]);
402		}
403		sep = ",";
404	}
405}
406
407/*
408 * Like strtol, but also translates service names into port numbers
409 * for some protocols.
410 * In particular:
411 *	proto == -1 disables the protocol check;
412 *	proto == IPPROTO_ETHERTYPE looks up an internal table
413 *	proto == <some value in /etc/protocols> matches the values there.
414 * Returns *end == s in case the parameter is not found.
415 */
416static int
417strtoport(char *s, char **end, int base, int proto)
418{
419	char *p, *buf;
420	char *s1;
421	int i;
422
423	*end = s;		/* default - not found */
424	if ( *s == '\0')
425		return 0;	/* not found */
426
427	if (isdigit(*s))
428		return strtol(s, end, base);
429
430	/*
431	 * find separator. '\\' escapes the next char.
432	 */
433	for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\') ; s1++)
434		if (*s1 == '\\' && s1[1] != '\0')
435			s1++;
436
437	buf = malloc(s1 - s + 1);
438	if (buf == NULL)
439		return 0;
440
441	/*
442	 * copy into a buffer skipping backslashes
443	 */
444	for (p = s, i = 0; p != s1 ; p++)
445		if ( *p != '\\')
446			buf[i++] = *p;
447	buf[i++] = '\0';
448
449	if (proto == IPPROTO_ETHERTYPE) {
450		i = match_token(ether_types, buf);
451		free(buf);
452		if (i != -1) {	/* found */
453			*end = s1;
454			return i;
455		}
456	} else {
457		struct protoent *pe = NULL;
458		struct servent *se;
459
460		if (proto != 0)
461			pe = getprotobynumber(proto);
462		setservent(1);
463		se = getservbyname(buf, pe ? pe->p_name : NULL);
464		free(buf);
465		if (se != NULL) {
466			*end = s1;
467			return ntohs(se->s_port);
468		}
469	}
470	return 0;	/* not found */
471}
472
473/*
474 * fill the body of the command with the list of port ranges.
475 * At the moment it only understands numeric ranges.
476 */
477static int
478fill_newports(ipfw_insn_u16 *cmd, char *av, int proto)
479{
480	u_int16_t *p = cmd->ports;
481	int i = 0;
482
483	for (; *av ; i++, p +=2 ) {
484		u_int16_t a, b;
485		char *s;
486
487		a = strtoport(av, &s, 0, proto);
488		if (s == av) /* no parameter */
489			break;
490		if (*s == '-') { /* a range */
491			av = s+1;
492			b = strtoport(av, &s, 0, proto);
493			if (s == av) /* no parameter */
494				break;
495			p[0] = a;
496			p[1] = b;
497		} else if (*s == ',' || *s == '\0' ) {
498			p[0] = p[1] = a;
499		} else	/* invalid separator */
500			break;
501		av = s+1;
502	}
503	if (i > 0) {
504		if (i+1 > F_LEN_MASK)
505			errx(EX_DATAERR, "too many port range\n");
506		cmd->o.len |= i+1; /* leave F_NOT and F_OR untouched */
507	}
508	return i;
509}
510
511static struct _s_x icmpcodes[] = {
512      { "net",			ICMP_UNREACH_NET },
513      { "host",			ICMP_UNREACH_HOST },
514      { "protocol",		ICMP_UNREACH_PROTOCOL },
515      { "port",			ICMP_UNREACH_PORT },
516      { "needfrag",		ICMP_UNREACH_NEEDFRAG },
517      { "srcfail",		ICMP_UNREACH_SRCFAIL },
518      { "net-unknown",		ICMP_UNREACH_NET_UNKNOWN },
519      { "host-unknown",		ICMP_UNREACH_HOST_UNKNOWN },
520      { "isolated",		ICMP_UNREACH_ISOLATED },
521      { "net-prohib",		ICMP_UNREACH_NET_PROHIB },
522      { "host-prohib",		ICMP_UNREACH_HOST_PROHIB },
523      { "tosnet",		ICMP_UNREACH_TOSNET },
524      { "toshost",		ICMP_UNREACH_TOSHOST },
525      { "filter-prohib",	ICMP_UNREACH_FILTER_PROHIB },
526      { "host-precedence",	ICMP_UNREACH_HOST_PRECEDENCE },
527      { "precedence-cutoff",	ICMP_UNREACH_PRECEDENCE_CUTOFF },
528      { NULL, 0 }
529};
530
531static void
532fill_reject_code(u_short *codep, char *str)
533{
534	int val;
535	char *s;
536
537	val = strtoul(str, &s, 0);
538	if (s == str || *s != '\0' || val >= 0x100)
539		val = match_token(icmpcodes, str);
540	if (val <= 0)
541		errx(EX_DATAERR, "unknown ICMP unreachable code ``%s''", str);
542	*codep = val;
543	return;
544}
545
546static void
547print_reject_code(u_int16_t code)
548{
549	char *s = match_value(icmpcodes, code);
550
551	if (s != NULL)
552		printf("unreach %s", s);
553	else
554		printf("unreach %u", code);
555}
556
557/*
558 * Returns the number of bits set (from left) in a contiguous bitmask,
559 * or -1 if the mask is not contiguous.
560 * XXX this needs a proper fix.
561 * This effectively works on masks in big-endian (network) format.
562 * when compiled on little endian architectures.
563 *
564 * First bit is bit 7 of the first byte -- note, for MAC addresses,
565 * the first bit on the wire is bit 0 of the first byte.
566 * len is the max length in bits.
567 */
568static int
569contigmask(u_char *p, int len)
570{
571	int i, n;
572	for (i=0; i<len ; i++)
573		if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
574			break;
575	for (n=i+1; n < len; n++)
576		if ( (p[n/8] & (1 << (7 - (n%8)))) != 0)
577			return -1; /* mask not contiguous */
578	return i;
579}
580
581/*
582 * print flags set/clear in the two bitmasks passed as parameters.
583 * There is a specialized check for f_tcpflags.
584 */
585static void
586print_flags(char *name, ipfw_insn *cmd, struct _s_x *list)
587{
588	char *comma="";
589	int i;
590	u_char set = cmd->arg1 & 0xff;
591	u_char clear = (cmd->arg1 >> 8) & 0xff;
592
593	if (list == f_tcpflags && set == TH_SYN && clear == TH_ACK) {
594		printf(" setup");
595		return;
596	}
597
598	printf(" %s ", name);
599	for (i=0; list[i].x != 0; i++) {
600		if (set & list[i].x) {
601			set &= ~list[i].x;
602			printf("%s%s", comma, list[i].s);
603			comma = ",";
604		}
605		if (clear & list[i].x) {
606			clear &= ~list[i].x;
607			printf("%s!%s", comma, list[i].s);
608			comma = ",";
609		}
610	}
611}
612
613/*
614 * Print the ip address contained in a command.
615 */
616static void
617print_ip(ipfw_insn_ip *cmd)
618{
619	struct hostent *he = NULL;
620	int mb;
621
622	printf("%s ", cmd->o.len & F_NOT ? " not": "");
623
624	if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) {
625		printf("me");
626		return;
627	}
628	if (cmd->o.opcode == O_IP_SRC_SET || cmd->o.opcode == O_IP_DST_SET) {
629		u_int32_t x, *d;
630		int i;
631		char comma = '{';
632
633		x = cmd->o.arg1 - 1;
634		x = htonl( ~x );
635		cmd->addr.s_addr = htonl(cmd->addr.s_addr);
636		printf("%s/%d", inet_ntoa(cmd->addr),
637			contigmask((u_char *)&x, 32));
638		x = cmd->addr.s_addr = htonl(cmd->addr.s_addr);
639		x &= 0xff; /* base */
640		d = (u_int32_t *)&(cmd->mask);
641		for (i=0; i < cmd->o.arg1; i++)
642			if (d[ i/32] & (1<<(i & 31))) {
643				printf("%c%d", comma, i+x);
644				comma = ',';
645			}
646		printf("}");
647		return;
648	}
649	if (cmd->o.opcode == O_IP_SRC || cmd->o.opcode == O_IP_DST)
650		mb = 32;
651	else
652		mb = contigmask((u_char *)&(cmd->mask.s_addr), 32);
653	if (mb == 32 && do_resolv)
654		he = gethostbyaddr((char *)&(cmd->addr.s_addr),
655		    sizeof(u_long), AF_INET);
656	if (he != NULL)		/* resolved to name */
657		printf("%s", he->h_name);
658	else if (mb == 0)	/* any */
659		printf("any");
660	else {		/* numeric IP followed by some kind of mask */
661		printf("%s", inet_ntoa(cmd->addr));
662		if (mb < 0)
663			printf(":%s", inet_ntoa(cmd->mask));
664		else if (mb < 32)
665			printf("/%d", mb);
666	}
667}
668
669/*
670 * prints a MAC address/mask pair
671 */
672static void
673print_mac(u_char *addr, u_char *mask)
674{
675	int l = contigmask(mask, 48);
676
677	if (l == 0)
678		printf(" any");
679	else {
680		printf(" %02x:%02x:%02x:%02x:%02x:%02x",
681		    addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
682		if (l == -1)
683			printf("&%02x:%02x:%02x:%02x:%02x:%02x",
684			    mask[0], mask[1], mask[2],
685			    mask[3], mask[4], mask[5]);
686		else if (l < 48)
687			printf("/%d", l);
688	}
689}
690
691static void
692fill_icmptypes(ipfw_insn_u32 *cmd, char *av)
693{
694	u_int8_t type;
695
696	cmd->d[0] = 0;
697	while (*av) {
698		if (*av == ',')
699			av++;
700
701		type = strtoul(av, &av, 0);
702
703		if (*av != ',' && *av != '\0')
704			errx(EX_DATAERR, "invalid ICMP type");
705
706		if (type > 31)
707			errx(EX_DATAERR, "ICMP type out of range");
708
709		cmd->d[0] |= 1 << type;
710	}
711	cmd->o.opcode = O_ICMPTYPE;
712	cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
713}
714
715static void
716print_icmptypes(ipfw_insn_u32 *cmd)
717{
718	int i;
719	char sep= ' ';
720
721	printf(" icmptypes");
722	for (i = 0; i < 32; i++) {
723		if ( (cmd->d[0] & (1 << (i))) == 0)
724			continue;
725		printf("%c%d", sep, i);
726		sep = ',';
727	}
728}
729
730/*
731 * show_ipfw() prints the body of an ipfw rule.
732 * Because the standard rule has at least proto src_ip dst_ip, we use
733 * a helper function to produce these entries if not provided explicitly.
734 */
735#define	HAVE_PROTO	1
736#define	HAVE_SRCIP	2
737#define	HAVE_DSTIP	4
738#define	HAVE_MAC	8
739
740static void
741show_prerequisites(int *flags, int want)
742{
743	if ( !(*flags & HAVE_PROTO) && (want & HAVE_PROTO))
744		printf(" ip");
745	if ( !(*flags & HAVE_SRCIP) && (want & HAVE_SRCIP))
746		printf(" from any");
747	if ( !(*flags & HAVE_DSTIP) && (want & HAVE_DSTIP))
748		printf(" to any");
749	*flags |= want;
750}
751
752static void
753show_ipfw(struct ip_fw *rule)
754{
755	int l;
756	ipfw_insn *cmd;
757	int proto = 0;		/* default */
758	int flags = 0;	/* prerequisites */
759	ipfw_insn_log *logptr = NULL; /* set if we find an O_LOG */
760	int or_block = 0;	/* we are in an or block */
761
762	u_int32_t set_disable = (u_int32_t)(rule->next_rule);
763
764	if (set_disable & (1 << rule->set)) { /* disabled */
765		if (!show_sets)
766			return;
767		else
768			printf("# DISABLED ");
769	}
770	printf("%05u ", rule->rulenum);
771
772	if (do_acct)
773		printf("%10qu %10qu ", rule->pcnt, rule->bcnt);
774
775	if (do_time) {
776		if (rule->timestamp) {
777			char timestr[30];
778			time_t t = _long_to_time(rule->timestamp);
779
780			strcpy(timestr, ctime(&t));
781			*strchr(timestr, '\n') = '\0';
782			printf("%s ", timestr);
783		} else {
784			printf("			 ");
785		}
786	}
787
788	if (show_sets)
789		printf("set %d ", rule->set);
790
791	/*
792	 * first print actions
793	 */
794        for (l = rule->cmd_len - rule->act_ofs, cmd = ACTION_PTR(rule);
795			l > 0 ; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
796		switch(cmd->opcode) {
797		case O_CHECK_STATE:
798			printf("check-state");
799			/* avoid printing anything else */
800			flags = HAVE_PROTO|HAVE_SRCIP|HAVE_DSTIP;
801			break;
802
803		case O_PROB:
804		    {
805			ipfw_insn_u32 *p = (ipfw_insn_u32 *)cmd;
806			double d = 1.0 * p->d[0];
807
808			d = 1 - (d / 0x7fffffff);
809			printf("prob %f ", d);
810		    }
811			break;
812
813		case O_ACCEPT:
814			printf("allow");
815			break;
816
817		case O_COUNT:
818			printf("count");
819			break;
820
821		case O_DENY:
822			printf("deny");
823			break;
824
825		case O_REJECT:
826			if (cmd->arg1 == ICMP_REJECT_RST)
827				printf("reset");
828			else if (cmd->arg1 == ICMP_UNREACH_HOST)
829				printf("reject");
830			else
831				print_reject_code(cmd->arg1);
832			break;
833
834		case O_SKIPTO:
835			printf("skipto %u", cmd->arg1);
836			break;
837
838		case O_PIPE:
839			printf("pipe %u", cmd->arg1);
840			break;
841
842		case O_QUEUE:
843			printf("queue %u", cmd->arg1);
844			break;
845
846		case O_DIVERT:
847			printf("divert %u", cmd->arg1);
848			break;
849
850		case O_TEE:
851			printf("tee %u", cmd->arg1);
852			break;
853
854		case O_FORWARD_IP:
855		    {
856			ipfw_insn_sa *s = (ipfw_insn_sa *)cmd;
857
858			printf("fwd %s", inet_ntoa(s->sa.sin_addr));
859			if (s->sa.sin_port)
860				printf(",%d", ntohs(s->sa.sin_port));
861		    }
862			break;
863
864		case O_LOG: /* O_LOG is printed last */
865			logptr = (ipfw_insn_log *)cmd;
866			break;
867
868		default:
869			printf("** unrecognized action %d len %d",
870				cmd->opcode, cmd->len);
871		}
872	}
873	if (logptr) {
874		if (logptr->max_log > 0)
875			printf(" log logamount %d", logptr->max_log);
876		else
877			printf(" log");
878	}
879	/*
880	 * then print the body
881	 */
882        for (l = rule->act_ofs, cmd = rule->cmd ;
883			l > 0 ; l -= F_LEN(cmd) , cmd += F_LEN(cmd)) {
884		/* useful alias */
885		ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;
886
887		switch(cmd->opcode) {
888		case O_PROBE_STATE:
889			break; /* no need to print anything here */
890
891		case O_MACADDR2: {
892			ipfw_insn_mac *m = (ipfw_insn_mac *)cmd;
893			if ( (flags & HAVE_MAC) == 0)
894				printf(" MAC");
895			flags |= HAVE_MAC;
896			if (cmd->len & F_NOT)
897				printf(" not");
898			print_mac( m->addr, m->mask);
899			print_mac( m->addr + 6, m->mask + 6);
900			}
901			break;
902
903		case O_MAC_TYPE:
904			print_newports((ipfw_insn_u16 *)cmd, IPPROTO_ETHERTYPE);
905			break;
906
907		case O_IP_SRC:
908		case O_IP_SRC_MASK:
909		case O_IP_SRC_ME:
910		case O_IP_SRC_SET:
911			show_prerequisites(&flags, HAVE_PROTO);
912			if (!(flags & HAVE_SRCIP))
913				printf(" from");
914			if ((cmd->len & F_OR) && !or_block)
915				printf(" {");
916			print_ip((ipfw_insn_ip *)cmd);
917			flags |= HAVE_SRCIP;
918			break;
919
920		case O_IP_DST:
921		case O_IP_DST_MASK:
922		case O_IP_DST_ME:
923		case O_IP_DST_SET:
924			show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP);
925			if (!(flags & HAVE_DSTIP))
926				printf(" to");
927			if ((cmd->len & F_OR) && !or_block)
928				printf(" {");
929			print_ip((ipfw_insn_ip *)cmd);
930			flags |= HAVE_DSTIP;
931			break;
932
933		case O_IP_DSTPORT:
934			show_prerequisites(&flags,
935				HAVE_PROTO|HAVE_SRCIP|HAVE_DSTIP);
936		case O_IP_SRCPORT:
937			show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP);
938			print_newports((ipfw_insn_u16 *)cmd, proto);
939			break;
940
941		case O_PROTO: {
942			struct protoent *pe;
943
944			if ((cmd->len & F_OR) && !or_block)
945				printf(" {");
946			if (cmd->len & F_NOT)
947				printf(" not");
948			proto = cmd->arg1;
949			pe = getprotobynumber(cmd->arg1);
950			if (pe)
951				printf(" %s", pe->p_name);
952			else
953				printf(" %u", cmd->arg1);
954			}
955			flags |= HAVE_PROTO;
956			break;
957
958		default: /*options ... */
959			show_prerequisites(&flags,
960			    HAVE_PROTO|HAVE_SRCIP|HAVE_DSTIP);
961			if ((cmd->len & F_OR) && !or_block)
962				printf(" {");
963			if (cmd->len & F_NOT && cmd->opcode != O_IN)
964				printf(" not");
965			switch(cmd->opcode) {
966			case O_FRAG:
967				printf(" frag");
968				break;
969
970			case O_IN:
971				printf(cmd->len & F_NOT ? " out" : " in");
972				break;
973
974			case O_LAYER2:
975				printf(" layer2");
976				break;
977			case O_XMIT:
978			case O_RECV:
979			case O_VIA: {
980				char *s;
981				ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd;
982
983				if (cmd->opcode == O_XMIT)
984					s = "xmit";
985				else if (cmd->opcode == O_RECV)
986					s = "recv";
987				else if (cmd->opcode == O_VIA)
988					s = "via";
989				if (cmdif->name[0] == '\0')
990					printf(" %s %s", s,
991					    inet_ntoa(cmdif->p.ip));
992				else if (cmdif->p.unit == -1)
993					printf(" %s %s*", s, cmdif->name);
994				else
995					printf(" %s %s%d", s, cmdif->name,
996					    cmdif->p.unit);
997				}
998				break;
999
1000			case O_IPID:
1001				printf(" ipid %u", cmd->arg1 );
1002				break;
1003
1004			case O_IPTTL:
1005				printf(" ipttl %u", cmd->arg1 );
1006				break;
1007
1008			case O_IPVER:
1009				printf(" ipver %u", cmd->arg1 );
1010				break;
1011
1012			case O_IPPRECEDENCE:
1013				printf(" ipprecedence %u", (cmd->arg1) >> 5 );
1014				break;
1015
1016			case O_IPLEN:
1017				printf(" iplen %u", cmd->arg1 );
1018				break;
1019
1020			case O_IPOPT:
1021				print_flags("ipoptions", cmd, f_ipopts);
1022				break;
1023
1024			case O_IPTOS:
1025				print_flags("iptos", cmd, f_iptos);
1026				break;
1027
1028			case O_ICMPTYPE:
1029				print_icmptypes((ipfw_insn_u32 *)cmd);
1030				break;
1031
1032			case O_ESTAB:
1033				printf(" established");
1034				break;
1035
1036			case O_TCPFLAGS:
1037				print_flags("tcpflags", cmd, f_tcpflags);
1038				break;
1039
1040			case O_TCPOPTS:
1041				print_flags("tcpoptions", cmd, f_tcpopts);
1042				break;
1043
1044			case O_TCPWIN:
1045				printf(" tcpwin %d", ntohs(cmd->arg1));
1046				break;
1047
1048			case O_TCPACK:
1049				printf(" tcpack %d", ntohl(cmd32->d[0]));
1050				break;
1051
1052			case O_TCPSEQ:
1053				printf(" tcpseq %d", ntohl(cmd32->d[0]));
1054				break;
1055
1056			case O_UID:
1057			    {
1058				struct passwd *pwd = getpwuid(cmd32->d[0]);
1059
1060				if (pwd)
1061					printf(" uid %s", pwd->pw_name);
1062				else
1063					printf(" uid %u", cmd32->d[0]);
1064			    }
1065				break;
1066
1067			case O_GID:
1068			    {
1069				struct group *grp = getgrgid(cmd32->d[0]);
1070
1071				if (grp)
1072					printf(" gid %s", grp->gr_name);
1073				else
1074					printf(" gid %u", cmd32->d[0]);
1075			    }
1076				break;
1077
1078			case O_KEEP_STATE:
1079				printf(" keep-state");
1080				break;
1081
1082			case O_LIMIT:
1083			    {
1084				struct _s_x *p = limit_masks;
1085				ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
1086				u_int8_t x = c->limit_mask;
1087				char *comma = " ";
1088
1089				printf(" limit");
1090				for ( ; p->x != 0 ; p++)
1091					if ((x & p->x) == p->x) {
1092						x &= ~p->x;
1093						printf("%s%s", comma, p->s);
1094						comma = ",";
1095					}
1096				printf(" %d", c->conn_limit);
1097			    }
1098				break;
1099
1100			default:
1101				printf(" [opcode %d len %d]",
1102				    cmd->opcode, cmd->len);
1103			}
1104		}
1105		if (cmd->len & F_OR) {
1106			printf(" or");
1107			or_block = 1;
1108		} else if (or_block) {
1109			printf(" }");
1110			or_block = 0;
1111		}
1112	}
1113	show_prerequisites(&flags, HAVE_PROTO|HAVE_SRCIP|HAVE_DSTIP);
1114
1115	printf("\n");
1116}
1117
1118static void
1119show_dyn_ipfw(ipfw_dyn_rule *d)
1120{
1121	struct protoent *pe;
1122	struct in_addr a;
1123
1124	if (!do_expired) {
1125		if (!d->expire && !(d->dyn_type == O_LIMIT_PARENT))
1126			return;
1127	}
1128
1129	printf("%05d %10qu %10qu (%ds)",
1130	    (int)(d->rule), d->pcnt, d->bcnt, d->expire);
1131	switch (d->dyn_type) {
1132	case O_LIMIT_PARENT:
1133		printf(" PARENT %d", d->count);
1134		break;
1135	case O_LIMIT:
1136		printf(" LIMIT");
1137		break;
1138	case O_KEEP_STATE: /* bidir, no mask */
1139		printf(" STATE");
1140		break;
1141	}
1142
1143	if ((pe = getprotobynumber(d->id.proto)) != NULL)
1144		printf(" %s", pe->p_name);
1145	else
1146		printf(" proto %u", d->id.proto);
1147
1148	a.s_addr = htonl(d->id.src_ip);
1149	printf(" %s %d", inet_ntoa(a), d->id.src_port);
1150
1151	a.s_addr = htonl(d->id.dst_ip);
1152	printf(" <-> %s %d", inet_ntoa(a), d->id.dst_port);
1153	printf("\n");
1154}
1155
1156int
1157sort_q(const void *pa, const void *pb)
1158{
1159	int rev = (do_sort < 0);
1160	int field = rev ? -do_sort : do_sort;
1161	long long res = 0;
1162	const struct dn_flow_queue *a = pa;
1163	const struct dn_flow_queue *b = pb;
1164
1165	switch (field) {
1166	case 1: /* pkts */
1167		res = a->len - b->len;
1168		break;
1169	case 2: /* bytes */
1170		res = a->len_bytes - b->len_bytes;
1171		break;
1172
1173	case 3: /* tot pkts */
1174		res = a->tot_pkts - b->tot_pkts;
1175		break;
1176
1177	case 4: /* tot bytes */
1178		res = a->tot_bytes - b->tot_bytes;
1179		break;
1180	}
1181	if (res < 0)
1182		res = -1;
1183	if (res > 0)
1184		res = 1;
1185	return (int)(rev ? res : -res);
1186}
1187
1188static void
1189list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q)
1190{
1191	int l;
1192
1193	printf("    mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
1194	    fs->flow_mask.proto,
1195	    fs->flow_mask.src_ip, fs->flow_mask.src_port,
1196	    fs->flow_mask.dst_ip, fs->flow_mask.dst_port);
1197	if (fs->rq_elements == 0)
1198		return;
1199
1200	printf("BKT Prot ___Source IP/port____ "
1201	    "____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp\n");
1202	if (do_sort != 0)
1203		heapsort(q, fs->rq_elements, sizeof *q, sort_q);
1204	for (l = 0; l < fs->rq_elements; l++) {
1205		struct in_addr ina;
1206		struct protoent *pe;
1207
1208		ina.s_addr = htonl(q[l].id.src_ip);
1209		printf("%3d ", q[l].hash_slot);
1210		pe = getprotobynumber(q[l].id.proto);
1211		if (pe)
1212			printf("%-4s ", pe->p_name);
1213		else
1214			printf("%4u ", q[l].id.proto);
1215		printf("%15s/%-5d ",
1216		    inet_ntoa(ina), q[l].id.src_port);
1217		ina.s_addr = htonl(q[l].id.dst_ip);
1218		printf("%15s/%-5d ",
1219		    inet_ntoa(ina), q[l].id.dst_port);
1220		printf("%4qu %8qu %2u %4u %3u\n",
1221		    q[l].tot_pkts, q[l].tot_bytes,
1222		    q[l].len, q[l].len_bytes, q[l].drops);
1223		if (verbose)
1224			printf("   S %20qd  F %20qd\n",
1225			    q[l].S, q[l].F);
1226	}
1227}
1228
1229static void
1230print_flowset_parms(struct dn_flow_set *fs, char *prefix)
1231{
1232	int l;
1233	char qs[30];
1234	char plr[30];
1235	char red[90];	/* Display RED parameters */
1236
1237	l = fs->qsize;
1238	if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
1239		if (l >= 8192)
1240			sprintf(qs, "%d KB", l / 1024);
1241		else
1242			sprintf(qs, "%d B", l);
1243	} else
1244		sprintf(qs, "%3d sl.", l);
1245	if (fs->plr)
1246		sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
1247	else
1248		plr[0] = '\0';
1249	if (fs->flags_fs & DN_IS_RED)	/* RED parameters */
1250		sprintf(red,
1251		    "\n\t  %cRED w_q %f min_th %d max_th %d max_p %f",
1252		    (fs->flags_fs & DN_IS_GENTLE_RED) ? 'G' : ' ',
1253		    1.0 * fs->w_q / (double)(1 << SCALE_RED),
1254		    SCALE_VAL(fs->min_th),
1255		    SCALE_VAL(fs->max_th),
1256		    1.0 * fs->max_p / (double)(1 << SCALE_RED));
1257	else
1258		sprintf(red, "droptail");
1259
1260	printf("%s %s%s %d queues (%d buckets) %s\n",
1261	    prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
1262}
1263
1264static void
1265list_pipes(void *data, int nbytes, int ac, char *av[])
1266{
1267	u_long rulenum;
1268	void *next = data;
1269	struct dn_pipe *p = (struct dn_pipe *) data;
1270	struct dn_flow_set *fs;
1271	struct dn_flow_queue *q;
1272	int l;
1273
1274	if (ac > 0)
1275		rulenum = strtoul(*av++, NULL, 10);
1276	else
1277		rulenum = 0;
1278	for (; nbytes >= sizeof *p; p = (struct dn_pipe *)next) {
1279		double b = p->bandwidth;
1280		char buf[30];
1281		char prefix[80];
1282
1283		if (p->next != (struct dn_pipe *)DN_IS_PIPE)
1284			break;	/* done with pipes, now queues */
1285
1286		/*
1287		 * compute length, as pipe have variable size
1288		 */
1289		l = sizeof(*p) + p->fs.rq_elements * sizeof(*q);
1290		next = (void *)p + l;
1291		nbytes -= l;
1292
1293		if (rulenum != 0 && rulenum != p->pipe_nr)
1294			continue;
1295
1296		/*
1297		 * Print rate (or clocking interface)
1298		 */
1299		if (p->if_name[0] != '\0')
1300			sprintf(buf, "%s", p->if_name);
1301		else if (b == 0)
1302			sprintf(buf, "unlimited");
1303		else if (b >= 1000000)
1304			sprintf(buf, "%7.3f Mbit/s", b/1000000);
1305		else if (b >= 1000)
1306			sprintf(buf, "%7.3f Kbit/s", b/1000);
1307		else
1308			sprintf(buf, "%7.3f bit/s ", b);
1309
1310		sprintf(prefix, "%05d: %s %4d ms ",
1311		    p->pipe_nr, buf, p->delay);
1312		print_flowset_parms(&(p->fs), prefix);
1313		if (verbose)
1314			printf("   V %20qd\n", p->V >> MY_M);
1315
1316		q = (struct dn_flow_queue *)(p+1);
1317		list_queues(&(p->fs), q);
1318	}
1319	for (fs = next; nbytes >= sizeof *fs; fs = next) {
1320		char prefix[80];
1321
1322		if (fs->next != (struct dn_flow_set *)DN_IS_QUEUE)
1323			break;
1324		l = sizeof(*fs) + fs->rq_elements * sizeof(*q);
1325		next = (void *)fs + l;
1326		nbytes -= l;
1327		q = (struct dn_flow_queue *)(fs+1);
1328		sprintf(prefix, "q%05d: weight %d pipe %d ",
1329		    fs->fs_nr, fs->weight, fs->parent_nr);
1330		print_flowset_parms(fs, prefix);
1331		list_queues(fs, q);
1332	}
1333}
1334
1335static void
1336list(int ac, char *av[])
1337{
1338	struct ip_fw *r;
1339	ipfw_dyn_rule *dynrules, *d;
1340
1341	void *lim, *data = NULL;
1342	int n, nbytes, nstat, ndyn;
1343	int exitval = EX_OK;
1344	int lac;
1345	char **lav;
1346	u_long rnum;
1347	char *endptr;
1348	int seen = 0;
1349
1350	const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
1351	int nalloc = 1024;	/* start somewhere... */
1352
1353	ac--;
1354	av++;
1355
1356	if (ac && !strncmp(*av, "sets", strlen(*av)) ) {
1357		int i;
1358		u_int32_t set_disable;
1359
1360		nbytes = sizeof(struct ip_fw);
1361		if ((data = malloc(nbytes)) == NULL)
1362			err(EX_OSERR, "malloc");
1363		if (getsockopt(s, IPPROTO_IP, IP_FW_GET, data, &nbytes) < 0)
1364			err(EX_OSERR, "getsockopt(IP_FW_GET)");
1365		set_disable = (u_int32_t)(((struct ip_fw *)data)->next_rule);
1366
1367		for (i = 0; i < 31; i++)
1368			printf("%s set %d\n",
1369			    set_disable & (1<<i) ? "disable" : "enable", i);
1370		return;
1371	}
1372
1373	/* get rules or pipes from kernel, resizing array as necessary */
1374	nbytes = nalloc;
1375
1376	while (nbytes >= nalloc) {
1377		nalloc = nalloc * 2 + 200;
1378		nbytes = nalloc;
1379		if ((data = realloc(data, nbytes)) == NULL)
1380			err(EX_OSERR, "realloc");
1381		if (getsockopt(s, IPPROTO_IP, ocmd, data, &nbytes) < 0)
1382			err(EX_OSERR, "getsockopt(IP_%s_GET)",
1383				do_pipe ? "DUMMYNET" : "FW");
1384	}
1385
1386	if (do_pipe) {
1387		list_pipes(data, nbytes, ac, av);
1388		goto done;
1389	}
1390
1391	/*
1392	 * Count static rules. They have variable size so we
1393	 * need to scan the list to count them.
1394	 */
1395	for (nstat = 1, r = data, lim = data + nbytes;
1396		    r->rulenum < 65535 && (void *)r < lim;
1397		    ++nstat, r = (void *)r + RULESIZE(r) )
1398		; /* nothing */
1399
1400	/*
1401	 * Count dynamic rules. This is easier as they have
1402	 * fixed size.
1403	 */
1404	r = (void *)r + RULESIZE(r);
1405	dynrules = (ipfw_dyn_rule *)r ;
1406	n = (void *)r - data;
1407	ndyn = (nbytes - n) / sizeof *dynrules;
1408
1409	/* if no rule numbers were specified, list all rules */
1410	if (ac == 0) {
1411		for (n = 0, r = data; n < nstat;
1412		    n++, r = (void *)r + RULESIZE(r) )
1413			show_ipfw(r);
1414
1415		if (do_dynamic && ndyn) {
1416			printf("## Dynamic rules (%d):\n", ndyn);
1417			for (n = 0, d = dynrules; n < ndyn; n++, d++)
1418				show_dyn_ipfw(d);
1419		}
1420		goto done;
1421	}
1422
1423	/* display specific rules requested on command line */
1424
1425	for (lac = ac, lav = av; lac != 0; lac--) {
1426		/* convert command line rule # */
1427		rnum = strtoul(*lav++, &endptr, 10);
1428		if (*endptr) {
1429			exitval = EX_USAGE;
1430			warnx("invalid rule number: %s", *(lav - 1));
1431			continue;
1432		}
1433		for (n = seen = 0, r = data; n < nstat;
1434		    n++, r = (void *)r + RULESIZE(r) ) {
1435			if (r->rulenum > rnum)
1436				break;
1437			if (r->rulenum == rnum) {
1438				show_ipfw(r);
1439				seen = 1;
1440			}
1441		}
1442		if (!seen) {
1443			/* give precedence to other error(s) */
1444			if (exitval == EX_OK)
1445				exitval = EX_UNAVAILABLE;
1446			warnx("rule %lu does not exist", rnum);
1447		}
1448	}
1449
1450	if (do_dynamic && ndyn) {
1451		printf("## Dynamic rules:\n");
1452		for (lac = ac, lav = av; lac != 0; lac--) {
1453			rnum = strtoul(*lav++, &endptr, 10);
1454			if (*endptr)
1455				/* already warned */
1456				continue;
1457			for (n = 0, d = dynrules; n < ndyn; n++, d++) {
1458				if ((int)(d->rule) > rnum)
1459					break;
1460				if ((int)(d->rule) == rnum)
1461					show_dyn_ipfw(d);
1462			}
1463		}
1464	}
1465
1466	ac = 0;
1467
1468done:
1469	free(data);
1470
1471	if (exitval != EX_OK)
1472		exit(exitval);
1473}
1474
1475static void
1476show_usage(void)
1477{
1478	fprintf(stderr, "usage: ipfw [options]\n"
1479"    add [number] rule\n"
1480"    pipe number config [pipeconfig]\n"
1481"    queue number config [queueconfig]\n"
1482"    [pipe] flush\n"
1483"    [pipe] delete number ...\n"
1484"    [pipe] {list|show} [number ...]\n"
1485"    {zero|resetlog} [number ...]\n"
1486"do \"ipfw -h\" or see ipfw manpage for details\n"
1487);
1488
1489	exit(EX_USAGE);
1490}
1491
1492static void
1493help(void)
1494{
1495
1496	fprintf(stderr, "ipfw syntax summary:\n"
1497"ipfw add [N] [prob {0..1}] ACTION [log [logamount N]] ADDR OPTIONS\n"
1498"ipfw {pipe|queue} N config BODY\n"
1499"ipfw [pipe] {zero|delete|show} [N{,N}]\n"
1500"\n"
1501"RULE:		[1..] [PROB] BODY\n"
1502"RULENUM:	INTEGER(1..65534)\n"
1503"PROB:		prob REAL(0..1)\n"
1504"BODY:		check-state [LOG] (no body) |\n"
1505"		ACTION [LOG] MATCH_ADDR [OPTION_LIST]\n"
1506"ACTION:	check-state | allow | count | deny | reject | skipto N |\n"
1507"		{divert|tee} PORT | forward ADDR | pipe N | queue N\n"
1508"ADDR:		[ MAC dst src ether_type ] \n"
1509"		[ from IPLIST [ PORT ] to IPLIST [ PORTLIST ] ]\n"
1510"IPLIST:	IPADDR | ( IPADDR or ... or IPADDR )\n"
1511"IPADDR:	[not] { any | me | ip | ip/bits | ip:mask | ip/bits{x,y,z} }\n"
1512"OPTION_LIST:	OPTION [,OPTION_LIST]\n"
1513);
1514exit(0);
1515}
1516
1517
1518static int
1519lookup_host (char *host, struct in_addr *ipaddr)
1520{
1521	struct hostent *he;
1522
1523	if (!inet_aton(host, ipaddr)) {
1524		if ((he = gethostbyname(host)) == NULL)
1525			return(-1);
1526		*ipaddr = *(struct in_addr *)he->h_addr_list[0];
1527	}
1528	return(0);
1529}
1530
1531/*
1532 * fills the addr and mask fields in the instruction as appropriate from av.
1533 * Update length as appropriate.
1534 * The following formats are allowed:
1535 *	any	matches any IP. Actually returns an empty instruction.
1536 *	me	returns O_IP_*_ME
1537 *	1.2.3.4		single IP address
1538 *	1.2.3.4:5.6.7.8	address:mask
1539 *	1.2.3.4/24	address/mask
1540 *	1.2.3.4/26{1,6,5,4,23}	set of addresses in a subnet
1541 */
1542static void
1543fill_ip(ipfw_insn_ip *cmd, char *av)
1544{
1545	char *p = 0, md = 0;
1546	u_int32_t i;
1547
1548	cmd->o.len &= ~F_LEN_MASK;	/* zero len */
1549
1550	if (!strncmp(av, "any", strlen(av)))
1551		return;
1552
1553	if (!strncmp(av, "me", strlen(av))) {
1554		cmd->o.len |= F_INSN_SIZE(ipfw_insn);
1555		return;
1556	}
1557
1558	p = strchr(av, '/');
1559	if (!p)
1560		p = strchr(av, ':');
1561	if (p) {
1562		md = *p;
1563		*p++ = '\0';
1564	}
1565
1566	if (lookup_host(av, &cmd->addr) != 0)
1567		errx(EX_NOHOST, "hostname ``%s'' unknown", av);
1568	switch (md) {
1569	case ':':
1570		if (!inet_aton(p, &cmd->mask))
1571			errx(EX_DATAERR, "bad netmask ``%s''", p);
1572		break;
1573	case '/':
1574		i = atoi(p);
1575		if (i == 0)
1576			cmd->mask.s_addr = htonl(0);
1577		else if (i > 32)
1578			errx(EX_DATAERR, "bad width ``%s''", p);
1579		else
1580			cmd->mask.s_addr = htonl(~0 << (32 - i));
1581		break;
1582	default:
1583		cmd->mask.s_addr = htonl(~0);
1584		break;
1585	}
1586	cmd->addr.s_addr &= cmd->mask.s_addr;
1587	/*
1588	 * now look if we have a set of addresses. They are stored as follows:
1589	 *   arg1	is the set size (powers of 2, 2..256)
1590	 *   addr	is the base address IN HOST FORMAT
1591	 *   mask..	is an array of u_int32_t with bits set.
1592	 */
1593	if (p)
1594		p = strchr(p, '{');
1595	if (p) {	/* fetch addresses */
1596		u_int32_t *d;
1597		int low, high;
1598		int i = contigmask((u_char *)&(cmd->mask), 32);
1599
1600		if (i < 24 || i > 31) {
1601			fprintf(stderr, "invalid set with mask %d\n",
1602				i);
1603			exit(0);
1604		}
1605		cmd->o.arg1 = 1<<(32-i);
1606		cmd->addr.s_addr = ntohl(cmd->addr.s_addr);
1607		d = (u_int32_t *)&cmd->mask;
1608		cmd->o.opcode = O_IP_DST_SET;	/* default */
1609		cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32) + (cmd->o.arg1+31)/32;
1610		for (i = 0; i < (cmd->o.arg1+31)/32 ; i++)
1611			d[i] = 0;	/* clear masks */
1612
1613		av = p+1;
1614		low = cmd->addr.s_addr & 0xff;
1615		high = low + cmd->o.arg1 - 1;
1616		while (isdigit(*av)) {
1617			char *s;
1618			u_int16_t a = strtol(av, &s, 0);
1619
1620			if (s == av) /* no parameter */
1621				break;
1622			if (a < low || a > high) {
1623			    fprintf(stderr, "addr %d out of range [%d-%d]\n",
1624				a, low, high);
1625			    exit(0);
1626			}
1627			a -= low;
1628			d[ a/32] |= 1<<(a & 31);
1629			if (*s != ',')
1630				break;
1631			av = s+1;
1632		}
1633		return;
1634	}
1635
1636	if (cmd->mask.s_addr == 0) { /* any */
1637		if (cmd->o.len & F_NOT)
1638			errx(EX_DATAERR, "not any never matches");
1639		else	/* useless, nuke it */
1640			return;
1641	} else if (cmd->mask.s_addr ==  IP_MASK_ALL)	/* one IP */
1642		cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
1643	else						/* addr/mask */
1644		cmd->o.len |= F_INSN_SIZE(ipfw_insn_ip);
1645}
1646
1647
1648/*
1649 * helper function to process a set of flags and set bits in the
1650 * appropriate masks.
1651 */
1652static void
1653fill_flags(ipfw_insn *cmd, enum ipfw_opcodes opcode,
1654	struct _s_x *flags, char *p)
1655{
1656	u_int8_t set=0, clear=0;
1657
1658	while (p && *p) {
1659		char *q;	/* points to the separator */
1660		int val;
1661		u_int8_t *which;	/* mask we are working on */
1662
1663		if (*p == '!') {
1664			p++;
1665			which = &clear;
1666		} else
1667			which = &set;
1668		q = strchr(p, ',');
1669		if (q)
1670			*q++ = '\0';
1671		val = match_token(flags, p);
1672		if (val <= 0)
1673			errx(EX_DATAERR, "invalid flag %s", p);
1674		*which |= (u_int8_t)val;
1675		p = q;
1676	}
1677        cmd->opcode = opcode;
1678        cmd->len =  (cmd->len & (F_NOT | F_OR)) | 1;
1679        cmd->arg1 = (set & 0xff) | ( (clear & 0xff) << 8);
1680}
1681
1682
1683static void
1684delete(int ac, char *av[])
1685{
1686	int rulenum;
1687	struct dn_pipe pipe;
1688	int i;
1689	int exitval = EX_OK;
1690	int do_set = 0;
1691
1692	memset(&pipe, 0, sizeof pipe);
1693
1694	if (!strncmp(*av, "disable", strlen(*av)))
1695		do_set = 2;	/* disable set */
1696	else if (!strncmp(*av, "enable", strlen(*av)))
1697		do_set = 3;	/* enable set */
1698	av++; ac--;
1699	if (!strncmp(*av, "set", strlen(*av))) {
1700		if (do_set == 0)
1701			do_set = 1;	/* delete set */
1702		ac--; av++;
1703	} else if (do_set != 0)
1704		errx(EX_DATAERR, "missing 'set' keyword");
1705
1706	/* Rule number */
1707	while (ac && isdigit(**av)) {
1708		i = atoi(*av); av++; ac--;
1709		if (do_pipe) {
1710			if (do_pipe == 1)
1711				pipe.pipe_nr = i;
1712			else
1713				pipe.fs.fs_nr = i;
1714			i = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_DEL,
1715			    &pipe, sizeof pipe);
1716			if (i) {
1717				exitval = 1;
1718				warn("rule %u: setsockopt(IP_DUMMYNET_DEL)",
1719				    do_pipe == 1 ? pipe.pipe_nr :
1720				    pipe.fs.fs_nr);
1721			}
1722		} else {
1723			rulenum =  (i & 0xffff) | (do_set << 16);
1724			i = setsockopt(s, IPPROTO_IP, IP_FW_DEL, &rulenum,
1725			    sizeof rulenum);
1726			if (i) {
1727				exitval = EX_UNAVAILABLE;
1728				warn("rule %u: setsockopt(IP_FW_DEL)",
1729				    rulenum);
1730			}
1731		}
1732	}
1733	if (exitval != EX_OK)
1734		exit(exitval);
1735}
1736
1737
1738/*
1739 * fill the interface structure. We do not check the name as we can
1740 * create interfaces dynamically, so checking them at insert time
1741 * makes relatively little sense.
1742 * A '*' following the name means any unit.
1743 */
1744static void
1745fill_iface(ipfw_insn_if *cmd, char *arg)
1746{
1747	cmd->name[0] = '\0';
1748	cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
1749
1750	/* Parse the interface or address */
1751	if (!strcmp(arg, "any"))
1752		cmd->o.len = 0;		/* effectively ignore this command */
1753	else if (!isdigit(*arg)) {
1754		char *q;
1755
1756		strncpy(cmd->name, arg, sizeof(cmd->name));
1757		cmd->name[sizeof(cmd->name) - 1] = '\0';
1758		/* find first digit or wildcard */
1759		for (q = cmd->name; *q && !isdigit(*q) && *q != '*'; q++)
1760			continue;
1761		cmd->p.unit = (*q == '*') ? -1 : atoi(q);
1762		*q = '\0';
1763	} else if (!inet_aton(arg, &cmd->p.ip))
1764		errx(EX_DATAERR, "bad ip address ``%s''", arg);
1765}
1766
1767/*
1768 * the following macro returns an error message if we run out of
1769 * arguments.
1770 */
1771#define	NEED1(msg)	{if (!ac) errx(EX_USAGE, msg);}
1772
1773static void
1774config_pipe(int ac, char **av)
1775{
1776	struct dn_pipe pipe;
1777	int i;
1778	char *end;
1779	u_int32_t a;
1780	void *par = NULL;
1781
1782	memset(&pipe, 0, sizeof pipe);
1783
1784	av++; ac--;
1785	/* Pipe number */
1786	if (ac && isdigit(**av)) {
1787		i = atoi(*av); av++; ac--;
1788		if (do_pipe == 1)
1789			pipe.pipe_nr = i;
1790		else
1791			pipe.fs.fs_nr = i;
1792	}
1793	while (ac > 0) {
1794		double d;
1795		int tok = match_token(dummynet_params, *av);
1796		ac--; av++;
1797
1798		switch(tok) {
1799		case TOK_PLR:
1800			NEED1("plr needs argument 0..1\n");
1801			d = strtod(av[0], NULL);
1802			if (d > 1)
1803				d = 1;
1804			else if (d < 0)
1805				d = 0;
1806			pipe.fs.plr = (int)(d*0x7fffffff);
1807			ac--; av++;
1808			break;
1809
1810		case TOK_QUEUE:
1811			NEED1("queue needs queue size\n");
1812			end = NULL;
1813			pipe.fs.qsize = strtoul(av[0], &end, 0);
1814			if (*end == 'K' || *end == 'k') {
1815				pipe.fs.flags_fs |= DN_QSIZE_IS_BYTES;
1816				pipe.fs.qsize *= 1024;
1817			} else if (*end == 'B' || !strncmp(end, "by", 2)) {
1818				pipe.fs.flags_fs |= DN_QSIZE_IS_BYTES;
1819			}
1820			ac--; av++;
1821			break;
1822
1823		case TOK_BUCKETS:
1824			NEED1("buckets needs argument\n");
1825			pipe.fs.rq_size = strtoul(av[0], NULL, 0);
1826			ac--; av++;
1827			break;
1828
1829		case TOK_MASK:
1830			NEED1("mask needs mask specifier\n");
1831			/*
1832			 * per-flow queue, mask is dst_ip, dst_port,
1833			 * src_ip, src_port, proto measured in bits
1834			 */
1835			par = NULL;
1836
1837			pipe.fs.flow_mask.dst_ip = 0;
1838			pipe.fs.flow_mask.src_ip = 0;
1839			pipe.fs.flow_mask.dst_port = 0;
1840			pipe.fs.flow_mask.src_port = 0;
1841			pipe.fs.flow_mask.proto = 0;
1842			end = NULL;
1843
1844			while (ac >= 1) {
1845			    u_int32_t *p32 = NULL;
1846			    u_int16_t *p16 = NULL;
1847
1848			    tok = match_token(dummynet_params, *av);
1849			    ac--; av++;
1850			    switch(tok) {
1851			    case TOK_ALL:
1852				    /*
1853				     * special case, all bits significant
1854				     */
1855				    pipe.fs.flow_mask.dst_ip = ~0;
1856				    pipe.fs.flow_mask.src_ip = ~0;
1857				    pipe.fs.flow_mask.dst_port = ~0;
1858				    pipe.fs.flow_mask.src_port = ~0;
1859				    pipe.fs.flow_mask.proto = ~0;
1860				    pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1861				    goto end_mask;
1862
1863			    case TOK_DSTIP:
1864				    p32 = &pipe.fs.flow_mask.dst_ip;
1865				    break;
1866
1867			    case TOK_SRCIP:
1868				    p32 = &pipe.fs.flow_mask.src_ip;
1869				    break;
1870
1871			    case TOK_DSTPORT:
1872				    p16 = &pipe.fs.flow_mask.dst_port;
1873				    break;
1874
1875			    case TOK_SRCPORT:
1876				    p16 = &pipe.fs.flow_mask.src_port;
1877				    break;
1878
1879			    case TOK_PROTO:
1880				    break;
1881
1882			    default:
1883				    ac++; av--; /* backtrack */
1884				    goto end_mask;
1885			    }
1886			    if (ac < 1)
1887				    errx(EX_USAGE, "mask: value missing");
1888			    if (*av[0] == '/') {
1889				    a = strtoul(av[0]+1, &end, 0);
1890				    a = (a == 32) ? ~0 : (1 << a) - 1;
1891			    } else
1892				    a = strtoul(av[0], &end, 0);
1893			    if (p32 != NULL)
1894				    *p32 = a;
1895			    else if (p16 != NULL) {
1896				    if (a > 65535)
1897					    errx(EX_DATAERR,
1898						"mask: must be 16 bit");
1899				    *p16 = (u_int16_t)a;
1900			    } else {
1901				    if (a > 255)
1902					    errx(EX_DATAERR,
1903						"mask: must be 8 bit");
1904				    pipe.fs.flow_mask.proto = (u_int8_t)a;
1905			    }
1906			    if (a != 0)
1907				    pipe.fs.flags_fs |= DN_HAVE_FLOW_MASK;
1908			    ac--; av++;
1909			} /* end while, config masks */
1910end_mask:
1911			break;
1912
1913		case TOK_RED:
1914		case TOK_GRED:
1915			NEED1("red/gred needs w_q/min_th/max_th/max_p\n");
1916			pipe.fs.flags_fs |= DN_IS_RED;
1917			if (tok == TOK_GRED)
1918				pipe.fs.flags_fs |= DN_IS_GENTLE_RED;
1919			/*
1920			 * the format for parameters is w_q/min_th/max_th/max_p
1921			 */
1922			if ((end = strsep(&av[0], "/"))) {
1923			    double w_q = strtod(end, NULL);
1924			    if (w_q > 1 || w_q <= 0)
1925				errx(EX_DATAERR, "0 < w_q <= 1");
1926			    pipe.fs.w_q = (int) (w_q * (1 << SCALE_RED));
1927			}
1928			if ((end = strsep(&av[0], "/"))) {
1929			    pipe.fs.min_th = strtoul(end, &end, 0);
1930			    if (*end == 'K' || *end == 'k')
1931				pipe.fs.min_th *= 1024;
1932			}
1933			if ((end = strsep(&av[0], "/"))) {
1934			    pipe.fs.max_th = strtoul(end, &end, 0);
1935			    if (*end == 'K' || *end == 'k')
1936				pipe.fs.max_th *= 1024;
1937			}
1938			if ((end = strsep(&av[0], "/"))) {
1939			    double max_p = strtod(end, NULL);
1940			    if (max_p > 1 || max_p <= 0)
1941				errx(EX_DATAERR, "0 < max_p <= 1");
1942			    pipe.fs.max_p = (int)(max_p * (1 << SCALE_RED));
1943			}
1944			ac--; av++;
1945			break;
1946
1947		case TOK_DROPTAIL:
1948			pipe.fs.flags_fs &= ~(DN_IS_RED|DN_IS_GENTLE_RED);
1949			break;
1950
1951		case TOK_BW:
1952			NEED1("bw needs bandwidth or interface\n");
1953			if (do_pipe != 1)
1954			    errx(EX_DATAERR, "bandwidth only valid for pipes");
1955			/*
1956			 * set clocking interface or bandwidth value
1957			 */
1958			if (av[0][0] >= 'a' && av[0][0] <= 'z') {
1959			    int l = sizeof(pipe.if_name)-1;
1960			    /* interface name */
1961			    strncpy(pipe.if_name, av[0], l);
1962			    pipe.if_name[l] = '\0';
1963			    pipe.bandwidth = 0;
1964			} else {
1965			    pipe.if_name[0] = '\0';
1966			    pipe.bandwidth = strtoul(av[0], &end, 0);
1967			    if (*end == 'K' || *end == 'k') {
1968				end++;
1969				pipe.bandwidth *= 1000;
1970			    } else if (*end == 'M') {
1971				end++;
1972				pipe.bandwidth *= 1000000;
1973			    }
1974			    if (*end == 'B' || !strncmp(end, "by", 2))
1975				pipe.bandwidth *= 8;
1976			    if (pipe.bandwidth < 0)
1977				errx(EX_DATAERR, "bandwidth too large");
1978			}
1979			ac--; av++;
1980			break;
1981
1982		case TOK_DELAY:
1983			if (do_pipe != 1)
1984				errx(EX_DATAERR, "delay only valid for pipes");
1985			NEED1("delay needs argument 0..10000ms\n");
1986			pipe.delay = strtoul(av[0], NULL, 0);
1987			ac--; av++;
1988			break;
1989
1990		case TOK_WEIGHT:
1991			if (do_pipe == 1)
1992				errx(EX_DATAERR,"weight only valid for queues");
1993			NEED1("weight needs argument 0..100\n");
1994			pipe.fs.weight = strtoul(av[0], &end, 0);
1995			ac--; av++;
1996			break;
1997
1998		case TOK_PIPE:
1999			if (do_pipe == 1)
2000				errx(EX_DATAERR,"pipe only valid for queues");
2001			NEED1("pipe needs pipe_number\n");
2002			pipe.fs.parent_nr = strtoul(av[0], &end, 0);
2003			ac--; av++;
2004			break;
2005
2006		default:
2007			errx(EX_DATAERR, "unrecognised option ``%s''", *av);
2008		}
2009	}
2010	if (do_pipe == 1) {
2011		if (pipe.pipe_nr == 0)
2012			errx(EX_DATAERR, "pipe_nr must be > 0");
2013		if (pipe.delay > 10000)
2014			errx(EX_DATAERR, "delay must be < 10000");
2015	} else { /* do_pipe == 2, queue */
2016		if (pipe.fs.parent_nr == 0)
2017			errx(EX_DATAERR, "pipe must be > 0");
2018		if (pipe.fs.weight >100)
2019			errx(EX_DATAERR, "weight must be <= 100");
2020	}
2021	if (pipe.fs.flags_fs & DN_QSIZE_IS_BYTES) {
2022		if (pipe.fs.qsize > 1024*1024)
2023			errx(EX_DATAERR, "queue size must be < 1MB");
2024	} else {
2025		if (pipe.fs.qsize > 100)
2026			errx(EX_DATAERR, "2 <= queue size <= 100");
2027	}
2028	if (pipe.fs.flags_fs & DN_IS_RED) {
2029		size_t len;
2030		int lookup_depth, avg_pkt_size;
2031		double s, idle, weight, w_q;
2032		struct clockinfo clock;
2033		int t;
2034
2035		if (pipe.fs.min_th >= pipe.fs.max_th)
2036		    errx(EX_DATAERR, "min_th %d must be < than max_th %d",
2037			pipe.fs.min_th, pipe.fs.max_th);
2038		if (pipe.fs.max_th == 0)
2039		    errx(EX_DATAERR, "max_th must be > 0");
2040
2041		len = sizeof(int);
2042		if (sysctlbyname("net.inet.ip.dummynet.red_lookup_depth",
2043			&lookup_depth, &len, NULL, 0) == -1)
2044
2045		    errx(1, "sysctlbyname(\"%s\")",
2046			"net.inet.ip.dummynet.red_lookup_depth");
2047		if (lookup_depth == 0)
2048		    errx(EX_DATAERR, "net.inet.ip.dummynet.red_lookup_depth"
2049			" must be greater than zero");
2050
2051		len = sizeof(int);
2052		if (sysctlbyname("net.inet.ip.dummynet.red_avg_pkt_size",
2053			&avg_pkt_size, &len, NULL, 0) == -1)
2054
2055		    errx(1, "sysctlbyname(\"%s\")",
2056			"net.inet.ip.dummynet.red_avg_pkt_size");
2057		if (avg_pkt_size == 0)
2058			errx(EX_DATAERR,
2059			    "net.inet.ip.dummynet.red_avg_pkt_size must"
2060			    " be greater than zero");
2061
2062		len = sizeof(struct clockinfo);
2063		if (sysctlbyname("kern.clockrate", &clock, &len, NULL, 0) == -1)
2064			errx(1, "sysctlbyname(\"%s\")", "kern.clockrate");
2065
2066		/*
2067		 * Ticks needed for sending a medium-sized packet.
2068		 * Unfortunately, when we are configuring a WF2Q+ queue, we
2069		 * do not have bandwidth information, because that is stored
2070		 * in the parent pipe, and also we have multiple queues
2071		 * competing for it. So we set s=0, which is not very
2072		 * correct. But on the other hand, why do we want RED with
2073		 * WF2Q+ ?
2074		 */
2075		if (pipe.bandwidth==0) /* this is a WF2Q+ queue */
2076			s = 0;
2077		else
2078			s = clock.hz * avg_pkt_size * 8 / pipe.bandwidth;
2079
2080		/*
2081		 * max idle time (in ticks) before avg queue size becomes 0.
2082		 * NOTA:  (3/w_q) is approx the value x so that
2083		 * (1-w_q)^x < 10^-3.
2084		 */
2085		w_q = ((double)pipe.fs.w_q) / (1 << SCALE_RED);
2086		idle = s * 3. / w_q;
2087		pipe.fs.lookup_step = (int)idle / lookup_depth;
2088		if (!pipe.fs.lookup_step)
2089			pipe.fs.lookup_step = 1;
2090		weight = 1 - w_q;
2091		for (t = pipe.fs.lookup_step; t > 0; --t)
2092			weight *= weight;
2093		pipe.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
2094	}
2095	i = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_CONFIGURE, &pipe,
2096			    sizeof pipe);
2097	if (i)
2098		err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
2099}
2100
2101static void
2102get_mac_addr_mask(char *p, u_char *addr, u_char *mask)
2103{
2104	int i, l;
2105
2106	for (i=0; i<6; i++)
2107		addr[i] = mask[i] = 0;
2108	if (!strcmp(p, "any"))
2109		return;
2110
2111	for (i=0; *p && i<6;i++, p++) {
2112		addr[i] = strtol(p, &p, 16);
2113		if (*p != ':') /* we start with the mask */
2114			break;
2115	}
2116	if (*p == '/') { /* mask len */
2117		l = strtol(p+1, &p, 0);
2118		for (i=0; l>0; l -=8, i++)
2119			mask[i] = (l >=8) ? 0xff : (~0) << (8-l);
2120	} else if (*p == '&') { /* mask */
2121		for (i=0, p++; *p && i<6;i++, p++) {
2122			mask[i] = strtol(p, &p, 16);
2123			if (*p != ':')
2124				break;
2125		}
2126	} else if (*p == '\0') {
2127		for (i=0; i<6; i++)
2128			mask[i] = 0xff;
2129	}
2130	for (i=0; i<6; i++)
2131		addr[i] &= mask[i];
2132}
2133
2134/*
2135 * helper function, updates the pointer to cmd with the length
2136 * of the current command, and also cleans up the first word of
2137 * the new command in case it has been clobbered before.
2138 */
2139static ipfw_insn *
2140next_cmd(ipfw_insn *cmd)
2141{
2142	cmd += F_LEN(cmd);
2143	bzero(cmd, sizeof(*cmd));
2144	return cmd;
2145}
2146
2147/*
2148 * A function to fill simple commands of size 1.
2149 * Existing flags are preserved.
2150 */
2151static void
2152fill_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode, int flags, u_int16_t arg)
2153{
2154	cmd->opcode = opcode;
2155	cmd->len =  ((cmd->len | flags) & (F_NOT | F_OR)) | 1;
2156	cmd->arg1 = arg;
2157}
2158
2159/*
2160 * Fetch and add the MAC address and type, with masks. This generates one or
2161 * two microinstructions, and returns the pointer to the last one.
2162 */
2163static ipfw_insn *
2164add_mac(ipfw_insn *cmd, int ac, char *av[])
2165{
2166	ipfw_insn_mac *mac; /* also *src */
2167
2168	if (ac <3)
2169		errx(EX_DATAERR, "MAC dst src type");
2170
2171	cmd->opcode = O_MACADDR2;
2172	cmd->len = (cmd->len & (F_NOT | F_OR)) | F_INSN_SIZE(ipfw_insn_mac);
2173
2174	mac = (ipfw_insn_mac *)cmd;
2175	get_mac_addr_mask(av[0], mac->addr, mac->mask);		/* dst */
2176	get_mac_addr_mask(av[1], &(mac->addr[6]), &(mac->mask[6])); /* src */
2177	av += 2;
2178
2179	if (strcmp(av[0], "any") != 0) {	/* we have a non-null port */
2180		cmd += F_LEN(cmd);
2181
2182		fill_newports((ipfw_insn_u16 *)cmd, av[0], IPPROTO_ETHERTYPE);
2183		cmd->opcode = O_MAC_TYPE;
2184	}
2185
2186	return cmd;
2187}
2188
2189/*
2190 * Parse arguments and assemble the microinstructions which make up a rule.
2191 * Rules are added into the 'rulebuf' and then copied in the correct order
2192 * into the actual rule.
2193 *
2194 * The syntax for a rule starts with the action, followed by an
2195 * optional log action, and the various match patterns.
2196 * In the assembled microcode, the first opcode must be a O_PROBE_STATE
2197 * (generated if the rule includes a keep-state option), then the
2198 * various match patterns, the "log" action, and the actual action.
2199 *
2200 */
2201static void
2202add(int ac, char *av[])
2203{
2204	/*
2205	 * rules are added into the 'rulebuf' and then copied in
2206	 * the correct order into the actual rule.
2207	 * Some things that need to go out of order (prob, action etc.)
2208	 * go into actbuf[].
2209	 */
2210	static u_int32_t rulebuf[255], actbuf[255], cmdbuf[255];
2211
2212	ipfw_insn *src, *dst, *cmd, *action, *prev;
2213
2214	struct ip_fw *rule;
2215
2216	/*
2217	 * various flags used to record that we entered some fields.
2218	 */
2219	int have_mac = 0;	/* set if we have a MAC address */
2220	ipfw_insn *have_state = NULL;	/* check-state or keep-state */
2221
2222	int i;
2223
2224	int open_par = 0;	/* open parenthesis ( */
2225
2226	/* proto is here because it is used to fetch ports */
2227	u_char proto = IPPROTO_IP;	/* default protocol */
2228
2229	bzero(actbuf, sizeof(actbuf));		/* actions go here */
2230	bzero(cmdbuf, sizeof(cmdbuf));
2231	bzero(rulebuf, sizeof(rulebuf));
2232
2233	rule = (struct ip_fw *)rulebuf;
2234	cmd = (ipfw_insn *)cmdbuf;
2235	action = (ipfw_insn *)actbuf;
2236
2237	av++; ac--;
2238
2239	/* [rule N]	-- Rule number optional */
2240	if (ac && isdigit(**av)) {
2241		rule->rulenum = atoi(*av);
2242		av++;
2243		ac--;
2244	}
2245
2246	/* [set N]	-- set number (0..30), optional */
2247	if (ac > 1 && !strncmp(*av, "set", strlen(*av))) {
2248		int set = strtoul(av[1], NULL, 10);
2249		if (set < 0 || set > 30)
2250			errx(EX_DATAERR, "illegal set %s", av[1]);
2251		rule->set = set;
2252		av += 2; ac -= 2;
2253	}
2254
2255	/* [prob D]	-- match probability, optional */
2256	if (ac > 1 && !strncmp(*av, "prob", strlen(*av))) {
2257		double d = strtod(av[1], NULL);
2258
2259		if (d <= 0 || d > 1)
2260			errx(EX_DATAERR, "illegal match prob. %s", av[1]);
2261		if (d != 1) { /* 1 means always match */
2262			action->opcode = O_PROB;
2263			action->len = 2;
2264			*((int32_t *)(action+1)) =
2265				(int32_t)((1 - d) * 0x7fffffff);
2266			action += action->len;
2267		}
2268		av += 2; ac -= 2;
2269	}
2270
2271	/* action	-- mandatory */
2272	NEED1("missing action");
2273	i = match_token(rule_actions, *av);
2274	ac--; av++;
2275	action->len = 1;	/* default */
2276	switch(i) {
2277	case TOK_CHECKSTATE:
2278		have_state = action;
2279		action->opcode = O_CHECK_STATE;
2280		break;
2281
2282	case TOK_ACCEPT:
2283		action->opcode = O_ACCEPT;
2284		break;
2285
2286	case TOK_DENY:
2287		action->opcode = O_DENY;
2288		action->arg1 = 0;
2289		break;
2290
2291	case TOK_REJECT:
2292		action->opcode = O_REJECT;
2293		action->arg1 = ICMP_UNREACH_HOST;
2294		break;
2295
2296	case TOK_RESET:
2297		action->opcode = O_REJECT;
2298		action->arg1 = ICMP_REJECT_RST;
2299		break;
2300
2301	case TOK_UNREACH:
2302		action->opcode = O_REJECT;
2303		NEED1("missing reject code");
2304		fill_reject_code(&action->arg1, *av);
2305		ac--; av++;
2306		break;
2307
2308	case TOK_COUNT:
2309		action->opcode = O_COUNT;
2310		break;
2311
2312	case TOK_QUEUE:
2313	case TOK_PIPE:
2314		action->len = F_INSN_SIZE(ipfw_insn_pipe);
2315	case TOK_SKIPTO:
2316		if (i == TOK_QUEUE)
2317			action->opcode = O_QUEUE;
2318		else if (i == TOK_PIPE)
2319			action->opcode = O_PIPE;
2320		else if (i == TOK_SKIPTO)
2321			action->opcode = O_SKIPTO;
2322		NEED1("missing skipto/pipe/queue number");
2323		action->arg1 = strtoul(*av, NULL, 10);
2324		av++; ac--;
2325		break;
2326
2327	case TOK_DIVERT:
2328	case TOK_TEE:
2329		action->opcode = (i == TOK_DIVERT) ? O_DIVERT : O_TEE;
2330		NEED1("missing divert/tee port");
2331		action->arg1 = strtoul(*av, NULL, 0);
2332		if (action->arg1 == 0) {
2333			struct servent *s;
2334			setservent(1);
2335			s = getservbyname(av[0], "divert");
2336			if (s != NULL)
2337				action->arg1 = ntohs(s->s_port);
2338			else
2339				errx(EX_DATAERR, "illegal divert/tee port");
2340		}
2341		ac--; av++;
2342		break;
2343
2344	case TOK_FORWARD: {
2345		ipfw_insn_sa *p = (ipfw_insn_sa *)action;
2346		char *s, *end;
2347
2348		NEED1("missing forward address[:port]");
2349
2350		action->opcode = O_FORWARD_IP;
2351		action->len = F_INSN_SIZE(ipfw_insn_sa);
2352
2353		p->sa.sin_len = sizeof(struct sockaddr_in);
2354		p->sa.sin_family = AF_INET;
2355		p->sa.sin_port = 0;
2356		/*
2357		 * locate the address-port separator (':' or ',')
2358		 */
2359		s = strchr(*av, ':');
2360		if (s == NULL)
2361			s = strchr(*av, ',');
2362		if (s != NULL) {
2363			*(s++) = '\0';
2364			i = strtoport(s, &end, 0 /* base */, 0 /* proto */);
2365			if (s == end)
2366				errx(EX_DATAERR,
2367				    "illegal forwarding port ``%s''", s);
2368			p->sa.sin_port = htons( (u_short)i );
2369		}
2370		lookup_host(*av, &(p->sa.sin_addr));
2371		}
2372		ac--; av++;
2373		break;
2374
2375	default:
2376		errx(EX_DATAERR, "invalid action %s\n", *av);
2377	}
2378	action = next_cmd(action);
2379
2380	/*
2381	 * [log [logamount N]]	-- log, optional
2382	 *
2383	 * If exists, it goes first in the cmdbuf, but then it is
2384	 * skipped in the copy section to the end of the buffer.
2385	 */
2386	if (ac && !strncmp(*av, "log", strlen(*av))) {
2387		ipfw_insn_log *c = (ipfw_insn_log *)cmd;
2388
2389		cmd->len = F_INSN_SIZE(ipfw_insn_log);
2390		cmd->opcode = O_LOG;
2391		av++; ac--;
2392		if (ac && !strncmp(*av, "logamount", strlen(*av))) {
2393			ac--; av++;
2394			NEED1("logamount requires argument");
2395			c->max_log = atoi(*av);
2396			if (c->max_log < 0)
2397				errx(EX_DATAERR, "logamount must be positive");
2398			ac--; av++;
2399		}
2400		cmd = next_cmd(cmd);
2401	}
2402
2403	if (have_state)	/* must be a check-state, we are done */
2404		goto done;
2405
2406#define OR_START(target)					\
2407	if (ac && (*av[0] == '(' || *av[0] == '{')) {		\
2408		if (open_par)					\
2409			errx(EX_USAGE, "nested \"(\" not allowed\n"); \
2410		open_par = 1;					\
2411		if ( (av[0])[1] == '\0') {			\
2412			ac--; av++;				\
2413		} else						\
2414			(*av)++;				\
2415	}							\
2416	target:							\
2417
2418
2419#define	CLOSE_PAR						\
2420	if (open_par) {						\
2421		if (ac && (					\
2422		    !strncmp(*av, ")", strlen(*av)) ||		\
2423		    !strncmp(*av, "}", strlen(*av)) )) {	\
2424			open_par = 0;				\
2425			ac--; av++;				\
2426		} else						\
2427			errx(EX_USAGE, "missing \")\"\n");	\
2428	}
2429
2430#define NOT_BLOCK						\
2431	if (ac && !strncmp(*av, "not", strlen(*av))) {		\
2432		if (cmd->len & F_NOT)				\
2433			errx(EX_USAGE, "double \"not\" not allowed\n"); \
2434		cmd->len |= F_NOT;				\
2435		ac--; av++;					\
2436	}
2437
2438#define OR_BLOCK(target)					\
2439	if (ac && !strncmp(*av, "or", strlen(*av))) {		\
2440		if (prev == NULL || open_par == 0)		\
2441			errx(EX_DATAERR, "invalid OR block");	\
2442		prev->len |= F_OR;				\
2443		ac--; av++;					\
2444		goto target;					\
2445	}							\
2446	CLOSE_PAR;
2447
2448	/*
2449	 * protocol, mandatory
2450	 */
2451    OR_START(get_proto);
2452	NOT_BLOCK;
2453	NEED1("missing protocol");
2454	{
2455	struct protoent *pe;
2456
2457	if (!strncmp(*av, "all", strlen(*av)))
2458		; /* same as "ip" */
2459	else if (!strncmp(*av, "MAC", strlen(*av))) {
2460		/* need exactly 3 fields */
2461		cmd = add_mac(cmd, ac-1, av+1);	/* exits in case of errors */
2462		ac -= 3;
2463		av += 3;
2464		have_mac = 1;
2465	} else if ((proto = atoi(*av)) > 0)
2466		; /* all done! */
2467	else if ((pe = getprotobyname(*av)) != NULL)
2468		proto = pe->p_proto;
2469	else
2470		errx(EX_DATAERR, "invalid protocol ``%s''", *av);
2471	av++; ac--;
2472	if (proto != IPPROTO_IP)
2473		fill_cmd(cmd, O_PROTO, 0, proto);
2474	}
2475	cmd = next_cmd(cmd);
2476    OR_BLOCK(get_proto);
2477
2478	/*
2479	 * "from", mandatory (unless we have a MAC address)
2480	 */
2481	if (!ac || strncmp(*av, "from", strlen(*av))) {
2482		if (have_mac)	/* we do not need a "to" address */
2483			goto read_to;
2484		errx(EX_USAGE, "missing ``from''");
2485	}
2486	ac--; av++;
2487
2488	/*
2489	 * source IP, mandatory
2490	 */
2491    OR_START(source_ip);
2492	NOT_BLOCK;	/* optional "not" */
2493	NEED1("missing source address");
2494
2495	/* source	-- mandatory */
2496	fill_ip((ipfw_insn_ip *)cmd, *av);
2497	if (cmd->opcode == O_IP_DST_SET)			/* set */
2498		cmd->opcode = O_IP_SRC_SET;
2499	else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn))		/* me */
2500		cmd->opcode = O_IP_SRC_ME;
2501	else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))	/* one IP */
2502		cmd->opcode = O_IP_SRC;
2503	else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_ip))	/* addr/mask */
2504		cmd->opcode = O_IP_SRC_MASK;
2505	/* otherwise len will be zero and the command skipped */
2506	ac--; av++;
2507	prev = cmd; /* in case we need to backtrack */
2508	cmd = next_cmd(cmd);
2509    OR_BLOCK(source_ip);
2510
2511	/*
2512	 * source ports, optional
2513	 */
2514	NOT_BLOCK;	/* optional "not" */
2515	if (ac && fill_newports((ipfw_insn_u16 *)cmd, *av, proto)) {
2516		/* XXX todo: check that we have a protocol with ports */
2517		cmd->opcode = O_IP_SRCPORT;
2518		ac--;
2519		av++;
2520		cmd = next_cmd(cmd);
2521	}
2522
2523read_to:
2524	/*
2525	 * "to", mandatory (unless we have a MAC address
2526	 */
2527	if (!ac || strncmp(*av, "to", strlen(*av))) {
2528		if (have_mac)
2529			goto read_options;
2530		errx(EX_USAGE, "missing ``to''");
2531	}
2532	av++; ac--;
2533
2534	/*
2535	 * destination, mandatory
2536	 */
2537    OR_START(dest_ip);
2538	NOT_BLOCK;	/* optional "not" */
2539	NEED1("missing dst address");
2540	fill_ip((ipfw_insn_ip *)cmd, *av);
2541	if (cmd->opcode == O_IP_DST_SET)			/* set */
2542		;
2543	else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn))		/* me */
2544		cmd->opcode = O_IP_DST_ME;
2545	else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))	/* one IP */
2546		cmd->opcode = O_IP_DST;
2547	else if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_ip))	/* addr/mask */
2548		cmd->opcode = O_IP_DST_MASK;
2549	ac--;
2550	av++;
2551	prev = cmd;
2552	cmd = next_cmd(cmd);
2553    OR_BLOCK(dest_ip);
2554
2555	/*
2556	 * dest. ports, optional
2557	 */
2558	NOT_BLOCK;	/* optional "not" */
2559	if (ac && fill_newports((ipfw_insn_u16 *)cmd, *av, proto)) {
2560		/* XXX todo: check that we have a protocol with ports */
2561		cmd->opcode = O_IP_DSTPORT;
2562		ac--;
2563		av++;
2564		cmd += F_LEN(cmd);
2565	}
2566
2567read_options:
2568	prev = NULL;
2569	while (ac) {
2570		char *s = *av;
2571		ipfw_insn_u32 *cmd32 = (ipfw_insn_u32 *)cmd;	/* alias */
2572
2573		if (*s == '!') {	/* alternate syntax for NOT */
2574			if (cmd->len & F_NOT)
2575				errx(EX_USAGE, "double \"not\" not allowed\n");
2576			cmd->len = F_NOT;
2577			s++;
2578		}
2579		i = match_token(rule_options, s);
2580		ac--; av++;
2581		switch(i) {
2582		case TOK_NOT:
2583			if (cmd->len & F_NOT)
2584				errx(EX_USAGE, "double \"not\" not allowed\n");
2585			cmd->len = F_NOT;
2586			break;
2587
2588		case TOK_OR:
2589			if (prev == NULL)
2590				errx(EX_USAGE, "invalid \"or\" block\n");
2591			prev->len |= F_OR;
2592			break;
2593
2594		case TOK_IN:
2595			fill_cmd(cmd, O_IN, 0, 0);
2596			break;
2597
2598		case TOK_OUT:
2599			cmd->len ^= F_NOT; /* toggle F_NOT */
2600			fill_cmd(cmd, O_IN, 0, 0);
2601			break;
2602
2603		case TOK_FRAG:
2604			fill_cmd(cmd, O_FRAG, 0, 0);
2605			break;
2606
2607		case TOK_LAYER2:
2608			fill_cmd(cmd, O_LAYER2, 0, 0);
2609			break;
2610
2611		case TOK_XMIT:
2612		case TOK_RECV:
2613		case TOK_VIA:
2614			NEED1("recv, xmit, via require interface name"
2615				" or address");
2616			fill_iface((ipfw_insn_if *)cmd, av[0]);
2617			ac--; av++;
2618			if (F_LEN(cmd) == 0)	/* not a valid address */
2619				break;
2620			if (i == TOK_XMIT)
2621				cmd->opcode = O_XMIT;
2622			else if (i == TOK_RECV)
2623				cmd->opcode = O_RECV;
2624			else if (i == TOK_VIA)
2625				cmd->opcode = O_VIA;
2626			break;
2627
2628		case TOK_ICMPTYPES:
2629			NEED1("icmptypes requires list of types");
2630			fill_icmptypes((ipfw_insn_u32 *)cmd, *av);
2631			av++; ac--;
2632			break;
2633
2634		case TOK_IPTTL:
2635			NEED1("ipttl requires TTL");
2636			fill_cmd(cmd, O_IPTTL, 0, strtoul(*av, NULL, 0));
2637			ac--; av++;
2638			break;
2639
2640		case TOK_IPID:
2641			NEED1("ipid requires length");
2642			fill_cmd(cmd, O_IPID, 0, strtoul(*av, NULL, 0));
2643			ac--; av++;
2644			break;
2645
2646		case TOK_IPLEN:
2647			NEED1("iplen requires length");
2648			fill_cmd(cmd, O_IPLEN, 0, strtoul(*av, NULL, 0));
2649			ac--; av++;
2650			break;
2651
2652		case TOK_IPVER:
2653			NEED1("ipver requires version");
2654			fill_cmd(cmd, O_IPVER, 0, strtoul(*av, NULL, 0));
2655			ac--; av++;
2656			break;
2657
2658		case TOK_IPPRECEDENCE:
2659			NEED1("ipprecedence requires value");
2660			fill_cmd(cmd, O_IPPRECEDENCE, 0,
2661			    (strtoul(*av, NULL, 0) & 7) << 5);
2662			ac--; av++;
2663			break;
2664
2665		case TOK_IPOPTS:
2666			NEED1("missing argument for ipoptions");
2667			fill_flags(cmd, O_IPOPT, f_ipopts, *av);
2668			ac--; av++;
2669			break;
2670
2671		case TOK_IPTOS:
2672			NEED1("missing argument for iptos");
2673			fill_flags(cmd, O_IPTOS, f_iptos, *av);
2674			ac--; av++;
2675			break;
2676
2677		case TOK_UID:
2678			NEED1("uid requires argument");
2679		    {
2680			char *end;
2681			uid_t uid;
2682			struct passwd *pwd;
2683
2684			cmd->opcode = O_UID;
2685			uid = strtoul(*av, &end, 0);
2686			pwd = (*end == '\0') ? getpwuid(uid) : getpwnam(*av);
2687			if (pwd == NULL)
2688				errx(EX_DATAERR, "uid \"%s\" nonexistent", *av);
2689			cmd32->d[0] = uid;
2690			cmd->len = F_INSN_SIZE(ipfw_insn_u32);
2691			ac--; av++;
2692		    }
2693			break;
2694
2695		case TOK_GID:
2696			NEED1("gid requires argument");
2697		    {
2698			char *end;
2699			gid_t gid;
2700			struct group *grp;
2701
2702			cmd->opcode = O_GID;
2703			gid = strtoul(*av, &end, 0);
2704			grp = (*end == '\0') ? getgrgid(gid) : getgrnam(*av);
2705			if (grp == NULL)
2706				errx(EX_DATAERR, "gid \"%s\" nonexistent", *av);
2707
2708			cmd32->d[0] = gid;
2709			cmd->len = F_INSN_SIZE(ipfw_insn_u32);
2710			ac--; av++;
2711		    }
2712			break;
2713
2714		case TOK_ESTAB:
2715			fill_cmd(cmd, O_ESTAB, 0, 0);
2716			break;
2717
2718		case TOK_SETUP:
2719			fill_cmd(cmd, O_TCPFLAGS, 0,
2720				(TH_SYN) | ( (TH_ACK) & 0xff) <<8 );
2721			break;
2722
2723		case TOK_TCPOPTS:
2724			NEED1("missing argument for tcpoptions");
2725			fill_flags(cmd, O_TCPOPTS, f_tcpopts, *av);
2726			ac--; av++;
2727			break;
2728
2729		case TOK_TCPSEQ:
2730		case TOK_TCPACK:
2731			NEED1("tcpseq/tcpack requires argument");
2732			cmd->len = F_INSN_SIZE(ipfw_insn_u32);
2733			cmd->opcode = (i == TOK_TCPSEQ) ? O_TCPSEQ : O_TCPACK;
2734			cmd32->d[0] = htonl(strtoul(*av, NULL, 0));
2735			ac--; av++;
2736			break;
2737
2738		case TOK_TCPWIN:
2739			NEED1("tcpwin requires length");
2740			fill_cmd(cmd, O_TCPWIN, 0,
2741			    htons(strtoul(*av, NULL, 0)));
2742			ac--; av++;
2743			break;
2744
2745		case TOK_TCPFLAGS:
2746			NEED1("missing argument for tcpflags");
2747			cmd->opcode = O_TCPFLAGS;
2748			fill_flags(cmd, O_TCPFLAGS, f_tcpflags, *av);
2749			ac--; av++;
2750			break;
2751
2752		case TOK_KEEPSTATE:
2753			if (have_state)
2754				errx(EX_USAGE, "only one of keep-state "
2755					"and limit is allowed");
2756			have_state = cmd;
2757			fill_cmd(cmd, O_KEEP_STATE, 0, 0);
2758			break;
2759
2760		case TOK_LIMIT:
2761			NEED1("limit needs mask and # of connections");
2762			if (have_state)
2763				errx(EX_USAGE, "only one of keep-state "
2764					"and limit is allowed");
2765			have_state = cmd;
2766		    {
2767			ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
2768
2769			cmd->len = F_INSN_SIZE(ipfw_insn_limit);
2770			cmd->opcode = O_LIMIT;
2771			c->limit_mask = 0;
2772			c->conn_limit = 0;
2773			for (; ac >1 ;) {
2774				int val;
2775
2776				val = match_token(limit_masks, *av);
2777				if (val <= 0)
2778					break;
2779				c->limit_mask |= val;
2780				ac--; av++;
2781			}
2782			c->conn_limit = atoi(*av);
2783			if (c->conn_limit == 0)
2784				errx(EX_USAGE, "limit: limit must be >0");
2785			if (c->limit_mask == 0)
2786				errx(EX_USAGE, "missing limit mask");
2787			ac--; av++;
2788		    }
2789			break;
2790
2791		default:
2792			errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
2793		}
2794		if (F_LEN(cmd) > 0) {	/* prepare to advance */
2795			prev = cmd;
2796			cmd = next_cmd(cmd);
2797		}
2798	}
2799
2800done:
2801	/*
2802	 * Now copy stuff into the rule.
2803	 * If we have a keep-state option, the first instruction
2804	 * must be a PROBE_STATE (which is generated here).
2805	 * If we have a LOG option, it was stored as the first command,
2806	 * and now must be moved to the top of the action part.
2807	 */
2808	dst = (ipfw_insn *)rule->cmd;
2809
2810	/*
2811	 * generate O_PROBE_STATE if necessary
2812	 */
2813	if (have_state && have_state->opcode != O_CHECK_STATE) {
2814		fill_cmd(dst, O_PROBE_STATE, 0, 0);
2815		dst = next_cmd(dst);
2816	}
2817	/*
2818	 * copy all commands but O_LOG, O_KEEP_STATE, O_LIMIT
2819	 */
2820	for (src = (ipfw_insn *)cmdbuf; src != cmd; src += i) {
2821		i = F_LEN(src);
2822
2823		switch (src->opcode) {
2824		case O_LOG:
2825		case O_KEEP_STATE:
2826		case O_LIMIT:
2827			break;
2828		default:
2829			bcopy(src, dst, i * sizeof(u_int32_t));
2830			dst += i;
2831		}
2832	}
2833
2834	/*
2835	 * put back the have_state command as last opcode
2836	 */
2837	if (have_state && have_state->opcode != O_CHECK_STATE) {
2838		i = F_LEN(have_state);
2839		bcopy(have_state, dst, i * sizeof(u_int32_t));
2840		dst += i;
2841	}
2842	/*
2843	 * start action section
2844	 */
2845	rule->act_ofs = dst - rule->cmd;
2846
2847	/*
2848	 * put back O_LOG if necessary
2849	 */
2850	src = (ipfw_insn *)cmdbuf;
2851	if ( src->opcode == O_LOG ) {
2852		i = F_LEN(src);
2853		bcopy(src, dst, i * sizeof(u_int32_t));
2854		dst += i;
2855	}
2856	/*
2857	 * copy all other actions
2858	 */
2859	for (src = (ipfw_insn *)actbuf; src != action; src += i) {
2860		i = F_LEN(src);
2861		bcopy(src, dst, i * sizeof(u_int32_t));
2862		dst += i;
2863	}
2864
2865	rule->cmd_len = (u_int32_t *)dst - (u_int32_t *)(rule->cmd);
2866	i = (void *)dst - (void *)rule;
2867	if (getsockopt(s, IPPROTO_IP, IP_FW_ADD, rule, &i) == -1)
2868		err(EX_UNAVAILABLE, "getsockopt(%s)", "IP_FW_ADD");
2869	if (!do_quiet)
2870		show_ipfw(rule);
2871}
2872
2873static void
2874zero (int ac, char *av[])
2875{
2876	int rulenum;
2877	int failed = EX_OK;
2878
2879	av++; ac--;
2880
2881	if (!ac) {
2882		/* clear all entries */
2883		if (setsockopt(s, IPPROTO_IP, IP_FW_ZERO, NULL, 0) < 0)
2884			err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_ZERO");
2885		if (!do_quiet)
2886			printf("Accounting cleared.\n");
2887
2888		return;
2889	}
2890
2891	while (ac) {
2892		/* Rule number */
2893		if (isdigit(**av)) {
2894			rulenum = atoi(*av);
2895			av++;
2896			ac--;
2897			if (setsockopt(s, IPPROTO_IP,
2898			    IP_FW_ZERO, &rulenum, sizeof rulenum)) {
2899				warn("rule %u: setsockopt(IP_FW_ZERO)",
2900				    rulenum);
2901				failed = EX_UNAVAILABLE;
2902			} else if (!do_quiet)
2903				printf("Entry %d cleared\n", rulenum);
2904		} else {
2905			errx(EX_USAGE, "invalid rule number ``%s''", *av);
2906		}
2907	}
2908	if (failed != EX_OK)
2909		exit(failed);
2910}
2911
2912static void
2913resetlog (int ac, char *av[])
2914{
2915	int rulenum;
2916	int failed = EX_OK;
2917
2918	av++; ac--;
2919
2920	if (!ac) {
2921		/* clear all entries */
2922		if (setsockopt(s, IPPROTO_IP, IP_FW_RESETLOG, NULL, 0) < 0)
2923			err(EX_UNAVAILABLE, "setsockopt(IP_FW_RESETLOG)");
2924		if (!do_quiet)
2925			printf("Logging counts reset.\n");
2926
2927		return;
2928	}
2929
2930	while (ac) {
2931		/* Rule number */
2932		if (isdigit(**av)) {
2933			rulenum = atoi(*av);
2934			av++;
2935			ac--;
2936			if (setsockopt(s, IPPROTO_IP,
2937			    IP_FW_RESETLOG, &rulenum, sizeof rulenum)) {
2938				warn("rule %u: setsockopt(IP_FW_RESETLOG)",
2939				    rulenum);
2940				failed = EX_UNAVAILABLE;
2941			} else if (!do_quiet)
2942				printf("Entry %d logging count reset\n",
2943				    rulenum);
2944		} else {
2945			errx(EX_DATAERR, "invalid rule number ``%s''", *av);
2946		}
2947	}
2948	if (failed != EX_OK)
2949		exit(failed);
2950}
2951
2952static void
2953flush()
2954{
2955	int cmd = do_pipe ? IP_DUMMYNET_FLUSH : IP_FW_FLUSH;
2956
2957	if (!do_force && !do_quiet) { /* need to ask user */
2958		int c;
2959
2960		printf("Are you sure? [yn] ");
2961		fflush(stdout);
2962		do {
2963			c = toupper(getc(stdin));
2964			while (c != '\n' && getc(stdin) != '\n')
2965				if (feof(stdin))
2966					return; /* and do not flush */
2967		} while (c != 'Y' && c != 'N');
2968		printf("\n");
2969		if (c == 'N')	/* user said no */
2970			return;
2971	}
2972	if (setsockopt(s, IPPROTO_IP, cmd, NULL, 0) < 0)
2973		err(EX_UNAVAILABLE, "setsockopt(IP_%s_FLUSH)",
2974		    do_pipe ? "DUMMYNET" : "FW");
2975	if (!do_quiet)
2976		printf("Flushed all %s.\n", do_pipe ? "pipes" : "rules");
2977}
2978
2979static int
2980ipfw_main(int ac, char **av)
2981{
2982	int ch;
2983
2984	if (ac == 1)
2985		show_usage();
2986
2987	/* Set the force flag for non-interactive processes */
2988	do_force = !isatty(STDIN_FILENO);
2989
2990	optind = optreset = 1;
2991	while ((ch = getopt(ac, av, "hs:adefNqStv")) != -1)
2992		switch (ch) {
2993		case 'h': /* help */
2994			help();
2995			break;	/* NOTREACHED */
2996
2997		case 's': /* sort */
2998			do_sort = atoi(optarg);
2999			break;
3000		case 'a':
3001			do_acct = 1;
3002			break;
3003		case 'd':
3004			do_dynamic = 1;
3005			break;
3006		case 'e':
3007			do_expired = 1;
3008			break;
3009		case 'f':
3010			do_force = 1;
3011			break;
3012		case 'N':
3013			do_resolv = 1;
3014			break;
3015		case 'q':
3016			do_quiet = 1;
3017			break;
3018		case 'S':
3019			show_sets = 1;
3020			break;
3021		case 't':
3022			do_time = 1;
3023			break;
3024		case 'v': /* verbose */
3025			verbose++;
3026			break;
3027		default:
3028			show_usage();
3029		}
3030
3031	ac -= optind;
3032	av += optind;
3033	NEED1("bad arguments, for usage summary ``ipfw''");
3034
3035	/*
3036	 * optional: pipe or queue
3037	 */
3038	if (!strncmp(*av, "pipe", strlen(*av))) {
3039		do_pipe = 1;
3040		ac--;
3041		av++;
3042	} else if (!strncmp(*av, "queue", strlen(*av))) {
3043		do_pipe = 2;
3044		ac--;
3045		av++;
3046	}
3047	NEED1("missing command");
3048
3049	/*
3050	 * for pipes and queues we normally say 'pipe NN config'
3051	 * but the code is easier to parse as 'pipe config NN'
3052	 * so we swap the two arguments.
3053	 */
3054	if (do_pipe > 0 && ac > 1 && *av[0] >= '0' && *av[0] <= '9') {
3055		char *p = av[0];
3056		av[0] = av[1];
3057		av[1] = p;
3058	}
3059	if (!strncmp(*av, "add", strlen(*av)))
3060		add(ac, av);
3061	else if (do_pipe && !strncmp(*av, "config", strlen(*av)))
3062		config_pipe(ac, av);
3063	else if (!strncmp(*av, "delete", strlen(*av))   ||
3064	         !strncmp(*av, "disable", strlen(*av))  ||
3065	         !strncmp(*av, "enable", strlen(*av)))
3066		delete(ac, av);
3067	else if (!strncmp(*av, "flush", strlen(*av)))
3068		flush();
3069	else if (!strncmp(*av, "zero", strlen(*av)))
3070		zero(ac, av);
3071	else if (!strncmp(*av, "resetlog", strlen(*av)))
3072		resetlog(ac, av);
3073	else if (!strncmp(*av, "print", strlen(*av)) ||
3074	         !strncmp(*av, "list", strlen(*av)))
3075		list(ac, av);
3076	else if (!strncmp(*av, "show", strlen(*av))) {
3077		do_acct++;
3078		list(ac, av);
3079	} else
3080		errx(EX_USAGE, "bad command `%s'", *av);
3081	return 0;
3082}
3083
3084
3085static void
3086ipfw_readfile(int ac, char *av[])
3087{
3088#define MAX_ARGS	32
3089#define WHITESP		" \t\f\v\n\r"
3090	char	buf[BUFSIZ];
3091	char	*a, *p, *args[MAX_ARGS], *cmd = NULL;
3092	char	linename[10];
3093	int	i=0, lineno=0, qflag=0, pflag=0, status;
3094	FILE	*f = NULL;
3095	pid_t	preproc = 0;
3096	int	c;
3097
3098	while ((c = getopt(ac, av, "D:U:p:q")) != -1)
3099		switch(c) {
3100		case 'D':
3101			if (!pflag)
3102				errx(EX_USAGE, "-D requires -p");
3103			if (i > MAX_ARGS - 2)
3104				errx(EX_USAGE,
3105				     "too many -D or -U options");
3106			args[i++] = "-D";
3107			args[i++] = optarg;
3108			break;
3109
3110		case 'U':
3111			if (!pflag)
3112				errx(EX_USAGE, "-U requires -p");
3113			if (i > MAX_ARGS - 2)
3114				errx(EX_USAGE,
3115				     "too many -D or -U options");
3116			args[i++] = "-U";
3117			args[i++] = optarg;
3118			break;
3119
3120		case 'p':
3121			pflag = 1;
3122			cmd = optarg;
3123			args[0] = cmd;
3124			i = 1;
3125			break;
3126
3127		case 'q':
3128			qflag = 1;
3129			break;
3130
3131		default:
3132			errx(EX_USAGE, "bad arguments, for usage"
3133			     " summary ``ipfw''");
3134		}
3135
3136	av += optind;
3137	ac -= optind;
3138	if (ac != 1)
3139		errx(EX_USAGE, "extraneous filename arguments");
3140
3141	if ((f = fopen(av[0], "r")) == NULL)
3142		err(EX_UNAVAILABLE, "fopen: %s", av[0]);
3143
3144	if (pflag) {
3145		/* pipe through preprocessor (cpp or m4) */
3146		int pipedes[2];
3147
3148		args[i] = 0;
3149
3150		if (pipe(pipedes) == -1)
3151			err(EX_OSERR, "cannot create pipe");
3152
3153		switch((preproc = fork())) {
3154		case -1:
3155			err(EX_OSERR, "cannot fork");
3156
3157		case 0:
3158			/* child */
3159			if (dup2(fileno(f), 0) == -1
3160			    || dup2(pipedes[1], 1) == -1)
3161				err(EX_OSERR, "dup2()");
3162			fclose(f);
3163			close(pipedes[1]);
3164			close(pipedes[0]);
3165			execvp(cmd, args);
3166			err(EX_OSERR, "execvp(%s) failed", cmd);
3167
3168		default:
3169			/* parent */
3170			fclose(f);
3171			close(pipedes[1]);
3172			if ((f = fdopen(pipedes[0], "r")) == NULL) {
3173				int savederrno = errno;
3174
3175				(void)kill(preproc, SIGTERM);
3176				errno = savederrno;
3177				err(EX_OSERR, "fdopen()");
3178			}
3179		}
3180	}
3181
3182	while (fgets(buf, BUFSIZ, f)) {
3183		lineno++;
3184		sprintf(linename, "Line %d", lineno);
3185		args[0] = linename;
3186
3187		if (*buf == '#')
3188			continue;
3189		if ((p = strchr(buf, '#')) != NULL)
3190			*p = '\0';
3191		i = 1;
3192		if (qflag)
3193			args[i++] = "-q";
3194		for (a = strtok(buf, WHITESP);
3195		    a && i < MAX_ARGS; a = strtok(NULL, WHITESP), i++)
3196			args[i] = a;
3197		if (i == (qflag? 2: 1))
3198			continue;
3199		if (i == MAX_ARGS)
3200			errx(EX_USAGE, "%s: too many arguments",
3201			    linename);
3202		args[i] = NULL;
3203
3204		ipfw_main(i, args);
3205	}
3206	fclose(f);
3207	if (pflag) {
3208		if (waitpid(preproc, &status, 0) == -1)
3209			errx(EX_OSERR, "waitpid()");
3210		if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
3211			errx(EX_UNAVAILABLE,
3212			    "preprocessor exited with status %d",
3213			    WEXITSTATUS(status));
3214		else if (WIFSIGNALED(status))
3215			errx(EX_UNAVAILABLE,
3216			    "preprocessor exited with signal %d",
3217			    WTERMSIG(status));
3218	}
3219}
3220
3221int
3222main(int ac, char *av[])
3223{
3224	s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
3225	if (s < 0)
3226		err(EX_UNAVAILABLE, "socket");
3227
3228	/*
3229	 * If the last argument is an absolute pathname, interpret it
3230	 * as a file to be preprocessed.
3231	 */
3232
3233	if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
3234		ipfw_readfile(ac, av);
3235	else
3236		ipfw_main(ac, av);
3237	return EX_OK;
3238}
3239