From owner-svn-src-all@FreeBSD.ORG Tue Jan 27 10:18:56 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0F6A4106564A; Tue, 27 Jan 2009 10:18:56 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id F07F58FC1C; Tue, 27 Jan 2009 10:18:55 +0000 (UTC) (envelope-from luigi@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n0RAItSA081173; Tue, 27 Jan 2009 10:18:55 GMT (envelope-from luigi@svn.freebsd.org) Received: (from luigi@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0RAItgK081169; Tue, 27 Jan 2009 10:18:55 GMT (envelope-from luigi@svn.freebsd.org) Message-Id: <200901271018.n0RAItgK081169@svn.freebsd.org> From: Luigi Rizzo Date: Tue, 27 Jan 2009 10:18:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187767 - head/sbin/ipfw X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Jan 2009 10:18:56 -0000 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 #include #include -#include + +#include "ipfw2.h" #include #include @@ -32,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -59,49 +59,9 @@ #include #include -/* - * 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] \n\n" -"where 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipfw2.h" + +static void +help(void) +{ + fprintf(stderr, +"ipfw syntax summary (but please do read the ipfw(8) manpage):\n\n" +"\tipfw [-abcdefhnNqStTv] \n\n" +"where 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 ***