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