svn commit: r187767 - head/sbin/ipfw

Luigi Rizzo luigi at FreeBSD.org
Tue Jan 27 02:18:56 PST 2009


Author: luigi
Date: Tue Jan 27 10:18:55 2009
New Revision: 187767
URL: http://svn.freebsd.org/changeset/base/187767

Log:
  Start splitting the monster file in smaller blocks.
  
  In this episode:
  - introduce a common header with a minimal set of common definitions;
  - bring the main() function and options parser in main.c
  - rename the main functions with an ipfw_ prefix
  
  No code changes except for the introduction of a global variable,
  resvd_set_number, which stores the RESVD_SET value from ip_fw.h
  and is used to remove the dependency of main.c from ip_fw.h
  (and the subtree of dependencies) for just a single constant.

Added:
  head/sbin/ipfw/ipfw2.h   (contents, props changed)
  head/sbin/ipfw/main.c   (contents, props changed)
Modified:
  head/sbin/ipfw/Makefile
  head/sbin/ipfw/ipfw2.c

Modified: head/sbin/ipfw/Makefile
==============================================================================
--- head/sbin/ipfw/Makefile	Tue Jan 27 09:38:44 2009	(r187766)
+++ head/sbin/ipfw/Makefile	Tue Jan 27 10:18:55 2009	(r187767)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PROG=	ipfw
-SRCS=	ipfw2.c
+SRCS=	ipfw2.c main.c
 WARNS?=	2
 MAN=	ipfw.8
 

Modified: head/sbin/ipfw/ipfw2.c
==============================================================================
--- head/sbin/ipfw/ipfw2.c	Tue Jan 27 09:38:44 2009	(r187766)
+++ head/sbin/ipfw/ipfw2.c	Tue Jan 27 10:18:55 2009	(r187767)
@@ -24,7 +24,8 @@
 #include <sys/socket.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
-#include <sys/wait.h>
+
+#include "ipfw2.h"
 
 #include <ctype.h>
 #include <err.h>
@@ -32,7 +33,6 @@
 #include <grp.h>
 #include <netdb.h>
 #include <pwd.h>
-#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -59,49 +59,9 @@
 #include <arpa/inet.h>
 #include <alias.h>
 
-/*
- * Options that can be set on the command line.
- * When reading commands from a file, a subset of the options can also
- * be applied globally by specifying them before the file name.
- * After that, each line can contain its own option that changes
- * the global value.
- * XXX The context is not restored after each line.
- */
-
-struct cmdline_opts {
-	/* boolean options: */
-	int	do_value_as_ip;	/* show table value as IP */
-	int	do_resolv;	/* try to resolve all ip to names */
-	int	do_time;	/* Show time stamps */
-	int	do_quiet;	/* Be quiet in add and flush */
-	int	do_pipe;	/* this cmd refers to a pipe */
-	int	do_nat; 	/* this cmd refers to a nat config */
-	int	do_dynamic;	/* display dynamic rules */
-	int	do_expired;	/* display expired dynamic rules */
-	int	do_compact;	/* show rules in compact mode */
-	int	do_force;	/* do not ask for confirmation */
-	int	show_sets;	/* display the set each rule belongs to */
-	int	test_only;	/* only check syntax */
-	int	comment_only;	/* only print action and comment */
-	int	verbose;	/* be verbose on some commands */
+struct cmdline_opts co;	/* global options */
 
-	/* The options below can have multiple values. */
-
-	int	do_sort;	/* field to sort results (0 = no) */
-		/* valid fields are 1 and above */
-
-	int	use_set;	/* work with specified set number */
-		/* 0 means all sets, otherwise apply to set use_set - 1 */
-
-};
-
-struct cmdline_opts co;
-
-/*
- * the following macro returns an error message if we run out of
- * arguments.
- */
-#define NEED1(msg)      {if (!ac) errx(EX_USAGE, msg);}
+int resvd_set_number = RESVD_SET;
 
 #define GET_UINT_ARG(arg, min, max, tok, s_x) do {			\
 	if (!ac)							\
@@ -143,19 +103,6 @@ PRINT_UINT_ARG(const char *str, uint32_t
 		printf("%u", arg);
 }
 
-/*
- * _s_x is a structure that stores a string <-> token pairs, used in
- * various places in the parser. Entries are stored in arrays,
- * with an entry with s=NULL as terminator.
- * The search routines are match_token() and match_value().
- * Often, an element with x=0 contains an error string.
- *
- */
-struct _s_x {
-	char const *s;
-	int x;
-};
-
 static struct _s_x f_tcpflags[] = {
 	{ "syn", TH_SYN },
 	{ "fin", TH_FIN },
@@ -528,7 +475,7 @@ align_uint64(uint64_t *pll) {
 	return ret;
 }
 
-static void *
+void *
 safe_calloc(size_t number, size_t size)
 {
 	void *ret = calloc(number, size);
@@ -538,7 +485,7 @@ safe_calloc(size_t number, size_t size)
 	return ret;
 }
 
-static void *
+void *
 safe_realloc(void *ptr, size_t size)
 {
 	void *ret = realloc(ptr, size);
@@ -615,7 +562,7 @@ match_value(struct _s_x *p, int value)
  * This function will be removed in the future through the usual
  * deprecation process.
  */
-static int
+int
 _substrcmp(const char *str1, const char* str2)
 {
 	
@@ -2396,8 +2343,8 @@ list_pipes(void *data, uint nbytes, int 
  * 	ipfw set move X to Y
  * 	ipfw set move rule X to Y
  */
-static void
-sets_handler(int ac, char *av[])
+void
+ipfw_sets_handler(int ac, char *av[])
 {
 	uint32_t set_disable, masks[2];
 	int i, nbytes;
@@ -2496,8 +2443,8 @@ sets_handler(int ac, char *av[])
 		errx(EX_USAGE, "invalid set command %s\n", *av);
 }
 
-static void
-sysctl_handler(int ac, char *av[], int which)
+void
+ipfw_sysctl_handler(int ac, char *av[], int which)
 {
 	ac--;
 	av++;
@@ -2526,8 +2473,8 @@ sysctl_handler(int ac, char *av[], int w
 	}
 }
 
-static void
-list(int ac, char *av[], int show_counters)
+void
+ipfw_list(int ac, char *av[], int show_counters)
 {
 	struct ip_fw *r;
 	ipfw_dyn_rule *dynrules, *d;
@@ -2723,52 +2670,6 @@ done:
 #undef NEXT
 }
 
-static void
-help(void)
-{
-	fprintf(stderr,
-"ipfw syntax summary (but please do read the ipfw(8) manpage):\n\n"
-"\tipfw [-abcdefhnNqStTv] <command>\n\n"
-"where <command> is one of the following:\n\n"
-"add [num] [set N] [prob x] RULE-BODY\n"
-"{pipe|queue} N config PIPE-BODY\n"
-"[pipe|queue] {zero|delete|show} [N{,N}]\n"
-"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n"
-"		reverse|proxy_only|redirect_addr linkspec|\n"
-"		redirect_port linkspec|redirect_proto linkspec}\n"
-"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
-"set N {show|list|zero|resetlog|delete} [N{,N}] | flush\n"
-"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
-"table all {flush | list}\n"
-"\n"
-"RULE-BODY:	check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
-"ACTION:	check-state | allow | count | deny | unreach{,6} CODE |\n"
-"               skipto N | {divert|tee} PORT | forward ADDR |\n"
-"               pipe N | queue N | nat N | setfib FIB\n"
-"PARAMS: 	[log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
-"ADDR:		[ MAC dst src ether_type ] \n"
-"		[ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
-"		[ ipv6|ip6 from IP6ADDR [ PORT ] to IP6ADDR [ PORTLIST ] ]\n"
-"IPADDR:	[not] { any | me | ip/bits{x,y,z} | table(t[,v]) | IPLIST }\n"
-"IP6ADDR:	[not] { any | me | me6 | ip6/bits | IP6LIST }\n"
-"IP6LIST:	{ ip6 | ip6/bits }[,IP6LIST]\n"
-"IPLIST:	{ ip | ip/bits | ip:mask }[,IPLIST]\n"
-"OPTION_LIST:	OPTION [OPTION_LIST]\n"
-"OPTION:	bridged | diverted | diverted-loopback | diverted-output |\n"
-"	{dst-ip|src-ip} IPADDR | {dst-ip6|src-ip6|dst-ipv6|src-ipv6} IP6ADDR |\n"
-"	{dst-port|src-port} LIST |\n"
-"	estab | frag | {gid|uid} N | icmptypes LIST | in | out | ipid LIST |\n"
-"	iplen LIST | ipoptions SPEC | ipprecedence | ipsec | iptos SPEC |\n"
-"	ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
-"	icmp6types LIST | ext6hdr LIST | flow-id N[,N] | fib FIB |\n"
-"	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
-"	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
-"	tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
-);
-exit(0);
-}
-
-
 static int
 lookup_host (char *host, struct in_addr *ipaddr)
 {
@@ -3240,8 +3141,8 @@ fill_flags(ipfw_insn *cmd, enum ipfw_opc
 }
 
 
-static void
-delete(int ac, char *av[])
+void
+ipfw_delete(int ac, char *av[])
 {
 	uint32_t rulenum;
 	struct dn_pipe p;
@@ -3871,9 +3772,6 @@ nospace:
 }
 
 static void
-show_nat(int ac, char **av);
-
-static void
 print_nat_config(unsigned char *buf)
 {
 	struct cfg_nat *n;
@@ -3988,8 +3886,8 @@ print_nat_config(unsigned char *buf)
 	printf("\n");
 }
 
-static void
-config_nat(int ac, char **av)
+void
+ipfw_config_nat(int ac, char **av)
 {
 	struct cfg_nat *n;              /* Nat instance configuration. */
 	int i, len, off, tok;
@@ -4087,12 +3985,12 @@ config_nat(int ac, char **av)
 		/* After every modification, we show the resultant rule. */
 		int _ac = 3;
 		char *_av[] = {"show", "config", id};
-		show_nat(_ac, _av);
+		ipfw_show_nat(_ac, _av);
 	}
 }
 
-static void
-config_pipe(int ac, char **av)
+void
+ipfw_config_pipe(int ac, char **av)
 {
 	struct dn_pipe p;
 	int i;
@@ -4772,8 +4670,8 @@ add_dst(ipfw_insn *cmd, char *av, u_char
  * various match patterns, log/altq actions, and the actual action.
  *
  */
-static void
-add(int ac, char *av[])
+void
+ipfw_add(int ac, char *av[])
 {
 	/*
 	 * rules are added into the 'rulebuf' and then copied in
@@ -5781,13 +5679,18 @@ done:
 		show_ipfw(rule, 0, 0);
 }
 
-static void
-zero(int ac, char *av[], int optname /* IP_FW_ZERO or IP_FW_RESETLOG */)
+/*
+ * clear the counters or the log counters.
+ */
+void
+ipfw_zero(int ac, char *av[], int optname /* 0 = IP_FW_ZERO, 1 = IP_FW_RESETLOG */)
 {
 	uint32_t arg, saved_arg;
 	int failed = EX_OK;
-	char const *name = optname == IP_FW_ZERO ?  "ZERO" : "RESETLOG";
 	char const *errstr;
+	char const *name = optname ? "RESETLOG" : "ZERO";
+
+	optname = optname ? IP_FW_RESETLOG : IP_FW_ZERO;
 
 	av++; ac--;
 
@@ -5830,8 +5733,8 @@ zero(int ac, char *av[], int optname /* 
 		exit(failed);
 }
 
-static void
-flush(int force)
+void
+ipfw_flush(int force)
 {
 	int cmd = co.do_pipe ? IP_DUMMYNET_FLUSH : IP_FW_FLUSH;
 
@@ -5862,18 +5765,6 @@ flush(int force)
 		printf("Flushed all %s.\n", co.do_pipe ? "pipes" : "rules");
 }
 
-/*
- * Free a the (locally allocated) copy of command line arguments.
- */
-static void
-free_args(int ac, char **av)
-{
-	int i;
-
-	for (i=0; i < ac; i++)
-		free(av[i]);
-	free(av);
-}
 
 static void table_list(ipfw_table_entry ent, int need_header);
 
@@ -5884,8 +5775,8 @@ static void table_list(ipfw_table_entry 
  * 	ipfw table {N | all} flush
  * 	ipfw table {N | all} list
  */
-static void
-table_handler(int ac, char *av[])
+void
+ipfw_table_handler(int ac, char *av[])
 {
 	ipfw_table_entry ent;
 	int do_add;
@@ -6033,8 +5924,8 @@ table_list(ipfw_table_entry ent, int nee
 	free(tbl);
 }
 
-static void
-show_nat(int ac, char **av)
+void
+ipfw_show_nat(int ac, char **av)
 {
 	struct cfg_nat *n;
 	struct cfg_redir *e;
@@ -6107,446 +5998,3 @@ show_nat(int ac, char **av)
 		}
 	}
 }
-
-/*
- * Called with the arguments, including program name because getopt
- * wants it to be present.
- * Returns 0 if successful, 1 if empty command, errx() in case of errors.
- */
-static int
-ipfw_main(int oldac, char **oldav)
-{
-	int ch, ac, save_ac;
-	const char *errstr;
-	char **av, **save_av;
-	int do_acct = 0;		/* Show packet/byte count */
-
-#define WHITESP		" \t\f\v\n\r"
-	if (oldac < 2)
-		return 1;	/* need at least one argument */
-	if (oldac == 2) {
-		/*
-		 * If we are called with a single string, try to split it into
-		 * arguments for subsequent parsing.
-		 * But first, remove spaces after a ',', by copying the string
-		 * in-place.
-		 */
-		char *arg = oldav[1];	/* The string is the first arg. */
-		int l = strlen(arg);
-		int copy = 0;		/* 1 if we need to copy, 0 otherwise */
-		int i, j;
-		for (i = j = 0; i < l; i++) {
-			if (arg[i] == '#')	/* comment marker */
-				break;
-			if (copy) {
-				arg[j++] = arg[i];
-				copy = !index("," WHITESP, arg[i]);
-			} else {
-				copy = !index(WHITESP, arg[i]);
-				if (copy)
-					arg[j++] = arg[i];
-			}
-		}
-		if (!copy && j > 0)	/* last char was a 'blank', remove it */
-			j--;
-		l = j;			/* the new argument length */
-		arg[j++] = '\0';
-		if (l == 0)		/* empty string! */
-			return 1;
-
-		/*
-		 * First, count number of arguments. Because of the previous
-		 * processing, this is just the number of blanks plus 1.
-		 */
-		for (i = 0, ac = 1; i < l; i++)
-			if (index(WHITESP, arg[i]) != NULL)
-				ac++;
-
-		/*
-		 * Allocate the argument list, including one entry for
-		 * the program name because getopt expects it.
-		 */
-		av = safe_calloc(ac + 1, sizeof(char *));
-
-		/*
-		 * Second, copy arguments from arg[] to av[]. For each one,
-		 * j is the initial character, i is the one past the end.
-		 */
-		for (ac = 1, i = j = 0; i < l; i++)
-			if (index(WHITESP, arg[i]) != NULL || i == l-1) {
-				if (i == l-1)
-					i++;
-				av[ac] = safe_calloc(i-j+1, 1);
-				bcopy(arg+j, av[ac], i-j);
-				ac++;
-				j = i + 1;
-			}
-	} else {
-		/*
-		 * If an argument ends with ',' join with the next one.
-		 */
-		int first, i, l;
-
-		av = safe_calloc(oldac, sizeof(char *));
-		for (first = i = ac = 1, l = 0; i < oldac; i++) {
-			char *arg = oldav[i];
-			int k = strlen(arg);
-
-			l += k;
-			if (arg[k-1] != ',' || i == oldac-1) {
-				/* Time to copy. */
-				av[ac] = safe_calloc(l+1, 1);
-				for (l=0; first <= i; first++) {
-					strcat(av[ac]+l, oldav[first]);
-					l += strlen(oldav[first]);
-				}
-				ac++;
-				l = 0;
-				first = i+1;
-			}
-		}
-	}
-
-	av[0] = strdup(oldav[0]);	/* copy progname from the caller */
-	/* Set the force flag for non-interactive processes */
-	if (!co.do_force)
-		co.do_force = !isatty(STDIN_FILENO);
-
-	/* Save arguments for final freeing of memory. */
-	save_ac = ac;
-	save_av = av;
-
-	optind = optreset = 1;	/* restart getopt() */
-	while ((ch = getopt(ac, av, "abcdefhinNqs:STtv")) != -1)
-		switch (ch) {
-		case 'a':
-			do_acct = 1;
-			break;
-
-		case 'b':
-			co.comment_only = 1;
-			co.do_compact = 1;
-			break;
-
-		case 'c':
-			co.do_compact = 1;
-			break;
-
-		case 'd':
-			co.do_dynamic = 1;
-			break;
-
-		case 'e':
-			co.do_expired = 1;
-			break;
-
-		case 'f':
-			co.do_force = 1;
-			break;
-
-		case 'h': /* help */
-			free_args(save_ac, save_av);
-			help();
-			break;	/* NOTREACHED */
-
-		case 'i':
-			co.do_value_as_ip = 1;
-			break;
-
-		case 'n':
-			co.test_only = 1;
-			break;
-
-		case 'N':
-			co.do_resolv = 1;
-			break;
-
-		case 'q':
-			co.do_quiet = 1;
-			break;
-
-		case 's': /* sort */
-			co.do_sort = atoi(optarg);
-			break;
-
-		case 'S':
-			co.show_sets = 1;
-			break;
-
-		case 't':
-			co.do_time = 1;
-			break;
-
-		case 'T':
-			co.do_time = 2;	/* numeric timestamp */
-			break;
-
-		case 'v': /* verbose */
-			co.verbose = 1;
-			break;
-
-		default:
-			free_args(save_ac, save_av);
-			return 1;
-		}
-
-	ac -= optind;
-	av += optind;
-	NEED1("bad arguments, for usage summary ``ipfw''");
-
-	/*
-	 * An undocumented behaviour of ipfw1 was to allow rule numbers first,
-	 * e.g. "100 add allow ..." instead of "add 100 allow ...".
-	 * In case, swap first and second argument to get the normal form.
-	 */
-	if (ac > 1 && isdigit(*av[0])) {
-		char *p = av[0];
-
-		av[0] = av[1];
-		av[1] = p;
-	}
-
-	/*
-	 * Optional: pipe, queue or nat.
-	 */
-	co.do_nat = 0;
-	co.do_pipe = 0;
-	if (!strncmp(*av, "nat", strlen(*av)))
- 	        co.do_nat = 1;
- 	else if (!strncmp(*av, "pipe", strlen(*av)))
-		co.do_pipe = 1;
-	else if (_substrcmp(*av, "queue") == 0)
-		co.do_pipe = 2;
-	else if (!strncmp(*av, "set", strlen(*av))) {
-		if (ac > 1 && isdigit(av[1][0])) {
-			co.use_set = strtonum(av[1], 0, RESVD_SET, &errstr);
-			if (errstr)
-				errx(EX_DATAERR,
-				    "invalid set number %s\n", av[1]);
-			ac -= 2; av += 2; co.use_set++;
-		}
-	}
-
-	if (co.do_pipe || co.do_nat) {
-		ac--;
-		av++;
-	}
-	NEED1("missing command");
-
-	/*
-	 * For pipes, queues and nats we normally say 'nat|pipe NN config'
-	 * but the code is easier to parse as 'nat|pipe config NN'
-	 * so we swap the two arguments.
-	 */
-	if ((co.do_pipe || co.do_nat) && ac > 1 && isdigit(*av[0])) {
-		char *p = av[0];
-
-		av[0] = av[1];
-		av[1] = p;
-	}
-
-	int try_next = 0;
-	if (co.use_set == 0) {
-		if (_substrcmp(*av, "add") == 0)
-			add(ac, av);
-		else if (co.do_nat && _substrcmp(*av, "show") == 0)
- 			show_nat(ac, av);
-		else if (co.do_pipe && _substrcmp(*av, "config") == 0)
-			config_pipe(ac, av);
-		else if (co.do_nat && _substrcmp(*av, "config") == 0)
- 			config_nat(ac, av);
-		else if (_substrcmp(*av, "set") == 0)
-			sets_handler(ac, av);
-		else if (_substrcmp(*av, "table") == 0)
-			table_handler(ac, av);
-		else if (_substrcmp(*av, "enable") == 0)
-			sysctl_handler(ac, av, 1);
-		else if (_substrcmp(*av, "disable") == 0)
-			sysctl_handler(ac, av, 0);
-		else
-			try_next = 1;
-	}
-
-	if (co.use_set || try_next) {
-		if (_substrcmp(*av, "delete") == 0)
-			delete(ac, av);
-		else if (_substrcmp(*av, "flush") == 0)
-			flush(co.do_force);
-		else if (_substrcmp(*av, "zero") == 0)
-			zero(ac, av, IP_FW_ZERO);
-		else if (_substrcmp(*av, "resetlog") == 0)
-			zero(ac, av, IP_FW_RESETLOG);
-		else if (_substrcmp(*av, "print") == 0 ||
-		         _substrcmp(*av, "list") == 0)
-			list(ac, av, do_acct);
-		else if (_substrcmp(*av, "show") == 0)
-			list(ac, av, 1 /* show counters */);
-		else
-			errx(EX_USAGE, "bad command `%s'", *av);
-	}
-
-	/* Free memory allocated in the argument parsing. */
-	free_args(save_ac, save_av);
-	return 0;
-}
-
-
-static void
-ipfw_readfile(int ac, char *av[])
-{
-#define MAX_ARGS	32
-	char	buf[BUFSIZ];
-	char *progname = av[0];		/* original program name */
-	const char *cmd = NULL;		/* preprocessor name, if any */
-	const char *filename = av[ac-1]; /* file to read */
-	int	c, lineno=0;
-	FILE	*f = NULL;
-	pid_t	preproc = 0;
-
-	while ((c = getopt(ac, av, "cfNnp:qS")) != -1) {
-		switch(c) {
-		case 'c':
-			co.do_compact = 1;
-			break;
-
-		case 'f':
-			co.do_force = 1;
-			break;
-
-		case 'N':
-			co.do_resolv = 1;
-			break;
-
-		case 'n':
-			co.test_only = 1;
-			break;
-
-		case 'p':
-			/*
-			 * ipfw -p cmd [args] filename
-			 *
-			 * We are done with getopt(). All arguments
-			 * except the filename go to the preprocessor,
-			 * so we need to do the following:
-			 * - check that a filename is actually present;
-			 * - advance av by optind-1 to skip arguments
-			 *   already processed;
-			 * - decrease ac by optind, to remove the args
-			 *   already processed and the final filename;
-			 * - set the last entry in av[] to NULL so
-			 *   popen() can detect the end of the array;
-			 * - set optind=ac to let getopt() terminate.
-			 */
-			if (optind == ac)
-				errx(EX_USAGE, "no filename argument");
-			cmd = optarg;
-			av[ac-1] = NULL;
-			av += optind - 1;
-			ac -= optind;
-			optind = ac;
-			break;
-
-		case 'q':
-			co.do_quiet = 1;
-			break;
-
-		case 'S':
-			co.show_sets = 1;
-			break;
-
-		default:
-			errx(EX_USAGE, "bad arguments, for usage"
-			     " summary ``ipfw''");
-		}
-
-	}
-
-	if (cmd == NULL && ac != optind + 1)
-		errx(EX_USAGE, "extraneous filename arguments %s", av[ac-1]);
-
-	if ((f = fopen(filename, "r")) == NULL)
-		err(EX_UNAVAILABLE, "fopen: %s", filename);
-
-	if (cmd != NULL) {			/* pipe through preprocessor */
-		int pipedes[2];
-
-		if (pipe(pipedes) == -1)
-			err(EX_OSERR, "cannot create pipe");
-
-		preproc = fork();
-		if (preproc == -1)
-			err(EX_OSERR, "cannot fork");
-
-		if (preproc == 0) {
-			/*
-			 * Child, will run the preprocessor with the
-			 * file on stdin and the pipe on stdout.
-			 */
-			if (dup2(fileno(f), 0) == -1
-			    || dup2(pipedes[1], 1) == -1)
-				err(EX_OSERR, "dup2()");
-			fclose(f);
-			close(pipedes[1]);
-			close(pipedes[0]);
-			execvp(cmd, av);
-			err(EX_OSERR, "execvp(%s) failed", cmd);
-		} else { /* parent, will reopen f as the pipe */
-			fclose(f);
-			close(pipedes[1]);
-			if ((f = fdopen(pipedes[0], "r")) == NULL) {
-				int savederrno = errno;
-
-				(void)kill(preproc, SIGTERM);
-				errno = savederrno;
-				err(EX_OSERR, "fdopen()");
-			}
-		}
-	}
-
-	while (fgets(buf, BUFSIZ, f)) {		/* read commands */
-		char linename[10];
-		char *args[2];
-
-		lineno++;
-		sprintf(linename, "Line %d", lineno);
-		setprogname(linename); /* XXX */
-		args[0] = progname;
-		args[1] = buf;
-		ipfw_main(2, args);
-	}
-	fclose(f);
-	if (cmd != NULL) {
-		int status;
-
-		if (waitpid(preproc, &status, 0) == -1)
-			errx(EX_OSERR, "waitpid()");
-		if (WIFEXITED(status) && WEXITSTATUS(status) != EX_OK)
-			errx(EX_UNAVAILABLE,
-			    "preprocessor exited with status %d",
-			    WEXITSTATUS(status));
-		else if (WIFSIGNALED(status))
-			errx(EX_UNAVAILABLE,
-			    "preprocessor exited with signal %d",
-			    WTERMSIG(status));
-	}
-}
-
-int
-main(int ac, char *av[])
-{
-	/*
-	 * If the last argument is an absolute pathname, interpret it
-	 * as a file to be preprocessed.
-	 */
-
-	if (ac > 1 && av[ac - 1][0] == '/' && access(av[ac - 1], R_OK) == 0)
-		ipfw_readfile(ac, av);
-	else {
-		if (ipfw_main(ac, av)) {
-			errx(EX_USAGE,
-			    "usage: ipfw [options]\n"
-			    "do \"ipfw -h\" or \"man ipfw\" for details");
-		}
-	}
-	return EX_OK;
-}

Added: head/sbin/ipfw/ipfw2.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/ipfw/ipfw2.h	Tue Jan 27 10:18:55 2009	(r187767)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2002-2003 Luigi Rizzo
+ * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Idea and grammar partially left from:
+ * Copyright (c) 1993 Daniel Boulet
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ *
+ * NEW command line interface for IP firewall facility
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Options that can be set on the command line.
+ * When reading commands from a file, a subset of the options can also
+ * be applied globally by specifying them before the file name.
+ * After that, each line can contain its own option that changes
+ * the global value.
+ * XXX The context is not restored after each line.
+ */
+
+struct cmdline_opts {
+	/* boolean options: */
+	int	do_value_as_ip;	/* show table value as IP */
+	int	do_resolv;	/* try to resolve all ip to names */
+	int	do_time;	/* Show time stamps */
+	int	do_quiet;	/* Be quiet in add and flush */
+	int	do_pipe;	/* this cmd refers to a pipe */
+	int	do_nat; 	/* this cmd refers to a nat config */
+	int	do_dynamic;	/* display dynamic rules */
+	int	do_expired;	/* display expired dynamic rules */
+	int	do_compact;	/* show rules in compact mode */
+	int	do_force;	/* do not ask for confirmation */
+	int	show_sets;	/* display the set each rule belongs to */
+	int	test_only;	/* only check syntax */
+	int	comment_only;	/* only print action and comment */
+	int	verbose;	/* be verbose on some commands */
+
+	/* The options below can have multiple values. */
+
+	int	do_sort;	/* field to sort results (0 = no) */
+		/* valid fields are 1 and above */
+
+	int	use_set;	/* work with specified set number */
+		/* 0 means all sets, otherwise apply to set use_set - 1 */
+
+};
+
+extern struct cmdline_opts co;
+
+/*
+ * _s_x is a structure that stores a string <-> token pairs, used in
+ * various places in the parser. Entries are stored in arrays,
+ * with an entry with s=NULL as terminator.
+ * The search routines are match_token() and match_value().
+ * Often, an element with x=0 contains an error string.
+ *
+ */
+struct _s_x {
+	char const *s;
+	int x;
+};
+
+/*
+ * the following macro returns an error message if we run out of
+ * arguments.
+ */
+#define NEED1(msg)      {if (!ac) errx(EX_USAGE, msg);}
+
+/* memory allocation support */
+void *safe_calloc(size_t number, size_t size);
+void *safe_realloc(void *ptr, size_t size);
+
+/* a string comparison function used for historical compatibility */
+int _substrcmp(const char *str1, const char* str2);
+
+/*
+ * The reserved set numer. This is a constant in ip_fw.h
+ * but we store it in a variable so other files do not depend
+ * in that header just for one constant.
+ */
+extern int resvd_set_number;
+
+void ipfw_add(int ac, char *av[]);
+void ipfw_show_nat(int ac, char **av);
+void ipfw_config_pipe(int ac, char **av);
+void ipfw_config_nat(int ac, char **av);
+void ipfw_sets_handler(int ac, char *av[]);
+void ipfw_table_handler(int ac, char *av[]);
+void ipfw_sysctl_handler(int ac, char *av[], int which);
+void ipfw_delete(int ac, char *av[]);
+void ipfw_flush(int force);
+void ipfw_zero(int ac, char *av[], int optname);
+void ipfw_list(int ac, char *av[], int show_counters);
+

Added: head/sbin/ipfw/main.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/ipfw/main.c	Tue Jan 27 10:18:55 2009	(r187767)
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2002-2003 Luigi Rizzo
+ * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Idea and grammar partially left from:
+ * Copyright (c) 1993 Daniel Boulet
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ *
+ * Command line interface for IP firewall facility
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/wait.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "ipfw2.h"
+
+static void
+help(void)
+{
+	fprintf(stderr,
+"ipfw syntax summary (but please do read the ipfw(8) manpage):\n\n"
+"\tipfw [-abcdefhnNqStTv] <command>\n\n"
+"where <command> is one of the following:\n\n"
+"add [num] [set N] [prob x] RULE-BODY\n"
+"{pipe|queue} N config PIPE-BODY\n"
+"[pipe|queue] {zero|delete|show} [N{,N}]\n"
+"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n"
+"		reverse|proxy_only|redirect_addr linkspec|\n"
+"		redirect_port linkspec|redirect_proto linkspec}\n"
+"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
+"set N {show|list|zero|resetlog|delete} [N{,N}] | flush\n"
+"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
+"table all {flush | list}\n"
+"\n"
+"RULE-BODY:	check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
+"ACTION:	check-state | allow | count | deny | unreach{,6} CODE |\n"
+"               skipto N | {divert|tee} PORT | forward ADDR |\n"
+"               pipe N | queue N | nat N | setfib FIB\n"
+"PARAMS: 	[log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
+"ADDR:		[ MAC dst src ether_type ] \n"
+"		[ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
+"		[ ipv6|ip6 from IP6ADDR [ PORT ] to IP6ADDR [ PORTLIST ] ]\n"
+"IPADDR:	[not] { any | me | ip/bits{x,y,z} | table(t[,v]) | IPLIST }\n"
+"IP6ADDR:	[not] { any | me | me6 | ip6/bits | IP6LIST }\n"
+"IP6LIST:	{ ip6 | ip6/bits }[,IP6LIST]\n"
+"IPLIST:	{ ip | ip/bits | ip:mask }[,IPLIST]\n"
+"OPTION_LIST:	OPTION [OPTION_LIST]\n"
+"OPTION:	bridged | diverted | diverted-loopback | diverted-output |\n"
+"	{dst-ip|src-ip} IPADDR | {dst-ip6|src-ip6|dst-ipv6|src-ipv6} IP6ADDR |\n"
+"	{dst-port|src-port} LIST |\n"
+"	estab | frag | {gid|uid} N | icmptypes LIST | in | out | ipid LIST |\n"
+"	iplen LIST | ipoptions SPEC | ipprecedence | ipsec | iptos SPEC |\n"
+"	ipttl LIST | ipversion VER | keep-state | layer2 | limit ... |\n"
+"	icmp6types LIST | ext6hdr LIST | flow-id N[,N] | fib FIB |\n"
+"	mac ... | mac-type LIST | proto LIST | {recv|xmit|via} {IF|IPADDR} |\n"
+"	setup | {tcpack|tcpseq|tcpwin} NN | tcpflags SPEC | tcpoptions SPEC |\n"
+"	tcpdatalen LIST | verrevpath | versrcreach | antispoof\n"
+);
+
+	exit(0);
+}
+
+/*
+ * Free a the (locally allocated) copy of command line arguments.
+ */
+static void
+free_args(int ac, char **av)
+{
+	int i;
+
+	for (i=0; i < ac; i++)
+		free(av[i]);
+	free(av);
+}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list