The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_fw.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1993 Daniel Boulet
    3  * Copyright (c) 1994 Ugen J.S.Antsilevich
    4  * Copyright (c) 1996 Alex Nash
    5  * Copyright (c) 2000-2002 Luigi Rizzo
    6  *
    7  * Redistribution and use in source forms, with and without modification,
    8  * are permitted provided that this entire comment appears intact.
    9  *
   10  * Redistribution in binary form may occur without any restrictions.
   11  * Obviously, it would be nice if you gave credit where credit is due
   12  * but requiring it would be too onerous.
   13  *
   14  * This software is provided ``AS IS'' without any warranties of any kind.
   15  *
   16  * $FreeBSD: releng/5.0/sys/netinet/ip_fw.c 98613 2002-06-22 11:51:02Z luigi $
   17  */
   18 
   19 #define        DEB(x)
   20 #define        DDB(x) x
   21 
   22 /*
   23  * Implement IP packet firewall
   24  */
   25 
   26 #if !defined(KLD_MODULE)
   27 #include "opt_ipfw.h"
   28 #include "opt_ipdn.h"
   29 #include "opt_ipdivert.h"
   30 #include "opt_inet.h"
   31 #ifndef INET
   32 #error IPFIREWALL requires INET.
   33 #endif /* INET */
   34 #endif
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/malloc.h>
   39 #include <sys/mbuf.h>
   40 #include <sys/kernel.h>
   41 #include <sys/proc.h>
   42 #include <sys/socket.h>
   43 #include <sys/socketvar.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/syslog.h>
   46 #include <sys/ucred.h>
   47 #include <net/if.h>
   48 #include <net/route.h>
   49 #include <netinet/in.h>
   50 #include <netinet/in_systm.h>
   51 #include <netinet/in_var.h>
   52 #include <netinet/in_pcb.h>
   53 #include <netinet/ip.h>
   54 #include <netinet/ip_var.h>
   55 #include <netinet/ip_icmp.h>
   56 #include <netinet/ip_fw.h>
   57 #include <netinet/ip_dummynet.h>
   58 #include <netinet/tcp.h>
   59 #include <netinet/tcp_timer.h>
   60 #include <netinet/tcp_var.h>
   61 #include <netinet/tcpip.h>
   62 #include <netinet/udp.h>
   63 #include <netinet/udp_var.h>
   64 
   65 #include <netinet/if_ether.h> /* XXX ethertype_ip */
   66 
   67 static int fw_debug = 1;
   68 #ifdef IPFIREWALL_VERBOSE
   69 static int fw_verbose = 1;
   70 #else
   71 static int fw_verbose = 0;
   72 #endif
   73 int fw_one_pass = 1 ;
   74 #ifdef IPFIREWALL_VERBOSE_LIMIT
   75 static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
   76 #else
   77 static int fw_verbose_limit = 0;
   78 #endif
   79 static int fw_permanent_rules = 0;
   80 
   81 /*
   82  * Right now, two fields in the IP header are changed to host format
   83  * by the IP layer before calling the firewall. Ideally, we would like
   84  * to have them in network format so that the packet can be
   85  * used as it comes from the device driver (and is thus readonly).
   86  */
   87 
   88 static u_int64_t counter;       /* counter for ipfw_report(NULL...) */
   89 
   90 #define IPFW_DEFAULT_RULE       ((u_int)(u_short)~0)
   91 
   92 LIST_HEAD (ip_fw_head, ip_fw) ip_fw_chain_head;
   93 
   94 MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
   95 
   96 #ifdef SYSCTL_NODE
   97 SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
   98 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, enable, CTLFLAG_RW,
   99     &fw_enable, 0, "Enable ipfw");
  100 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO,one_pass,CTLFLAG_RW, 
  101     &fw_one_pass, 0, 
  102     "Only do a single pass through ipfw when using dummynet(4)");
  103 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, 
  104     &fw_debug, 0, "Enable printing of debug ip_fw statements");
  105 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, 
  106     &fw_verbose, 0, "Log matches to ipfw rules");
  107 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, 
  108     &fw_verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
  109 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, permanent_rules, CTLFLAG_RW, 
  110     &fw_permanent_rules, 0, "Set rule number, below which rules are permanent");
  111 
  112 /*
  113  * Extension for stateful ipfw.
  114  *
  115  * Dynamic rules are stored in lists accessed through a hash table
  116  * (ipfw_dyn_v) whose size is curr_dyn_buckets. This value can
  117  * be modified through the sysctl variable dyn_buckets which is
  118  * updated when the table becomes empty.
  119  *
  120  * XXX currently there is only one list, ipfw_dyn.
  121  *
  122  * When a packet is received, it is first hashed, then matched
  123  * against the entries in the corresponding list.
  124  * Matching occurs according to the rule type. The default is to
  125  * match the four fields and the protocol, and rules are bidirectional.
  126  *
  127  * For a busy proxy/web server we will have lots of connections to
  128  * the server. We could decide for a rule type where we ignore
  129  * ports (different hashing) and avoid special SYN/RST/FIN handling.
  130  *
  131  * XXX when we decide to support more than one rule type, we should
  132  * repeat the hashing multiple times uing only the useful fields.
  133  * Or, we could run the various tests in parallel, because the
  134  * 'move to front' technique should shorten the average search.
  135  *
  136  * The lifetime of dynamic rules is regulated by dyn_*_lifetime,
  137  * measured in seconds and depending on the flags.
  138  *
  139  * The total number of dynamic rules is stored in dyn_count.
  140  * The max number of dynamic rules is dyn_max. When we reach
  141  * the maximum number of rules we do not create anymore. This is
  142  * done to avoid consuming too much memory, but also too much
  143  * time when searching on each packet (ideally, we should try instead
  144  * to put a limit on the length of the list on each bucket...).
  145  *
  146  * Each dynamic rules holds a pointer to the parent ipfw rule so
  147  * we know what action to perform. Dynamic rules are removed when
  148  * the parent rule is deleted.
  149  * There are some limitations with dynamic rules -- we do not
  150  * obey the 'randomized match', and we do not do multiple
  151  * passes through the firewall.
  152  * XXX check the latter!!!
  153  */
  154 static struct ipfw_dyn_rule **ipfw_dyn_v = NULL ;
  155 static u_int32_t dyn_buckets = 256 ; /* must be power of 2 */
  156 static u_int32_t curr_dyn_buckets = 256 ; /* must be power of 2 */
  157 
  158 /*
  159  * timeouts for various events in handing dynamic rules.
  160  */
  161 static u_int32_t dyn_ack_lifetime = 300 ;
  162 static u_int32_t dyn_syn_lifetime = 20 ;
  163 static u_int32_t dyn_fin_lifetime = 1 ;
  164 static u_int32_t dyn_rst_lifetime = 1 ;
  165 static u_int32_t dyn_udp_lifetime = 10 ;
  166 static u_int32_t dyn_short_lifetime = 5 ;
  167 
  168 /*
  169  * after reaching 0, dynamic rules are considered still valid for
  170  * an additional grace time, unless there is lack of resources.
  171  */
  172 static u_int32_t dyn_grace_time = 10 ;
  173 
  174 static u_int32_t static_count = 0 ;     /* # of static rules */
  175 static u_int32_t dyn_count = 0 ;        /* # of dynamic rules */
  176 static u_int32_t dyn_max = 1000 ;       /* max # of dynamic rules */
  177 
  178 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_buckets, CTLFLAG_RW,
  179     &dyn_buckets, 0, "Number of dyn. buckets");
  180 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, curr_dyn_buckets, CTLFLAG_RD,
  181     &curr_dyn_buckets, 0, "Current Number of dyn. buckets");
  182 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_count, CTLFLAG_RD,
  183     &dyn_count, 0, "Number of dyn. rules");
  184 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_max, CTLFLAG_RW,
  185     &dyn_max, 0, "Max number of dyn. rules");
  186 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, static_count, CTLFLAG_RD,
  187     &static_count, 0, "Number of static rules");
  188 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_ack_lifetime, CTLFLAG_RW,
  189     &dyn_ack_lifetime, 0, "Lifetime of dyn. rules for acks");
  190 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_syn_lifetime, CTLFLAG_RW,
  191     &dyn_syn_lifetime, 0, "Lifetime of dyn. rules for syn");
  192 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_fin_lifetime, CTLFLAG_RW,
  193     &dyn_fin_lifetime, 0, "Lifetime of dyn. rules for fin");
  194 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_rst_lifetime, CTLFLAG_RW,
  195     &dyn_rst_lifetime, 0, "Lifetime of dyn. rules for rst");
  196 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_udp_lifetime, CTLFLAG_RW,
  197     &dyn_udp_lifetime, 0, "Lifetime of dyn. rules for UDP");
  198 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_short_lifetime, CTLFLAG_RW,
  199     &dyn_short_lifetime, 0, "Lifetime of dyn. rules for other situations");
  200 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, dyn_grace_time, CTLFLAG_RD,
  201     &dyn_grace_time, 0, "Grace time for dyn. rules");
  202 
  203 #endif /* SYSCTL_NODE */
  204 
  205 #define dprintf(a)      do {                                            \
  206                                 if (fw_debug)                           \
  207                                         printf a;                       \
  208                         } while (0)
  209 #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0
  210 
  211 static int      add_entry (struct ip_fw_head *chainptr, struct ip_fw *frwl);
  212 static int      del_entry (struct ip_fw_head *chainptr, u_short number);
  213 static int      zero_entry (struct ip_fw *, int);
  214 static int      check_ipfw_struct (struct ip_fw *m);
  215 static int      iface_match (struct ifnet *ifp, union ip_fw_if *ifu,
  216                                  int byname);
  217 static int      ipopts_match (struct ip *ip, struct ip_fw *f);
  218 static int      iptos_match (struct ip *ip, struct ip_fw *f);
  219 static __inline int
  220                 port_match (u_short *portptr, int nports, u_short port,
  221                                 int range_flag, int mask);
  222 static int      tcpflg_match (struct tcphdr *tcp, struct ip_fw *f);
  223 static int      icmptype_match (struct icmp *  icmp, struct ip_fw * f);
  224 static void     ipfw_report (struct ip_fw *f, struct ip *ip, int ip_off,
  225                                 int ip_len, struct ifnet *rif,
  226                                 struct ifnet *oif);
  227 
  228 static void flush_rule_ptrs(void);
  229 
  230 static ip_fw_chk_t      ip_fw_chk;
  231 static int      ip_fw_ctl (struct sockopt *sopt);
  232 
  233 ip_dn_ruledel_t *ip_dn_ruledel_ptr = NULL;
  234 
  235 static char err_prefix[] = "ip_fw_ctl:";
  236 
  237 /*
  238  * Returns 1 if the port is matched by the vector, 0 otherwise
  239  */
  240 static __inline int 
  241 port_match(u_short *portptr, int nports, u_short port, int range_flag, int mask)
  242 {
  243         if (!nports)
  244                 return 1;
  245         if (mask) {
  246                 if ( 0 == ((portptr[0] ^ port) & portptr[1]) )
  247                         return 1;
  248                 nports -= 2;
  249                 portptr += 2;
  250         }
  251         if (range_flag) {
  252                 if (portptr[0] <= port && port <= portptr[1])
  253                         return 1;
  254                 nports -= 2;
  255                 portptr += 2;
  256         }
  257         while (nports-- > 0)
  258                 if (*portptr++ == port)
  259                         return 1;
  260         return 0;
  261 }
  262 
  263 static int
  264 tcpflg_match(struct tcphdr *tcp, struct ip_fw *f)
  265 {
  266         u_char          flg_set, flg_clr;
  267 
  268         /*
  269          * If an established connection is required, reject packets that
  270          * have only SYN of RST|ACK|SYN set.  Otherwise, fall through to
  271          * other flag requirements.
  272          */
  273         if ((f->fw_ipflg & IP_FW_IF_TCPEST) &&
  274             ((tcp->th_flags & (TH_RST | TH_ACK | TH_SYN)) == TH_SYN))
  275                 return 0;
  276 
  277         flg_set = tcp->th_flags & f->fw_tcpf;
  278         flg_clr = tcp->th_flags & f->fw_tcpnf;
  279 
  280         if (flg_set != f->fw_tcpf)
  281                 return 0;
  282         if (flg_clr)
  283                 return 0;
  284 
  285         return 1;
  286 }
  287 
  288 static int
  289 icmptype_match(struct icmp *icmp, struct ip_fw *f)
  290 {
  291         int type;
  292 
  293         if (!(f->fw_flg & IP_FW_F_ICMPBIT))
  294                 return(1);
  295 
  296         type = icmp->icmp_type;
  297 
  298         /* check for matching type in the bitmap */
  299         if (type < IP_FW_ICMPTYPES_MAX &&
  300             (f->fw_uar.fw_icmptypes[type / (sizeof(unsigned) * NBBY)] & 
  301             (1U << (type % (sizeof(unsigned) * NBBY)))))
  302                 return(1);
  303 
  304         return(0); /* no match */
  305 }
  306 
  307 static int
  308 is_icmp_query(struct ip *ip)
  309 {
  310         const struct icmp *icmp;
  311         int icmp_type;
  312 
  313         icmp = (struct icmp *)((u_int32_t *)ip + ip->ip_hl);
  314         icmp_type = icmp->icmp_type;
  315 
  316         if (icmp_type == ICMP_ECHO || icmp_type == ICMP_ROUTERSOLICIT ||
  317             icmp_type == ICMP_TSTAMP || icmp_type == ICMP_IREQ ||
  318             icmp_type == ICMP_MASKREQ)
  319                 return(1);
  320 
  321         return(0);
  322 }
  323 
  324 static int
  325 ipopts_match(struct ip *ip, struct ip_fw *f)
  326 {
  327         register u_char *cp;
  328         int opt, optlen, cnt;
  329         u_char  opts, nopts, nopts_sve;
  330 
  331         cp = (u_char *)(ip + 1);
  332         cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  333         opts = f->fw_ipopt;
  334         nopts = nopts_sve = f->fw_ipnopt;
  335 
  336         for (; cnt > 0; cnt -= optlen, cp += optlen) {
  337                 opt = cp[IPOPT_OPTVAL];
  338                 if (opt == IPOPT_EOL)
  339                         break;
  340                 if (opt == IPOPT_NOP)
  341                         optlen = 1;
  342                 else {
  343                         optlen = cp[IPOPT_OLEN];
  344                         if (optlen <= 0 || optlen > cnt) {
  345                                 return 0; /*XXX*/
  346                         }
  347                 }
  348                 switch (opt) {
  349 
  350                 default:
  351                         break;
  352 
  353                 case IPOPT_LSRR:
  354                         opts &= ~IP_FW_IPOPT_LSRR;
  355                         nopts &= ~IP_FW_IPOPT_LSRR;
  356                         break;
  357 
  358                 case IPOPT_SSRR:
  359                         opts &= ~IP_FW_IPOPT_SSRR;
  360                         nopts &= ~IP_FW_IPOPT_SSRR;
  361                         break;
  362 
  363                 case IPOPT_RR:
  364                         opts &= ~IP_FW_IPOPT_RR;
  365                         nopts &= ~IP_FW_IPOPT_RR;
  366                         break;
  367                 case IPOPT_TS:
  368                         opts &= ~IP_FW_IPOPT_TS;
  369                         nopts &= ~IP_FW_IPOPT_TS;
  370                         break;
  371                 }
  372                 if (opts == nopts)
  373                         break;
  374         }
  375         if (opts == 0 && nopts == nopts_sve)
  376                 return 1;
  377         else
  378                 return 0;
  379 }
  380 
  381 static int
  382 iptos_match(struct ip *ip, struct ip_fw *f)
  383 {
  384 
  385         u_int flags = (ip->ip_tos & 0x1f);
  386         u_char opts, nopts, nopts_sve;
  387 
  388         opts = (f->fw_iptos & 0x1f);
  389         nopts = nopts_sve = f->fw_ipntos;
  390 
  391         while (flags != 0) {
  392                 u_int flag;
  393 
  394                 flag = 1 << (ffs(flags) -1);
  395                 opts &= ~flag;
  396                 nopts &= ~flag;
  397                 flags &= ~flag;
  398         }
  399 
  400         if (opts == 0 && nopts == nopts_sve)
  401                 return 1;
  402         else
  403                 return 0;
  404 
  405 }
  406 
  407 
  408 static int
  409 tcpopts_match(struct tcphdr *tcp, struct ip_fw *f)
  410 {
  411         register u_char *cp;
  412         int opt, optlen, cnt;
  413         u_char  opts, nopts, nopts_sve;
  414 
  415         cp = (u_char *)(tcp + 1);
  416         cnt = (tcp->th_off << 2) - sizeof (struct tcphdr);
  417         opts = f->fw_tcpopt;
  418         nopts = nopts_sve = f->fw_tcpnopt;
  419 
  420         for (; cnt > 0; cnt -= optlen, cp += optlen) {
  421                 opt = cp[0];
  422                 if (opt == TCPOPT_EOL)
  423                         break;
  424                 if (opt == TCPOPT_NOP)
  425                         optlen = 1;
  426                 else {
  427                         optlen = cp[1];
  428                         if (optlen <= 0)
  429                                 break;
  430                 }
  431 
  432 
  433                 switch (opt) {
  434 
  435                 default:
  436                         break;
  437 
  438                 case TCPOPT_MAXSEG:
  439                         opts &= ~IP_FW_TCPOPT_MSS;
  440                         nopts &= ~IP_FW_TCPOPT_MSS;
  441                         break;
  442 
  443                 case TCPOPT_WINDOW:
  444                         opts &= ~IP_FW_TCPOPT_WINDOW;
  445                         nopts &= ~IP_FW_TCPOPT_WINDOW;
  446                         break;
  447 
  448                 case TCPOPT_SACK_PERMITTED:
  449                 case TCPOPT_SACK:
  450                         opts &= ~IP_FW_TCPOPT_SACK;
  451                         nopts &= ~IP_FW_TCPOPT_SACK;
  452                         break;
  453 
  454                 case TCPOPT_TIMESTAMP:
  455                         opts &= ~IP_FW_TCPOPT_TS;
  456                         nopts &= ~IP_FW_TCPOPT_TS;
  457                         break;
  458 
  459                 case TCPOPT_CC:
  460                 case TCPOPT_CCNEW:
  461                 case TCPOPT_CCECHO:
  462                         opts &= ~IP_FW_TCPOPT_CC;
  463                         nopts &= ~IP_FW_TCPOPT_CC;
  464                         break;
  465                 }
  466                 if (opts == nopts)
  467                         break;
  468         }
  469         if (opts == 0 && nopts == nopts_sve)
  470                 return 1;
  471         else
  472                 return 0;
  473 }
  474 
  475 static int
  476 iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname)
  477 {
  478         /* Check by name or by IP address */
  479         if (byname) {
  480                 /* Check unit number (-1 is wildcard) */
  481                 if (ifu->fu_via_if.unit != -1
  482                     && ifp->if_unit != ifu->fu_via_if.unit)
  483                         return(0);
  484                 /* Check name */
  485                 if (strncmp(ifp->if_name, ifu->fu_via_if.name, FW_IFNLEN))
  486                         return(0);
  487                 return(1);
  488         } else if (ifu->fu_via_ip.s_addr != 0) {        /* Zero == wildcard */
  489                 struct ifaddr *ia;
  490 
  491                 TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
  492                         if (ia->ifa_addr == NULL)
  493                                 continue;
  494                         if (ia->ifa_addr->sa_family != AF_INET)
  495                                 continue;
  496                         if (ifu->fu_via_ip.s_addr != ((struct sockaddr_in *)
  497                             (ia->ifa_addr))->sin_addr.s_addr)
  498                                 continue;
  499                         return(1);
  500                 }
  501                 return(0);
  502         }
  503         return(1);
  504 }
  505 
  506 static void
  507 ipfw_report(struct ip_fw *f, struct ip *ip, int ip_off, int ip_len,
  508         struct ifnet *rif, struct ifnet *oif)
  509 {
  510     struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl);
  511     struct udphdr *const udp = (struct udphdr *) ((u_int32_t *) ip+ ip->ip_hl);
  512     struct icmp *const icmp = (struct icmp *) ((u_int32_t *) ip + ip->ip_hl);
  513     u_int64_t count;
  514     char *action;
  515     char action2[32], proto[47], name[18], fragment[27];
  516     int len;
  517     int offset = ip_off & IP_OFFMASK;
  518 
  519     count = f ? f->fw_pcnt : ++counter;
  520     if ((f == NULL && fw_verbose_limit != 0 && count > fw_verbose_limit) ||
  521         (f && f->fw_logamount != 0 && count > f->fw_loghighest))
  522             return;
  523 
  524     /* Print command name */
  525     snprintf(SNPARGS(name, 0), "ipfw: %d", f ? f->fw_number : -1);
  526 
  527     action = action2;
  528     if (!f)
  529             action = "Refuse";
  530     else {
  531             switch (f->fw_flg & IP_FW_F_COMMAND) {
  532             case IP_FW_F_DENY:
  533                     action = "Deny";
  534                     break;
  535             case IP_FW_F_REJECT:
  536                     if (f->fw_reject_code == IP_FW_REJECT_RST)
  537                             action = "Reset";
  538                     else
  539                             action = "Unreach";
  540                     break;
  541             case IP_FW_F_ACCEPT:
  542                     action = "Accept";
  543                     break;
  544             case IP_FW_F_COUNT:
  545                     action = "Count";
  546                     break;
  547 #ifdef IPDIVERT
  548             case IP_FW_F_DIVERT:
  549                     snprintf(SNPARGS(action2, 0), "Divert %d",
  550                         f->fw_divert_port);
  551                     break;
  552             case IP_FW_F_TEE:
  553                     snprintf(SNPARGS(action2, 0), "Tee %d",
  554                         f->fw_divert_port);
  555                     break;
  556 #endif
  557             case IP_FW_F_SKIPTO:
  558                     snprintf(SNPARGS(action2, 0), "SkipTo %d",
  559                         f->fw_skipto_rule);
  560                     break;
  561             case IP_FW_F_PIPE:
  562                     snprintf(SNPARGS(action2, 0), "Pipe %d",
  563                         f->fw_skipto_rule);
  564                     break;
  565             case IP_FW_F_QUEUE:
  566                     snprintf(SNPARGS(action2, 0), "Queue %d",
  567                         f->fw_skipto_rule);
  568                     break;
  569 
  570             case IP_FW_F_FWD:
  571                     if (f->fw_fwd_ip.sin_port)
  572                             snprintf(SNPARGS(action2, 0),
  573                                 "Forward to %s:%d",
  574                                 inet_ntoa(f->fw_fwd_ip.sin_addr),
  575                                 f->fw_fwd_ip.sin_port);
  576                     else
  577                             snprintf(SNPARGS(action2, 0), "Forward to %s",
  578                                 inet_ntoa(f->fw_fwd_ip.sin_addr));
  579                     break;
  580 
  581             default:    
  582                     action = "UNKNOWN";
  583                     break;
  584             }
  585     }
  586 
  587     switch (ip->ip_p) {
  588     case IPPROTO_TCP:
  589             len = snprintf(SNPARGS(proto, 0), "TCP %s",
  590                 inet_ntoa(ip->ip_src));
  591             if (offset == 0)
  592                     len += snprintf(SNPARGS(proto, len), ":%d ",
  593                         ntohs(tcp->th_sport));
  594             else
  595                     len += snprintf(SNPARGS(proto, len), " ");
  596             len += snprintf(SNPARGS(proto, len), "%s",
  597                 inet_ntoa(ip->ip_dst));
  598             if (offset == 0)
  599                     snprintf(SNPARGS(proto, len), ":%d",
  600                         ntohs(tcp->th_dport));
  601             break;
  602     case IPPROTO_UDP:
  603             len = snprintf(SNPARGS(proto, 0), "UDP %s",
  604                 inet_ntoa(ip->ip_src));
  605             if (offset == 0)
  606                     len += snprintf(SNPARGS(proto, len), ":%d ",
  607                         ntohs(udp->uh_sport));
  608             else
  609                     len += snprintf(SNPARGS(proto, len), " ");
  610             len += snprintf(SNPARGS(proto, len), "%s",
  611                 inet_ntoa(ip->ip_dst));
  612             if (offset == 0)
  613                     snprintf(SNPARGS(proto, len), ":%d",
  614                         ntohs(udp->uh_dport));
  615             break;
  616     case IPPROTO_ICMP:
  617             if (offset == 0)
  618                     len = snprintf(SNPARGS(proto, 0), "ICMP:%u.%u ",
  619                         icmp->icmp_type, icmp->icmp_code);
  620             else
  621                     len = snprintf(SNPARGS(proto, 0), "ICMP ");
  622             len += snprintf(SNPARGS(proto, len), "%s",
  623                 inet_ntoa(ip->ip_src));
  624             snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
  625             break;
  626     default:
  627             len = snprintf(SNPARGS(proto, 0), "P:%d %s", ip->ip_p,
  628                 inet_ntoa(ip->ip_src));
  629             snprintf(SNPARGS(proto, len), " %s", inet_ntoa(ip->ip_dst));
  630             break;
  631     }
  632 
  633     if (ip_off & (IP_MF | IP_OFFMASK))
  634             snprintf(SNPARGS(fragment, 0), " (frag %d:%d@%d%s)",
  635                      ntohs(ip->ip_id), ip_len - (ip->ip_hl << 2),
  636                      offset << 3,
  637                      (ip_off & IP_MF) ? "+" : "");
  638     else
  639             fragment[0] = '\0';
  640     if (oif)
  641             log(LOG_SECURITY | LOG_INFO, "%s %s %s out via %s%d%s\n",
  642                 name, action, proto, oif->if_name, oif->if_unit, fragment);
  643     else if (rif)
  644             log(LOG_SECURITY | LOG_INFO, "%s %s %s in via %s%d%s\n", name,
  645                 action, proto, rif->if_name, rif->if_unit, fragment);
  646     else
  647             log(LOG_SECURITY | LOG_INFO, "%s %s %s%s\n", name, action,
  648                 proto, fragment);
  649     if ((f ? f->fw_logamount != 0 : 1) &&
  650         count == (f ? f->fw_loghighest : fw_verbose_limit))
  651             log(LOG_SECURITY | LOG_NOTICE,
  652                 "ipfw: limit %d reached on entry %d\n",
  653                 f ? f->fw_logamount : fw_verbose_limit,
  654                 f ? f->fw_number : -1);
  655 }
  656 
  657 static __inline int
  658 hash_packet(struct ipfw_flow_id *id)
  659 {
  660     u_int32_t i ;
  661 
  662     i = (id->dst_ip) ^ (id->src_ip) ^ (id->dst_port) ^ (id->src_port);
  663     i &= (curr_dyn_buckets - 1) ;
  664     return i ;
  665 }
  666 
  667 /**
  668  * unlink a dynamic rule from a chain. prev is a pointer to
  669  * the previous one, q is a pointer to the rule to delete,
  670  * head is a pointer to the head of the queue.
  671  * Modifies q and potentially also head.
  672  */
  673 #define UNLINK_DYN_RULE(prev, head, q) {                                \
  674         struct ipfw_dyn_rule *old_q = q;                                \
  675                                                                         \
  676         /* remove a refcount to the parent */                           \
  677         if (q->dyn_type == DYN_LIMIT)                                   \
  678                 q->parent->count--;                                     \
  679         DEB(printf("-- unlink entry 0x%08x %d -> 0x%08x %d, %d left\n", \
  680                 (q->id.src_ip), (q->id.src_port),                       \
  681                 (q->id.dst_ip), (q->id.dst_port), dyn_count-1 ); )      \
  682         if (prev != NULL)                                               \
  683                 prev->next = q = q->next ;                              \
  684         else                                                            \
  685                 ipfw_dyn_v[i] = q = q->next ;                           \
  686         dyn_count-- ;                                                   \
  687         free(old_q, M_IPFW); }
  688 
  689 #define TIME_LEQ(a,b)       ((int)((a)-(b)) <= 0)
  690 /**
  691  * Remove all dynamic rules pointing to a given rule, or all
  692  * rules if rule == NULL. Second parameter is 1 if we want to
  693  * delete unconditionally, otherwise only expired rules are removed.
  694  */
  695 static void
  696 remove_dyn_rule(struct ip_fw *rule, int force)
  697 {
  698     struct ipfw_dyn_rule *prev, *q;
  699     int i, pass, max_pass ;
  700     static u_int32_t last_remove = 0 ;
  701 
  702     if (ipfw_dyn_v == NULL || dyn_count == 0)
  703         return ;
  704     /* do not expire more than once per second, it is useless */
  705     if (force == 0 && last_remove == time_second)
  706         return ;
  707     last_remove = time_second ;
  708 
  709     /*
  710      * because DYN_LIMIT refer to parent rules, during the first pass only
  711      * remove child and mark any pending LIMIT_PARENT, and remove
  712      * them in a second pass.
  713      */
  714   for (pass = max_pass = 0; pass <= max_pass ; pass++ ) {
  715     for (i = 0 ; i < curr_dyn_buckets ; i++) {
  716         for (prev=NULL, q = ipfw_dyn_v[i] ; q ; ) {
  717             /*
  718              * logic can become complex here, so we split tests.
  719              * First, test if we match any rule,
  720              * then make sure the rule is expired or we want to kill it,
  721              * and possibly more in the future.
  722              */
  723             int zap = ( rule == NULL || rule == q->rule);
  724             if (zap)
  725                 zap = force || TIME_LEQ( q->expire , time_second );
  726             /* do not zap parent in first pass, record we need a second pass */
  727             if (q->dyn_type == DYN_LIMIT_PARENT) {
  728                 max_pass = 1; /* we need a second pass */
  729                 if (zap == 1 && (pass == 0 || q->count != 0) ) {
  730                     zap = 0 ;
  731                     if (pass == 1) /* should not happen */
  732                         printf("OUCH! cannot remove rule, count %d\n",
  733                                 q->count);
  734                 }
  735             }
  736             if (zap) {
  737                 UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q);
  738             } else {
  739                 prev = q ;
  740                 q = q->next ;
  741             }
  742         }
  743     }
  744   }
  745 }
  746 
  747 #define EXPIRE_DYN_CHAIN(rule) remove_dyn_rule(rule, 0 /* expired ones */)
  748 #define EXPIRE_DYN_CHAINS() remove_dyn_rule(NULL, 0 /* expired ones */)
  749 #define DELETE_DYN_CHAIN(rule) remove_dyn_rule(rule, 1 /* force removal */)
  750 #define DELETE_DYN_CHAINS() remove_dyn_rule(NULL, 1 /* force removal */)
  751 
  752 /**
  753  * lookup a dynamic rule.
  754  */
  755 static struct ipfw_dyn_rule *
  756 lookup_dyn_rule(struct ipfw_flow_id *pkt, int *match_direction)
  757 {
  758     /*
  759      * stateful ipfw extensions.
  760      * Lookup into dynamic session queue
  761      */
  762     struct ipfw_dyn_rule *prev, *q ;
  763     int i, dir = 0;
  764 #define MATCH_FORWARD 1
  765 
  766     if (ipfw_dyn_v == NULL)
  767         return NULL ;
  768     i = hash_packet( pkt );
  769     for (prev=NULL, q = ipfw_dyn_v[i] ; q != NULL ; ) {
  770         if (q->dyn_type == DYN_LIMIT_PARENT)
  771             goto next;
  772         if (TIME_LEQ( q->expire , time_second ) ) { /* expire entry */
  773             UNLINK_DYN_RULE(prev, ipfw_dyn_v[i], q);
  774             continue;
  775         }
  776         if ( pkt->proto == q->id.proto) {
  777             if (pkt->src_ip == q->id.src_ip &&
  778                     pkt->dst_ip == q->id.dst_ip &&
  779                     pkt->src_port == q->id.src_port &&
  780                     pkt->dst_port == q->id.dst_port ) {
  781                 dir = MATCH_FORWARD ;
  782                 goto found ;
  783             }
  784             if (pkt->src_ip == q->id.dst_ip &&
  785                     pkt->dst_ip == q->id.src_ip &&
  786                     pkt->src_port == q->id.dst_port &&
  787                     pkt->dst_port == q->id.src_port ) {
  788                 dir = 0 ; /* reverse match */
  789                 goto found ;
  790             }
  791         }
  792 next:
  793         prev = q ;
  794         q = q->next ;
  795     }
  796     return NULL ; /* clearly not found */
  797 found:
  798     if ( prev != NULL) { /* found and not in front */
  799         prev->next = q->next ;
  800         q->next = ipfw_dyn_v[i] ;
  801         ipfw_dyn_v[i] = q ;
  802     }
  803     if (pkt->proto == IPPROTO_TCP) {
  804         /* update state according to flags */
  805         u_char flags = pkt->flags & (TH_FIN|TH_SYN|TH_RST);
  806         q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8);
  807         switch (q->state) {
  808         case TH_SYN :
  809             /* opening */
  810             q->expire = time_second + dyn_syn_lifetime ;
  811             break ;
  812         case TH_SYN | (TH_SYN << 8) :
  813             /* move to established */
  814             q->expire = time_second + dyn_ack_lifetime ;
  815             break ;
  816         case TH_SYN | (TH_SYN << 8) | TH_FIN :
  817         case TH_SYN | (TH_SYN << 8) | (TH_FIN << 8) :
  818             /* one side tries to close */
  819             q->expire = time_second + dyn_ack_lifetime ;
  820             break ;
  821         case TH_SYN | (TH_SYN << 8) | TH_FIN | (TH_FIN << 8) :
  822             /* both sides closed */
  823             q->expire = time_second + dyn_fin_lifetime ;
  824             break ;
  825         default:
  826 #if 0
  827             /*
  828              * reset or some invalid combination, but can also
  829              * occur if we use keep-state the wrong way.
  830              */
  831             if ( (q->state & ((TH_RST << 8)|TH_RST)) == 0)
  832                 printf("invalid state: 0x%x\n", q->state);
  833 #endif
  834             q->expire = time_second + dyn_rst_lifetime ;
  835             break ;
  836         }
  837     } else if (pkt->proto == IPPROTO_UDP) {
  838         q->expire = time_second + dyn_udp_lifetime ;
  839     } else {
  840         /* other protocols */
  841         q->expire = time_second + dyn_short_lifetime ;
  842     }
  843     if (match_direction)
  844         *match_direction = dir ;
  845     return q ;
  846 }
  847 
  848 /**
  849  * Install state of type 'type' for a dynamic session.
  850  * The hash table contains two type of rules:
  851  * - regular rules (DYN_KEEP_STATE)
  852  * - rules for sessions with limited number of sess per user
  853  *   (DYN_LIMIT). When they are created, the parent is
  854  *   increased by 1, and decreased on delete. In this case,
  855  *   the third parameter is the parent rule and not the chain.
  856  * - "parent" rules for the above (DYN_LIMIT_PARENT).
  857  */
  858 
  859 static struct ipfw_dyn_rule *
  860 add_dyn_rule(struct ipfw_flow_id *id, u_int8_t dyn_type, struct ip_fw *rule)
  861 {
  862     struct ipfw_dyn_rule *r ;
  863 
  864     int i ;
  865     if (ipfw_dyn_v == NULL ||
  866                 (dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
  867         /* try reallocation, make sure we have a power of 2 */
  868         u_int32_t i = dyn_buckets ;
  869         while ( i > 0 && (i & 1) == 0 )
  870             i >>= 1 ;
  871         if (i != 1) /* not a power of 2 */
  872             dyn_buckets = curr_dyn_buckets ; /* reset */
  873         else {
  874             curr_dyn_buckets = dyn_buckets ;
  875             if (ipfw_dyn_v != NULL)
  876                 free(ipfw_dyn_v, M_IPFW);
  877             ipfw_dyn_v = malloc(curr_dyn_buckets * sizeof r,
  878                    M_IPFW, M_DONTWAIT | M_ZERO);
  879             if (ipfw_dyn_v == NULL)
  880                 return NULL; /* failed ! */
  881         }
  882     }
  883     i = hash_packet(id);
  884 
  885     r = malloc(sizeof *r, M_IPFW, M_DONTWAIT | M_ZERO);
  886     if (r == NULL) {
  887         printf ("sorry cannot allocate state\n");
  888         return NULL ;
  889     }
  890 
  891     /* increase refcount on parent, and set pointer */
  892     if (dyn_type == DYN_LIMIT) {
  893         struct ipfw_dyn_rule *parent = (struct ipfw_dyn_rule *)rule;
  894         if ( parent->dyn_type != DYN_LIMIT_PARENT)
  895             panic("invalid parent");
  896         parent->count++ ;
  897         r->parent = parent ;
  898         rule = parent->rule;
  899     }
  900 
  901     r->id = *id ;
  902     r->expire = time_second + dyn_syn_lifetime ;
  903     r->rule = rule ;
  904     r->dyn_type = dyn_type ;
  905     r->pcnt = r->bcnt = 0 ;
  906     r->count = 0 ;
  907 
  908     r->bucket = i ;
  909     r->next = ipfw_dyn_v[i] ;
  910     ipfw_dyn_v[i] = r ;
  911     dyn_count++ ;
  912     DEB(printf("-- add entry 0x%08x %d -> 0x%08x %d, total %d\n",
  913        (r->id.src_ip), (r->id.src_port),
  914        (r->id.dst_ip), (r->id.dst_port),
  915        dyn_count ); )
  916     return r;
  917 }
  918 
  919 /**
  920  * lookup dynamic parent rule using pkt and rule as search keys.
  921  * If the lookup fails, then install one.
  922  */
  923 static struct ipfw_dyn_rule *
  924 lookup_dyn_parent(struct ipfw_flow_id *pkt, struct ip_fw *rule)
  925 {
  926     struct ipfw_dyn_rule *q;
  927     int i;
  928 
  929     if (ipfw_dyn_v) {
  930         i = hash_packet( pkt );
  931         for (q = ipfw_dyn_v[i] ; q != NULL ; q=q->next)
  932             if (q->dyn_type == DYN_LIMIT_PARENT && rule == q->rule &&
  933                     pkt->proto == q->id.proto &&
  934                     pkt->src_ip == q->id.src_ip &&
  935                     pkt->dst_ip == q->id.dst_ip &&
  936                     pkt->src_port == q->id.src_port &&
  937                     pkt->dst_port == q->id.dst_port) {
  938                 q->expire = time_second + dyn_short_lifetime ;
  939                 DEB(printf("lookup_dyn_parent found 0x%p\n", q);)
  940                 return q;
  941             }
  942     }
  943     return add_dyn_rule(pkt, DYN_LIMIT_PARENT, rule);
  944 }
  945 
  946 /*
  947  * Install dynamic state.
  948  * There are different types of dynamic rules which can be installed.
  949  * The type is in rule->dyn_type.
  950  * Type 0 (default) is a bidirectional rule
  951  *
  952  * Returns 1 (failure) if state is not installed because of errors or because
  953  * session limitations are enforced.
  954  */
  955 static int
  956 install_state(struct ip_fw *rule, struct ip_fw_args *args)
  957 {
  958     struct ipfw_dyn_rule *q ;
  959     static int last_log ;
  960 
  961     u_int8_t type = rule->dyn_type ;
  962 
  963     DEB(printf("-- install state type %d 0x%08x %u -> 0x%08x %u\n",
  964        type,
  965        (args->f_id.src_ip), (args->f_id.src_port),
  966        (args->f_id.dst_ip), (args->f_id.dst_port) );)
  967 
  968     q = lookup_dyn_rule(&args->f_id, NULL) ;
  969     if (q != NULL) { /* should never occur */
  970         if (last_log != time_second) {
  971             last_log = time_second ;
  972             printf(" entry already present, done\n");
  973         }
  974         return 0 ;
  975     }
  976     if (dyn_count >= dyn_max) /* try remove old ones... */
  977         EXPIRE_DYN_CHAINS();
  978     if (dyn_count >= dyn_max) {
  979         if (last_log != time_second) {
  980             last_log = time_second ;
  981             printf(" Too many dynamic rules, sorry\n");
  982         }
  983         return 1; /* cannot install, notify caller */
  984     }
  985 
  986     switch (type) {
  987     case DYN_KEEP_STATE: /* bidir rule */
  988         add_dyn_rule(&args->f_id, DYN_KEEP_STATE, rule);
  989         break ;
  990     case DYN_LIMIT: /* limit number of sessions */
  991         {
  992         u_int16_t limit_mask = rule->limit_mask ;
  993         u_int16_t conn_limit = rule->conn_limit ;
  994         struct ipfw_flow_id id;
  995         struct ipfw_dyn_rule *parent;
  996 
  997         DEB(printf("installing dyn-limit rule %d\n", conn_limit);)
  998 
  999         id.dst_ip = id.src_ip = 0;
 1000         id.dst_port = id.src_port = 0 ;
 1001         id.proto = args->f_id.proto ;
 1002 
 1003         if (limit_mask & DYN_SRC_ADDR)
 1004             id.src_ip = args->f_id.src_ip;
 1005         if (limit_mask & DYN_DST_ADDR)
 1006             id.dst_ip = args->f_id.dst_ip;
 1007         if (limit_mask & DYN_SRC_PORT)
 1008             id.src_port = args->f_id.src_port;
 1009         if (limit_mask & DYN_DST_PORT)
 1010             id.dst_port = args->f_id.dst_port;
 1011         parent = lookup_dyn_parent(&id, rule);
 1012         if (parent == NULL) {
 1013             printf("add parent failed\n");
 1014             return 1;
 1015         }
 1016         if (parent->count >= conn_limit) {
 1017             EXPIRE_DYN_CHAIN(rule); /* try to expire some */
 1018             if (parent->count >= conn_limit) {
 1019                 printf("drop session, too many entries\n");
 1020                 return 1;
 1021             }
 1022         }
 1023         add_dyn_rule(&args->f_id, DYN_LIMIT, (struct ip_fw *)parent);
 1024         }
 1025         break ;
 1026     default:
 1027         printf("unknown dynamic rule type %u\n", type);
 1028         return 1 ;
 1029     }
 1030     lookup_dyn_rule(&args->f_id, NULL) ; /* XXX just set the lifetime */
 1031     return 0;
 1032 }
 1033 
 1034 /*
 1035  * given an ip_fw *, lookup_next_rule will return a pointer
 1036  * of the same type to the next one. This can be either the jump
 1037  * target (for skipto instructions) or the next one in the list (in
 1038  * all other cases including a missing jump target).
 1039  * Backward jumps are not allowed, so start looking from the next
 1040  * rule...
 1041  */ 
 1042 static struct ip_fw * lookup_next_rule(struct ip_fw *me);
 1043 
 1044 static struct ip_fw *
 1045 lookup_next_rule(struct ip_fw *me)
 1046 {
 1047     struct ip_fw *rule ;
 1048     int rulenum = me->fw_skipto_rule ; /* guess... */
 1049 
 1050     if ( (me->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_SKIPTO )
 1051         for (rule = LIST_NEXT(me,next); rule ; rule = LIST_NEXT(rule,next))
 1052             if (rule->fw_number >= rulenum)
 1053                 return rule ;
 1054     return LIST_NEXT(me,next) ; /* failure or not a skipto */
 1055 }
 1056 
 1057 /*
 1058  * Parameters:
 1059  *
 1060  *      *m      The packet; we set to NULL when/if we nuke it.
 1061  *      oif     Outgoing interface, or NULL if packet is incoming
 1062  *      *cookie Skip up to the first rule past this rule number;
 1063  *              upon return, non-zero port number for divert or tee.
 1064  *              Special case: cookie == NULL on input for bridging.
 1065  *      *flow_id pointer to the last matching rule (in/out)
 1066  *      *next_hop socket we are forwarding to (in/out).
 1067  *              For bridged packets, this is a pointer to the MAC header.
 1068  *
 1069  * Return value:
 1070  *
 1071  *      IP_FW_PORT_DENY_FLAG    the packet must be dropped.
 1072  *      0       The packet is to be accepted and routed normally OR
 1073  *              the packet was denied/rejected and has been dropped;
 1074  *              in the latter case, *m is equal to NULL upon return.
 1075  *      port    Divert the packet to port, with these caveats:
 1076  *
 1077  *              - If IP_FW_PORT_TEE_FLAG is set, tee the packet instead
 1078  *                of diverting it (ie, 'ipfw tee').
 1079  *
 1080  *              - If IP_FW_PORT_DYNT_FLAG is set, interpret the lower
 1081  *                16 bits as a dummynet pipe number instead of diverting
 1082  */
 1083 
 1084 static int 
 1085 ip_fw_chk(struct ip_fw_args *args)
 1086 #if 0 /* the old interface was this: */
 1087         struct mbuf **m, struct ifnet *oif, u_int16_t *cookie,
 1088         struct ip_fw **flow_id, struct sockaddr_in **next_hop)
 1089 #endif
 1090 {
 1091         /*
 1092          * grab things into variables to minimize diffs.
 1093          * XXX this has to be cleaned up later.
 1094          */
 1095         struct mbuf **m = &(args->m);
 1096         struct ifnet *oif = args->oif;
 1097         u_int16_t *cookie = &(args->divert_rule);
 1098         struct ip_fw **flow_id = &(args->rule);
 1099         struct sockaddr_in **next_hop = &(args->next_hop);
 1100 
 1101         struct ip_fw *f = NULL;         /* matching rule */
 1102         struct ip *ip = mtod(*m, struct ip *);
 1103         struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
 1104         struct ifnet *tif;
 1105         u_int hlen = ip->ip_hl << 2;
 1106         struct ether_header * eh = NULL;
 1107 
 1108         u_short ip_off=0, offset = 0 ;
 1109         /* local copy of addresses for faster matching */
 1110         u_short src_port = 0, dst_port = 0;
 1111         struct in_addr src_ip, dst_ip;
 1112         u_int8_t proto= 0, flags = 0;
 1113 
 1114         u_int16_t skipto;
 1115         u_int16_t ip_len=0;
 1116 
 1117         int dyn_checked = 0 ; /* set after dyn.rules have been checked. */
 1118         int direction = MATCH_FORWARD ; /* dirty trick... */
 1119         struct ipfw_dyn_rule *q = NULL ;
 1120 
 1121 #define BRIDGED (args->eh != NULL)
 1122         if (BRIDGED) {  /* this is a bridged packet */
 1123             eh = args->eh;
 1124             if ( (*m)->m_pkthdr.len >= sizeof(struct ip) &&
 1125                         ntohs(eh->ether_type) == ETHERTYPE_IP)
 1126                 hlen = ip->ip_hl << 2;
 1127         } else
 1128             hlen = ip->ip_hl << 2;
 1129 
 1130         /* Grab and reset cookie */
 1131         skipto = *cookie;
 1132         *cookie = 0;
 1133 
 1134         /*
 1135          * Collect parameters into local variables for faster matching.
 1136          */
 1137         if (hlen > 0) { /* this is an IP packet */
 1138             proto = ip->ip_p;
 1139             src_ip = ip->ip_src;
 1140             dst_ip = ip->ip_dst;
 1141             if (BRIDGED) { /* bridged packets are as on the wire */
 1142                 ip_off = ntohs(ip->ip_off);
 1143                 ip_len = ntohs(ip->ip_len);
 1144             } else {
 1145                 ip_off = ip->ip_off;
 1146                 ip_len = ip->ip_len;
 1147             }
 1148             offset = ip_off & IP_OFFMASK;
 1149             if (offset == 0) {
 1150 
 1151 #define PULLUP_TO(len)                                          \
 1152                 do {                                            \
 1153                         if ((*m)->m_len < (len)) {              \
 1154                             *m = m_pullup(*m, (len));           \
 1155                             if (*m == 0)                        \
 1156                                 goto bogusfrag;                 \
 1157                             ip = mtod(*m, struct ip *);         \
 1158                         }                                       \
 1159                 } while (0)
 1160 
 1161                 switch (proto) {
 1162                 case IPPROTO_TCP : {
 1163                     struct tcphdr *tcp;
 1164 
 1165                     PULLUP_TO(hlen + sizeof(struct tcphdr));
 1166                     tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl);
 1167                     dst_port = tcp->th_dport ;
 1168                     src_port = tcp->th_sport ;
 1169                     flags = tcp->th_flags ;
 1170                     }
 1171                     break ;
 1172 
 1173                 case IPPROTO_UDP : {
 1174                     struct udphdr *udp;
 1175 
 1176                     PULLUP_TO(hlen + sizeof(struct udphdr));
 1177                     udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl);
 1178                     dst_port = udp->uh_dport ;
 1179                     src_port = udp->uh_sport ;
 1180                     }
 1181                     break;
 1182 
 1183                 case IPPROTO_ICMP:
 1184                     PULLUP_TO(hlen + 4);        /* type, code and checksum. */
 1185                     flags = ((struct icmp *)
 1186                             ((u_int32_t *)ip + ip->ip_hl))->icmp_type ;
 1187                     break ;
 1188 
 1189                 default :
 1190                     break;
 1191                 }
 1192 #undef PULLUP_TO
 1193             }
 1194         }
 1195         args->f_id.src_ip = ntohl(src_ip.s_addr);
 1196         args->f_id.dst_ip = ntohl(dst_ip.s_addr);
 1197         args->f_id.proto = proto;
 1198         args->f_id.src_port = ntohs(src_port);
 1199         args->f_id.dst_port = ntohs(dst_port);
 1200         args->f_id.flags = flags;
 1201 
 1202         if (*flow_id) {
 1203             /*
 1204              * Packet has already been tagged. Look for the next rule
 1205              * to restart processing.
 1206              */
 1207             if (fw_one_pass) /* just accept if fw_one_pass is set */
 1208                 return 0;
 1209 
 1210             f = (*flow_id)->next_rule_ptr ;
 1211             if (f == NULL)
 1212                 f = (*flow_id)->next_rule_ptr = lookup_next_rule(*flow_id);
 1213             if (f == NULL)
 1214                 goto dropit;
 1215         } else {
 1216             /*
 1217              * Go down the list, looking for enlightment.
 1218              * If we've been asked to start at a given rule, do so.
 1219              */
 1220             f = LIST_FIRST(&ip_fw_chain_head);
 1221             if (skipto != 0) {
 1222                 if (skipto >= IPFW_DEFAULT_RULE)
 1223                     goto dropit;
 1224                 while (f && f->fw_number <= skipto)
 1225                     f = LIST_NEXT(f, next);
 1226                 if (f == NULL)
 1227                     goto dropit;
 1228             }
 1229         }
 1230 
 1231         for (; f; f = LIST_NEXT(f, next)) {
 1232 again:
 1233                 if (f->fw_number == IPFW_DEFAULT_RULE)
 1234                     goto got_match ;
 1235 
 1236                 /* Check if rule only valid for bridged packets */
 1237                 if ((f->fw_flg & IP_FW_BRIDGED) != 0 && !(BRIDGED))
 1238                     continue;
 1239 #undef BRIDGED
 1240 
 1241                 if (oif) {
 1242                     /* Check direction outbound */
 1243                     if (!(f->fw_flg & IP_FW_F_OUT))
 1244                         continue;
 1245                 } else {
 1246                     /* Check direction inbound */
 1247                     if (!(f->fw_flg & IP_FW_F_IN))
 1248                         continue;
 1249                 }
 1250 
 1251                 if (f->fw_flg & IP_FW_F_MAC) {
 1252                     u_int32_t *want, *mask, *hdr;
 1253 
 1254                     if (eh == NULL) /* header not available */
 1255                         continue;
 1256 
 1257                     want = (void *)&(f->fw_mac_hdr);
 1258                     mask = (void *)&(f->fw_mac_mask);
 1259                     hdr = (void *)eh;
 1260 
 1261                     if ( want[0] != (hdr[0] & mask[0]) )
 1262                         continue;
 1263                     if ( want[1] != (hdr[1] & mask[1]) )
 1264                         continue;
 1265                     if ( want[2] != (hdr[2] & mask[2]) )
 1266                         continue;
 1267                     if (f->fw_flg & IP_FW_F_SRNG) {
 1268                         u_int16_t type = ntohs(eh->ether_type);
 1269                         if (type < (u_int16_t)(f->fw_mac_type) ||
 1270                                 type > (u_int16_t)(f->fw_mac_mask_type) )
 1271                             continue;
 1272                     } else {
 1273                         if ((u_int16_t)(f->fw_mac_type) != (eh->ether_type &
 1274                                 (u_int16_t)(f->fw_mac_mask_type)) )
 1275                             continue;
 1276                     }
 1277                 }
 1278 
 1279                 /* Interface check */
 1280                 if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
 1281                         struct ifnet *const iface = oif ? oif : rif;
 1282 
 1283                         /* Backwards compatibility hack for "via" */
 1284                         if (!iface || !iface_match(iface,
 1285                             &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME))
 1286                                 continue;
 1287                 } else {
 1288                         /* Check receive interface */
 1289                         if ((f->fw_flg & IP_FW_F_IIFACE)
 1290                             && (!rif || !iface_match(rif,
 1291                               &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME)))
 1292                                 continue;
 1293                         /* Check outgoing interface */
 1294                         if ((f->fw_flg & IP_FW_F_OIFACE)
 1295                             && (!oif || !iface_match(oif,
 1296                               &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME)))
 1297                                 continue;
 1298                 }
 1299 
 1300                 /*
 1301                  * For packets which matched the MAC check, we do not need
 1302                  * to continue, this is a valid match.
 1303                  * For not-ip packets, the rule does not apply.
 1304                  */
 1305                 if (f->fw_flg & IP_FW_F_MAC)
 1306                         goto rnd_then_got_match;
 1307 
 1308                 if (hlen == 0)
 1309                         continue;
 1310 
 1311                 /*
 1312                  * dynamic rules are checked at the first keep-state or
 1313                  * check-state occurrence.
 1314                  */
 1315                 if (f->fw_flg & (IP_FW_F_KEEP_S|IP_FW_F_CHECK_S) &&
 1316                          dyn_checked == 0 ) {
 1317                     dyn_checked = 1 ;
 1318                     q = lookup_dyn_rule(&args->f_id, &direction);
 1319                     if (q != NULL) {
 1320                         DEB(printf("-- dynamic match 0x%08x %d %s 0x%08x %d\n",
 1321                             (q->id.src_ip), (q->id.src_port),
 1322                             (direction == MATCH_FORWARD ? "-->" : "<--"),
 1323                             (q->id.dst_ip), (q->id.dst_port) ); )
 1324                         f = q->rule ;
 1325                         q->pcnt++ ;
 1326                         q->bcnt += ip_len;
 1327                         goto got_match ; /* random not allowed here */
 1328                     }
 1329                     /* if this was a check-only rule, continue with next */
 1330                     if (f->fw_flg & IP_FW_F_CHECK_S)
 1331                         continue ;
 1332                 }
 1333 
 1334                 /* Fragments */
 1335                 if ((f->fw_flg & IP_FW_F_FRAG) && offset == 0 )
 1336                         continue;
 1337 
 1338                 /*
 1339                  * For matching addresses, tif != NULL means we matched
 1340                  * the address we requested (either "me" or addr/mask).
 1341                  * Then the check for "xxx" or "not xxx" can be done
 1342                  * with an XOR.
 1343                  */
 1344 
 1345                 /* source address --    mandatory */
 1346                 if (f->fw_flg & IP_FW_F_SME) {
 1347                         INADDR_TO_IFP(src_ip, tif);
 1348                 } else
 1349                         (int)tif = f->fw_src.s_addr ==
 1350                             (src_ip.s_addr & f->fw_smsk.s_addr);
 1351                 if ( ((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ (tif == NULL) )
 1352                         continue;
 1353                 
 1354                 /* dst address --       mandatory */
 1355                 if (f->fw_flg & IP_FW_F_DME) {
 1356                         INADDR_TO_IFP(dst_ip, tif);
 1357                 } else
 1358                         (int)tif = f->fw_dst.s_addr ==
 1359                             (dst_ip.s_addr & f->fw_dmsk.s_addr);
 1360                 if ( ((f->fw_flg & IP_FW_F_INVDST) != 0) ^ (tif == NULL) )
 1361                         continue;
 1362                 
 1363                 /* Check IP header values */
 1364                 if (f->fw_ipflg & IP_FW_IF_IPOPT && !ipopts_match(ip, f))
 1365                         continue;
 1366                 if (f->fw_ipflg & IP_FW_IF_IPLEN && f->fw_iplen != ip_len)
 1367                         continue;
 1368                 if (f->fw_ipflg & IP_FW_IF_IPID && f->fw_ipid != ntohs(ip->ip_id))
 1369                         continue;
 1370                 if (f->fw_ipflg & IP_FW_IF_IPPRE &&
 1371                      (f->fw_iptos & 0xe0) != (ip->ip_tos & 0xe0))
 1372                         continue;
 1373                 if (f->fw_ipflg & IP_FW_IF_IPTOS && !iptos_match(ip, f))
 1374                         continue;
 1375                 if (f->fw_ipflg & IP_FW_IF_IPTTL && f->fw_ipttl != ip->ip_ttl)
 1376                         continue;
 1377                 if (f->fw_ipflg & IP_FW_IF_IPVER && f->fw_ipver != ip->ip_v)
 1378                         continue;
 1379 
 1380                 /* Check protocol; if wildcard, and no [ug]id, match */
 1381                 if (f->fw_prot == IPPROTO_IP) {
 1382                         if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
 1383                                 goto rnd_then_got_match;
 1384                 } else
 1385                     /* If different, don't match */
 1386                     if (proto != f->fw_prot) 
 1387                             continue;
 1388 
 1389                 /* Protocol specific checks for uid only */
 1390                 if (f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)) {
 1391                     switch (proto) {
 1392                     case IPPROTO_TCP:
 1393                         {
 1394                             struct inpcb *P;
 1395 
 1396                             if (offset == 1)    /* cf. RFC 1858 */
 1397                                     goto bogusfrag;
 1398                             if (offset != 0)
 1399                                     continue;
 1400 
 1401                             if (oif)
 1402                                 P = in_pcblookup_hash(&tcbinfo, dst_ip,
 1403                                    dst_port, src_ip, src_port, 0,
 1404                                    oif);
 1405                             else
 1406                                 P = in_pcblookup_hash(&tcbinfo, src_ip,
 1407                                    src_port, dst_ip, dst_port, 0,
 1408                                    NULL);
 1409 
 1410                             if (P && P->inp_socket) {
 1411                                 if (f->fw_flg & IP_FW_F_UID) {
 1412                                         if (socheckuid(P->inp_socket, f->fw_uid))
 1413                                                 continue;
 1414                                 } else if (!groupmember(f->fw_gid,
 1415                                             P->inp_socket->so_cred))
 1416                                                 continue;
 1417                             } else
 1418                                 continue;
 1419                             break;
 1420                         }
 1421 
 1422                     case IPPROTO_UDP:
 1423                         {
 1424                             struct inpcb *P;
 1425 
 1426                             if (offset != 0)
 1427                                 continue;
 1428 
 1429                             if (oif)
 1430                                 P = in_pcblookup_hash(&udbinfo, dst_ip,
 1431                                    dst_port, src_ip, src_port, 1,
 1432                                    oif);
 1433                             else
 1434                                 P = in_pcblookup_hash(&udbinfo, src_ip,
 1435                                    src_port, dst_ip, dst_port, 1,
 1436                                    NULL);
 1437 
 1438                             if (P && P->inp_socket) {
 1439                                 if (f->fw_flg & IP_FW_F_UID) {
 1440                                         if (socheckuid(P->inp_socket, f->fw_uid))
 1441                                                 continue;
 1442                                 } else if (!groupmember(f->fw_gid,
 1443                                             P->inp_socket->so_cred))
 1444                                                 continue;
 1445                             } else
 1446                                 continue;
 1447                             break;
 1448                         }
 1449 
 1450                     default:
 1451                             continue;
 1452                     }
 1453                 }
 1454                     
 1455                 /* Protocol specific checks */
 1456                 switch (proto) {
 1457                 case IPPROTO_TCP:
 1458                     {
 1459                         struct tcphdr *tcp;
 1460 
 1461                         if (offset == 1)        /* cf. RFC 1858 */
 1462                                 goto bogusfrag;
 1463                         if (offset != 0) {
 1464                                 /*
 1465                                  * TCP flags and ports aren't available in this
 1466                                  * packet -- if this rule specified either one,
 1467                                  * we consider the rule a non-match.
 1468                                  */
 1469                                 if (IP_FW_HAVEPORTS(f) != 0 ||
 1470                                     f->fw_ipflg & IP_FW_IF_TCPMSK)
 1471                                         continue;
 1472 
 1473                                 break;
 1474                         }
 1475                         tcp = (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
 1476 
 1477                         if (f->fw_ipflg & IP_FW_IF_TCPOPT && !tcpopts_match(tcp, f))
 1478                                 continue;
 1479                         if (((f->fw_ipflg & IP_FW_IF_TCPFLG) ||
 1480                             (f->fw_ipflg & IP_FW_IF_TCPEST)) &&
 1481                             !tcpflg_match(tcp, f))
 1482                                 continue;
 1483                         if (f->fw_ipflg & IP_FW_IF_TCPSEQ && tcp->th_seq != f->fw_tcpseq)
 1484                                 continue;
 1485                         if (f->fw_ipflg & IP_FW_IF_TCPACK && tcp->th_ack != f->fw_tcpack)
 1486                                 continue;
 1487                         if (f->fw_ipflg & IP_FW_IF_TCPWIN && tcp->th_win != f->fw_tcpwin)
 1488                                 continue;
 1489                         goto check_ports;
 1490                     }
 1491 
 1492                 case IPPROTO_UDP:
 1493                         if (offset != 0) {
 1494                                 /*
 1495                                  * Port specification is unavailable -- if this
 1496                                  * rule specifies a port, we consider the rule
 1497                                  * a non-match.
 1498                                  */
 1499                                 if (IP_FW_HAVEPORTS(f) )
 1500                                         continue;
 1501 
 1502                                 break;
 1503                         }
 1504 check_ports:
 1505                         if (!port_match(&f->fw_uar.fw_pts[0],
 1506                             IP_FW_GETNSRCP(f), ntohs(src_port),
 1507                             f->fw_flg & IP_FW_F_SRNG,
 1508                             f->fw_flg & IP_FW_F_SMSK))
 1509                                 continue;
 1510                         if (!port_match(&f->fw_uar.fw_pts[IP_FW_GETNSRCP(f)],
 1511                             IP_FW_GETNDSTP(f), ntohs(dst_port),
 1512                             f->fw_flg & IP_FW_F_DRNG,
 1513                             f->fw_flg & IP_FW_F_DMSK)) 
 1514                                 continue;
 1515                         break;
 1516 
 1517                 case IPPROTO_ICMP:
 1518                     {
 1519                         struct icmp *icmp;
 1520 
 1521                         if (offset != 0)        /* Type isn't valid */
 1522                                 break;
 1523                         icmp = (struct icmp *) ((u_int32_t *)ip + ip->ip_hl);
 1524                         if (!icmptype_match(icmp, f))
 1525                                 continue;
 1526                         break;
 1527                     }
 1528 
 1529                 default:
 1530                         break;
 1531 
 1532 bogusfrag:
 1533                 if (fw_verbose) {
 1534                         if (*m != NULL)
 1535                                 ipfw_report(NULL, ip, ip_off, ip_len, rif, oif);
 1536                         else
 1537                                 printf("pullup failed\n");
 1538                 }
 1539                 goto dropit;
 1540 
 1541                 }
 1542 
 1543 rnd_then_got_match:
 1544                 if ( f->dont_match_prob && random() < f->dont_match_prob )
 1545                         continue ;
 1546 got_match:
 1547                 /*
 1548                  * If not a dynamic match (q == NULL) and keep-state, install
 1549                  * a new dynamic entry.
 1550                  */
 1551                 if (q == NULL && f->fw_flg & IP_FW_F_KEEP_S) {
 1552                     if (install_state(f, args)) /* error or limit violation */
 1553                         goto dropit;
 1554                 }
 1555                 /* Update statistics */
 1556                 f->fw_pcnt += 1;
 1557                 f->fw_bcnt += ip_len;
 1558                 f->timestamp = time_second;
 1559 
 1560                 /* Log to console if desired */
 1561                 if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose && hlen >0)
 1562                         ipfw_report(f, ip, ip_off, ip_len, rif, oif);
 1563 
 1564                 /* Take appropriate action */
 1565                 switch (f->fw_flg & IP_FW_F_COMMAND) {
 1566                 case IP_FW_F_ACCEPT:
 1567                         return(0);
 1568                 case IP_FW_F_COUNT:
 1569                         continue;
 1570 #ifdef IPDIVERT
 1571                 case IP_FW_F_DIVERT:
 1572                         *cookie = f->fw_number;
 1573                         return(f->fw_divert_port);
 1574                 case IP_FW_F_TEE:
 1575                         *cookie = f->fw_number;
 1576                         return(f->fw_divert_port | IP_FW_PORT_TEE_FLAG);
 1577 #endif
 1578                 case IP_FW_F_SKIPTO: /* XXX check */
 1579                         if (f->next_rule_ptr == NULL)
 1580                             f->next_rule_ptr = lookup_next_rule(f) ;
 1581                         f = f->next_rule_ptr;
 1582                         if (!f)
 1583                             goto dropit;
 1584                         goto again ;
 1585 
 1586                 case IP_FW_F_PIPE:
 1587                 case IP_FW_F_QUEUE:
 1588                         *flow_id = f; /* XXX set flow id */
 1589                         return(f->fw_pipe_nr | IP_FW_PORT_DYNT_FLAG);
 1590 
 1591                 case IP_FW_F_FWD:
 1592                         /* Change the next-hop address for this packet.
 1593                          * Initially we'll only worry about directly
 1594                          * reachable next-hop's, but ultimately
 1595                          * we will work out for next-hops that aren't
 1596                          * direct the route we would take for it. We
 1597                          * [cs]ould leave this latter problem to
 1598                          * ip_output.c. We hope to high [name the abode of
 1599                          * your favourite deity] that ip_output doesn't modify
 1600                          * the new value of next_hop (which is dst there)
 1601                          * XXX warning-- there is a dangerous reference here
 1602                          * from next_hop to a field within the rule. If the
 1603                          * rule is deleted, weird things might occur.
 1604                          */
 1605                         if (next_hop != NULL /* Make sure, first... */
 1606                             && (q == NULL || direction == MATCH_FORWARD) )
 1607                                 *next_hop = &(f->fw_fwd_ip);
 1608                         return(0); /* Allow the packet */
 1609 
 1610                 }
 1611 
 1612                 /* Deny/reject this packet using this rule */
 1613                 break;
 1614         }
 1615 
 1616         /* Rule IPFW_DEFAULT_RULE should always be there and match */
 1617         KASSERT(f != NULL, ("ip_fw: no chain"));
 1618 
 1619         /*
 1620          * At this point, we're going to drop the packet.
 1621          * Send a reject notice if all of the following are true:
 1622          *
 1623          * - The packet matched a reject rule
 1624          * - The packet is not an ICMP packet, or is an ICMP query packet
 1625          * - The packet is not a multicast or broadcast packet
 1626          */
 1627         if ((f->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
 1628             && (proto != IPPROTO_ICMP || is_icmp_query(ip))
 1629             && !((*m)->m_flags & (M_BCAST|M_MCAST))
 1630             && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
 1631                 switch (f->fw_reject_code) {
 1632                 case IP_FW_REJECT_RST:
 1633                     {
 1634                         /* XXX warning, this code writes into the mbuf */
 1635                         struct tcphdr *const tcp =
 1636                                 (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
 1637                         struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip;
 1638 
 1639                         if (offset != 0 || (tcp->th_flags & TH_RST))
 1640                                 break;
 1641                         ti.ti_i = *((struct ipovly *) ip);
 1642                         ti.ti_t = *tcp;
 1643                         bcopy(&ti, ip, sizeof(ti));
 1644                         tip->ti_seq = ntohl(tip->ti_seq);
 1645                         tip->ti_ack = ntohl(tip->ti_ack);
 1646                         tip->ti_len = ip_len - hlen - (tip->ti_off << 2);
 1647                         if (tcp->th_flags & TH_ACK) {
 1648                                 tcp_respond(NULL, (void *)ip, tcp, *m,
 1649                                     (tcp_seq)0, tcp->th_ack, TH_RST);
 1650                         } else {
 1651                                 if (tcp->th_flags & TH_SYN)
 1652                                         tip->ti_len++;
 1653                                 tcp_respond(NULL, (void *)ip, tcp, *m, 
 1654                                     tip->ti_seq + tip->ti_len,
 1655                                     (tcp_seq)0, TH_RST|TH_ACK);
 1656                         }
 1657                         *m = NULL;
 1658                         break;
 1659                     }
 1660                 default:        /* Send an ICMP unreachable using code */
 1661                         icmp_error(*m, ICMP_UNREACH,
 1662                             f->fw_reject_code, 0L, 0);
 1663                         *m = NULL;
 1664                         break;
 1665                 }
 1666         }
 1667 
 1668 dropit:
 1669         /*
 1670          * Finally, drop the packet.
 1671          */
 1672         return(IP_FW_PORT_DENY_FLAG);
 1673 }
 1674 
 1675 /*
 1676  * when a rule is added/deleted, zero the direct pointers within
 1677  * all firewall rules. These will be reconstructed on the fly
 1678  * as packets are matched.
 1679  * Must be called at splimp().
 1680  */
 1681 static void
 1682 flush_rule_ptrs()
 1683 {
 1684     struct ip_fw *fcp ;
 1685 
 1686     LIST_FOREACH(fcp, &ip_fw_chain_head, next) {
 1687         fcp->next_rule_ptr = NULL ;
 1688     }
 1689 }
 1690 
 1691 static int
 1692 add_entry(struct ip_fw_head *head, struct ip_fw *rule)
 1693 {
 1694         struct ip_fw *ftmp, *fcp, *fcpl;
 1695         u_short nbr = 0;
 1696         int s;
 1697 
 1698         ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT | M_ZERO);
 1699         if (!ftmp)
 1700                 return (ENOSPC);
 1701         bcopy(rule, ftmp, sizeof(*ftmp));
 1702 
 1703         ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0';
 1704         ftmp->fw_pcnt = 0L;
 1705         ftmp->fw_bcnt = 0L;
 1706         ftmp->next_rule_ptr = NULL ;
 1707         ftmp->pipe_ptr = NULL ;
 1708         
 1709         s = splimp();
 1710 
 1711         if (LIST_FIRST(head) == 0) {
 1712                 LIST_INSERT_HEAD(head, ftmp, next);
 1713                 goto done;
 1714         }
 1715 
 1716         /* If entry number is 0, find highest numbered rule and add 100 */
 1717         if (ftmp->fw_number == 0) {
 1718                 LIST_FOREACH(fcp, head, next) {
 1719                         if (fcp->fw_number != IPFW_DEFAULT_RULE)
 1720                                 nbr = fcp->fw_number;
 1721                         else
 1722                                 break;
 1723                 }
 1724                 if (nbr < IPFW_DEFAULT_RULE - 100)
 1725                         nbr += 100;
 1726                 ftmp->fw_number = rule->fw_number = nbr;
 1727         }
 1728 
 1729         /* Got a valid number; now insert it, keeping the list ordered */
 1730         fcpl = NULL ;
 1731         LIST_FOREACH(fcp, head, next) {
 1732                 if (fcp->fw_number > ftmp->fw_number) {
 1733                         if (fcpl) {
 1734                                 LIST_INSERT_AFTER(fcpl, ftmp, next);
 1735                         } else {
 1736                                 LIST_INSERT_HEAD(head, ftmp, next);
 1737                         }
 1738                         break;
 1739                 } else {
 1740                         fcpl = fcp;
 1741                 }
 1742         }
 1743         flush_rule_ptrs();
 1744 done:
 1745         static_count++;
 1746         splx(s);
 1747         DEB(printf("++ installed rule %d, static count now %d\n",
 1748                 ftmp->fw_number, static_count);)
 1749         return (0);
 1750 }
 1751 
 1752 /**
 1753  * free storage associated with a static rule entry (including
 1754  * dependent dynamic rules), and zeroes rule pointers to avoid
 1755  * dangling pointer dereferences.
 1756  * @return a pointer to the next entry.
 1757  * Must be called at splimp() and with a non-null argument.
 1758  */
 1759 static struct ip_fw *
 1760 free_chain(struct ip_fw *fcp)
 1761 {
 1762     struct ip_fw *n;
 1763 
 1764     n = LIST_NEXT(fcp, next);
 1765     DELETE_DYN_CHAIN(fcp);
 1766     LIST_REMOVE(fcp, next);
 1767     static_count--;
 1768     if (DUMMYNET_LOADED)
 1769         ip_dn_ruledel_ptr(fcp) ;
 1770     flush_rule_ptrs(); /* more efficient to do outside the loop */
 1771     free(fcp, M_IPFW);
 1772     return n;
 1773 }
 1774 
 1775 /**
 1776  * remove all rules with given number.
 1777  */
 1778 static int
 1779 del_entry(struct ip_fw_head *chainptr, u_short number)
 1780 {
 1781     struct ip_fw *rule;
 1782 
 1783     if (number != IPFW_DEFAULT_RULE) {
 1784         LIST_FOREACH(rule, chainptr, next) {
 1785             if (rule->fw_number == number) {
 1786                 int s ;
 1787 
 1788                 s = splimp(); /* prevent access to rules while removing */
 1789                 while (rule && rule->fw_number == number)
 1790                     rule = free_chain(rule);
 1791                 /* XXX could move flush_rule_ptrs() here */
 1792                 splx(s);
 1793                 return 0 ;
 1794             }
 1795         }
 1796     }
 1797     return (EINVAL);
 1798 }
 1799 
 1800 /**
 1801  * Reset some or all counters on firewall rules.
 1802  * @arg frwl is null to clear all entries, or contains a specific
 1803  * rule number.
 1804  * @arg log_only is 1 if we only want to reset logs, zero otherwise.
 1805  */
 1806 
 1807 static int
 1808 zero_entry(struct ip_fw *frwl, int log_only)
 1809 {
 1810     struct ip_fw *rule;
 1811     int s;
 1812     u_short number = 0 ;
 1813     char *msg ;
 1814 
 1815     if (frwl == 0) {
 1816         s = splimp();
 1817         LIST_FOREACH(rule, &ip_fw_chain_head, next) {
 1818             if (log_only == 0) {
 1819                 rule->fw_bcnt = rule->fw_pcnt = 0;
 1820                 rule->timestamp = 0;
 1821             }
 1822             rule->fw_loghighest = rule->fw_pcnt+rule->fw_logamount;
 1823         }
 1824         splx(s);
 1825         msg = log_only ? "ipfw: All logging counts cleared.\n" :
 1826                         "ipfw: Accounting cleared.\n";
 1827     } else {
 1828         int cleared = 0;
 1829         number = frwl->fw_number ;
 1830         /*
 1831          * It is possible to insert multiple chain entries with the
 1832          * same number, so we don't stop after finding the first
 1833          * match if zeroing a specific entry.
 1834          */
 1835         LIST_FOREACH(rule, &ip_fw_chain_head, next)
 1836             if (number == rule->fw_number) {
 1837                 s = splimp();
 1838                 while (rule && number == rule->fw_number) {
 1839                     if (log_only == 0) {
 1840                         rule->fw_bcnt = rule->fw_pcnt = 0;
 1841                         rule->timestamp = 0;
 1842                     }
 1843                     rule->fw_loghighest = rule->fw_pcnt+ rule->fw_logamount;
 1844                     rule = LIST_NEXT(rule, next);
 1845                 }
 1846                 splx(s);
 1847                 cleared = 1;
 1848                 break;
 1849             }
 1850         if (!cleared)   /* we did not find any matching rules */
 1851             return (EINVAL);
 1852         msg = log_only ? "ipfw: Entry %d logging count reset.\n" :
 1853                         "ipfw: Entry %d cleared.\n";
 1854     }
 1855     if (fw_verbose)
 1856         log(LOG_SECURITY | LOG_NOTICE, msg, number);
 1857     return (0);
 1858 }
 1859 
 1860 static int
 1861 check_ipfw_struct(struct ip_fw *frwl)
 1862 {
 1863         /* Check for invalid flag bits */
 1864         if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) {
 1865                 dprintf(("%s undefined flag bits set (flags=%x)\n",
 1866                     err_prefix, frwl->fw_flg));
 1867                 return (EINVAL);
 1868         }
 1869         if ( (frwl->fw_flg & IP_FW_F_MAC) ) {   /* match MAC address */
 1870                 return 0;
 1871         }
 1872         if (frwl->fw_flg == IP_FW_F_CHECK_S) {
 1873                 /* check-state */
 1874                 return 0 ;
 1875         }
 1876         /* Must apply to incoming or outgoing (or both) */
 1877         if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) {
 1878                 dprintf(("%s neither in nor out\n", err_prefix));
 1879                 return (EINVAL);
 1880         }
 1881         /* Empty interface name is no good */
 1882         if (((frwl->fw_flg & IP_FW_F_IIFNAME)
 1883               && !*frwl->fw_in_if.fu_via_if.name)
 1884             || ((frwl->fw_flg & IP_FW_F_OIFNAME)
 1885               && !*frwl->fw_out_if.fu_via_if.name)) {
 1886                 dprintf(("%s empty interface name\n", err_prefix));
 1887                 return (EINVAL);
 1888         }
 1889         /* Sanity check interface matching */
 1890         if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
 1891                 ;               /* allow "via" backwards compatibility */
 1892         } else if ((frwl->fw_flg & IP_FW_F_IN)
 1893             && (frwl->fw_flg & IP_FW_F_OIFACE)) {
 1894                 dprintf(("%s outgoing interface check on incoming\n",
 1895                     err_prefix));
 1896                 return (EINVAL);
 1897         }
 1898         /* Sanity check port ranges */
 1899         if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) {
 1900                 dprintf(("%s src range set but n_src_p=%d\n",
 1901                     err_prefix, IP_FW_GETNSRCP(frwl)));
 1902                 return (EINVAL);
 1903         }
 1904         if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) {
 1905                 dprintf(("%s dst range set but n_dst_p=%d\n",
 1906                     err_prefix, IP_FW_GETNDSTP(frwl)));
 1907                 return (EINVAL);
 1908         }
 1909         if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) {
 1910                 dprintf(("%s too many ports (%d+%d)\n",
 1911                     err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl)));
 1912                 return (EINVAL);
 1913         }
 1914         /*
 1915          *      Protocols other than TCP/UDP don't use port range
 1916          */
 1917         if ((frwl->fw_prot != IPPROTO_TCP) &&
 1918             (frwl->fw_prot != IPPROTO_UDP) &&
 1919             (IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) {
 1920                 dprintf(("%s port(s) specified for non TCP/UDP rule\n",
 1921                     err_prefix));
 1922                 return (EINVAL);
 1923         }
 1924 
 1925         /*
 1926          *      Rather than modify the entry to make such entries work, 
 1927          *      we reject this rule and require user level utilities
 1928          *      to enforce whatever policy they deem appropriate.
 1929          */
 1930         if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) || 
 1931                 (frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) {
 1932                 dprintf(("%s rule never matches\n", err_prefix));
 1933                 return (EINVAL);
 1934         }
 1935 
 1936         if ((frwl->fw_flg & IP_FW_F_FRAG) &&
 1937                 (frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {
 1938                 if (IP_FW_HAVEPORTS(frwl)) {
 1939                         dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));
 1940                         return (EINVAL);
 1941                 }
 1942                 if (frwl->fw_prot == IPPROTO_TCP &&
 1943                         frwl->fw_tcpf != frwl->fw_tcpnf) {
 1944                         dprintf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
 1945                         return (EINVAL);
 1946                 }
 1947         }
 1948 
 1949         if (frwl->fw_flg & (IP_FW_F_UID | IP_FW_F_GID)) {
 1950                 if ((frwl->fw_prot != IPPROTO_TCP) &&
 1951                    (frwl->fw_prot != IPPROTO_UDP) &&
 1952                    (frwl->fw_prot != IPPROTO_IP)) {
 1953                         dprintf(("%s cannot use uid/gid logic on non-TCP/UDP\n", err_prefix));
 1954                         return (EINVAL);
 1955                 }
 1956         }
 1957 
 1958         /* Check command specific stuff */
 1959         switch (frwl->fw_flg & IP_FW_F_COMMAND) {
 1960         case IP_FW_F_REJECT:
 1961                 if (frwl->fw_reject_code >= 0x100
 1962                     && !(frwl->fw_prot == IPPROTO_TCP
 1963                       && frwl->fw_reject_code == IP_FW_REJECT_RST)) {
 1964                         dprintf(("%s unknown reject code\n", err_prefix));
 1965                         return (EINVAL);
 1966                 }
 1967                 break;
 1968 #ifdef IPDIVERT
 1969         case IP_FW_F_DIVERT:            /* Diverting to port zero is invalid */
 1970         case IP_FW_F_TEE:
 1971 #endif
 1972         case IP_FW_F_PIPE:              /* pipe 0 is invalid */
 1973         case IP_FW_F_QUEUE:             /* queue 0 is invalid */
 1974                 if (frwl->fw_divert_port == 0) {
 1975                         dprintf(("%s 0 is an invalid argument\n", err_prefix));
 1976                         return (EINVAL);
 1977                 }
 1978                 break;
 1979         case IP_FW_F_DENY:
 1980         case IP_FW_F_ACCEPT:
 1981         case IP_FW_F_COUNT:
 1982         case IP_FW_F_SKIPTO:
 1983         case IP_FW_F_FWD:
 1984                 break;
 1985         default:
 1986                 dprintf(("%s invalid command\n", err_prefix));
 1987                 return (EINVAL);
 1988         }
 1989 
 1990         return 0;
 1991 }
 1992 
 1993 static int
 1994 ip_fw_ctl(struct sockopt *sopt)
 1995 {
 1996         int error, s;
 1997         size_t size;
 1998         struct ip_fw *fcp;
 1999         struct ip_fw frwl, *bp , *buf;
 2000 
 2001         /*
 2002          * Disallow modifications in really-really secure mode, but still allow
 2003          * the logging counters to be reset.
 2004          */
 2005         if (sopt->sopt_name == IP_FW_ADD ||
 2006             (sopt->sopt_dir == SOPT_SET && sopt->sopt_name != IP_FW_RESETLOG)) {
 2007                 error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
 2008                 if (error)
 2009                         return (error);
 2010         }
 2011 
 2012         error = 0;
 2013 
 2014         switch (sopt->sopt_name) {
 2015         case IP_FW_GET:
 2016                 /*
 2017                  * pass up a copy of the current rules. Static rules
 2018                  * come first (the last of which has number 65535),
 2019                  * followed by a possibly empty list of dynamic rule.
 2020                  * The last dynamic rule has NULL in the "next" field.
 2021                  */
 2022                 s = splimp();
 2023                 /* size of static rules */
 2024                 size = static_count * sizeof(struct ip_fw) ;
 2025                 if (ipfw_dyn_v)         /* add size of dyn.rules */
 2026                     size += (dyn_count * sizeof(struct ipfw_dyn_rule));
 2027 
 2028                 /*
 2029                  * XXX todo: if the user passes a short length to know how
 2030                  * much room is needed, do not
 2031                  * bother filling up the buffer, just jump to the
 2032                  * sooptcopyout.
 2033                  */
 2034                 buf = malloc(size, M_TEMP, M_WAITOK);
 2035                 if (buf == 0) {
 2036                     splx(s);
 2037                     error = ENOBUFS;
 2038                     break;
 2039                 }
 2040 
 2041                 bp = buf ;
 2042                 LIST_FOREACH(fcp, &ip_fw_chain_head, next) {
 2043                     bcopy(fcp, bp, sizeof *fcp);
 2044                     bp++;
 2045                 }
 2046                 if (ipfw_dyn_v) {
 2047                     int i ;
 2048                     struct ipfw_dyn_rule *p, *dst, *last = NULL ;
 2049 
 2050                     dst = (struct ipfw_dyn_rule *)bp ;
 2051                     for (i = 0 ; i < curr_dyn_buckets ; i++ )
 2052                         for ( p = ipfw_dyn_v[i] ; p != NULL ; p = p->next, dst++ ) {
 2053                             bcopy(p, dst, sizeof *p);
 2054                             (int)dst->rule = p->rule->fw_number ;
 2055                             /*
 2056                              * store a non-null value in "next". The userland
 2057                              * code will interpret a NULL here as a marker
 2058                              * for the last dynamic rule.
 2059                              */
 2060                             dst->next = dst ;
 2061                             last = dst ;
 2062                             if (TIME_LEQ(dst->expire, time_second) )
 2063                                 dst->expire = 0 ;
 2064                             else
 2065                                 dst->expire -= time_second ;
 2066                             }
 2067                     if (last != NULL)
 2068                         last->next = NULL ;     /* mark last dynamic rule */
 2069                 }
 2070                 splx(s);
 2071 
 2072                 error = sooptcopyout(sopt, buf, size);
 2073                 free(buf, M_TEMP);
 2074                 break;
 2075 
 2076         case IP_FW_FLUSH:
 2077                 /*
 2078                  * Normally we cannot release the lock on each iteration.
 2079                  * We could do it here only because we start from the head all
 2080                  * the times so there is no risk of missing some entries.
 2081                  * On the other hand, the risk is that we end up with
 2082                  * a very inconsistent ruleset, so better keep the lock
 2083                  * around the whole cycle.
 2084                  * 
 2085                  * XXX this code can be improved by resetting the head of
 2086                  * the list to point to the default rule, and then freeing
 2087                  * the old list without the need for a lock.
 2088                  */
 2089 
 2090                 s = splimp();
 2091                 while ( (fcp = LIST_FIRST(&ip_fw_chain_head)) &&
 2092                         fcp->fw_number != IPFW_DEFAULT_RULE )
 2093                     free_chain(fcp);
 2094                 splx(s);
 2095                 break;
 2096 
 2097         case IP_FW_ADD:
 2098                 error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
 2099                 if (error || (error = check_ipfw_struct(&frwl)))
 2100                         break;
 2101 
 2102                 if (frwl.fw_number == IPFW_DEFAULT_RULE) {
 2103                         dprintf(("%s can't add rule %u\n", err_prefix,
 2104                                  (unsigned)IPFW_DEFAULT_RULE));
 2105                         error = EINVAL;
 2106                 } else {
 2107                         error = add_entry(&ip_fw_chain_head, &frwl);
 2108                         if (!error && sopt->sopt_dir == SOPT_GET)
 2109                                 error = sooptcopyout(sopt, &frwl, sizeof frwl);
 2110                 }
 2111                 break;
 2112 
 2113         case IP_FW_DEL:
 2114                 error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
 2115                 if (error)
 2116                         break;
 2117 
 2118                 if (frwl.fw_number == IPFW_DEFAULT_RULE) {
 2119                         dprintf(("%s can't delete rule %u\n", err_prefix,
 2120                                  (unsigned)IPFW_DEFAULT_RULE));
 2121                         error = EINVAL;
 2122                 } else {
 2123                         error = del_entry(&ip_fw_chain_head, frwl.fw_number);
 2124                 }
 2125                 break;
 2126 
 2127         case IP_FW_ZERO:
 2128         case IP_FW_RESETLOG:
 2129             {
 2130                 int cmd = (sopt->sopt_name == IP_FW_RESETLOG );
 2131                 void *arg = NULL ;
 2132 
 2133                 if (sopt->sopt_val != 0) {
 2134                     error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
 2135                     if (error)
 2136                         break;
 2137                     arg = &frwl ;
 2138                 }
 2139                 error = zero_entry(arg, cmd);
 2140             }
 2141             break;
 2142 
 2143         default:
 2144                 printf("ip_fw_ctl invalid option %d\n", sopt->sopt_name);
 2145                 error = EINVAL ;
 2146         }
 2147 
 2148         return (error);
 2149 }
 2150 
 2151 /**
 2152  * dummynet needs a reference to the default rule, because rules can
 2153  * be deleted while packets hold a reference to them (e.g. to resume
 2154  * processing at the next rule). When this happens, dummynet changes
 2155  * the reference to the default rule (probably it could well be a
 2156  * NULL pointer, but this way we do not need to check for the special
 2157  * case, plus here he have info on the default behaviour.
 2158  */
 2159 struct ip_fw *ip_fw_default_rule ;
 2160 
 2161 void
 2162 ip_fw_init(void)
 2163 {
 2164         struct ip_fw default_rule;
 2165 
 2166         ip_fw_chk_ptr = ip_fw_chk;
 2167         ip_fw_ctl_ptr = ip_fw_ctl;
 2168         LIST_INIT(&ip_fw_chain_head);
 2169 
 2170         bzero(&default_rule, sizeof default_rule);
 2171         default_rule.fw_prot = IPPROTO_IP;
 2172         default_rule.fw_number = IPFW_DEFAULT_RULE;
 2173 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
 2174         default_rule.fw_flg |= IP_FW_F_ACCEPT;
 2175 #else
 2176         default_rule.fw_flg |= IP_FW_F_DENY;
 2177 #endif
 2178         default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;
 2179         if (check_ipfw_struct(&default_rule) != 0 ||
 2180             add_entry(&ip_fw_chain_head, &default_rule))
 2181                 panic("ip_fw_init");
 2182 
 2183         ip_fw_default_rule = LIST_FIRST(&ip_fw_chain_head) ;
 2184         printf("IP packet filtering initialized, "
 2185 #ifdef IPDIVERT
 2186                 "divert enabled, "
 2187 #else
 2188                 "divert disabled, "
 2189 #endif
 2190                 "rule-based forwarding enabled, "
 2191 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
 2192                 "default to accept, ");
 2193 #else
 2194                 "default to deny, " );
 2195 #endif
 2196 #ifndef IPFIREWALL_VERBOSE
 2197         printf("logging disabled\n");
 2198 #else
 2199         if (fw_verbose_limit == 0)
 2200                 printf("unlimited logging\n");
 2201         else
 2202                 printf("logging limited to %d packets/entry by default\n",
 2203                     fw_verbose_limit);
 2204 #endif
 2205 }
 2206 
 2207 static int
 2208 ipfw_modevent(module_t mod, int type, void *unused)
 2209 {
 2210         int s;
 2211         int err = 0 ;
 2212 #if defined(KLD_MODULE)
 2213         struct ip_fw *fcp;
 2214 #endif
 2215         
 2216         switch (type) {
 2217         case MOD_LOAD:
 2218                 s = splimp();
 2219                 if (IPFW_LOADED) {
 2220                         splx(s);
 2221                         printf("IP firewall already loaded\n");
 2222                         err = EEXIST ;
 2223                 } else {
 2224                         ip_fw_init();
 2225                         splx(s);
 2226                 }
 2227                 break ;
 2228         case MOD_UNLOAD:
 2229 #if !defined(KLD_MODULE)
 2230                 printf("ipfw statically compiled, cannot unload\n");
 2231                 err = EBUSY;
 2232 #else
 2233                 s = splimp();
 2234                 ip_fw_chk_ptr = NULL ;
 2235                 ip_fw_ctl_ptr = NULL ;
 2236                 while ( (fcp = LIST_FIRST(&ip_fw_chain_head)) != NULL)
 2237                     free_chain(fcp);
 2238                 splx(s);
 2239                 printf("IP firewall unloaded\n");
 2240 #endif
 2241                 break;
 2242         default:
 2243                 break;
 2244         }
 2245         return err;
 2246 }
 2247 
 2248 static moduledata_t ipfwmod = {
 2249         "ipfw",
 2250         ipfw_modevent,
 2251         0
 2252 };
 2253 DECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
 2254 MODULE_VERSION(ipfw, 1);

Cache object: 8173a8e57876cc175d7e69dbf1fd2ce0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.