xref: /dflybsd-src/lib/libipfw3/basic/ipfw3_basic.c (revision 10f846f51bac6e64af644ef98faf46f72d181f51)
16a03354eSMatthew Dillon /*
24408d548SBill Yuan  * Copyright (c) 2014 - 2018 The DragonFly Project.  All rights reserved.
36a03354eSMatthew Dillon  *
46a03354eSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
59187b359SBill Yuan  * by Bill Yuan <bycn82@dragonflybsd.org>
66a03354eSMatthew Dillon  *
76a03354eSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
86a03354eSMatthew Dillon  * modification, are permitted provided that the following conditions
96a03354eSMatthew Dillon  * are met:
106a03354eSMatthew Dillon  *
116a03354eSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
126a03354eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
136a03354eSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
146a03354eSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
156a03354eSMatthew Dillon  *    the documentation and/or other materials provided with the
166a03354eSMatthew Dillon  *    distribution.
176a03354eSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
186a03354eSMatthew Dillon  *    contributors may be used to endorse or promote products derived
196a03354eSMatthew Dillon  *    from this software without specific, prior written permission.
206a03354eSMatthew Dillon  *
216a03354eSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
226a03354eSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
236a03354eSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
246a03354eSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
256a03354eSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
266a03354eSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
276a03354eSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
286a03354eSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
296a03354eSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
306a03354eSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
316a03354eSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
326a03354eSMatthew Dillon  * SUCH DAMAGE.
336a03354eSMatthew Dillon  */
346a03354eSMatthew Dillon 
356a03354eSMatthew Dillon #include <ctype.h>
366a03354eSMatthew Dillon #include <err.h>
376a03354eSMatthew Dillon #include <errno.h>
386a03354eSMatthew Dillon #include <grp.h>
396a03354eSMatthew Dillon #include <limits.h>
406a03354eSMatthew Dillon #include <netdb.h>
416a03354eSMatthew Dillon #include <pwd.h>
426a03354eSMatthew Dillon #include <signal.h>
436a03354eSMatthew Dillon #include <stdio.h>
446a03354eSMatthew Dillon #include <stdlib.h>
456a03354eSMatthew Dillon #include <stdarg.h>
466a03354eSMatthew Dillon #include <string.h>
476a03354eSMatthew Dillon #include <sysexits.h>
486a03354eSMatthew Dillon #include <timeconv.h>
496a03354eSMatthew Dillon #include <unistd.h>
506a03354eSMatthew Dillon 
516a03354eSMatthew Dillon #include <netinet/in.h>
526a03354eSMatthew Dillon 
536a03354eSMatthew Dillon #include <arpa/inet.h>
546a03354eSMatthew Dillon #include <net/if.h>
556a03354eSMatthew Dillon #include <net/route.h>
566a03354eSMatthew Dillon #include <net/pfil.h>
576a03354eSMatthew Dillon 
5859ea0e34SBill Yuan #include <net/ipfw3/ip_fw3.h>
599187b359SBill Yuan #include "../../../sbin/ipfw3/ipfw3.h"
606a03354eSMatthew Dillon #include "ipfw3_basic.h"
616a03354eSMatthew Dillon 
626a03354eSMatthew Dillon 
636a03354eSMatthew Dillon #define	IP_MASK_ALL	0xffffffff
646a03354eSMatthew Dillon /*
656a03354eSMatthew Dillon  * we use IPPROTO_ETHERTYPE as a fake protocol id to call the print routines
666a03354eSMatthew Dillon  * This is only used in this code.
676a03354eSMatthew Dillon  */
686a03354eSMatthew Dillon #define IPPROTO_ETHERTYPE	0x1000
696a03354eSMatthew Dillon 
706a03354eSMatthew Dillon 
716a03354eSMatthew Dillon struct char_int_map limit_types[] = {
726a03354eSMatthew Dillon 	{ "src-addr", 	1 },
736a03354eSMatthew Dillon 	{ "src-port", 	2 },
746a03354eSMatthew Dillon 	{ "dst-addr", 	3 },
756a03354eSMatthew Dillon 	{ "dst-port", 	4 },
766a03354eSMatthew Dillon 	{ NULL, 	0 }
776a03354eSMatthew Dillon };
786a03354eSMatthew Dillon 
796a03354eSMatthew Dillon static struct char_int_map ether_types[] = {
806a03354eSMatthew Dillon 	{ "ip", 	0x0800 },
816a03354eSMatthew Dillon 	{ "ipv4", 	0x0800 },
826a03354eSMatthew Dillon 	{ "ipv6", 	0x86dd },
836a03354eSMatthew Dillon 	{ "arp", 	0x0806 },
846a03354eSMatthew Dillon 	{ "rarp", 	0x8035 },
856a03354eSMatthew Dillon 	{ "vlan", 	0x8100 },
866a03354eSMatthew Dillon 	{ "loop", 	0x9000 },
876a03354eSMatthew Dillon 	{ "trail", 	0x1000 },
886a03354eSMatthew Dillon 	{ "pppoe_disc", 0x8863 },
896a03354eSMatthew Dillon 	{ "pppoe_sess", 0x8864 },
906a03354eSMatthew Dillon 	{ "ipx_8022", 	0x00E0 },
916a03354eSMatthew Dillon 	{ "ipx_8023", 	0x0000 },
926a03354eSMatthew Dillon 	{ "ipx_ii", 	0x8137 },
936a03354eSMatthew Dillon 	{ "ipx_snap", 	0x8137 },
946a03354eSMatthew Dillon 	{ "ipx", 	0x8137 },
956a03354eSMatthew Dillon 	{ "ns", 	0x0600 },
966a03354eSMatthew Dillon 	{ NULL, 	0 }
976a03354eSMatthew Dillon };
986a03354eSMatthew Dillon 
996a03354eSMatthew Dillon 
1002ca766abSBill Yuan int
match_token(struct char_int_map * table,char * string)1012ca766abSBill Yuan match_token(struct char_int_map *table, char *string)
1022ca766abSBill Yuan {
1032ca766abSBill Yuan 	while (table->key) {
1042ca766abSBill Yuan 		if (strcmp(table->key, string) == 0) {
1052ca766abSBill Yuan 			return table->val;
1062ca766abSBill Yuan 		}
1072ca766abSBill Yuan 		table++;
1082ca766abSBill Yuan 	}
1092ca766abSBill Yuan 	return 0;
1102ca766abSBill Yuan }
1116a03354eSMatthew Dillon 
1126a03354eSMatthew Dillon static char *
match_token2(struct char_int_map * table,int val)1136a03354eSMatthew Dillon match_token2(struct char_int_map *table, int val)
1146a03354eSMatthew Dillon {
1156a03354eSMatthew Dillon 	while (table->val) {
1166a03354eSMatthew Dillon 		if (table->val == val)
1176a03354eSMatthew Dillon 			return table->key;
1186a03354eSMatthew Dillon 
1196a03354eSMatthew Dillon 		table++;
1206a03354eSMatthew Dillon 	}
1216a03354eSMatthew Dillon 	return NULL;
1226a03354eSMatthew Dillon };
1236a03354eSMatthew Dillon 
1246a03354eSMatthew Dillon static void
fill_iface(ipfw_insn_if * cmd,char * arg)1256a03354eSMatthew Dillon fill_iface(ipfw_insn_if *cmd, char *arg)
1266a03354eSMatthew Dillon {
1276a03354eSMatthew Dillon 	cmd->name[0] = '\0';
1286a03354eSMatthew Dillon 	cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
1296a03354eSMatthew Dillon 
1306a03354eSMatthew Dillon 	/* Parse the interface or address */
1316a03354eSMatthew Dillon 	if (!strcmp(arg, "any")){
1326a03354eSMatthew Dillon 		cmd->o.len = 0;
1336a03354eSMatthew Dillon 	} else if (!isdigit(*arg)) {
1346a03354eSMatthew Dillon 		strlcpy(cmd->name, arg, sizeof(cmd->name));
1356a03354eSMatthew Dillon 		cmd->p.glob = strpbrk(arg, "*?[") != NULL ? 1 : 0;
1366a03354eSMatthew Dillon 	} else if (!inet_aton(arg, &cmd->p.ip))
1376a03354eSMatthew Dillon 		errx(EX_DATAERR, "bad ip address ``%s''", arg);
1386a03354eSMatthew Dillon }
1396a03354eSMatthew Dillon 
1406a03354eSMatthew Dillon static int
lookup_host(char * host,struct in_addr * ipaddr)1416a03354eSMatthew Dillon lookup_host (char *host, struct in_addr *ipaddr)
1426a03354eSMatthew Dillon {
1436a03354eSMatthew Dillon 	struct hostent *he;
1446a03354eSMatthew Dillon 
1456a03354eSMatthew Dillon 	if (!inet_aton(host, ipaddr)) {
1466a03354eSMatthew Dillon 		if ((he = gethostbyname(host)) == NULL)
1478b5a5700SBill Yuan 			return -1;
1486a03354eSMatthew Dillon 		*ipaddr = *(struct in_addr *)he->h_addr_list[0];
1496a03354eSMatthew Dillon 	}
150dd95fb5dSBill Yuan 	return 0;
1516a03354eSMatthew Dillon }
1526a03354eSMatthew Dillon 
1536a03354eSMatthew Dillon /*
1546a03354eSMatthew Dillon  * Like strtol, but also translates service names into port numbers
1556a03354eSMatthew Dillon  * for some protocols.
1566a03354eSMatthew Dillon  * In particular:
1576a03354eSMatthew Dillon  *	proto == -1 disables the protocol check;
1586a03354eSMatthew Dillon  *	proto == IPPROTO_ETHERTYPE looks up an internal table
1596a03354eSMatthew Dillon  *	proto == <some value in /etc/protocols> matches the values there.
1606a03354eSMatthew Dillon  * Returns *end == s in case the parameter is not found.
1616a03354eSMatthew Dillon  */
1626a03354eSMatthew Dillon static int
strtoport(char * s,char ** end,int base,int proto)1636a03354eSMatthew Dillon strtoport(char *s, char **end, int base, int proto)
1646a03354eSMatthew Dillon {
1656a03354eSMatthew Dillon 	char *p, *buf;
1666a03354eSMatthew Dillon 	char *s1;
1676a03354eSMatthew Dillon 	int i;
1686a03354eSMatthew Dillon 
1696a03354eSMatthew Dillon 	*end = s; 		/* default - not found */
1706a03354eSMatthew Dillon 	if ( *s == '\0')
1716a03354eSMatthew Dillon 		return 0; 	/* not found */
1726a03354eSMatthew Dillon 
1736a03354eSMatthew Dillon 	if (isdigit(*s))
1746a03354eSMatthew Dillon 		return strtol(s, end, base);
1756a03354eSMatthew Dillon 
1766a03354eSMatthew Dillon 	/*
1776a03354eSMatthew Dillon 	 * find separator. '\\' escapes the next char.
1786a03354eSMatthew Dillon 	 */
1796a03354eSMatthew Dillon 	for (s1 = s; *s1 && (isalnum(*s1) || *s1 == '\\') ; s1++) {
1806a03354eSMatthew Dillon 		if (*s1 == '\\' && s1[1] != '\0')
1816a03354eSMatthew Dillon 			s1++;
1826a03354eSMatthew Dillon 	}
1836a03354eSMatthew Dillon 
1846a03354eSMatthew Dillon 	buf = malloc(s1 - s + 1);
1856a03354eSMatthew Dillon 	if (buf == NULL)
1866a03354eSMatthew Dillon 		return 0;
1876a03354eSMatthew Dillon 
1886a03354eSMatthew Dillon 	/*
1896a03354eSMatthew Dillon 	 * copy into a buffer skipping backslashes
1906a03354eSMatthew Dillon 	 */
1916a03354eSMatthew Dillon 	for (p = s, i = 0; p != s1 ; p++)
1926a03354eSMatthew Dillon 		if ( *p != '\\')
1936a03354eSMatthew Dillon 			buf[i++] = *p;
1946a03354eSMatthew Dillon 	buf[i++] = '\0';
1956a03354eSMatthew Dillon 
1966a03354eSMatthew Dillon 	if (proto == IPPROTO_ETHERTYPE) {
1976a03354eSMatthew Dillon 		i = match_token(ether_types, buf);
1986a03354eSMatthew Dillon 		free(buf);
1996a03354eSMatthew Dillon 		if (i != -1) {	/* found */
2006a03354eSMatthew Dillon 			*end = s1;
2016a03354eSMatthew Dillon 			return i;
2026a03354eSMatthew Dillon 		}
2036a03354eSMatthew Dillon 	} else {
2046a03354eSMatthew Dillon 		struct protoent *pe = NULL;
2056a03354eSMatthew Dillon 		struct servent *se;
2066a03354eSMatthew Dillon 
2076a03354eSMatthew Dillon 		if (proto != 0)
2086a03354eSMatthew Dillon 			pe = getprotobynumber(proto);
2096a03354eSMatthew Dillon 		setservent(1);
2106a03354eSMatthew Dillon 		se = getservbyname(buf, pe ? pe->p_name : NULL);
2116a03354eSMatthew Dillon 		free(buf);
2126a03354eSMatthew Dillon 		if (se != NULL) {
2136a03354eSMatthew Dillon 			*end = s1;
2146a03354eSMatthew Dillon 			return ntohs(se->s_port);
2156a03354eSMatthew Dillon 		}
2166a03354eSMatthew Dillon 	}
2176a03354eSMatthew Dillon 	return 0; 	/* not found */
2186a03354eSMatthew Dillon }
2196a03354eSMatthew Dillon 
2206a03354eSMatthew Dillon static int
contigmask(u_char * p,int len)2216a03354eSMatthew Dillon contigmask(u_char *p, int len)
2226a03354eSMatthew Dillon {
2236a03354eSMatthew Dillon 	int i, n;
2246a03354eSMatthew Dillon 	for (i=0; i<len ; i++) {
2256a03354eSMatthew Dillon 		if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */
2266a03354eSMatthew Dillon 			break;
2276a03354eSMatthew Dillon 	}
2286a03354eSMatthew Dillon 	for (n=i+1; n < len; n++) {
2296a03354eSMatthew Dillon 		if ( (p[n/8] & (1 << (7 - (n%8)))) != 0)
2306a03354eSMatthew Dillon 			return -1; /* mask not contiguous */
2316a03354eSMatthew Dillon 	}
2326a03354eSMatthew Dillon 	return i;
2336a03354eSMatthew Dillon }
2346a03354eSMatthew Dillon 
2355f62bb52SBill Yuan static ipfw_insn
add_proto(ipfw_insn * cmd,char * av)2365f62bb52SBill Yuan *add_proto(ipfw_insn *cmd, char *av)
2376a03354eSMatthew Dillon {
2386a03354eSMatthew Dillon 	struct protoent *pe;
2396a03354eSMatthew Dillon 	u_char proto = 0;
2406a03354eSMatthew Dillon 	if (!strncmp(av, "all", strlen(av))) {
2416a03354eSMatthew Dillon 		;
2426a03354eSMatthew Dillon 	} else if ((proto = atoi(av)) > 0) {
2436a03354eSMatthew Dillon 		;
2446a03354eSMatthew Dillon 	} else if ((pe = getprotobyname(av)) != NULL) {
2456a03354eSMatthew Dillon 		proto = pe->p_proto;
2466a03354eSMatthew Dillon 	} else {
2476a03354eSMatthew Dillon 		errx(EX_USAGE, "protocol `%s' not recognizable\n", av);
2486a03354eSMatthew Dillon 	}
2496a03354eSMatthew Dillon 	if (proto != IPPROTO_IP) {
2506a03354eSMatthew Dillon 		cmd->opcode = O_BASIC_PROTO;
2516a03354eSMatthew Dillon 		cmd->module = MODULE_BASIC_ID;
2525f62bb52SBill Yuan 		cmd->len |= LEN_OF_IPFWINSN;
2536a03354eSMatthew Dillon 		cmd->arg1 = proto;
2546a03354eSMatthew Dillon 	}
2556a03354eSMatthew Dillon 	return cmd;
2566a03354eSMatthew Dillon }
2576a03354eSMatthew Dillon 
2586a03354eSMatthew Dillon void
parse_count(ipfw_insn ** cmd,int * ac,char ** av[])2596a03354eSMatthew Dillon parse_count(ipfw_insn **cmd, int *ac, char **av[])
2606a03354eSMatthew Dillon {
2616a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_COUNT;
2626a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
2635f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
2646a03354eSMatthew Dillon 	NEXT_ARG1;
2656a03354eSMatthew Dillon }
2666a03354eSMatthew Dillon 
2676a03354eSMatthew Dillon void
parse_skipto(ipfw_insn ** cmd,int * ac,char ** av[])2686a03354eSMatthew Dillon parse_skipto(ipfw_insn **cmd, int *ac, char **av[])
2696a03354eSMatthew Dillon {
2706a03354eSMatthew Dillon 	NEXT_ARG1;
2716a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_SKIPTO;
2726a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
2735f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
2746a03354eSMatthew Dillon 	(*cmd)->arg1 = strtoul(**av, NULL, 10);
2756a03354eSMatthew Dillon 	NEXT_ARG1;
2766a03354eSMatthew Dillon }
2776a03354eSMatthew Dillon 
2786a03354eSMatthew Dillon /*
2796a03354eSMatthew Dillon  * cmd->arg3 is count of the destination
2806a03354eSMatthew Dillon  * cmd->arg1 is the type, random 0, round-robin 1, sticky 2
2816a03354eSMatthew Dillon  */
2826a03354eSMatthew Dillon void
parse_forward(ipfw_insn ** cmd,int * ac,char ** av[])2836a03354eSMatthew Dillon parse_forward(ipfw_insn **cmd, int *ac, char **av[])
2846a03354eSMatthew Dillon {
2856a03354eSMatthew Dillon 	ipfw_insn_sa *p = (ipfw_insn_sa *)(*cmd);
2866a03354eSMatthew Dillon 	struct sockaddr_in *sa;
287*10f846f5SSascha Wildner 	char *tok, *end = NULL;
2886a03354eSMatthew Dillon 	char *str;
2896a03354eSMatthew Dillon 	int count, port;
2906a03354eSMatthew Dillon 
2916a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_FORWARD;
2926a03354eSMatthew Dillon 	NEXT_ARG1;
2936a03354eSMatthew Dillon 	/*
2946a03354eSMatthew Dillon 	 * multiple forward destinations are seperated by colon
2956a03354eSMatthew Dillon 	 * ip address and port are seperated by comma
2966a03354eSMatthew Dillon 	 * e.g. 192.168.1.1:80,192.168.1.2:8080
2976a03354eSMatthew Dillon 	 *      192.168.1.1,192.168.1.2 or keep the port the same
2986a03354eSMatthew Dillon 	 */
2996a03354eSMatthew Dillon 	tok = strtok(**av, ",");
3006a03354eSMatthew Dillon 	sa = &p->sa;
3016a03354eSMatthew Dillon 	count = 0;
3026a03354eSMatthew Dillon 	while (tok != NULL) {
3036a03354eSMatthew Dillon 		sa->sin_len = sizeof(struct sockaddr_in);
3046a03354eSMatthew Dillon 		sa->sin_family = AF_INET;
3056a03354eSMatthew Dillon 		sa->sin_port = 0;
3066a03354eSMatthew Dillon 		str = strchr(tok,':');
3076a03354eSMatthew Dillon 		if (str != NULL) {
3086a03354eSMatthew Dillon 			*(str++) = '\0';
3096a03354eSMatthew Dillon 			port = strtoport(str, &end, 0, 0);
3106a03354eSMatthew Dillon 			sa->sin_port = (u_short)port;
3116a03354eSMatthew Dillon 		}
3128b5a5700SBill Yuan 		if (lookup_host(tok, &(sa->sin_addr)) != 0)
3138b5a5700SBill Yuan 			errx(EX_DATAERR, "forward `%s' invalid dst", tok);
3146a03354eSMatthew Dillon 		tok = strtok (NULL, ",");
3156a03354eSMatthew Dillon 		sa++;
3166a03354eSMatthew Dillon 		count++;
3176a03354eSMatthew Dillon 	}
3186a03354eSMatthew Dillon 	(*cmd)->arg3 = count;
3196a03354eSMatthew Dillon 	if (count == 0) {
3206a03354eSMatthew Dillon 		errx(EX_DATAERR, "forward `%s' not recognizable", **av);
3216a03354eSMatthew Dillon 	}
3226a03354eSMatthew Dillon 	NEXT_ARG1;
3236a03354eSMatthew Dillon 	if (count > 1) {
3246a03354eSMatthew Dillon 		if (strcmp(**av, "round-robin") == 0) {
3256a03354eSMatthew Dillon 			NEXT_ARG1;
3266a03354eSMatthew Dillon 			(*cmd)->arg1 = 1;
3276a03354eSMatthew Dillon 		} else if (strcmp(**av, "sticky") == 0) {
3286a03354eSMatthew Dillon 			NEXT_ARG1;
3296a03354eSMatthew Dillon 			(*cmd)->arg1 = 2;
3306a03354eSMatthew Dillon 		} else {
3316a03354eSMatthew Dillon 			/* random */
3326a03354eSMatthew Dillon 			(*cmd)->arg1 = 0;
3336a03354eSMatthew Dillon 		}
3346a03354eSMatthew Dillon 	}
3356a03354eSMatthew Dillon 	(*cmd)->len = LEN_OF_IPFWINSN + count * sizeof(struct sockaddr_in);
3366a03354eSMatthew Dillon }
3376a03354eSMatthew Dillon 
3386a03354eSMatthew Dillon void
parse_in(ipfw_insn ** cmd,int * ac,char ** av[])3396a03354eSMatthew Dillon parse_in(ipfw_insn **cmd, int *ac, char **av[])
3406a03354eSMatthew Dillon {
3416a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_IN;
3426a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
3435f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
3446a03354eSMatthew Dillon 	(*cmd)->arg1 = 0;
3456a03354eSMatthew Dillon 	NEXT_ARG1;
3466a03354eSMatthew Dillon }
3476a03354eSMatthew Dillon 
3486a03354eSMatthew Dillon void
parse_out(ipfw_insn ** cmd,int * ac,char ** av[])3496a03354eSMatthew Dillon parse_out(ipfw_insn **cmd, int *ac, char **av[])
3506a03354eSMatthew Dillon {
3516a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_OUT;
3526a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
3535f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
3546a03354eSMatthew Dillon 	(*cmd)->arg1 = 0;
3556a03354eSMatthew Dillon 	NEXT_ARG1;
3566a03354eSMatthew Dillon }
3576a03354eSMatthew Dillon 
3586a03354eSMatthew Dillon 
3596a03354eSMatthew Dillon void
parse_via(ipfw_insn ** cmd,int * ac,char ** av[])3606a03354eSMatthew Dillon parse_via(ipfw_insn **cmd, int *ac, char **av[])
3616a03354eSMatthew Dillon {
3626a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
3635f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
3646a03354eSMatthew Dillon 	if (strcmp(*av[0], "via")==0) {
3656a03354eSMatthew Dillon 		(*cmd)->opcode = O_BASIC_VIA;
3666a03354eSMatthew Dillon 	} else if (strcmp(*av[0], "xmit")==0) {
3676a03354eSMatthew Dillon 		(*cmd)->opcode = O_BASIC_XMIT;
3686a03354eSMatthew Dillon 	} else if (strcmp(*av[0], "recv")==0) {
3696a03354eSMatthew Dillon 		(*cmd)->opcode = O_BASIC_RECV;
3706a03354eSMatthew Dillon 	}
3716a03354eSMatthew Dillon 	NEXT_ARG1;
3726a03354eSMatthew Dillon 	fill_iface((ipfw_insn_if *)(*cmd), *av[0]);
3736a03354eSMatthew Dillon 	NEXT_ARG1;
3746a03354eSMatthew Dillon }
3756a03354eSMatthew Dillon 
376c1bde762SBill Yuan void
parse_src_port(ipfw_insn ** cmd,int * ac,char ** av[])377c1bde762SBill Yuan parse_src_port(ipfw_insn **cmd, int *ac, char **av[])
378c1bde762SBill Yuan {
379c1bde762SBill Yuan 	NEXT_ARG1;
380c1bde762SBill Yuan 	(*cmd)->opcode = O_BASIC_IP_SRCPORT;
381c1bde762SBill Yuan 	(*cmd)->module = MODULE_BASIC_ID;
3825f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
383c1bde762SBill Yuan 	double v = strtol(**av, NULL, 0);
384c1bde762SBill Yuan 	if (v <= 0 || v >= 65535)
385c1bde762SBill Yuan 		errx(EX_NOHOST, "port `%s' invalid", **av);
386c1bde762SBill Yuan 	(*cmd)->arg1 = v;
387c1bde762SBill Yuan 	NEXT_ARG1;
388c1bde762SBill Yuan }
389c1bde762SBill Yuan 
390c1bde762SBill Yuan void
parse_dst_port(ipfw_insn ** cmd,int * ac,char ** av[])391c1bde762SBill Yuan parse_dst_port(ipfw_insn **cmd, int *ac, char **av[])
392c1bde762SBill Yuan {
393c1bde762SBill Yuan 	NEXT_ARG1;
394c1bde762SBill Yuan 	(*cmd)->opcode = O_BASIC_IP_DSTPORT;
395c1bde762SBill Yuan 	(*cmd)->module = MODULE_BASIC_ID;
3965f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
397c1bde762SBill Yuan 	double v = strtol(**av, NULL, 0);
398c1bde762SBill Yuan 	if (v <= 0 || v >= 65535)
399c1bde762SBill Yuan 		errx(EX_NOHOST, "port `%s' invalid", **av);
400c1bde762SBill Yuan 	(*cmd)->arg1 = v;
401c1bde762SBill Yuan 	NEXT_ARG1;
402c1bde762SBill Yuan }
403c1bde762SBill Yuan 
40463317b93SBill Yuan /*
40563317b93SBill Yuan  * Below formats are supported:
4065284582fSBill Yuan  * from table 1		O_BASIC_IP_SRC_LOOKUP
40763317b93SBill Yuan  * from any		return 0 len instruction
40863317b93SBill Yuan  * from me		O_BASIC_IP_SRC_ME
40963317b93SBill Yuan  * from 1.2.3.4  	O_BASIC_IP_SRC
41063317b93SBill Yuan  * from 1.2.3.4/24	O_BASIC_IP_SRC_MASK
41163317b93SBill Yuan  */
4126a03354eSMatthew Dillon void
parse_from(ipfw_insn ** cmd,int * ac,char ** av[])4136a03354eSMatthew Dillon parse_from(ipfw_insn **cmd, int *ac, char **av[])
4146a03354eSMatthew Dillon {
41563317b93SBill Yuan 	ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd);
416c1bde762SBill Yuan 	double port;
41763317b93SBill Yuan 	int i;
41863317b93SBill Yuan 
4196a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
4206a03354eSMatthew Dillon 	NEXT_ARG1;
4215284582fSBill Yuan 	if (strcmp(**av, "table") == 0) {
4225284582fSBill Yuan 		NEXT_ARG1;
4235284582fSBill Yuan 		NEED(*ac, 1, "table id missing");
4245f62bb52SBill Yuan 		(*cmd)->len |= F_INSN_SIZE(ipfw_insn);
4255284582fSBill Yuan 		(*cmd)->opcode = O_BASIC_IP_SRC_LOOKUP;
4265284582fSBill Yuan 		(*cmd)->arg1 = strtoul(**av, NULL, 10);
4275284582fSBill Yuan 	} else if (strcmp(**av, "any") == 0) {
42863317b93SBill Yuan 		(*cmd)->len &= ~F_LEN_MASK;
42963317b93SBill Yuan 	} else if (strcmp(**av, "me") == 0) {
43063317b93SBill Yuan 		(*cmd)->len |= F_INSN_SIZE(ipfw_insn);
43163317b93SBill Yuan 		(*cmd)->opcode = O_BASIC_IP_SRC_ME;
43263317b93SBill Yuan 	} else {
43363317b93SBill Yuan 		char *c = NULL, md = 0;
43463317b93SBill Yuan 		c = strchr(**av, '/');
435c1bde762SBill Yuan 		if (!c)
436c1bde762SBill Yuan 			c = strchr(**av, ':');
43763317b93SBill Yuan 		if (c) {
43863317b93SBill Yuan 			md = *c;
43963317b93SBill Yuan 			*c++ = '\0';
44063317b93SBill Yuan 		}
44163317b93SBill Yuan 		if (lookup_host(**av, &p->addr) != 0)
44263317b93SBill Yuan 			errx(EX_NOHOST, "hostname ``%s'' unknown", **av);
44363317b93SBill Yuan 		switch (md) {
444c1bde762SBill Yuan 			case ':':
445c1bde762SBill Yuan 				port = strtol(c, NULL, 0);
446c1bde762SBill Yuan 				if (port <= 0 || port >= 65535)
447c1bde762SBill Yuan 					errx(EX_NOHOST, "port `%s' invalid", c);
448c1bde762SBill Yuan 				(*cmd)->arg1 = port;
449c1bde762SBill Yuan 				(*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
450c1bde762SBill Yuan 				(*cmd)->opcode = O_BASIC_IP_SRC_N_PORT;
451c1bde762SBill Yuan 				break;
45263317b93SBill Yuan 			case '/':
45363317b93SBill Yuan 				i = atoi(c);
45463317b93SBill Yuan 				if (i == 0)
45563317b93SBill Yuan 					p->mask.s_addr = htonl(0);
45663317b93SBill Yuan 				else if (i > 32)
45763317b93SBill Yuan 					errx(EX_DATAERR, "bad width ``%s''", c);
45863317b93SBill Yuan 				else
45963317b93SBill Yuan 					p->mask.s_addr = htonl(~0 << (32 - i));
460c1bde762SBill Yuan 				(*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
461c1bde762SBill Yuan 				(*cmd)->opcode = O_BASIC_IP_SRC_MASK;
462c1bde762SBill Yuan 				p->addr.s_addr &= p->mask.s_addr;
46363317b93SBill Yuan 				break;
46463317b93SBill Yuan 			default:
46563317b93SBill Yuan 				p->mask.s_addr = htonl(~0);
46663317b93SBill Yuan 				(*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
46763317b93SBill Yuan 				(*cmd)->opcode = O_BASIC_IP_SRC;
468c1bde762SBill Yuan 				break;
46963317b93SBill Yuan 		}
47063317b93SBill Yuan 	}
4716a03354eSMatthew Dillon 	NEXT_ARG1;
4726a03354eSMatthew Dillon }
4736a03354eSMatthew Dillon 
4746a03354eSMatthew Dillon void
parse_to(ipfw_insn ** cmd,int * ac,char ** av[])4756a03354eSMatthew Dillon parse_to(ipfw_insn **cmd, int *ac, char **av[])
4766a03354eSMatthew Dillon {
47763317b93SBill Yuan 	ipfw_insn_ip *p = (ipfw_insn_ip *)(*cmd);
478c1bde762SBill Yuan 	double port;
47963317b93SBill Yuan 	int i;
48063317b93SBill Yuan 
4816a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
4826a03354eSMatthew Dillon 	NEXT_ARG1;
4835284582fSBill Yuan 	if (strcmp(**av, "table") == 0) {
4845284582fSBill Yuan 		NEXT_ARG1;
4855284582fSBill Yuan 		NEED(*ac, 1, "table id missing");
4865f62bb52SBill Yuan 		(*cmd)->len |= F_INSN_SIZE(ipfw_insn);
4875284582fSBill Yuan 		(*cmd)->opcode = O_BASIC_IP_DST_LOOKUP;
4885284582fSBill Yuan 		(*cmd)->arg1 = strtoul(**av, NULL, 10);
4895284582fSBill Yuan 	} else if (strcmp(**av, "any") == 0) {
49063317b93SBill Yuan 		(*cmd)->len &= ~F_LEN_MASK;
49163317b93SBill Yuan 	} else if (strcmp(**av, "me") == 0) {
49263317b93SBill Yuan 		(*cmd)->len |= F_INSN_SIZE(ipfw_insn);
49363317b93SBill Yuan 		(*cmd)->opcode = O_BASIC_IP_DST_ME;
49463317b93SBill Yuan 	} else {
49563317b93SBill Yuan 		char *c = NULL, md = 0;
49663317b93SBill Yuan 		c = strchr(**av, '/');
497c1bde762SBill Yuan 		if (!c)
498c1bde762SBill Yuan 			c = strchr(**av, ':');
49963317b93SBill Yuan 		if (c) {
50063317b93SBill Yuan 			md = *c;
50163317b93SBill Yuan 			*c++ = '\0';
50263317b93SBill Yuan 		}
50363317b93SBill Yuan 		if (lookup_host(**av, &p->addr) != 0)
50463317b93SBill Yuan 			errx(EX_NOHOST, "hostname ``%s'' unknown", **av);
50563317b93SBill Yuan 		switch (md) {
506c1bde762SBill Yuan 			case ':':
507c1bde762SBill Yuan 				port = strtol(c, NULL, 0);
508c1bde762SBill Yuan 				if (port <= 0 || port >= 65535)
509c1bde762SBill Yuan 					errx(EX_NOHOST, "port `%s' invalid", c);
510c1bde762SBill Yuan 				(*cmd)->arg1 = port;
511c1bde762SBill Yuan 				(*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
512c1bde762SBill Yuan 				(*cmd)->opcode = O_BASIC_IP_DST_N_PORT;
513c1bde762SBill Yuan 				break;
51463317b93SBill Yuan 			case '/':
51563317b93SBill Yuan 				i = atoi(c);
51663317b93SBill Yuan 				if (i == 0)
51763317b93SBill Yuan 					p->mask.s_addr = htonl(0);
51863317b93SBill Yuan 				else if (i > 32)
51963317b93SBill Yuan 					errx(EX_DATAERR, "bad width ``%s''", c);
52063317b93SBill Yuan 				else
52163317b93SBill Yuan 					p->mask.s_addr = htonl(~0 << (32 - i));
522c1bde762SBill Yuan 				(*cmd)->len |= F_INSN_SIZE(ipfw_insn_ip);
523c1bde762SBill Yuan 				(*cmd)->opcode = O_BASIC_IP_DST_MASK;
524c1bde762SBill Yuan 				p->addr.s_addr &= p->mask.s_addr;
52563317b93SBill Yuan 				break;
52663317b93SBill Yuan 			default:
52763317b93SBill Yuan 				p->mask.s_addr = htonl(~0);
52863317b93SBill Yuan 				(*cmd)->len |= F_INSN_SIZE(ipfw_insn_u32);
52963317b93SBill Yuan 				(*cmd)->opcode = O_BASIC_IP_DST;
530c1bde762SBill Yuan 				break;
53163317b93SBill Yuan 		}
53263317b93SBill Yuan 	}
5336a03354eSMatthew Dillon 	NEXT_ARG1;
534c1bde762SBill Yuan 
5356a03354eSMatthew Dillon }
5366a03354eSMatthew Dillon 
5376a03354eSMatthew Dillon void
parse_proto(ipfw_insn ** cmd,int * ac,char ** av[])5386a03354eSMatthew Dillon parse_proto(ipfw_insn **cmd, int *ac, char **av[])
5396a03354eSMatthew Dillon {
5406a03354eSMatthew Dillon 	add_proto(*cmd, **av);
5416a03354eSMatthew Dillon 	NEXT_ARG1;
5426a03354eSMatthew Dillon }
5436a03354eSMatthew Dillon 
5446a03354eSMatthew Dillon void
parse_prob(ipfw_insn ** cmd,int * ac,char ** av[])5456a03354eSMatthew Dillon parse_prob(ipfw_insn **cmd, int *ac, char **av[])
5466a03354eSMatthew Dillon {
5476a03354eSMatthew Dillon 	NEXT_ARG1;
5486a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_PROB;
5496a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
5505f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
5516a03354eSMatthew Dillon 	(*cmd)->arg1 = strtoul(**av, NULL, 10);
5526a03354eSMatthew Dillon 	NEXT_ARG1;
5536a03354eSMatthew Dillon }
5546a03354eSMatthew Dillon 
5556a03354eSMatthew Dillon void
parse_keep_state(ipfw_insn ** cmd,int * ac,char ** av[])5566a03354eSMatthew Dillon parse_keep_state(ipfw_insn **cmd, int *ac, char **av[])
5576a03354eSMatthew Dillon {
5586a03354eSMatthew Dillon 	NEXT_ARG1;
5596a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_KEEP_STATE;
5606a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
5615f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
5626a03354eSMatthew Dillon 	if (strcmp(**av, "limit") == 0) {
5636a03354eSMatthew Dillon 		NEXT_ARG1;
5646a03354eSMatthew Dillon 		(*cmd)->arg3 = match_token(limit_types, **av);
5656a03354eSMatthew Dillon 		if ((*cmd)->arg3 == 0)
5666a03354eSMatthew Dillon 			errx(EX_DATAERR, "limit `%s' not recognizable", **av);
5676a03354eSMatthew Dillon 
5686a03354eSMatthew Dillon 		NEXT_ARG1;
5696a03354eSMatthew Dillon 		(*cmd)->arg1 = strtoul(**av, NULL, 10);
5706a03354eSMatthew Dillon 		if ((*cmd)->arg1 == 0)
5716a03354eSMatthew Dillon 			errx(EX_DATAERR, "bad limit `%s'", **av);
5726a03354eSMatthew Dillon 
5736a03354eSMatthew Dillon 		NEXT_ARG1;
5746a03354eSMatthew Dillon 	}
5756a03354eSMatthew Dillon 	if (strcmp(**av, "live") == 0) {
5766a03354eSMatthew Dillon 		NEXT_ARG1;
5776a03354eSMatthew Dillon 		(*cmd)->arg2 = strtoul(**av, NULL, 10);
5786a03354eSMatthew Dillon 		NEXT_ARG1;
5796a03354eSMatthew Dillon 	}
5806a03354eSMatthew Dillon }
5816a03354eSMatthew Dillon 
5826a03354eSMatthew Dillon void
parse_check_state(ipfw_insn ** cmd,int * ac,char ** av[])5836a03354eSMatthew Dillon parse_check_state(ipfw_insn **cmd, int *ac, char **av[])
5846a03354eSMatthew Dillon {
5856a03354eSMatthew Dillon 	NEXT_ARG1;
5866a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_CHECK_STATE;
5876a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
5885f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
5896a03354eSMatthew Dillon }
5906a03354eSMatthew Dillon 
5916a03354eSMatthew Dillon void
parse_tagged(ipfw_insn ** cmd,int * ac,char ** av[])5926a03354eSMatthew Dillon parse_tagged(ipfw_insn **cmd, int *ac, char **av[])
5936a03354eSMatthew Dillon {
5946a03354eSMatthew Dillon 	NEXT_ARG1;
5956a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_TAGGED;
5966a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
5975f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
5986a03354eSMatthew Dillon 	(*cmd)->arg1 = strtoul(**av, NULL, 10);
5996a03354eSMatthew Dillon 	NEXT_ARG1;
6006a03354eSMatthew Dillon }
6016a03354eSMatthew Dillon 
6026a03354eSMatthew Dillon void
parse_comment(ipfw_insn ** cmd,int * ac,char ** av[])6036a03354eSMatthew Dillon parse_comment(ipfw_insn **cmd, int *ac, char **av[])
6046a03354eSMatthew Dillon {
6056a03354eSMatthew Dillon 	int l = 0;
6066a03354eSMatthew Dillon 	char *p = (char *)((*cmd) + 1);
6076a03354eSMatthew Dillon 
6086a03354eSMatthew Dillon 	NEXT_ARG1;
6096a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_COMMENT;
6106a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
6116a03354eSMatthew Dillon 
6126a03354eSMatthew Dillon 	while (*ac > 0) {
6136a03354eSMatthew Dillon 		l += strlen(**av) + 1;
6146a03354eSMatthew Dillon 		if (l > 84) {
6156a03354eSMatthew Dillon 			errx(EX_DATAERR, "comment too long (max 80 chars)");
6166a03354eSMatthew Dillon 		}
6176a03354eSMatthew Dillon 		strcpy(p, **av);
6186a03354eSMatthew Dillon 		p += strlen(**av);
6196a03354eSMatthew Dillon 		*p++ = ' ';
6206a03354eSMatthew Dillon 		NEXT_ARG1;
6216a03354eSMatthew Dillon 	}
6226a03354eSMatthew Dillon 	l = 1 + (l + 3) / 4;
6235f62bb52SBill Yuan 	(*cmd)->len |= l;
6246a03354eSMatthew Dillon 	*(--p) = '\0';
6256a03354eSMatthew Dillon }
6266a03354eSMatthew Dillon 
6276a03354eSMatthew Dillon void
parse_tag(ipfw_insn ** cmd,int * ac,char ** av[])6286a03354eSMatthew Dillon parse_tag(ipfw_insn **cmd, int *ac, char **av[])
6296a03354eSMatthew Dillon {
6306a03354eSMatthew Dillon 	NEXT_ARG1;
6316a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_TAG;
6326a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
6335f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
6346a03354eSMatthew Dillon 	(*cmd)->arg1 = strtoul(**av, NULL, 10);
6356a03354eSMatthew Dillon 	NEXT_ARG1;
6366a03354eSMatthew Dillon }
6376a03354eSMatthew Dillon 
6386a03354eSMatthew Dillon void
parse_untag(ipfw_insn ** cmd,int * ac,char ** av[])6396a03354eSMatthew Dillon parse_untag(ipfw_insn **cmd, int *ac, char **av[])
6406a03354eSMatthew Dillon {
6416a03354eSMatthew Dillon 	NEXT_ARG1;
6426a03354eSMatthew Dillon 	(*cmd)->opcode = O_BASIC_UNTAG;
6436a03354eSMatthew Dillon 	(*cmd)->module = MODULE_BASIC_ID;
6445f62bb52SBill Yuan 	(*cmd)->len |= LEN_OF_IPFWINSN;
6456a03354eSMatthew Dillon 	(*cmd)->arg1 = strtoul(**av, NULL, 10);
6466a03354eSMatthew Dillon 	NEXT_ARG1;
6476a03354eSMatthew Dillon }
6486a03354eSMatthew Dillon 
6496a03354eSMatthew Dillon void
show_count(ipfw_insn * cmd,int show_or)6506ce8c93fSBill Yuan show_count(ipfw_insn *cmd, int show_or)
6516a03354eSMatthew Dillon {
6526a03354eSMatthew Dillon 	printf(" count");
6536a03354eSMatthew Dillon }
6546a03354eSMatthew Dillon 
6556a03354eSMatthew Dillon void
show_skipto(ipfw_insn * cmd,int show_or)6566ce8c93fSBill Yuan show_skipto(ipfw_insn *cmd, int show_or)
6576a03354eSMatthew Dillon {
6586a03354eSMatthew Dillon 	printf(" skipto %u", cmd->arg1);
6596a03354eSMatthew Dillon }
6606a03354eSMatthew Dillon 
6616a03354eSMatthew Dillon void
show_forward(ipfw_insn * cmd,int show_or)6626ce8c93fSBill Yuan show_forward(ipfw_insn *cmd, int show_or)
6636a03354eSMatthew Dillon {
6646a03354eSMatthew Dillon 	struct sockaddr_in *sa;
6656a03354eSMatthew Dillon 	int i;
6666a03354eSMatthew Dillon 
6676a03354eSMatthew Dillon 	ipfw_insn_sa *s = (ipfw_insn_sa *)cmd;
6686a03354eSMatthew Dillon 	sa = &s->sa;
6696a03354eSMatthew Dillon 	printf(" forward");
6706a03354eSMatthew Dillon 	for (i = 0; i < cmd->arg3; i++){
6716a03354eSMatthew Dillon 		if (i > 0)
6726a03354eSMatthew Dillon 			printf(",");
6736a03354eSMatthew Dillon 		else
6746a03354eSMatthew Dillon 			printf(" ");
6756a03354eSMatthew Dillon 
6766a03354eSMatthew Dillon 		printf("%s", inet_ntoa(sa->sin_addr));
6776a03354eSMatthew Dillon 		if (sa->sin_port != 0)
6786a03354eSMatthew Dillon 			printf(":%d", sa->sin_port);
6796a03354eSMatthew Dillon 
6806a03354eSMatthew Dillon 		sa++;
6816a03354eSMatthew Dillon 	}
6826a03354eSMatthew Dillon 	if (cmd->arg1 == 1)
6836a03354eSMatthew Dillon 		printf(" round-robin");
6846a03354eSMatthew Dillon 	else if (cmd->arg1 == 2)
6856a03354eSMatthew Dillon 		printf(" sticky");
6866a03354eSMatthew Dillon 
6876a03354eSMatthew Dillon }
6886a03354eSMatthew Dillon 
6896a03354eSMatthew Dillon void
show_in(ipfw_insn * cmd,int show_or)6906ce8c93fSBill Yuan show_in(ipfw_insn *cmd, int show_or)
6916a03354eSMatthew Dillon {
6926a03354eSMatthew Dillon 	printf(" in");
6936a03354eSMatthew Dillon }
6946a03354eSMatthew Dillon 
6956a03354eSMatthew Dillon void
show_out(ipfw_insn * cmd,int show_or)6966ce8c93fSBill Yuan show_out(ipfw_insn *cmd, int show_or)
6976a03354eSMatthew Dillon {
6986a03354eSMatthew Dillon 	printf(" out");
6996a03354eSMatthew Dillon }
7006a03354eSMatthew Dillon 
7016a03354eSMatthew Dillon void
show_via(ipfw_insn * cmd,int show_or)7026ce8c93fSBill Yuan show_via(ipfw_insn *cmd, int show_or)
7036a03354eSMatthew Dillon {
7046a03354eSMatthew Dillon 	char *s;
7056a03354eSMatthew Dillon 	ipfw_insn_if *cmdif = (ipfw_insn_if *)cmd;
7066a03354eSMatthew Dillon 
7076a03354eSMatthew Dillon 	if ((int)cmd->opcode == O_BASIC_XMIT)
7086a03354eSMatthew Dillon 		s = "xmit";
7096a03354eSMatthew Dillon 	else if ((int)cmd->opcode == O_BASIC_RECV)
7106a03354eSMatthew Dillon 		s = "recv";
7116a03354eSMatthew Dillon 	else if ((int)cmd->opcode == O_BASIC_VIA)
7126a03354eSMatthew Dillon 		s = "via";
7136a03354eSMatthew Dillon 	else
7146a03354eSMatthew Dillon 		s = "?huh?";
7156ce8c93fSBill Yuan 	if (show_or)
7166ce8c93fSBill Yuan 		s = "or";
7176a03354eSMatthew Dillon 	if (cmdif->name[0] == '\0')
7186a03354eSMatthew Dillon 		printf(" %s %s", s, inet_ntoa(cmdif->p.ip));
7196a03354eSMatthew Dillon 
7206a03354eSMatthew Dillon 	printf(" %s %s", s, cmdif->name);
7216a03354eSMatthew Dillon }
7226a03354eSMatthew Dillon 
7236a03354eSMatthew Dillon void
show_src_port(ipfw_insn * cmd,int show_or)724c1bde762SBill Yuan show_src_port(ipfw_insn *cmd, int show_or)
725c1bde762SBill Yuan {
7265f62bb52SBill Yuan 	char *word = "src-port";
7275f62bb52SBill Yuan 	if (show_or)
7285f62bb52SBill Yuan 		word = "or";
7295f62bb52SBill Yuan 	printf(" %s %d", word, cmd->arg1);
730c1bde762SBill Yuan }
731c1bde762SBill Yuan 
732c1bde762SBill Yuan void
show_dst_port(ipfw_insn * cmd,int show_or)733c1bde762SBill Yuan show_dst_port(ipfw_insn *cmd, int show_or)
734c1bde762SBill Yuan {
7355f62bb52SBill Yuan 	char *word = "dst-port";
7365f62bb52SBill Yuan 	if (show_or)
7375f62bb52SBill Yuan 		word = "or";
7385f62bb52SBill Yuan 	printf(" %s %d", word, cmd->arg1);
739c1bde762SBill Yuan }
740c1bde762SBill Yuan 
741c1bde762SBill Yuan void
show_from(ipfw_insn * cmd,int show_or)7426ce8c93fSBill Yuan show_from(ipfw_insn *cmd, int show_or)
7436a03354eSMatthew Dillon {
7446ce8c93fSBill Yuan 	char *word = "from";
7456ce8c93fSBill Yuan 	if (show_or)
7466ce8c93fSBill Yuan 		word = "or";
7476ce8c93fSBill Yuan 	printf(" %s %s", word, inet_ntoa(((ipfw_insn_ip *)cmd)->addr));
7486a03354eSMatthew Dillon }
7496a03354eSMatthew Dillon 
7506a03354eSMatthew Dillon void
show_from_lookup(ipfw_insn * cmd,int show_or)7515284582fSBill Yuan show_from_lookup(ipfw_insn *cmd, int show_or)
7525284582fSBill Yuan {
7535284582fSBill Yuan 	char *word = "from";
7545284582fSBill Yuan 	if (show_or)
7555284582fSBill Yuan 		word = "or";
7565284582fSBill Yuan 	printf(" %s table %d", word, cmd->arg1);
7575284582fSBill Yuan }
7585284582fSBill Yuan 
7595284582fSBill Yuan void
show_from_me(ipfw_insn * cmd,int show_or)7606ce8c93fSBill Yuan show_from_me(ipfw_insn *cmd, int show_or)
76163317b93SBill Yuan {
7626ce8c93fSBill Yuan 	char *word = "from";
7636ce8c93fSBill Yuan 	if (show_or)
7646ce8c93fSBill Yuan 		word = "or";
7656ce8c93fSBill Yuan 	printf(" %s me", word);
76663317b93SBill Yuan }
76763317b93SBill Yuan 
76863317b93SBill Yuan void
show_from_mask(ipfw_insn * cmd,int show_or)7696ce8c93fSBill Yuan show_from_mask(ipfw_insn *cmd, int show_or)
77063317b93SBill Yuan {
77163317b93SBill Yuan 	int mask;
7726ce8c93fSBill Yuan 	char *word = "from";
7736ce8c93fSBill Yuan 	if (show_or)
7746ce8c93fSBill Yuan 		word = "or";
77563317b93SBill Yuan 	ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
7766ce8c93fSBill Yuan 	printf(" %s %s", word, inet_ntoa(p->addr));
77763317b93SBill Yuan 
77863317b93SBill Yuan 	mask = contigmask((u_char *)&(p->mask.s_addr), 32);
77963317b93SBill Yuan 	if (mask < 32)
78063317b93SBill Yuan 		printf("/%d", mask);
78163317b93SBill Yuan }
78263317b93SBill Yuan 
78363317b93SBill Yuan void
show_from_src_n_port(ipfw_insn * cmd,int show_or)784c1bde762SBill Yuan show_from_src_n_port(ipfw_insn *cmd, int show_or)
785c1bde762SBill Yuan {
786c1bde762SBill Yuan 	char *word = "from";
787c1bde762SBill Yuan 	if (show_or)
788c1bde762SBill Yuan 		word = "or";
789c1bde762SBill Yuan 	ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
790c1bde762SBill Yuan 	printf(" %s %s", word, inet_ntoa(p->addr));
791c1bde762SBill Yuan 	printf(":%d", cmd->arg1);
792c1bde762SBill Yuan }
793c1bde762SBill Yuan 
794c1bde762SBill Yuan void
show_to(ipfw_insn * cmd,int show_or)7956ce8c93fSBill Yuan show_to(ipfw_insn *cmd, int show_or)
7966a03354eSMatthew Dillon {
7976ce8c93fSBill Yuan 	char *word = "to";
7986ce8c93fSBill Yuan 	if (show_or)
7996ce8c93fSBill Yuan 		word = "or";
800c1bde762SBill Yuan 	ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
801c1bde762SBill Yuan 	printf(" %s %s", word, inet_ntoa(p->addr));
8026a03354eSMatthew Dillon }
8036a03354eSMatthew Dillon 
8046a03354eSMatthew Dillon void
show_to_lookup(ipfw_insn * cmd,int show_or)8055284582fSBill Yuan show_to_lookup(ipfw_insn *cmd, int show_or)
8065284582fSBill Yuan {
8075284582fSBill Yuan 	char *word = "to";
8085284582fSBill Yuan 	if (show_or)
8095284582fSBill Yuan 		word = "or";
8105284582fSBill Yuan 	printf(" %s table %d", word, cmd->arg1);
8115284582fSBill Yuan }
8125284582fSBill Yuan 
8135284582fSBill Yuan void
show_to_me(ipfw_insn * cmd,int show_or)8146ce8c93fSBill Yuan show_to_me(ipfw_insn *cmd, int show_or)
81563317b93SBill Yuan {
8166ce8c93fSBill Yuan 	char *word = "to";
8176ce8c93fSBill Yuan 	if (show_or)
8186ce8c93fSBill Yuan 		word = "or";
8196ce8c93fSBill Yuan 	printf(" %s me", word);
82063317b93SBill Yuan }
82163317b93SBill Yuan 
82263317b93SBill Yuan void
show_to_mask(ipfw_insn * cmd,int show_or)8236ce8c93fSBill Yuan show_to_mask(ipfw_insn *cmd, int show_or)
82463317b93SBill Yuan {
82563317b93SBill Yuan 	int mask;
8266ce8c93fSBill Yuan 	char *word = "to";
8276ce8c93fSBill Yuan 	if (show_or)
8286ce8c93fSBill Yuan 		word = "or";
82963317b93SBill Yuan 	ipfw_insn_ip *p = (ipfw_insn_ip *)cmd;
8306ce8c93fSBill Yuan 	printf(" %s %s", word, inet_ntoa(p->addr));
83163317b93SBill Yuan 
83263317b93SBill Yuan 	mask = contigmask((u_char *)&(p->mask.s_addr), 32);
83363317b93SBill Yuan 	if (mask < 32)
83463317b93SBill Yuan 		printf("/%d", mask);
83563317b93SBill Yuan }
83663317b93SBill Yuan 
83763317b93SBill Yuan void
show_to_src_n_port(ipfw_insn * cmd,int show_or)838c1bde762SBill Yuan show_to_src_n_port(ipfw_insn *cmd, int show_or)
839c1bde762SBill Yuan {
840c1bde762SBill Yuan 	char *word = "to";
841c1bde762SBill Yuan 	if (show_or)
842c1bde762SBill Yuan 		word = "or";
843c1bde762SBill Yuan 	printf(" %s %s", word, inet_ntoa(((ipfw_insn_ip *)cmd)->addr));
844c1bde762SBill Yuan 	printf(":%d", cmd->arg1);
845c1bde762SBill Yuan }
846c1bde762SBill Yuan 
847c1bde762SBill Yuan void
show_proto(ipfw_insn * cmd,int show_or)8486ce8c93fSBill Yuan show_proto(ipfw_insn *cmd, int show_or)
8496a03354eSMatthew Dillon {
8506a03354eSMatthew Dillon 	struct protoent *pe;
8516a03354eSMatthew Dillon 	u_char proto = 0;
8526a03354eSMatthew Dillon 	proto = cmd->arg1;
8536a03354eSMatthew Dillon 	pe = getprotobynumber(cmd->arg1);
8546a03354eSMatthew Dillon 	printf(" %s", pe->p_name);
8556a03354eSMatthew Dillon }
8566a03354eSMatthew Dillon 
8576a03354eSMatthew Dillon void
show_prob(ipfw_insn * cmd,int show_or)8586ce8c93fSBill Yuan show_prob(ipfw_insn *cmd, int show_or)
8596a03354eSMatthew Dillon {
8605f62bb52SBill Yuan 	char *word = "prob";
8615f62bb52SBill Yuan 	if (show_or)
8625f62bb52SBill Yuan 		word = "or";
8635f62bb52SBill Yuan 	printf(" %s %d%%", word, cmd->arg1);
8646a03354eSMatthew Dillon }
8656a03354eSMatthew Dillon 
8666a03354eSMatthew Dillon void
show_keep_state(ipfw_insn * cmd,int show_or)8676ce8c93fSBill Yuan show_keep_state(ipfw_insn *cmd, int show_or)
8686a03354eSMatthew Dillon {
8696a03354eSMatthew Dillon 	printf(" keep-state");
8706a03354eSMatthew Dillon 	if (cmd->arg1 != 0) {
8716a03354eSMatthew Dillon 		char *type=match_token2(limit_types, cmd->arg3);
8726a03354eSMatthew Dillon 		printf(" limit %s %d", type, cmd->arg1);
8736a03354eSMatthew Dillon 	}
8746a03354eSMatthew Dillon 	if (cmd->arg2 != 0) {
8756a03354eSMatthew Dillon 		printf(" live %d", cmd->arg2);
8766a03354eSMatthew Dillon 	}
8776a03354eSMatthew Dillon }
8786a03354eSMatthew Dillon 
8796a03354eSMatthew Dillon void
show_check_state(ipfw_insn * cmd,int show_or)8806ce8c93fSBill Yuan show_check_state(ipfw_insn *cmd, int show_or)
8816a03354eSMatthew Dillon {
8826a03354eSMatthew Dillon 	printf(" check-state");
8836a03354eSMatthew Dillon }
8846a03354eSMatthew Dillon 
8856a03354eSMatthew Dillon void
show_tagged(ipfw_insn * cmd,int show_or)8866ce8c93fSBill Yuan show_tagged(ipfw_insn *cmd, int show_or)
8876a03354eSMatthew Dillon {
8886a03354eSMatthew Dillon 	printf(" tagged %d", cmd->arg1);
8896a03354eSMatthew Dillon }
8906a03354eSMatthew Dillon 
8916a03354eSMatthew Dillon void
show_comment(ipfw_insn * cmd,int show_or)8926ce8c93fSBill Yuan show_comment(ipfw_insn *cmd, int show_or)
8936a03354eSMatthew Dillon {
8946a03354eSMatthew Dillon 	printf(" // %s", (char *)(cmd + 1));
8956a03354eSMatthew Dillon }
8966a03354eSMatthew Dillon 
8976a03354eSMatthew Dillon void
show_tag(ipfw_insn * cmd,int show_or)8986ce8c93fSBill Yuan show_tag(ipfw_insn *cmd, int show_or)
8996a03354eSMatthew Dillon {
9006a03354eSMatthew Dillon 	printf(" tag %d", cmd->arg1);
9016a03354eSMatthew Dillon }
9026a03354eSMatthew Dillon 
9036a03354eSMatthew Dillon void
show_untag(ipfw_insn * cmd,int show_or)9046ce8c93fSBill Yuan show_untag(ipfw_insn *cmd, int show_or)
9056a03354eSMatthew Dillon {
9066a03354eSMatthew Dillon 	printf(" untag %d", cmd->arg1);
9076a03354eSMatthew Dillon }
9086a03354eSMatthew Dillon 
9096a03354eSMatthew Dillon void
load_module(register_func function,register_keyword keyword)9106a03354eSMatthew Dillon load_module(register_func function, register_keyword keyword)
9116a03354eSMatthew Dillon {
9123b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_COUNT, "count", ACTION);
9136a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_COUNT,
9146a03354eSMatthew Dillon 			(parser_func)parse_count, (shower_func)show_count);
9156a03354eSMatthew Dillon 
9163b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_SKIPTO, "skipto", ACTION);
9176a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_SKIPTO,
9186a03354eSMatthew Dillon 			(parser_func)parse_skipto, (shower_func)show_skipto);
9196a03354eSMatthew Dillon 
9203b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_FORWARD, "forward", ACTION);
9216a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_FORWARD,
9226a03354eSMatthew Dillon 			(parser_func)parse_forward, (shower_func)show_forward);
9236a03354eSMatthew Dillon 
9243b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IN, "in", FILTER);
9256a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_IN,
9266a03354eSMatthew Dillon 			(parser_func)parse_in, (shower_func)show_in);
9276a03354eSMatthew Dillon 
9283b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_OUT, "out", FILTER);
9296a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_OUT,
9306a03354eSMatthew Dillon 			(parser_func)parse_out, (shower_func)show_out);
9316a03354eSMatthew Dillon 
9323b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_VIA, "via", FILTER);
9336a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_VIA,
9346a03354eSMatthew Dillon 			(parser_func)parse_via, (shower_func)show_via);
9356a03354eSMatthew Dillon 
9363b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_XMIT, "xmit", FILTER);
9376a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_XMIT,
9386a03354eSMatthew Dillon 			(parser_func)parse_via, (shower_func)show_via);
9396a03354eSMatthew Dillon 
9403b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_RECV, "recv", FILTER);
9416a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_RECV,
9426a03354eSMatthew Dillon 			(parser_func)parse_via, (shower_func)show_via);
9436a03354eSMatthew Dillon 
944c1bde762SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_SRCPORT, "src-port", FILTER);
945c1bde762SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_SRCPORT,
946c1bde762SBill Yuan 	                (parser_func)parse_src_port, (shower_func)show_src_port);
947c1bde762SBill Yuan 
948c1bde762SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_DSTPORT, "dst-port", FILTER);
949c1bde762SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_DSTPORT,
950c1bde762SBill Yuan 	                (parser_func)parse_dst_port, (shower_func)show_dst_port);
951c1bde762SBill Yuan 
9523b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC, "from", FROM);
9536a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_IP_SRC,
9546a03354eSMatthew Dillon 			(parser_func)parse_from, (shower_func)show_from);
9555284582fSBill Yuan 
95662f8e481SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_LOOKUP, "from-[table]", FROM);
9575284582fSBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_SRC_LOOKUP,
9585284582fSBill Yuan 			(parser_func)parse_from, (shower_func)show_from_lookup);
9595284582fSBill Yuan 
96062f8e481SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME, "from-[me]", FROM);
96163317b93SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_SRC_ME,
96263317b93SBill Yuan 			(parser_func)parse_from, (shower_func)show_from_me);
963c1bde762SBill Yuan 
96462f8e481SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK, "from-[mask]", FROM);
96563317b93SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_SRC_MASK,
96663317b93SBill Yuan 			(parser_func)parse_from, (shower_func)show_from_mask);
967c1bde762SBill Yuan 
968c1bde762SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_SRC_N_PORT, "from-[ip:port]", FROM);
969c1bde762SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_SRC_N_PORT,
970c1bde762SBill Yuan 			(parser_func)parse_from, (shower_func)show_from_src_n_port);
971c1bde762SBill Yuan 
9723b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_DST, "to", TO);
9736a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_IP_DST,
9746a03354eSMatthew Dillon 			(parser_func)parse_to, (shower_func)show_to);
9755284582fSBill Yuan 
97662f8e481SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_LOOKUP, "to-[table]", TO);
9775284582fSBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_DST_LOOKUP,
9785284582fSBill Yuan 			(parser_func)parse_to, (shower_func)show_to_lookup);
9795284582fSBill Yuan 
98062f8e481SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_ME, "to-[me]", TO);
98163317b93SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_DST_ME,
98263317b93SBill Yuan 			(parser_func)parse_to, (shower_func)show_to_me);
983c1bde762SBill Yuan 
98462f8e481SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK, "to-[mask]", TO);
98563317b93SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_DST_MASK,
98663317b93SBill Yuan 			(parser_func)parse_to, (shower_func)show_to_mask);
9876a03354eSMatthew Dillon 
988c1bde762SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_IP_DST_N_PORT, "to-[ip:port]", FROM);
989c1bde762SBill Yuan 	function(MODULE_BASIC_ID, O_BASIC_IP_DST_N_PORT,
990c1bde762SBill Yuan 			(parser_func)parse_to, (shower_func)show_to_src_n_port);
991c1bde762SBill Yuan 
9923b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_PROTO, "proto", PROTO);
9936a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_PROTO,
9946a03354eSMatthew Dillon 			(parser_func)parse_proto, (shower_func)show_proto);
9956a03354eSMatthew Dillon 
9963b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_PROB, "prob", FILTER);
9976a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_PROB,
9986a03354eSMatthew Dillon 			(parser_func)parse_prob, (shower_func)show_prob);
9996a03354eSMatthew Dillon 
10003b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_KEEP_STATE, "keep-state", FILTER);
10016a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_KEEP_STATE,
10026a03354eSMatthew Dillon 			(parser_func)parse_keep_state,
10036a03354eSMatthew Dillon 			(shower_func)show_keep_state);
10046a03354eSMatthew Dillon 
100526a55228SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_CHECK_STATE, "check-state", BEFORE);
10066a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_CHECK_STATE,
10076a03354eSMatthew Dillon 			(parser_func)parse_check_state,
10086a03354eSMatthew Dillon 			(shower_func)show_check_state);
10096a03354eSMatthew Dillon 
10103b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_TAG, "tag", ACTION);
10116a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_TAG,
10126a03354eSMatthew Dillon 			(parser_func)parse_tag, (shower_func)show_tag);
10136a03354eSMatthew Dillon 
10143b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_UNTAG, "untag", ACTION);
10156a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_UNTAG,
10166a03354eSMatthew Dillon 			(parser_func)parse_untag, (shower_func)show_untag);
10176a03354eSMatthew Dillon 
10183b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_TAGGED, "tagged", FILTER);
10196a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_TAGGED,
10206a03354eSMatthew Dillon 			(parser_func)parse_tagged, (shower_func)show_tagged);
10216a03354eSMatthew Dillon 
10223b6ebdc3SBill Yuan 	keyword(MODULE_BASIC_ID, O_BASIC_COMMENT, "//", AFTER);
10236a03354eSMatthew Dillon 	function(MODULE_BASIC_ID, O_BASIC_COMMENT,
10246a03354eSMatthew Dillon 			(parser_func)parse_comment, (shower_func)show_comment);
10256a03354eSMatthew Dillon }
1026