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

Cache object: 0614e7e46e64e6533743d87e888e1535


[ 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.