Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

inline.c

Go to the documentation of this file.
00001 // $Id$
00002 #ifdef GIDS
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <pcap.h>
00006 #include <dnet.h>
00007 
00008 #include "snort.h"
00009 #include "decode.h"
00010 #include "inline.h"
00011 #include "rules.h"
00012 #include "checksum.h"
00013 #include "bounds.h"
00014 #include "util.h"
00015 #include "mstring.h"
00016 #include "stream.h"
00017 #define PKT_BUFSIZE 70000
00018 
00019 /* Most of the code related to libdnet (resets and icmp unreach) was
00020  * taken from sp_respond2.c, actually Jeff Nathan did all of the hard work
00021  * We just stole it to create respond2 for dummies via RejectFu*/
00022 
00023 /* vars */
00024 ip_t *rawdev;                       /* dnet(3) raw IP handle */
00025 eth_t *ethdev;                      /* dnet(3) ethernet device handle */
00026 rand_t *randh;                      /* dnet(3) rand handle */
00027 
00028 static void *tcp_pkt = NULL;            /* TCP packet memory placeholder */
00029 static void *icmp_pkt = NULL;           /* ICMP packet memory placeholder */
00030 
00031 static u_int8_t link_offset;            /* offset from L2 to L3 header */
00032 static u_int8_t alignment;              /* force alignment ?? */
00033 
00034 static INLINE u_int8_t CalcOriginalTTL(Packet *p);
00035 Packet *tmpP;
00036 extern Stream4Data s4data;
00037 
00038 #ifdef NFNETLINKQ
00039 
00040 /* Oct. 3, 2005 -  Per the GPL (2.0), this code has been modified by NitroSecurity,
00041 and in keeping with the GPL, NitroSecurity releases these changes under version 2
00042 of the GPL. Also, as per version 2 of the GPL, there is no expressed or implied warranty.
00043 If this code decides to have your computer for lunch, it's your problem, not ours.
00044 This code is in working development, and as such is unsuitable for most anything.
00045 NitroSecurity - Dave Remien */
00046 
00047 /* Since nfnetlink_queue can't deliver an ipq_packet_msg to us,
00048 just most of the pieces/parts, we'll build an ipq_packet_msg on
00049 the fly from the parts we got. Ugly, as Harald himself says in the libipq emulation.
00050 DAR - 050916
00051 
00052 Just to note this - Harald Welte has called for the ip_queue stuff to disappear in
00053 the future - see http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.14
00054 */
00055 
00056 
00057 struct my_ipq_packet_msg {
00058         unsigned long packet_id;        /* ID of queued packet */
00059         unsigned long mark;             /* Netfilter mark value */
00060         long timestamp_sec;             /* Packet arrival time (seconds) */
00061         long timestamp_usec;            /* Packet arrvial time (+useconds) */
00062         unsigned int hook;              /* Netfilter hook we rode in on */
00063         char indev_name[IFNAMSIZ];      /* Name of incoming interface */
00064         char outdev_name[IFNAMSIZ];     /* Name of outgoing interface */
00065         unsigned short hw_protocol;     /* Hardware protocol (network order) */
00066         unsigned short hw_type;         /* Hardware type */
00067         unsigned char hw_addrlen;       /* Hardware address length */
00068         unsigned char hw_addr[8];       /* Hardware address */
00069         size_t data_len;                /* Length of packet data */
00070         unsigned char payload[PKT_BUFSIZE];    /* Optional packet data */
00071 }  ipq_pkt;
00072 unsigned char buf[PKT_BUFSIZE];
00073 unsigned int glid;
00074 char ifnames[32][IF_NAMESIZE];
00075 int nl_fd, rv;
00076 struct nfq_handle *nfqh;
00077 struct nfq_q_handle *qhndl;
00078 struct nfnl_handle *nh;
00079 int rcvstatus, done;
00080 
00081 #endif /* NFNETLINKQ */
00082 
00083 #ifndef IPFW
00084 ipq_packet_msg_t *g_m = NULL;
00085 #endif
00086 
00087 /* predeclarations */
00088 #ifndef IPFW
00089 void HandlePacket(ipq_packet_msg_t *);
00090 void TranslateToPcap(ipq_packet_msg_t *, struct pcap_pkthdr *);
00091 #else
00092 void HandlePacket();
00093 void TranslateToPcap(struct pcap_pkthdr *phdr, ssize_t len);
00094 #endif /* IPFW */
00095 void ResetIV(void);
00096 
00097 
00098 /**
00099  *  InlineMode - determine if we are in inline mode
00100  *  
00101  *  @returns 1 if we are in inline mode, 0 otherwise
00102  */
00103 int InlineMode()
00104 {
00105         if (pv.inline_flag)
00106                 return 1;
00107 
00108         return 0;
00109 }
00110 
00111 
00112 #ifndef IPFW
00113 void TranslateToPcap(ipq_packet_msg_t *m, struct pcap_pkthdr *phdr)
00114 {
00115     static struct timeval t;
00116     if (!m->timestamp_sec) 
00117     {
00118         memset (&t, 0, sizeof(struct timeval));
00119         gettimeofday(&t, NULL);
00120         phdr->ts.tv_sec = t.tv_sec;
00121         phdr->ts.tv_usec = t.tv_usec;
00122     }
00123     else 
00124     {
00125         phdr->ts.tv_sec = m->timestamp_sec;
00126         phdr->ts.tv_usec = m->timestamp_usec;
00127     }
00128     phdr->caplen = m->data_len;
00129     phdr->len = m->data_len;
00130 }
00131 #else
00132 void TranslateToPcap(struct pcap_pkthdr *phdr, ssize_t len)
00133 {
00134     static struct timeval t;
00135     memset (&t, 0, sizeof(struct timeval));
00136     gettimeofday(&t, NULL);
00137     phdr->ts.tv_sec = t.tv_sec;
00138     phdr->ts.tv_usec = t.tv_usec;
00139     phdr->caplen = len;
00140     phdr->len = len;
00141 
00142 }
00143 #endif
00144 
00145 static INLINE u_int8_t CalcOriginalTTL(Packet *p)
00146 {        
00147     switch (tmpP->iph->ip_ttl / 64)
00148     {
00149         case 3:              
00150             return 255;
00151         case 2:
00152             return 192;
00153         case 1:
00154             return 128;
00155         default:
00156             return 64;
00157     }
00158 }
00159 
00160 void RejectFuRestart()
00161 {
00162 
00163     /* device and raw IP handles */                 
00164     if (rawdev != NULL)
00165         rawdev = ip_close(rawdev);
00166     if (ethdev != NULL)
00167         ethdev = eth_close(ethdev);
00168 
00169     /* free packet memory */
00170 
00171     if (tcp_pkt != NULL)
00172     {
00173         tcp_pkt -= alignment;      
00174         free(tcp_pkt);
00175         tcp_pkt = NULL;
00176     }
00177     if (icmp_pkt != NULL)
00178     {
00179         icmp_pkt -= alignment;
00180         free(icmp_pkt);
00181         icmp_pkt = NULL;
00182     }
00183 
00184     /* Close random handle */
00185     if (randh != NULL)
00186         randh = rand_close(randh);
00187 
00188     return;
00189 }
00190 
00191 void ResetIV()
00192 {
00193     iv.drop = 0;
00194     iv.rejectsrc = 0;
00195     iv.rejectdst = 0;
00196     iv.reinject = 0;
00197     iv.replace = 0;
00198 }
00199 
00200 
00201 /*
00202  *    Function: void InitInlinePostConfig
00203  *
00204  *    Purpose: perform initialization tasks that depend on the configfile
00205  *
00206  *    Args: none
00207  *    
00208  *    Returns: nothing void function
00209  */
00210 void InitInlinePostConfig(void)
00211 {
00212 
00213     printf("InitInline stage 2: InitInlinePostConfig starting...\n");
00214 
00215     /* Let's initialize dnet set the size of the tcp/icmp packets and
00216      * allocate memory for the data.
00217      */  
00218 #ifndef IPFW
00219     if(pv.layer2_resets)
00220     {
00221         link_offset = ETH_HDR_LEN;
00222         alignment = 2;
00223         if ((randh = rand_open()) == NULL)
00224         {
00225             printf("could no open random handle\n");
00226         }
00227 
00228     }
00229     else
00230     {
00231 #ifdef DEBUG_GIDS
00232         printf("opening raw socket in IP-mode\n");
00233 #endif
00234         link_offset = 0;
00235         alignment = 0;
00236         
00237         if ((rawdev = ip_open()) == NULL)
00238         {
00239            printf("InitInline: Unable to open raw socket for dnet.\n");
00240         }
00241  
00242     }
00243 #else
00244         link_offset = 0;
00245         alignment = 0;
00246 
00247         if ((rawdev = ip_open()) == NULL)
00248         {
00249            printf("InitInline: Unable to open raw socket for dnet.\n");
00250         }
00251 
00252 #endif    
00253     tcp_pkt = SnortAlloc(alignment + link_offset + IP_HDR_LEN + TCP_HDR_LEN);
00254     tcp_pkt += alignment;
00255     icmp_pkt = SnortAlloc(alignment + link_offset + IP_HDR_LEN + ICMP_LEN_MIN + 68);
00256     icmp_pkt += alignment;
00257 }
00258 
00259 #ifdef NFNETLINKQ
00260 
00261 /*
00262  * This "cb" routine is a callback function, which is called from the netlink_queue
00263  * code to get the various parts of the packet from the skbuff needed in user space.
00264  * It's based on code found in utils/nfqnl_test.c, from the libnetfilter_queue tar ball.
00265  * I liked the name xyzzy, from Adventure, just to see if any oldtimers recognized it,
00266  * but it probably should be "callback" or "cb".
00267  */ 
00268   
00269 static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
00270               struct nfq_data *nfa, void *data)
00271 {  
00272    int iret;
00273    u_int32_t ifi;
00274    char *junkdata;
00275    struct nfqnl_msg_packet_timestamp ts;
00276 
00277    ipq_pkt.data_len = nfq_get_payload(nfa, &junkdata);
00278 
00279    memcpy(ipq_pkt.payload, junkdata, ipq_pkt.data_len);
00280       
00281    struct nfqnl_msg_packet_hdr *ph =
00282                    nfq_get_msg_packet_hdr(nfa);
00283    glid = ntohl(ph->packet_id);
00284    ipq_pkt.packet_id = glid;
00285    ipq_pkt.hw_protocol = ntohs(ph->hw_protocol);
00286    ipq_pkt.hook = ph->hook;
00287    ipq_pkt.mark = nfq_get_nfmark(nfa);
00288 
00289    ifi = nfq_get_indev(nfa);
00290    strncpy(ipq_pkt.indev_name, ifnames[ifi], 16);
00291 
00292    ifi = nfq_get_outdev(nfa);
00293    strncpy(ipq_pkt.outdev_name, ifnames[ifi], 16);
00294 
00295 
00296    struct nfqnl_msg_packet_hw *hw = nfq_get_packet_hw(nfa);
00297    if(hw){
00298        ipq_pkt.hw_addrlen = ntohs(hw->hw_addrlen);
00299        //memcpy(ipq_pkt.hw_addr, hw->hw_addr,  sizeof(ipq_pkt.hw_addr));
00300        memcpy(ipq_pkt.hw_addr, hw->hw_addr,  ipq_pkt.hw_addrlen);
00301    }
00302 
00303    iret = nfq_get_timestamp(nfa, &ts);
00304    if(iret){
00305        ipq_pkt.timestamp_sec = (long)(ts.sec);
00306        ipq_pkt.timestamp_usec = (long)(ts.usec);
00307    }
00308 
00309    return(0);
00310 }
00311 
00312 #endif /* NFNETLINKQ */
00313 
00314 
00315 /* InitInline is called before the Snort_inline configuration file is read. */
00316 int InitInline()
00317 {
00318 #ifndef IPFW
00319     int status;
00320 #endif
00321 
00322 #ifdef DEBUG_GIDS
00323     printf("Initializing Inline mode \n");
00324 #endif
00325 
00326     printf("Initializing Inline mode \n");
00327 
00328 #ifndef IPFW
00329 
00330 #ifdef NFNETLINKQ
00331    /* Get interface names as strings; only the numbers are in the skbuff */
00332 
00333      struct if_nameindex *if_nameindex(void);
00334      struct if_nameindex *blah;
00335      int i,j;
00336 
00337      for (j = 0; j < 32; j++)
00338         for(i = 0; i < IF_NAMESIZE; i++)ifnames[j][i] = 0;
00339 
00340      blah = if_nameindex();
00341      for(i = 0; i < 32; i++){
00342 
00343         if(blah[i].if_index == 0)break;
00344         strlcpy(ifnames[blah[i].if_index], blah[i].if_name, IF_NAMESIZE);
00345 
00346      }
00347      if_freenameindex(blah);
00348 #else
00349 
00350     ipqh = ipq_create_handle(0, PF_INET);
00351     if (!ipqh)
00352     {
00353         ipq_perror("InlineInit: ");
00354         ipq_destroy_handle(ipqh);
00355         exit(1);
00356     }
00357  
00358     status = ipq_set_mode(ipqh, IPQ_COPY_PACKET, PKT_BUFSIZE);
00359     if (status < 0)
00360     {
00361         ipq_perror("InitInline: ");
00362         ipq_destroy_handle(ipqh);
00363         exit(1);
00364     }
00365 
00366 /*
00367  * netlink_queue initialization moved into beginning of NfnetlinkQLoop() - DAR
00368  */
00369 
00370 #endif /* NFNETLINKQ */
00371 #endif /* IPFW */
00372 
00373     ResetIV();
00374 
00375     /* Just in case someone wants to write to a pcap file
00376      * using DLT_RAW because iptables does not give us datalink layer.
00377      */
00378     pd = pcap_open_dead(DLT_RAW, SNAPLEN);
00379 
00380     return 0;
00381 }
00382 
00383 #ifndef IPFW
00384 #ifndef NFNETLINKQ
00385 void IpqLoop()
00386 {
00387     int status = 0;
00388     struct pcap_pkthdr PHdr;
00389     unsigned char buf[PKT_BUFSIZE];
00390     static ipq_packet_msg_t *m;
00391 
00392 #ifdef DEBUG_GIDS
00393     printf("Reading Packets from ipq handle \n");
00394 #endif
00395 
00396 
00397     while(1)
00398     {
00399         ResetIV();
00400         status = ipq_read(ipqh, buf, PKT_BUFSIZE, 0);
00401         if (status < 0)
00402         {
00403             ipq_perror("IpqLoop: ");
00404         }
00405         else
00406         {
00407             switch(ipq_message_type(buf))
00408             {
00409                 case NLMSG_ERROR:
00410                     fprintf(stderr, "Received error message %d\n", 
00411                             ipq_get_msgerr(buf));
00412                     break;
00413 
00414                 case IPQM_PACKET: 
00415                     m = ipq_get_packet(buf);
00416                     g_m = m;
00417 #ifdef DEBUG_INLINE
00418                     printf("%02X:%02X:%02X:%02X:%02X:%02X\n", m->hw_addr[0], m->hw_addr[1],
00419                            m->hw_addr[2], m->hw_addr[3], m->hw_addr[4], m->hw_addr[5]);
00420 #endif              
00421 
00422                     TranslateToPcap(m, &PHdr);
00423                     PcapProcessPacket(NULL, &PHdr, (u_char *)m->payload);
00424                     HandlePacket(m);
00425                     break;
00426             } /* switch */
00427         } /* if - else */
00428     } /* while() */
00429 }
00430 #endif /* NFNETLINKQ */
00431 #endif /* IPFW */
00432 
00433 
00434 #ifndef IPFW
00435 #ifdef NFNETLINKQ
00436 void NfnetlinkQLoop()
00437 {
00438     int status = 0;
00439     struct pcap_pkthdr PHdr;
00440     static ipq_packet_msg_t *m;
00441 
00442 
00443 #ifdef DEBUG_GIDS
00444     printf("Reading Packets from ipq handle \n");
00445 #endif
00446 
00447     m = &ipq_pkt;
00448     g_m = m;
00449 
00450     /* The following sequence was "borrowed" from Harald Welte's 
00451      * utils/nfqnl_test.c, same as the callback routine - 
00452      * which is setup in the nfq_create_queue() call below.
00453      */
00454 
00455     nfqh = nfq_open();
00456     if (!nfqh) {
00457          printf("[%d] error during nfq_open()\n",getpid());
00458             exit(1);
00459     }
00460 
00461     if (nfq_unbind_pf(nfqh, AF_INET) < 0) {
00462             printf("[%d] error during nfq_unbind_pf()\n",getpid());
00463             exit(1);
00464     }
00465 
00466     if (nfq_bind_pf(nfqh, AF_INET) < 0) {
00467             printf("[%d] error during nfq_bind_pf()\n",getpid());
00468             exit(1);
00469     }
00470 
00471     qhndl = nfq_create_queue(nfqh, nfqueue_num, &cb, NULL);
00472     if (!qhndl) {
00473             printf("[%d] error during nfq_create_queue() (queue %d busy ?)\n",
00474             getpid(),nfqueue_num);
00475        exit(1);
00476     }
00477 
00478     if (nfq_set_mode(qhndl, NFQNL_COPY_PACKET, 0xffff) < 0) {
00479             printf("[%d] can't set packet_copy mode\n",getpid());
00480        exit(1);
00481     }
00482 
00483     nh = nfq_nfnlh(nfqh);
00484     nl_fd = nfnl_fd(nh);
00485 
00486     /* The following loop basically gets executed forever, or until
00487      * snort blows or gets signalled to exit. As with libipq, 
00488      * netlink_queue requires that every single packet asked for
00489      * from the queue be acknowledged. A future enhancement
00490      * might be to ask for multiple packets at once, then
00491      * either ack them individually as processed (to reduce latency),
00492      * or possibly all-at-once, in the hope of reducing the user-space
00493      * to kernel overhead time and increasing throughput. The underlying
00494      * nfnetlink code can already deal with multiple packets, so this
00495      * might not be too painful to do. Another simplification might be to
00496      * build the packet as a pcap packet directly, avoiding the ipq
00497      * emulation; and subsequent "TranslateToPcap(). So far, though,
00498      * profiling seems to indicate that the things snort is doing with the 
00499      * packet take the vast majority of CPU cycles. 
00500      */
00501 
00502     while(1)
00503     {
00504         done = 0;
00505         ResetIV();
00506 
00507         /* zero the the buffer, just to be on the safe side.
00508          * Pretty sure this isn't needed. */
00509         memset(buf, 0, sizeof(buf));
00510         rcvstatus = recv(nl_fd, buf, PKT_BUFSIZE, 0);
00511         //printf("recvd %i bytes glid = %u\n", rcvstatus, glid);
00512         if (rcvstatus < 0)
00513         {
00514             printf("[%d] packet recv contents failure\n",getpid());
00515         }
00516         else
00517         {
00518             TranslateToPcap(m, &PHdr);
00519             ProcessPacket(NULL, &PHdr, (u_char *)m->payload, NULL);
00520             HandlePacket(m);
00521             if(!done){
00522                status = nfq_set_verdict(qhndl, glid, NF_ACCEPT, 0, NULL);
00523                if (status < 0)
00524                {  
00525                   fprintf(stderr,"NF_ACCEPT: ");
00526                }
00527                nfq_handle_packet(nfqh, buf, rcvstatus);
00528             }
00529         } /* if - else */
00530 
00531     } /* while() */
00532 }
00533 #endif /* NFNETLINKQ */
00534 #endif /* IPFW */
00535 
00536 
00537 #ifdef IPFW
00538 /* Loop reading packets from IPFW
00539    - borrowed mostly from the TCP-MSSD daemon in FreeBSD ports tree
00540     Questions, comments send to:  nick@rogness.net
00541 */
00542 void IpfwLoop()
00543 {
00544     char pkt[IP_MAXPACKET];
00545     struct pcap_pkthdr PHdr;
00546     ssize_t pktlen; 
00547     struct sockaddr_in sin;
00548     socklen_t sinlen;
00549     int rtsock;
00550     int ifindex;
00551     fd_set fdset;
00552     ifindex = 0;
00553     rtsock = -1;
00554 
00555 #ifdef DEBUG_GIDS
00556     printf("Reading Packets from ipfw divert socket \n");
00557 #endif
00558 
00559     /* Build divert socket */
00560     if ((divert_socket = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT)) == -1) 
00561     {
00562         perror("IpfwLoop: can't create divert socket");
00563         exit(-1);
00564     }
00565 
00566     /* Fill in necessary fields */
00567     bzero(&sin, sizeof(sin));
00568     sin.sin_family = PF_INET;
00569     sin.sin_addr.s_addr = INADDR_ANY;
00570     sin.sin_port = htons(pv.divert_port);
00571 
00572     /* Bind that biatch */
00573     if (bind(divert_socket, (struct sockaddr *)&sin, sizeof(sin)) == -1) 
00574     {
00575         perror("IpfwLoop: can't bind divert socket");
00576         exit(-1);
00577     }
00578 
00579     /* Lets process the packet */
00580     while (1) 
00581     {
00582         ResetIV();
00583         FD_ZERO(&fdset);
00584         FD_SET(divert_socket, &fdset);
00585         if (rtsock != -1)
00586         {
00587             FD_SET(rtsock, &fdset);
00588         }
00589 
00590         if (select(32, &fdset, (fd_set *)NULL, (fd_set *)NULL, (struct timeval *)NULL) == -1)
00591         {
00592             printf("select failed");
00593             continue;
00594         }
00595 
00596         if (FD_ISSET(divert_socket, &fdset)) 
00597         {
00598             sinlen = sizeof(sin);
00599 
00600             if ((pktlen = recvfrom(divert_socket, pkt, sizeof(pkt), 0,(struct sockaddr *)&sin, &sinlen)) == -1)
00601             {
00602                 if (errno != EINTR)
00603                 {
00604                      printf("IpfwLoop: read from divert socket failed");
00605                      continue;
00606                 }
00607             }
00608 
00609             TranslateToPcap(&PHdr,pktlen);
00610             PcapProcessPacket(NULL, &PHdr, pkt);
00611             HandlePacket();
00612 
00613             /* If we don't drop and don't reject, reinject it back into ipfw,
00614              * otherwise, we just drop it
00615             */
00616             if (! iv.drop && ! iv.rejectsrc)
00617             {
00618                 if (iv.reinject) 
00619                 {
00620                     if (pv.ipfw_reinject_rule)
00621                     {
00622                         if (pv.ipfw_reinject_rule < sin.sin_port)
00623                         {
00624                             printf("IpfwLoop: reinjection loop: start=%d,end=%d\n",sin.sin_port,pv.ipfw_reinject_rule);
00625                             continue;
00626                         }
00627                     
00628                         sin.sin_port=pv.ipfw_reinject_rule;
00629                     }
00630                 }
00631 
00632                 if (sendto(divert_socket, pkt, pktlen, 0,(struct sockaddr *)&sin, sinlen) == -1)
00633                 {
00634                     printf("IpfwLoop: write to divert socket failed");
00635                 }
00636             }
00637          } /* end if */
00638 
00639     } /* end while */
00640 }
00641 #endif
00642 
00643 /*
00644  *    Function: static void RejectFu(ipq_packet_msg_t *m)
00645  *
00646  *    Purpose: send a reject packet (tcp-reset or icmp-unreachable)
00647  *
00648  *    Args: the ipq_packet_msg_t m for determining the output interface
00649  *          and the source mac for our packet.
00650  *    
00651  *    Returns: nothing void function
00652  *
00653  *    TODO: make it also work on *BSD.
00654  */
00655 #ifndef IPFW
00656 static void
00657 RejectFu(ipq_packet_msg_t *m, int mode)
00658 #else 
00659 static void
00660 RejectFu(int mode)
00661 #endif
00662 {
00663     if(tmpP->iph == NULL)return;
00664     int proto = tmpP->iph->ip_proto;
00665     int noreverse = 0;
00666     IPHdr *iph;
00667 #ifndef IPFW
00668     int i = 0;
00669     char **macbytes;
00670     int num_macbytes;
00671     EtherHdr *eh;
00672 
00673 #endif /* IPFW */
00674 
00675     if(mode == 1)
00676     {
00677       noreverse = 1;
00678     }
00679 #ifndef IPFW         
00680     char *device; /*int name for eth_open*/           
00681     eth_addr_t srclinkaddr; /*used to get mac address for layer2*/
00682     u_char enet_src[6]; /* mac addr for creating the ethernet packet. */
00683 
00684     if(s4data.stream4inline_mode && opdsize)
00685     {
00686         tmpP->dsize = opdsize;
00687     } 
00688     if(link_offset) 
00689     {
00690         /* we can't get the proper dst mac address for a non reversed reset */
00691        
00692         if(noreverse)
00693         {
00694             printf("layer2 resets don't work for non reversed packets\n");
00695             return;
00696         }
00697 
00698         /* read int name from iptables, indev and outdev are the same in bridge mode */
00699         if(m->indev_name[0] != '\0') 
00700            device = m->indev_name;
00701         else
00702            device = m->outdev_name;
00703                    
00704         if ((ethdev = eth_open(device)) != NULL) 
00705         {
00706           if (eth_get(ethdev, &srclinkaddr)< 0)
00707           {
00708 #ifdef DEBUG_GIDS
00709             printf("failed to get macaddy\n");
00710 #endif
00711           }
00712           else
00713           {
00714 #ifdef DEBUG_GIDS
00715             printf("mac addy of src int is %s\n",eth_ntoa(&srclinkaddr));
00716 #endif
00717           }
00718         }
00719 
00720         /* copy the mac out of the snort.conf
00721          * but only if the mac wasn't supplied in the configfile */
00722          if(pv.enet_src[0] == 0 && pv.enet_src[1] == 0 && pv.enet_src[2] == 0 && pv.enet_src[3] == 0 && pv.enet_src[4] == 0 && pv.enet_src[5] == 0)
00723          {
00724              /* mac is blank or user set 00:00:00:00:00, let's set it */
00725              macbytes = mSplit(eth_ntoa(&srclinkaddr), ":", 6, &num_macbytes, '\\');
00726          
00727              if (num_macbytes < 6)
00728              {
00729 #ifdef DEBUG_GIDS
00730                  printf("That is one crazy mac addy");
00731 #endif
00732              }
00733              else
00734              {
00735                  for (i = 0; i < 6; i++)
00736                  enet_src[i] = (u_int8_t) strtoul(macbytes[i], NULL, 16);
00737              }
00738              mSplitFree(&macbytes, num_macbytes);
00739          }
00740          else
00741          {
00742                for(i = 0; i < 6; i++)
00743                  enet_src[i] = pv.enet_src[i];
00744   
00745          }
00746       
00747     }
00748 #endif /* IPFW */
00749     switch(proto)
00750     {
00751         case IPPROTO_TCP:
00752             if (!tmpP->frag_flag)
00753             {
00754                 TCPHdr *tcp;
00755                 size_t sz = IP_HDR_LEN + TCP_HDR_LEN;
00756                 ssize_t n;
00757                 u_int32_t i, ack, seq;
00758                 u_int16_t window, dsize;
00759                 iph = (IPHdr *)(tcp_pkt + link_offset);
00760                 tcp = (TCPHdr *)(tcp_pkt + IP_HDR_LEN + link_offset);
00761 #ifndef IPFW               
00762                 if(link_offset)
00763                 {
00764                    eh = (EtherHdr *)tcp_pkt;
00765                    eh->ether_type = htons(ETH_TYPE_IP);
00766                    memcpy(eh->ether_src, enet_src, 6);
00767                    memcpy(eh->ether_dst, m->hw_addr, 6);
00768                 }
00769 #endif
00770                 SET_IP_VER(iph, 4);
00771                 SET_IP_HLEN(iph, (IP_HDR_LEN >> 2));  
00772                 iph->ip_proto = IPPROTO_TCP;     
00773 
00774                 /* points to the start of the TCP header */
00775                 tcp = (TCPHdr *)(tcp_pkt + IP_HDR_LEN + link_offset);
00776                 tcp->th_flags = TH_RST|TH_ACK;
00777                 SET_TCP_OFFSET(tcp, (TCP_HDR_LEN >> 2));
00778 
00779                 /* save p->dsize */
00780                 dsize = tmpP->dsize;
00781                 if(noreverse)
00782                 {
00783                    /* Keep the source and destination IP addr for attack-response rules */
00784                    iph->ip_src.s_addr = tmpP->iph->ip_src.s_addr;
00785                    iph->ip_dst.s_addr = tmpP->iph->ip_dst.s_addr;
00786 
00787                    if(tmpP->tcph == NULL)return;
00788                    tcp->th_sport = tmpP->tcph->th_sport;
00789                    tcp->th_dport = tmpP->tcph->th_dport;
00790                    seq = ntohl(tmpP->tcph->th_seq);
00791                    ack = ntohl(tmpP->tcph->th_ack);
00792                    iph->ip_ttl = CalcOriginalTTL(tmpP);
00793                    tcp->th_win = tmpP->tcph->th_win;
00794 
00795                    /* save the window size for all calculations */
00796                    window = ntohs(tcp->th_win);
00797                 }
00798 
00799                 else 
00800                 {
00801                    /* Reverse the source and destination IP addr for attack-response rules */
00802                    iph->ip_src.s_addr = tmpP->iph->ip_dst.s_addr;
00803                    iph->ip_dst.s_addr = tmpP->iph->ip_src.s_addr;
00804                    
00805                    if(tmpP->tcph == NULL)return;
00806                    tcp->th_sport = tmpP->tcph->th_dport;
00807                    tcp->th_dport = tmpP->tcph->th_sport;
00808                    seq = ntohl(tmpP->tcph->th_ack);
00809                    ack = ntohl(tmpP->tcph->th_seq) + tmpP->dsize;
00810                    iph->ip_ttl = CalcOriginalTTL(tmpP);
00811                    tcp->th_win = tmpP->tcph->th_win;
00812 
00813                    /* save the window size for all calculations */
00814                    window = ntohs(tcp->th_win);
00815                 }
00816 
00817                 /* Master Jeff say's calculating sequence number variations is important */
00818                 for (i = 0; i < 4; i++)
00819                 {
00820                     if (link_offset)
00821                     {
00822                         iph->ip_id = rand_uint16(randh);
00823                     }
00824                     switch (i)
00825                     {
00826                         case 0:
00827                         break;
00828                       case 1:
00829                         seq += dsize;
00830                         break;
00831                       case 2:
00832                         seq += (dsize << 1);
00833                         ack += (dsize << 1);
00834                         break;
00835                       case 3:
00836                         seq += (dsize << 1);
00837                         ack += (dsize << 1);
00838                         break;
00839                       case 4:
00840                         seq += (dsize << 2);
00841                         ack += (dsize << 2);
00842                         break;
00843                       default:
00844                         seq += (window >> 1);
00845                         ack += (window >> 1);
00846                       break;
00847                    }
00848 
00849 #ifndef IPFW
00850                    tcp->th_seq = htonl(seq);
00851                    tcp->th_ack = htonl(ack);
00852 
00853 #else
00854                    /* fix resets on FreeBSD */
00855                    tcp->th_ack = htonl(ack + 1);
00856 #endif /* IPFW */
00857 
00858                    iph->ip_len = htons(sz);
00859                    ip_checksum(tcp_pkt + link_offset, sz);
00860 
00861                    /* sending the reset */
00862                    if (link_offset)
00863                       n = eth_send(ethdev, tcp_pkt, sz + link_offset);
00864                    else
00865                       n = ip_send(rawdev, tcp_pkt, sz);
00866                       
00867                    if (n < sz)
00868                        printf("failed to send reset\n");
00869                  }
00870             } /* end if !tmpP->frag_flag */
00871             break;
00872 
00873         case IPPROTO_UDP:
00874             if (!tmpP->frag_flag)
00875             {
00876                ICMPHdr *icmph;
00877                u_int16_t payload_len;
00878                size_t sz;
00879                ssize_t n;
00880 
00881                /* only send ICMP port unreachable responses for TCP and UDP */
00882                if (tmpP->iph->ip_proto == IPPROTO_ICMP && tmpP->icmph->code == ICMP_UNREACH_PORT)
00883                {
00884 #ifdef DEBUG_GIDS
00885                   printf("ignoring icmp_port set on ICMP packet.\n");
00886 #endif
00887                   return;
00888                }
00889 
00890                iph = (IPHdr *)(icmp_pkt + link_offset);
00891                icmph = (ICMPHdr *)(icmp_pkt + IP_HDR_LEN + link_offset);
00892    
00893                /* points to the start of the IP header */            
00894                iph = (IPHdr *)(icmp_pkt + link_offset);
00895                SET_IP_VER(iph, 4);
00896                SET_IP_HLEN(iph, (IP_HDR_LEN >> 2));
00897                iph->ip_proto = IPPROTO_ICMP;
00898 
00899                /* points to the start of the TCP header */
00900                icmph = (ICMPHdr *)(icmp_pkt + IP_HDR_LEN + link_offset);
00901                icmph->type = ICMP_UNREACH;
00902 
00903                if(noreverse)
00904                {
00905                   iph->ip_src.s_addr = tmpP->iph->ip_src.s_addr;
00906                   iph->ip_dst.s_addr = tmpP->iph->ip_dst.s_addr;
00907                }
00908                else
00909                {
00910                   iph->ip_src.s_addr = tmpP->iph->ip_dst.s_addr;
00911                   iph->ip_dst.s_addr = tmpP->iph->ip_src.s_addr;
00912                }
00913         
00914                iph->ip_ttl = CalcOriginalTTL(tmpP);
00915 
00916                icmph->code = ICMP_UNREACH_PORT;
00917 #ifndef IPFW
00918                if(link_offset)
00919                {
00920                   /* setup the Ethernet header */
00921                   eh = (EtherHdr *)icmp_pkt;
00922                   eh->ether_type = htons(ETH_TYPE_IP);
00923                   if(noreverse)
00924                   {
00925                      memcpy(eh->ether_src, m->hw_addr, 6);
00926                      memcpy(eh->ether_dst, enet_src, 6);
00927                   }
00928                   else
00929                   {
00930                      memcpy(eh->ether_src, enet_src, 6);
00931                      memcpy(eh->ether_dst, m->hw_addr, 6);
00932                   }
00933                   iph->ip_id = rand_uint16(randh);
00934                }
00935 #endif
00936                if ((payload_len = ntohs(tmpP->iph->ip_len) - (IP_HLEN(tmpP->iph) << 2)) > 8)
00937                     payload_len = 8;
00938 
00939                memcpy((char *)icmph + ICMP_LEN_MIN, tmpP->iph, (IP_HLEN(tmpP->iph) << 2)
00940                      + payload_len);
00941                sz = IP_HDR_LEN + ICMP_LEN_MIN + (IP_HLEN(tmpP->iph) << 2) + payload_len;
00942 
00943                iph->ip_len = htons(sz);
00944                ip_checksum(icmp_pkt + link_offset, sz);
00945                sz += link_offset;
00946              
00947                if (link_offset)
00948                   n = eth_send(ethdev, icmp_pkt, sz);
00949                else
00950                   n = ip_send(rawdev, icmp_pkt, sz);
00951  
00952                if (n < sz)
00953                   printf("failed to send icmp reset");
00954             }
00955             break;
00956     } /* end switch(proto) */
00957     if(link_offset)
00958     {
00959         eth_close(ethdev);
00960     } 
00961 }
00962 
00963 
00964 #ifndef IPFW
00965 void HandlePacket(ipq_packet_msg_t *m)
00966 #else
00967 void HandlePacket()
00968 #endif
00969 {
00970 #ifndef IPFW
00971     int status;
00972 #endif
00973     if (iv.drop)
00974     {
00975 #ifndef IPFW
00976 #ifdef NFNETLINKQ
00977         status = nfq_set_verdict(qhndl, glid, NF_DROP, 0, NULL);
00978         if (status < 0)
00979         { 
00980           fprintf(stderr,"NF_DROP: ");
00981          }
00982         //printf("handle DROP - packetid = %d\n", glid);
00983 #else
00984         status = ipq_set_verdict(ipqh, m->packet_id, NF_DROP, 0, NULL);
00985         if (status < 0)
00986         {
00987             ipq_perror("NF_DROP: ");
00988         }
00989 #endif /* NFNETLINKQ */
00990 #endif
00991         if (iv.rejectsrc)
00992         {
00993 #ifndef IPFW
00994            RejectFu(m,0);
00995 #else
00996            RejectFu(0);
00997 #endif /* IPFW */
00998         }
00999         if (iv.rejectdst)
01000         {
01001 #ifndef IPFW
01002            RejectFu(m,1);
01003 #else
01004            RejectFu(1);
01005 #endif /* IPFW */
01006         }
01007 
01008     }
01009 #ifndef IPFW
01010 
01011     else if (!iv.replace)
01012     {
01013 #ifdef NFNETLINKQ
01014       if(!done)
01015       {
01016               status = nfq_set_verdict(qhndl, glid, NF_ACCEPT, 0, NULL);
01017               if (status < 0)
01018               {
01019                 fprintf(stderr, "NF_ACCEPT: ");
01020               }
01021               //printf("handle OK - packetid = %d\n", glid);
01022       }
01023 #else
01024         status = ipq_set_verdict(ipqh, m->packet_id, NF_ACCEPT, 0, NULL);
01025         if (status < 0)
01026         {
01027             ipq_perror("NF_ACCEPT: ");
01028         }
01029 #endif /* NFNETLINKQ */
01030     }
01031     else
01032     {
01033 #ifdef NFNETLINKQ
01034       if(!done)
01035       {
01036           status = nfq_set_verdict(qhndl, glid, NF_ACCEPT, m->data_len, m->payload);
01037           if (status < 0)
01038           { 
01039              fprintf(stderr,"NF_ACCEPT: ");
01040           }
01041           nfq_handle_packet(nfqh, buf, rcvstatus);
01042           done = 1;
01043       }
01044 #else
01045         status = ipq_set_verdict(ipqh, m->packet_id, NF_ACCEPT, 
01046                  m->data_len, m->payload);
01047         if (status < 0)
01048         {
01049             ipq_perror("NF_ACCEPT: ");
01050         }
01051 #endif /* NFNETLINKQ */
01052     }
01053 #ifdef NFNETLINKQ
01054      nfq_handle_packet(nfqh, buf, rcvstatus);
01055      done = 1;
01056 #endif
01057 
01058 #endif
01059 }
01060   
01061 
01062 int InlineDrop()
01063 {
01064     iv.drop = 1;
01065     return 0;
01066 }
01067 
01068 int InlineReject(Packet *p)
01069 {
01070     iv.rejectsrc = 1;
01071     iv.drop = 1;
01072     tmpP = p;
01073     return 0;
01074 }
01075 
01076 int InlineRejectBoth(Packet *p)
01077 {
01078     iv.rejectsrc = 1;
01079     iv.rejectdst = 1;
01080     iv.drop = 1;
01081     tmpP = p;
01082     return 0;
01083 }
01084 
01085 int InlineRejectSrc(Packet *p)
01086 {
01087     iv.rejectsrc = 1;
01088     iv.drop = 1;
01089     tmpP = p;
01090     return 0;
01091 }
01092 
01093 int InlineRejectDst(Packet *p)
01094 {
01095     iv.rejectdst = 1;
01096     iv.drop = 1;
01097     tmpP = p;
01098     return 0;
01099 }
01100 
01101 #ifdef IPFW
01102 int InlineReinject(Packet *p)
01103 {
01104     iv.rejectsrc = 0;
01105     iv.rejectdst = 0;
01106     iv.drop = 0;
01107     iv.reinject = 1;
01108     tmpP = p;
01109     return 0;
01110 }
01111 #endif /* IPFW */
01112 
01113 int InlineAccept()
01114 {
01115     iv.drop = 0;
01116     return 0;
01117 }
01118 
01119 int InlineReplace()
01120 {
01121     iv.replace = 1;
01122     return 0;
01123 }
01124 
01125 #else
01126 
01127 #include "snort.h"
01128 
01129 extern int g_drop_pkt;
01130 extern PV  pv;
01131 
01132 /*
01133 **  Let's define these for non-inline use.
01134 */
01135 int InlineMode()
01136 {
01137         if (pv.inline_flag)
01138                 return 1;
01139 
01140         return 0;
01141 }
01142 
01143 int InlineDrop()
01144 {
01145     g_drop_pkt = 1;
01146     
01147     return 0;
01148 }
01149 #endif /* GIDS */
01150 

Generated on Sun May 14 14:51:13 2006 by  doxygen 1.4.2