home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NET-TOOL.1 / NET-TOOL / net-tools / ipfw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-11  |  30.1 KB  |  1,424 lines

  1. /*
  2.  ********************************************************************************
  3.  *
  4.  * Copyright (c) 1993 Daniel Boulet
  5.  *
  6.  * Redistribution and use in source forms, with and without modification,
  7.  * are permitted provided that this entire comment appears intact.
  8.  *
  9.  * Redistribution in binary form may occur without any restrictions.
  10.  * Obviously, it would be nice if you gave credit where credit is due
  11.  * but requiring it would be too onerous.
  12.  *
  13.  * This software is provided ``AS IS'' without any warranties of any kind.
  14.  *
  15.  ********************************************************************************
  16.  *
  17.  *
  18.  *  Linux port (c) 1994 Bob Beck
  19.  *
  20.  * Redistribution and use in source forms, with and without modification,
  21.  * are permitted provided that this entire comment appears intact.
  22.  *
  23.  * This software is provided ``AS IS'' without any warranties of any kind.
  24.  *
  25.  ********************************************************************************
  26.  *
  27.  *    Drastically cleaned up: Alan Cox <Alan.Cox@linux.org>
  28.  *    More (major) cleanups and bug fixes by Salvador Abreu <spa@fct.unl.pt>
  29.  *    Additional options Lutz Pre"sler <Lutz.Pressler@med-stat.gwdg.de>
  30.  *    Masquerade client support added <Alan.Cox@linux.org>
  31.  */
  32.  
  33. #include <sys/types.h>
  34. #ifdef _LINUX_TYPES_H
  35. /* Yep. it's Linux */
  36. #ifndef LINUX
  37. #define LINUX
  38. #endif
  39. #endif
  40. #include <sys/socket.h>
  41. #define IPFIREWALL
  42. #include <netinet/in.h>
  43. #include <netinet/ip.h>
  44. #include <netinet/tcp.h>
  45. #include <netinet/udp.h>
  46. #ifndef LINUX
  47. #include <netinet/ip_fw.h>
  48. #else
  49. #include <linux/ip_fw.h>    /* Until it gets into stdinc */
  50. #endif
  51. #include <netdb.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <errno.h>
  56. #ifdef LINUX
  57. #include <ctype.h>
  58. #define IPVERSION 4
  59. #endif
  60.  
  61. #ifdef IP_FW_F_MASQ
  62. #define DO_MASQUERADE
  63. #endif
  64.  
  65. typedef enum
  66. {
  67.     IPF_BLOCKING = 0,
  68.     IPF_FORWARDING = 1,
  69.     IPF_ACCOUNTING = 2,
  70.     IPF_MASQUERADE = 3
  71. } ipf_kind;
  72.  
  73. static char *ipf_names[4] =     {"blocking", "forwarding", "accounting", "maquerading"};
  74. static long ipf_addfunc[4] =     {IP_FW_ADD_BLK, IP_FW_ADD_FWD, IP_ACCT_ADD, IP_FW_ADD_FWD};
  75. static long ipf_delfunc[4] =     {IP_FW_DEL_BLK, IP_FW_DEL_FWD, IP_ACCT_DEL, IP_FW_DEL_FWD};
  76. static int lookup = 1;
  77.  
  78. void show_usage()
  79. {
  80.     fprintf(stderr, "usage: ipfirewall [-n] l[ist]\n");
  81.     fprintf(stderr, "\t\t| f[lush] a[ccounting]\n");
  82.     fprintf(stderr, "\t\t| f[lush] f[irewall]\n");
  83.     fprintf(stderr, "\t\t| c[heck] b[locking]   <type> from <src> to <dst>\n");
  84.     fprintf(stderr, "\t\t| c[heck] f[orwarding] <type> from <src> to <dst>\n");
  85.     fprintf(stderr, "\t\t| a[dd]   a[ccounting] <type> from <src> to <dst>\n");
  86.     fprintf(stderr, "\t\t| a[dd]   b[locking]   <type> from <src> to <dst>\n");
  87.     fprintf(stderr, "\t\t| a[dd]   f[orwarding] <type> from <src> to <dst>\n");
  88. #ifdef DO_MASQUERADE    
  89.     fprintf(stderr, "\t\t| a[dd]   m[asquerade] <type> from <src> to <dst>\n");
  90. #endif    
  91.     fprintf(stderr, "\t\t| d[el]   a[ccounting] <type> from <src> to <dst>\n");
  92.     fprintf(stderr, "\t\t| d[el]   b[locking]   <type> from <src> to <dst>\n");
  93.     fprintf(stderr, "\t\t| d[el]   f[orwarding] <type> from <src> to <dst>\n");
  94. #ifdef DO_MASQUERADE    
  95.     fprintf(stderr, "\t\t| d[el]   m[asquerade] <type> from <src> to <dst>\n");
  96. #endif
  97.     fprintf(stderr, "\t\t| zero[accounting]\n");
  98. }
  99.  
  100. /*
  101.  * I'm not sure that this is practical ...
  102.  */
  103.  
  104. void show_help()
  105. {
  106.     show_usage();
  107.     fprintf(stderr, "where:\n");
  108.     fprintf(stderr, "       <src> ::= <host>:<port> /* for TCP or UDP */\n");
  109.     fprintf(stderr, "       <src> ::= <host>        /* for ICMP */\n");
  110.     fprintf(stderr, "      <host> ::= <byte>.<byte>.<byte>.<byte>[/<width>]\n");
  111.     fprintf(stderr, "               | <hostname>\n");
  112.     fprintf(stderr, "      <port> ::= <short> | <servicename>\n");
  113.     fprintf(stderr, "     <short> ::= an integer in the range 1-65535\n");
  114.     fprintf(stderr, "      <byte> ::= an integer in the range 0-255\n");
  115.     fprintf(stderr, "     <width> ::= an integer in the range 0-32\n");
  116.     exit(1);
  117. }
  118.  
  119. static char *fmtip(u_long uaddr)
  120. {
  121.     static char tbuf[100];
  122.  
  123.     sprintf(tbuf, "%d.%d.%d.%d",
  124.         ((char *) &uaddr)[0] & 0xff,
  125.         ((char *) &uaddr)[1] & 0xff,
  126.         ((char *) &uaddr)[2] & 0xff,
  127.         ((char *) &uaddr)[3] & 0xff);
  128.  
  129.     return (&tbuf[0]);
  130. }
  131.  
  132. static void print_ports(int cnt, int range, u_short * ports)
  133. {
  134.     int ix;
  135.     char *pad;
  136.  
  137.     if (range)
  138.     {
  139.         if (cnt < 2)
  140.         {
  141.             fprintf(stderr,
  142.                 "ipfw: range flag set but only %d ports\n", cnt);
  143.             exit(1);
  144.         }
  145.         printf("%d:%d", ports[0], ports[1]);
  146.         ix = 2;
  147.         pad = " ";
  148.     }
  149.     else
  150.     {
  151.         ix = 0;
  152.         pad = "";
  153.     }
  154.  
  155.     while (ix < cnt)
  156.     {
  157.         printf("%s%d", pad, ports[ix]);
  158.         pad = " ";
  159.         ix += 1;
  160.     }
  161. }
  162.  
  163. static int do_setsockopt(char *what, int fd, int proto, int cmd, void *data, int datalen, int ok_errno)
  164. {
  165.     char *cmdname;
  166.  
  167. #define CASE(NAME) case IP_##NAME: cmdname = "IP_" #NAME; break
  168.  
  169.     switch (cmd)
  170.     {
  171.         CASE(FW_FLUSH);
  172.         CASE(FW_CHK_BLK);
  173.         CASE(FW_CHK_FWD);
  174.         CASE(FW_ADD_BLK);
  175.         CASE(FW_ADD_FWD);
  176.         CASE(FW_DEL_BLK);
  177.         CASE(FW_DEL_FWD);
  178.         CASE(ACCT_ADD);
  179.         CASE(ACCT_DEL);
  180.         CASE(ACCT_FLUSH);
  181.         CASE(ACCT_ZERO);
  182.     default:
  183.         fprintf(stderr, "ipfw: "
  184.             "unknown command (%d) passed to do_setsockopt - bye!\n", cmd);
  185.         exit(1);
  186.     }
  187.  
  188. #undef CASE
  189.  
  190.     if (fd < 0)
  191.     {
  192.         printf("setsockopt(%d, %d, %s, 0x%x, 0x%x)\n",
  193.             fd, proto, cmdname, (int) data, datalen);
  194.         if (cmd == IP_FW_CHK_BLK || cmd == IP_FW_CHK_FWD)
  195.         {
  196.             struct iphdr *ip = (struct iphdr *) data;
  197.             struct tcphdr *tcp = (struct tcphdr *) &(((int *) ip)[ip->ihl]);
  198.             if (ip->ihl != sizeof(struct iphdr) / sizeof(int))
  199.             {
  200.                 fprintf(stderr, "ip header length %d, should be %d\n",
  201.                     ip->ihl, sizeof(struct iphdr) / sizeof(int));
  202.             }
  203.             if (ip->protocol != IPPROTO_TCP && ip->protocol != IPPROTO_UDP)
  204.                 exit(1);
  205.             printf("data = struct iphdr : struct %shdr {\n",
  206.                 ip->protocol == IPPROTO_TCP ? "tcp" : "udp");
  207.             printf("\tsrc=%s ", fmtip(ip->saddr));
  208.             printf("%d\n", ntohs(tcp->th_sport));
  209.             printf("\tdst=%s  ", fmtip(ip->daddr));
  210.             printf("%d\n", ntohs(tcp->th_dport));
  211.             printf("}\n");
  212.         }
  213.         else if (cmd == IP_FW_ADD_BLK ||
  214.                 cmd == IP_FW_ADD_FWD ||
  215.             cmd == IP_ACCT_ADD)
  216.         {
  217.             struct ip_fw *fp = (struct ip_fw *) data;
  218.             int fmt_ports = 0;
  219.             printf("data = struct ip_fw {\n");
  220.             if (fp->flags & IP_FW_F_ACCEPT)
  221.             {
  222.                 printf("\taccept ");
  223.             }
  224.             else
  225.             {
  226.                 printf("\tdeny ");
  227.             }
  228.             switch (fp->flags & IP_FW_F_KIND)
  229.             {
  230.             case IP_FW_F_ALL:
  231.                 printf("\tuniversal\n");
  232.                 fmt_ports = 0;
  233.                 break;
  234.             case IP_FW_F_TCP:
  235.                 printf("tcp\n");
  236.                 fmt_ports = 1;
  237.                 break;
  238.             case IP_FW_F_UDP:
  239.                 printf("udp\n");
  240.                 fmt_ports = 1;
  241.                 break;
  242.             case IP_FW_F_ICMP:
  243.                 printf("icmp\n");
  244.                 fmt_ports = 0;
  245.                 break;
  246.             }
  247.             printf("\tsrc=%s:", fmtip(fp->src.s_addr));
  248.             printf("%s ", fmtip(fp->src_mask.s_addr));
  249.             if (fmt_ports)
  250.             {
  251.                 print_ports(fp->n_src_p, fp->flags & IP_FW_F_SRNG, &fp->ports[0]);
  252.             }
  253.             else if (fp->flags & (IP_FW_F_SRNG | IP_FW_F_DRNG))
  254.             {
  255.                 exit(1);
  256.             }
  257.             else if (fp->n_src_p > 0 || fp->n_dst_p > 0)
  258.             {
  259.                 exit(1);
  260.             }
  261.             printf("\n");
  262.             printf("\tdst=%s:", fmtip(fp->dst.s_addr));
  263.             printf("%s ", fmtip(fp->dst_mask.s_addr));
  264.             if (fmt_ports)
  265.             {
  266.                 print_ports(fp->n_dst_p,
  267.                     fp->flags & IP_FW_F_DRNG,
  268.                     &fp->ports[fp->n_src_p]);
  269.             }
  270.             printf("\n");
  271.             printf("}\n");
  272.         }
  273.     }
  274.     else
  275.     {
  276.         if (setsockopt(fd, proto, cmd, data, datalen) < 0)
  277.         {
  278.             char msg[128];
  279.  
  280.             if (errno == ok_errno)
  281.             {
  282.                 return (errno);
  283.             }
  284.             sprintf(msg, "ipfw: setsockopt(%s)", cmdname);
  285.             perror(msg);
  286.             exit(1);
  287.         }
  288.     }
  289.     return (0);
  290. }
  291.  
  292. void show_parms(char **argv)
  293. {
  294.     while (*argv)
  295.     {
  296.         printf("%s ", *argv++);
  297.     }
  298. }
  299.  
  300. int get_protocol(char *arg, void (*cmd_usage) (ipf_kind), ipf_kind kind)
  301. {
  302.     if (arg == NULL)
  303.     {
  304.         fprintf(stderr, "ipfw: missing protocol name\n");
  305.     }
  306.     else if (strcmp(arg, "tcp") == 0)
  307.     {
  308.         return (IP_FW_F_TCP);
  309.     }
  310.     else if (strcmp(arg, "udp") == 0)
  311.     {
  312.         return (IP_FW_F_UDP);
  313.     }
  314.     else if (strcmp(arg, "icmp") == 0)
  315.     {
  316.         return (IP_FW_F_ICMP);
  317.     }
  318.     else if (strcmp(arg, "all") == 0)
  319.     {
  320.         return (IP_FW_F_ALL);
  321.     }
  322.     else
  323.     {
  324.         fprintf(stderr, "illegal protocol name \"%s\"\n", arg);
  325.     }
  326.     (*cmd_usage) (kind);
  327.     exit(1);
  328.     return (0);
  329. }
  330.  
  331. void get_ipaddr(char *arg, struct in_addr *addr, struct in_addr *mask, void (*usage) (ipf_kind), ipf_kind kind)
  332. {
  333.     char *p, *tbuf;
  334.     int period_cnt, non_digit;
  335.     struct hostent *hptr;
  336.  
  337.     if (arg == NULL)
  338.     {
  339.         fprintf(stderr, "ipfw: missing ip address\n");
  340.         exit(1);
  341.     }
  342.     period_cnt = 0;
  343.     non_digit = 0;
  344.     for (p = arg; *p != '\0' && *p != '/' && *p != ':'; p += 1)
  345.     {
  346.         if (*p == '.')
  347.         {
  348.             if (p > arg && *(p - 1) == '.')
  349.             {
  350.                 fprintf(stderr, "ipfw: two periods in a row in ip address (%s)\n", arg);
  351.                 exit(1);
  352.             }
  353.             period_cnt += 1;
  354.         }
  355.         else if (!isdigit(*p))
  356.         {
  357.             non_digit = 1;
  358.         }
  359.     }
  360.  
  361.     tbuf = malloc(p - arg + 1);
  362.     strncpy(tbuf, arg, p - arg);
  363.     tbuf[p - arg] = '\0';
  364.  
  365.     if (non_digit)
  366.     {
  367.         hptr = gethostbyname(tbuf);
  368.         if (hptr == NULL)
  369.         {
  370.             fprintf(stderr, "ipfw: unknown host \"%s\"\n", tbuf);
  371.             exit(1);
  372.         }
  373.         if (hptr->h_length != sizeof(struct in_addr))
  374.         {
  375.             fprintf(stderr,
  376.                 "ipfw: hostentry addr length = %d, expected %d"
  377.                 "(i.e. sizeof(struct in_addr))\n",
  378.                 hptr->h_length, sizeof(struct in_addr));
  379.             exit(1);
  380.         }
  381.         bcopy(hptr->h_addr, addr, sizeof(struct in_addr));
  382.     }
  383.     else
  384.     {
  385.         if (period_cnt == 3)
  386.         {
  387.  
  388.             int a1, a2, a3, a4, matched;
  389.  
  390.             if ((matched = sscanf(tbuf, "%d.%d.%d.%d", &a1, &a2, &a3, &a4))
  391.                 != 4)
  392.             {
  393.                 fprintf(stderr,
  394.                     "ipfw: Only %d fields matched in IP address!\n",
  395.                     matched);
  396.                 /* should this exit here? or catch it later? -BB */
  397.             }
  398.             if (a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255)
  399.             {
  400.                 fprintf(stderr, "ipfw: number too large in ip address (%s)\n", arg);
  401.                 exit(1);
  402.             }
  403.             ((char *) addr)[0] = a1;
  404.             ((char *) addr)[1] = a2;
  405.             ((char *) addr)[2] = a3;
  406.             ((char *) addr)[3] = a4;
  407.  
  408.         }
  409.         else if (strcmp(tbuf, "0") == 0)
  410.         {
  411.  
  412.             ((char *) addr)[0] = 0;
  413.             ((char *) addr)[1] = 0;
  414.             ((char *) addr)[2] = 0;
  415.             ((char *) addr)[3] = 0;
  416.  
  417.         }
  418.         else
  419.         {
  420.  
  421.             fprintf(stderr, "ipfw: incorrect ip address format \"%s\" (expected 3 periods)\n", tbuf);
  422.             exit(1);
  423.         }
  424.     }
  425.  
  426.     free(tbuf);
  427.  
  428.     if (mask == NULL)
  429.     {
  430.         if (*p != '\0')
  431.         {
  432.             fprintf(stderr, "ipfw: ip netmask not allowed here (%s)\n", (char *) addr);
  433.             exit(1);
  434.         }
  435.     }
  436.     else
  437.     {
  438.         if (*p == ':')
  439.         {
  440.             get_ipaddr(p + 1, mask, NULL, usage, kind);
  441.         }
  442.         else if (*p == '/')
  443.         {
  444.             int bits;
  445.             char *end;
  446.  
  447.             p += 1;
  448.             if (*p == '\0')
  449.             {
  450.                 fprintf(stderr, "ipfw: missing mask value (%s)\n", arg);
  451.                 exit(1);
  452.             }
  453.             else if (!isdigit(*p))
  454.             {
  455.                 fprintf(stderr, "ipfw: non-numeric mask value (%s)\n", arg);
  456.                 exit(1);
  457.             }
  458.             bits = strtol(p, &end, 10);
  459.             if (*end != '\0')
  460.             {
  461.                 fprintf(stderr, "ipfw: junk after mask (%s)\n", arg);
  462.                 exit(1);
  463.             }
  464.             if (bits < 0 || bits > sizeof(u_long) * 8)
  465.             {
  466.                 fprintf(stderr, "ipfw: mask length value out of range (%s)\n", arg);
  467.                 exit(1);
  468.             }
  469.             if (bits == 0)
  470.             {    /* left shifts of 32 aren't defined */
  471.                 mask->s_addr = 0;
  472.             }
  473.             else
  474.             {
  475.                 ((char *) mask)[0] = (-1 << (32 - bits)) >> 24;
  476.                 ((char *) mask)[1] = (-1 << (32 - bits)) >> 16;
  477.                 ((char *) mask)[2] = (-1 << (32 - bits)) >> 8;
  478.                 ((char *) mask)[3] = (-1 << (32 - bits)) >> 0;
  479.             }
  480.  
  481.         }
  482.         else if (*p == '\0')
  483.         {
  484.             mask->s_addr = 0xffffffff;
  485.         }
  486.         else
  487.         {
  488.             fprintf(stderr, "ipfw: junk after ip address (%s)\n", arg);
  489.             exit(1);
  490.         }
  491.  
  492.         /*
  493.          * Mask off any bits in the address that are zero in the mask.
  494.          * This allows the user to describe a network by specifying
  495.          * any host on the network masked with the network's netmask.
  496.          */
  497.         addr->s_addr &= mask->s_addr;
  498.  
  499.     }
  500.  
  501. }
  502.  
  503. u_short get_one_port(char *arg, void (*usage) (ipf_kind), ipf_kind kind, const char *proto_name)
  504. {
  505.     int slen = strlen(arg);
  506.  
  507.     if (slen > 0 && strspn(arg, "0123456789") == slen)
  508.     {
  509.         int port;
  510.         char *end;
  511.  
  512.         port = strtol(arg, &end, 10);
  513.         if (*end != '\0')
  514.         {
  515.             fprintf(stderr, "ipfw: illegal port number (%s)\n", arg);
  516.             exit(1);
  517.         }
  518.         if (port <= 0 || port > 65535)
  519.         {
  520.             fprintf(stderr, "ipfw: port number out of range (%d)\n", port);
  521.             exit(1);
  522.         }
  523.         return (port);
  524.     }
  525.     else
  526.     {
  527.         struct servent *sptr;
  528.  
  529.         sptr = getservbyname(arg, proto_name);
  530.  
  531.         if (sptr == NULL)
  532.         {
  533.             fprintf(stderr, "ipfw: unknown %s service \"%s\"\n", proto_name, arg);
  534.             exit(1);
  535.         }
  536.         return (ntohs(sptr->s_port));
  537.     }
  538. }
  539.  
  540. int get_ports(char ***argv_ptr, u_short * ports, int min_ports, int max_ports, void (*usage) (ipf_kind), ipf_kind kind, const char *proto_name)
  541. {
  542.     int ix;
  543.     char *arg;
  544.     int sign;
  545.  
  546.     ix = 0;
  547.     sign = 1;
  548.     while ((arg = **argv_ptr) != NULL &&
  549.         strcmp(arg, "from") != 0 &&
  550.         strcmp(arg, "to") != 0)
  551.     {
  552.         char *p;
  553.  
  554.         /*
  555.          * Check that we havn't found too many port numbers.
  556.          * We do this here instead of with another condition on the while loop
  557.          * so that the caller can assume that the next parameter is NOT a
  558.          * port number.
  559.          */
  560.  
  561.         if (ix >= max_ports)
  562.         {
  563.             fprintf(stderr, "ipfw: too many port numbers "
  564.                 "(max %d, got at least %d, next parm=\"%s\")\n",
  565.                 max_ports, max_ports + 1, arg);
  566.             exit(1);
  567.         }
  568.         if ((p = strchr(arg, ':')) == NULL)
  569.         {
  570.             ports[ix++] = get_one_port(arg, usage, kind, proto_name);
  571.         }
  572.         else
  573.         {
  574.             if (ix > 0)
  575.             {
  576.                 fprintf(stderr, "ipfw: "
  577.                     "port ranges are only allowed for "
  578.                     "the first port value pair (%s)\n", arg);
  579.                 exit(1);
  580.             }
  581.             if (max_ports > 1)
  582.             {
  583.                 char *tbuf;
  584.  
  585.                 tbuf = malloc((p - arg) + 1);
  586.                 strncpy(tbuf, arg, p - arg);
  587.                 tbuf[p - arg] = '\0';
  588.  
  589.                 ports[ix++] = get_one_port(tbuf, usage, kind, proto_name);
  590.                 ports[ix++] = get_one_port(p + 1, usage, kind, proto_name);
  591.                 sign = -1;
  592.             }
  593.             else
  594.             {
  595.                 fprintf(stderr,
  596.                     "ipfw: port range not allowed here (%s)\n", arg);
  597.                 exit(1);
  598.             }
  599.         }
  600.  
  601.         *argv_ptr += 1;
  602.     }
  603.  
  604.     if (ix < min_ports)
  605.     {
  606.         if (min_ports == 1)
  607.         {
  608.             fprintf(stderr, "ipfw: missing port number%s\n",
  609.                 max_ports == 1 ? "" : "(s)");
  610.         }
  611.         else
  612.         {
  613.             fprintf(stderr,
  614.                 "ipfw: not enough port numbers (expected %d, got %d)\n",
  615.                 min_ports, ix);
  616.         }
  617.         exit(1);
  618.     }
  619.     return (sign * ix);
  620. }
  621.  
  622. void check_usage(ipf_kind kind)
  623. {
  624.     fprintf(stderr, "usage: ipfirewall check %s ...\n", ipf_names[kind]);
  625. }
  626.  
  627. void check(ipf_kind kind, int socket_fd, char **argv)
  628. {
  629.     int protocol;
  630.     struct iphdr *packet;
  631.     char *proto_name;
  632.  
  633.     packet = (struct iphdr *) malloc
  634.         (sizeof(struct iphdr) + sizeof(struct tcphdr));
  635.     packet->version = IPVERSION;
  636.     packet->ihl = sizeof(struct iphdr) / sizeof(int);
  637.     printf("check %s ", kind == IPF_BLOCKING ? "blocking" : "forwarding");
  638.     show_parms(argv);
  639.     printf("\n");
  640.  
  641.     proto_name = *argv++;
  642.     protocol = get_protocol(proto_name, check_usage, kind);
  643.     switch (protocol)
  644.     {
  645.     case IP_FW_F_TCP:
  646.         packet->protocol = IPPROTO_TCP;
  647.         break;
  648.     case IP_FW_F_UDP:
  649.         packet->protocol = IPPROTO_UDP;
  650.         break;
  651.     default:
  652.         fprintf(stderr, "ipfw: can only check TCP or UDP packets\n");
  653.         break;
  654.     }
  655.  
  656.     if (*argv == NULL)
  657.     {
  658.         fprintf(stderr, "ipfw: missing \"from\" keyword\n");
  659.         exit(1);
  660.     }
  661.     if (strcmp(*argv, "from") == 0)
  662.     {
  663.         argv += 1;
  664.         get_ipaddr(*argv++, (struct in_addr *) &packet->saddr,
  665.             NULL, check_usage, kind);
  666.         if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
  667.         {
  668.             get_ports(&argv, &((struct tcphdr *) (&packet[1]))->th_sport,
  669.                 1, 1, check_usage, kind, proto_name);
  670.             ((struct tcphdr *) (&packet[1]))->th_sport = htons(
  671.                 ((struct tcphdr *) (&packet[1]))->th_sport);
  672.         }
  673.     }
  674.     else
  675.     {
  676.         fprintf(stderr,
  677.             "ipfw: expected \"from\" keyword, got \"%s\"\n", *argv);
  678.         exit(1);
  679.     }
  680.  
  681.     if (*argv == NULL)
  682.     {
  683.         fprintf(stderr, "ipfw: missing \"to\" keyword\n");
  684.         exit(1);
  685.     }
  686.     if (strcmp(*argv, "to") == 0)
  687.     {
  688.         argv += 1;
  689.         get_ipaddr(*argv++, (struct in_addr *) &packet->daddr,
  690.             NULL, check_usage, kind);
  691.         if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
  692.         {
  693.             get_ports(&argv, &((struct tcphdr *) (&packet[1]))->th_dport,
  694.                 1, 1, check_usage, kind, proto_name);
  695.             ((struct tcphdr *) (&packet[1]))->th_dport = htons(
  696.                 ((struct tcphdr *) (&packet[1]))->th_dport);
  697.         }
  698.     }
  699.     else
  700.     {
  701.         fprintf(stderr,
  702.             "ipfw: expected \"to\" keyword, got \"%s\"\n", *argv);
  703.         exit(1);
  704.     }
  705.  
  706.     if (*argv == NULL)
  707.     {
  708.         if (do_setsockopt(kind == IPF_BLOCKING ? "checkblocking" : "checkforwarding",
  709.             socket_fd, IPPROTO_IP,
  710.             kind == IPF_BLOCKING ? IP_FW_CHK_BLK : IP_FW_CHK_FWD,
  711.             packet,
  712.             sizeof(struct iphdr) + sizeof(struct tcphdr),
  713.             EACCES) == 0)
  714.         {
  715.             printf("packet accepted by %s firewall\n",
  716.                 kind == IPF_BLOCKING ? "blocking" : "forwarding");
  717.         }
  718.         else
  719.         {
  720.             printf("packet rejected by %s firewall\n",
  721.                 kind == IPF_BLOCKING ? "blocking" : "forwarding");
  722.         }
  723.  
  724.         return;
  725.     }
  726.     else
  727.     {
  728.         fprintf(stderr, "ipfw: extra parameters at end of command (");
  729.         show_parms(argv);
  730.         fprintf(stderr, ")\n");
  731.         exit(1);
  732.     }
  733. }
  734.  
  735. void add_usage(ipf_kind kind)
  736. {
  737.     fprintf(stderr, "usage: ipfirewall add %s ...\n", ipf_names[kind]);
  738. }
  739.  
  740. void add(ipf_kind kind, int socket_fd, char **argv)
  741. {
  742.     int protocol, accept_firewall, src_range, dst_range;
  743.     struct ip_fw firewall;
  744.     char *proto_name;
  745.  
  746.     printf("add %s ", ipf_names[kind]);
  747.     show_parms(argv);
  748.     printf("\n");
  749.  
  750.     if (kind != IPF_ACCOUNTING && kind != IPF_MASQUERADE)
  751.     {
  752.         if (*argv == NULL)
  753.         {
  754.             fprintf(stderr, "ipfw: missing \"accept\" or \"deny\" keyword\n");
  755.             exit(1);
  756.         }
  757.         if (strcmp(*argv, "deny") == 0)
  758.         {
  759.             accept_firewall = 0;
  760.         }
  761.         else if (strcmp(*argv, "accept") == 0)
  762.         {
  763.             accept_firewall = IP_FW_F_ACCEPT;
  764.         }
  765.         else
  766.         {
  767.             fprintf(stderr,
  768.                 "ipfw: expected \"accept\" or \"deny\", got \"%s\"\n",
  769.                 *argv);
  770.             exit(1);
  771.         }
  772.  
  773.         argv += 1;
  774.     }
  775.     else
  776.         accept_firewall = 1;
  777.     proto_name = *argv++;
  778.     protocol = get_protocol(proto_name, add_usage, kind);
  779.  
  780.     if (*argv == NULL)
  781.     {
  782.         fprintf(stderr, "ipfw: missing \"from\" keyword\n");
  783.         exit(1);
  784.     }
  785.     if (strcmp(*argv, "from") == 0)
  786.     {
  787.         argv++;
  788.         get_ipaddr(*argv++, &firewall.src, &firewall.src_mask, add_usage, kind);
  789.         if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
  790.         {
  791.             int cnt;
  792.             cnt = get_ports(&argv, &firewall.ports[0], 0, IP_FW_MAX_PORTS,
  793.                 add_usage, kind, proto_name);
  794.             if (cnt < 0)
  795.             {
  796.                 src_range = IP_FW_F_SRNG;
  797.                 cnt = -cnt;
  798.             }
  799.             else
  800.             {
  801.                 src_range = 0;
  802.             }
  803.             firewall.n_src_p = cnt;
  804.         }
  805.         else
  806.         {
  807.             firewall.n_src_p = 0;
  808.             src_range = 0;
  809.         }
  810.     }
  811.     else
  812.     {
  813.         fprintf(stderr, "ipfw: expected \"from\", got \"%s\"\n", *argv);
  814.         exit(1);
  815.     }
  816.  
  817.     if (*argv == NULL)
  818.     {
  819.         fprintf(stderr, "ipfw: missing \"to\" keyword\n");
  820.         exit(1);
  821.     }
  822.     if (strcmp(*argv, "to") == 0)
  823.     {
  824.         argv++;
  825.         get_ipaddr(*argv++, &firewall.dst, &firewall.dst_mask, add_usage, kind);
  826.         if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
  827.         {
  828.             int cnt;
  829.             cnt = get_ports(&argv, &firewall.ports[firewall.n_src_p], 0,
  830.                 IP_FW_MAX_PORTS - firewall.n_src_p,
  831.                 add_usage, kind, proto_name);
  832.             if (cnt < 0)
  833.             {
  834.                 dst_range = IP_FW_F_DRNG;
  835.                 cnt = -cnt;
  836.             }
  837.             else
  838.             {
  839.                 dst_range = 0;
  840.             }
  841.             firewall.n_dst_p = cnt;
  842.         }
  843.         else
  844.         {
  845.             firewall.n_dst_p = 0;
  846.             dst_range = 0;
  847.         }
  848.     }
  849.     else
  850.     {
  851.         fprintf(stderr, "ipfw: expected \"to\", got \"%s\"\n", *argv);
  852.         exit(1);
  853.     }
  854.  
  855.     if (*argv == NULL)
  856.     {
  857.         firewall.flags = protocol | accept_firewall | src_range | dst_range;
  858. #ifdef DO_MASQUERADE        
  859.         if (kind == IPF_MASQUERADE)
  860.             firewall.flags |= IP_FW_F_MASQ;
  861. #endif
  862.         (void) do_setsockopt(ipf_names[kind],
  863.             socket_fd, IPPROTO_IP,
  864.             ipf_addfunc[kind],
  865.             &firewall,
  866.             sizeof(firewall),
  867.             0);
  868.     }
  869.     else
  870.     {
  871.         fprintf(stderr, "ipfw: extra parameters at end of command (");
  872.         show_parms(argv);
  873.         fprintf(stderr, ")\n");
  874.         exit(1);
  875.     }
  876. }
  877.  
  878. void del_usage(ipf_kind kind)
  879. {
  880.     fprintf(stderr, "usage: ipfirewall delete %s ...\n", ipf_names[kind]);
  881. }
  882.  
  883. void del(ipf_kind kind, int socket_fd, char **argv)
  884. {
  885.     int protocol, accept_firewall, src_range, dst_range;
  886.     struct ip_fw firewall;
  887.     char *proto_name;
  888.  
  889.     printf("delete %s ", ipf_names[kind]);
  890.     show_parms(argv);
  891.     printf("\n");
  892.  
  893.     if (kind != IPF_ACCOUNTING && kind != IPF_MASQUERADE)
  894.     {
  895.         if (*argv == NULL)
  896.         {
  897.             fprintf(stderr, "ipfw: missing \"accept\" or \"deny\" keyword\n");
  898.             exit(1);
  899.         }
  900.         if (strcmp(*argv, "deny") == 0)
  901.         {
  902.             accept_firewall = 0;
  903.         }
  904.         else if (strcmp(*argv, "accept") == 0)
  905.         {
  906.             accept_firewall = IP_FW_F_ACCEPT;
  907.         }
  908.         else
  909.         {
  910.             fprintf(stderr,
  911.                 "ipfw: expected \"accept\" or \"deny\", got \"%s\"\n",
  912.                 *argv);
  913.             exit(1);
  914.         }
  915.  
  916.         argv += 1;
  917.     }
  918.     else
  919.         accept_firewall = 1;
  920.     proto_name = *argv++;
  921.     protocol = get_protocol(proto_name, del_usage, kind);
  922.  
  923.     if (*argv == NULL)
  924.     {
  925.         fprintf(stderr, "ipfw: missing \"from\" keyword\n");
  926.         exit(1);
  927.     }
  928.     if (strcmp(*argv, "from") == 0)
  929.     {
  930.         argv++;
  931.         get_ipaddr(*argv++, &firewall.src, &firewall.src_mask, del_usage, kind);
  932.         if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
  933.         {
  934.             int cnt;
  935.             cnt = get_ports(&argv, &firewall.ports[0], 0, IP_FW_MAX_PORTS,
  936.                 del_usage, kind, proto_name);
  937.             if (cnt < 0)
  938.             {
  939.                 src_range = IP_FW_F_SRNG;
  940.                 cnt = -cnt;
  941.             }
  942.             else
  943.             {
  944.                 src_range = 0;
  945.             }
  946.             firewall.n_src_p = cnt;
  947.         }
  948.         else
  949.         {
  950.             firewall.n_src_p = 0;
  951.             src_range = 0;
  952.         }
  953.     }
  954.     else
  955.     {
  956.         fprintf(stderr, "ipfw: expected \"from\", got \"%s\"\n", *argv);
  957.         exit(1);
  958.     }
  959.  
  960.     if (*argv == NULL)
  961.     {
  962.         fprintf(stderr, "ipfw: missing \"to\" keyword\n");
  963.         exit(1);
  964.     }
  965.     if (strcmp(*argv, "to") == 0)
  966.     {
  967.         argv++;
  968.         get_ipaddr(*argv++, &firewall.dst, &firewall.dst_mask, del_usage, kind);
  969.         if (protocol == IP_FW_F_TCP || protocol == IP_FW_F_UDP)
  970.         {
  971.             int cnt;
  972.             cnt = get_ports(&argv, &firewall.ports[firewall.n_src_p], 0,
  973.                 IP_FW_MAX_PORTS - firewall.n_src_p,
  974.                 del_usage, kind, proto_name);
  975.             if (cnt < 0)
  976.             {
  977.                 dst_range = IP_FW_F_DRNG;
  978.                 cnt = -cnt;
  979.             }
  980.             else
  981.             {
  982.                 dst_range = 0;
  983.             }
  984.             firewall.n_dst_p = cnt;
  985.         }
  986.         else
  987.         {
  988.             firewall.n_dst_p = 0;
  989.             dst_range = 0;
  990.         }
  991.     }
  992.     else
  993.     {
  994.         fprintf(stderr, "ipfw: expected \"to\", got \"%s\"\n", *argv);
  995.         exit(1);
  996.     }
  997.  
  998.     if (*argv == NULL)
  999.     {
  1000.         firewall.flags = protocol | accept_firewall | src_range | dst_range;
  1001. #ifdef DO_MASQUERADE
  1002.         if (kind == IPF_MASQUERADE)
  1003.             firewall.flags |= IP_FW_F_MASQ;
  1004. #endif            
  1005.         (void) do_setsockopt(ipf_names[kind],
  1006.             socket_fd, IPPROTO_IP,
  1007.             ipf_delfunc[kind],
  1008.             &firewall,
  1009.             sizeof(firewall),
  1010.             0);
  1011.     }
  1012.     else
  1013.     {
  1014.         fprintf(stderr, "ipfw: extra parameters at end of command (");
  1015.         show_parms(argv);
  1016.         fprintf(stderr, ")\n");
  1017.         exit(1);
  1018.     }
  1019. }
  1020.  
  1021. static int count_mask(unsigned long mask)
  1022. {
  1023.     int ct;
  1024.     for (ct = 0; (mask & 0x80000000); ct++)
  1025.         mask <<= 1;
  1026.     return ct;
  1027. }
  1028.  
  1029. typedef struct
  1030. {
  1031.     int acct;
  1032.     unsigned long sa, da, sm, dm;
  1033.     unsigned int nsp, ndp;
  1034.     unsigned long npkt, nbyt;
  1035.     unsigned int ports[10];
  1036.     int flags;
  1037. } fw_rec;
  1038.  
  1039. #define MIN(a,b) ((a)<(b)? (a): (b))
  1040. #define SRC(x)   ((x)->sa & (x)->sm)
  1041. #define DST(x)   ((x)->da & (x)->dm)
  1042.  
  1043. static int int_order(const void *L, const void *R)
  1044. {
  1045.     return (*(unsigned int *) R - *(unsigned int *) L);
  1046. }
  1047.  
  1048. static int list_order(const void *L, const void *R)
  1049. {
  1050.     register const fw_rec *l = L;
  1051.     register const fw_rec *r = R;
  1052.  
  1053.     register int result =
  1054.     ((r->flags & IP_FW_F_KIND) - (l->flags & IP_FW_F_KIND)) ? :
  1055.     (MIN(SRC(r), DST(r)) - MIN(SRC(l), DST(l)));
  1056.  
  1057.     if (result == 0 && (l->flags & (IP_FW_F_TCP | IP_FW_F_UDP)))
  1058.     {
  1059.         unsigned int nlp, lp[10], nrp, rp[10];
  1060.         unsigned int i;
  1061.  
  1062.         bzero(lp, 10 * sizeof(unsigned int));
  1063.         bzero(rp, 10 * sizeof(unsigned int));
  1064.  
  1065.         bcopy(l->ports, lp, (nlp = l->nsp + l->ndp) * sizeof(unsigned int));
  1066.         bcopy(r->ports, rp, (nrp = r->nsp + r->ndp) * sizeof(unsigned int));
  1067.  
  1068.         qsort(lp, nlp, sizeof(unsigned int), int_order);
  1069.         qsort(rp, nrp, sizeof(unsigned int), int_order);
  1070.  
  1071.         for (i = 0; i < 10; ++i)
  1072.             if (lp[i] != rp[i])
  1073.                 return (lp[i] - rp[i]);
  1074.     }
  1075.     return result;
  1076. }
  1077.  
  1078. static char *addr_to_name(unsigned int a, unsigned int m)
  1079. {
  1080.     static char tbuf[128];
  1081.     struct hostent *hptr;
  1082.     struct netent *nptr;
  1083.  
  1084.     if (m == 0)
  1085.         strcpy(tbuf, "anywhere");
  1086.     else
  1087.     {
  1088.         int mask_len = count_mask(m);
  1089.         struct in_addr ia =
  1090.         {htonl(a)};
  1091.  
  1092.         if (lookup && (hptr = gethostbyaddr((char *) &ia, sizeof ia, AF_INET)))
  1093.             strcpy(tbuf, hptr->h_name);
  1094.         else if (lookup && (nptr = getnetbyaddr(a, AF_INET)))
  1095.             sprintf(tbuf, "=%s", nptr->n_name);
  1096.         else
  1097.             sprintf(tbuf, "%s/%d", fmtip(htonl(a)), mask_len);
  1098.     }
  1099.  
  1100.     return tbuf;
  1101. }
  1102.  
  1103. void list_file(char *path, int acct)
  1104. {
  1105.     FILE *f = fopen(path, "r");
  1106.     int nrecs = 8;
  1107.     int nused = 0;
  1108.     fw_rec *recs = (void *) malloc(sizeof(fw_rec) * nrecs);
  1109.     fw_rec *rec;
  1110.     char buf[256];
  1111.     struct servent *sptr;
  1112.  
  1113.     if (f == NULL)
  1114.     {
  1115.         perror(path);
  1116.         exit(1);
  1117.     }
  1118.     fgets(buf, 255, f);    /* skip title */
  1119.     while (fgets(buf, 255, f))
  1120.     {            /* read in the data */
  1121.         if (nused >= nrecs)
  1122.         {
  1123.             nrecs <<= 1;
  1124.             recs = (void *) realloc(recs, sizeof(fw_rec) * nrecs);
  1125.         }
  1126.         rec = &recs[nused++];
  1127.  
  1128.         rec->acct = acct;
  1129.         sscanf(buf,
  1130.             "%lX/%lX->%lX/%lX %X %u %u %lu %lu %u %u %u %u %u %u %u %u %u %u",
  1131.             &rec->sa, &rec->sm, &rec->da, &rec->dm,
  1132.             &rec->flags, &rec->nsp, &rec->ndp, &rec->npkt, &rec->nbyt,
  1133.             &rec->ports[0], &rec->ports[1], &rec->ports[2], &rec->ports[3],
  1134.             &rec->ports[4], &rec->ports[5], &rec->ports[6], &rec->ports[7],
  1135.             &rec->ports[8], &rec->ports[9]);
  1136.     }
  1137.     fclose(f);
  1138.  
  1139.     qsort(recs, nused, sizeof(fw_rec), list_order);
  1140.  
  1141.     if (acct)
  1142.         printf("Packets\t Bytes\t");
  1143.     else
  1144.         printf("Type\t");
  1145.     printf("Proto %19.19s %19.19s    Ports\n",
  1146.         "From        ", "To         ");
  1147.  
  1148.     for (rec = recs; nused-- > 0; ++rec)
  1149.     {
  1150.         unsigned int *pp = &rec->ports[0];
  1151.  
  1152.         if (!rec->acct)
  1153.         {
  1154. #ifdef DO_MASQUERADE        
  1155.             if (rec->flags & IP_FW_F_MASQ)
  1156.                 printf("(masquerade");
  1157.             else
  1158. #endif
  1159.             {
  1160.                 if (rec->flags & IP_FW_F_ACCEPT)
  1161.                     printf("accept\t");
  1162.                 else
  1163.                     printf("deny\t");
  1164.             }
  1165.         }
  1166.         else
  1167.         {
  1168.             printf("%7lu\t", rec->npkt);
  1169.             if (rec->nbyt > 100 * 1024)
  1170.             {
  1171.                 unsigned long kbyt = (rec->nbyt + 1023) / 1024;
  1172.                 if (kbyt > 100 * 1024)
  1173.                 {
  1174.                     unsigned long mbyt = (kbyt + 1023) / 1024;
  1175.                     printf("%6luM\t", mbyt);
  1176.                 }
  1177.                 else
  1178.                     printf("%6luK\t", kbyt);
  1179.             }
  1180.             else
  1181.                 printf("%6lu \t", rec->nbyt);
  1182.         }
  1183.  
  1184.         switch (rec->flags & IP_FW_F_KIND)
  1185.         {
  1186.         case IP_FW_F_ALL:
  1187.             printf("all   ");
  1188.             break;
  1189.         case IP_FW_F_TCP:
  1190.             printf("tcp   ");
  1191.             break;
  1192.         case IP_FW_F_UDP:
  1193.             printf("udp   ");
  1194.             break;
  1195.         case IP_FW_F_ICMP:
  1196.             printf("icmp  ");
  1197.             break;
  1198.         }
  1199.  
  1200.         printf("%-19.19s ", addr_to_name(rec->sa, rec->sm));
  1201.         printf("%-19.19s ", addr_to_name(rec->da, rec->dm));
  1202.  
  1203.         if (rec->flags & (IP_FW_F_TCP | IP_FW_F_UDP))
  1204.         {
  1205.             char *sep = "";
  1206.             char *proto = (rec->flags & IP_FW_F_TCP) ? "tcp" : "udp";
  1207.  
  1208.             if (rec->nsp == 0)
  1209.                 printf("any");
  1210.             else
  1211.             {
  1212.                 if (rec->flags & IP_FW_F_SRNG)
  1213.                 {
  1214.                     printf("%u-%u", pp[0], pp[1]);
  1215.                     sep = ",";
  1216.                     pp += 2;
  1217.                     rec->nsp -= 2;
  1218.                 }
  1219.                 while (rec->nsp-- > 0)
  1220.                 {
  1221.                     sptr = getservbyport(htons(*pp), proto);
  1222.                     if (sptr)
  1223.                         printf("%s%s", sep, sptr->s_name);
  1224.                     else
  1225.                         printf("%s%u", sep, *pp);
  1226.                     ++pp;
  1227.                     sep = ",";
  1228.                 }
  1229.             }
  1230.  
  1231.             printf(" -> ");
  1232.  
  1233.             sep = "";
  1234.             if (rec->ndp == 0)
  1235.                 printf("any");
  1236.             else
  1237.             {
  1238.                 if (rec->flags & IP_FW_F_DRNG)
  1239.                 {
  1240.                     printf("%u-%u", pp[0], pp[1]);
  1241.                     sep = ",";
  1242.                     pp += 2;
  1243.                 }
  1244.                 while (rec->ndp-- > 0)
  1245.                 {
  1246.                     sptr = getservbyport(htons(*pp), proto);
  1247.                     if (sptr)
  1248.                         printf("%s%s", sep, sptr->s_name);
  1249.                     else
  1250.                         printf("%s%u", sep, *pp);
  1251.                     ++pp;
  1252.                     sep = ",";
  1253.                 }
  1254.             }
  1255.         }
  1256.         printf("\n");
  1257.     }
  1258.     endservent();
  1259. }
  1260.  
  1261. void list(int socket_fd, char **argv)
  1262. {
  1263.     if (*argv == NULL || !**argv)
  1264.     {
  1265.         fprintf(stderr, "blocking, forwarding or accounting keyword expected.\n");
  1266.         exit(1);
  1267.     }
  1268.     if (strncmp(*argv, "blocking", strlen(*argv)) == 0)
  1269.     {
  1270.         list_file("/proc/net/ip_block", 0);
  1271.         return;
  1272.     }
  1273.     if (strncmp(*argv, "forwarding", strlen(*argv)) == 0)
  1274.     {
  1275.         list_file("/proc/net/ip_forward", 0);
  1276.         return;
  1277.     }
  1278.     if (strncmp(*argv, "accounting", strlen(*argv)) == 0)
  1279.     {
  1280.         list_file("/proc/net/ip_acct", 1);
  1281.         return;
  1282.     }
  1283.     fprintf(stderr, "Found '%s': 'blocking', 'forwarding' or 'accounting' keyword expected.\n", *argv);
  1284.     exit(1);
  1285. }
  1286.  
  1287. #define MATCH(in,pat) ( in && in[0] && (strncmp(in, pat, strlen(in)) == 0) )
  1288.  
  1289. void main(argc, argv)
  1290. int argc;
  1291. char **argv;
  1292. {
  1293.     int socket_fd;
  1294.     char *type = NULL;
  1295.  
  1296.     socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  1297.  
  1298.     if (socket_fd < 0)
  1299.     {
  1300.         perror("ipfw: raw socket creation");
  1301.         exit(1);
  1302.     }
  1303.     /* -n disables nameserver lookups */
  1304.  
  1305.     if (argv[1] && strcmp(argv[1], "-n")==0)
  1306.     {
  1307.         argc--;
  1308.         argv++;
  1309.         lookup = 0;
  1310.     }
  1311.     if (argc == 1)
  1312.     {
  1313.         show_usage();
  1314.         exit(1);
  1315.     }
  1316.     if (MATCH(argv[1], "list"))
  1317.     {
  1318.         type = "list";
  1319.         list(socket_fd, &argv[2]);
  1320.     }
  1321.     else if (MATCH(argv[1], "flush"))
  1322.     {
  1323.         if (MATCH(argv[2], "accounting"))
  1324.         {
  1325.             /* Same kludge as above, see above ranting and griping -BB */
  1326.             unsigned long fred = 1;
  1327.             (void) do_setsockopt(argv[1], socket_fd, IPPROTO_IP, IP_ACCT_FLUSH, &fred, sizeof(unsigned long), 0);
  1328.  
  1329.         }
  1330.         else if (MATCH(argv[2], "firewall"))
  1331.         {
  1332.             /* Same kludge as above, see above ranting and griping -BB */
  1333.             unsigned long fred = 1;
  1334.             (void) do_setsockopt(argv[1], socket_fd, IPPROTO_IP, IP_FW_FLUSH, &fred, sizeof(unsigned long), 0);
  1335.         }
  1336.         else
  1337.         {
  1338.             fprintf(stderr,
  1339.                 "ipfw: expected \"accounting\" or \"firewall\".");
  1340.             exit(1);
  1341.  
  1342.  
  1343.         }
  1344.     }
  1345.     else if (MATCH(argv[1], "check"))
  1346.     {
  1347.         if (MATCH(argv[2], "blocking"))
  1348.             check(IPF_BLOCKING, socket_fd, &argv[3]);
  1349.  
  1350.         else if (MATCH(argv[2], "forwarding"))
  1351.             check(IPF_FORWARDING, socket_fd, &argv[3]);
  1352.  
  1353.         else
  1354.         {
  1355.             fprintf(stderr, "ipfw: illegal `check' keyword: %s\n",
  1356.                 argv[2]);
  1357.             show_usage();
  1358.             exit(1);
  1359.         }
  1360.     }
  1361.     else
  1362.     {
  1363.         int is_add = MATCH(argv[1], "add");
  1364.         int is_del = MATCH(argv[1], "delete");
  1365.         char *op = NULL;
  1366.  
  1367.         if (is_add)
  1368.         {
  1369.             type = "add";
  1370.             if (MATCH(argv[2], "blocking"))
  1371.                 add(IPF_BLOCKING, socket_fd, &argv[3]);
  1372.             else if (MATCH(argv[2], "forwarding"))
  1373.                 add(IPF_FORWARDING, socket_fd, &argv[3]);
  1374.             else if (MATCH(argv[2], "accounting"))
  1375.                 add(IPF_ACCOUNTING, socket_fd, &argv[3]);
  1376. #ifdef DO_MASQUERADE                
  1377.             else if (MATCH(argv[2], "masquerade"))
  1378.                 add(IPF_MASQUERADE, socket_fd, &argv[3]);
  1379. #endif
  1380.             else
  1381.                 op = argv[2] ? : "(missing)";
  1382.         }
  1383.         else if (is_del)
  1384.         {
  1385.             type = "del";
  1386.             if (MATCH(argv[2], "blocking"))
  1387.                 del(IPF_BLOCKING, socket_fd, &argv[3]);
  1388.             else if (MATCH(argv[2], "forwarding"))
  1389.                 del(IPF_FORWARDING, socket_fd, &argv[3]);
  1390.             else if (MATCH(argv[2], "accounting"))
  1391.                 del(IPF_ACCOUNTING, socket_fd, &argv[3]);
  1392. #ifdef DO_MASQUERADE
  1393.             else if (MATCH(argv[2], "masquerade"))
  1394.                 del(IPF_MASQUERADE, socket_fd, &argv[3]);
  1395. #endif        
  1396.             else
  1397.                 op = argv[2] ? : "(missing)";
  1398.         }
  1399.         else if (MATCH(argv[1], "zeroaccounting"))
  1400.         {
  1401.             unsigned long fred = 1;
  1402.             type = "zero";
  1403.             /* Same kludge as above, see above ranting and griping -BB */
  1404.             (void) do_setsockopt(argv[1], socket_fd, IPPROTO_IP, IP_ACCT_ZERO, &fred, sizeof(unsigned long), 0);
  1405.  
  1406.         }
  1407.         if (!type)
  1408.         {
  1409.             fprintf(stderr, "ipfw: unknown command `%s'\n\n", argv[1]);
  1410.             show_help();
  1411.             exit(1);
  1412.         }
  1413.         else if (op)
  1414.         {
  1415.             fprintf(stderr, "ipfw: unknown `%s' keyword: `%s'\n",
  1416.                 type, op);
  1417.             show_usage();
  1418.             exit(1);
  1419.         }
  1420.     }
  1421.  
  1422.     exit(0);
  1423. }
  1424.