Main Page | Data Structures | File List | Data Fields | Globals | Related Pages

sniff.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Copyright 2005 Daniel Ferullo                                             *
00003  *                                                                           *
00004  * Licensed under the Apache License, Version 2.0 (the "License");           *
00005  * you may not use this file except in compliance with the License.          *
00006  * You may obtain a copy of the License at                                   *
00007  *                                                                           *
00008  *    http://www.apache.org/licenses/LICENSE-2.0                             *
00009  *                                                                           *
00010  * Unless required by applicable law or agreed to in writing, software       *
00011  * distributed under the License is distributed on an "AS IS" BASIS,         *
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00013  * See the License for the specific language governing permissions and       *
00014  * limitations under the License.                                            *
00015  *                                                                           *
00016  *****************************************************************************/
00017 
00018 /**
00019  * @file sniff.c
00020  * @author Daniel Ferullo (ferullo@cmu.edu)
00021  *
00022  * @brief functions to aid in sniffing packets off the wire
00023  */
00024 
00025 #include "sniff.h"
00026 #include "sniff_private.h"
00027 #include "debug.h"
00028 #include "util.h"
00029 #include <string.h>
00030 #include "nethelp.h"
00031 
00032 errorcode capture_peer_to_buddy_syn(peer_conn_info_t *info) {
00033 
00034         /* declare local variables */
00035         char errbuf[PCAP_ERRBUF_SIZE]; /* pcap error string buffer */
00036         pcap_t *pcap_desc = NULL; /* pcap capture descriptor */
00037 
00038         /* error check arguments */
00039         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00040 
00041         /* do function */
00042 
00043         /* initalize the pcap functions */
00044         CHECK_FAILED(init_packet_capture(&pcap_desc,info->device,1000,
00045                 errbuf, PCAP_ERRBUF_SIZE),ERROR_1);
00046 
00047         /* fill in the syn info to look for */
00048         info->buddy_syn.d_addr    = info->buddy.ext_ip;
00049         info->buddy_syn.d_port    = info->buddy.ext_port;
00050         info->buddy_syn.s_addr    = info->peer.ip;
00051         info->buddy_syn.s_port    = info->peer.port;
00052         info->buddy_syn.syn_flag  = FLAG_SET;
00053         info->buddy_syn.ack_flag  = FLAG_UNSET;
00054 
00055         /* now loop, checking packets for the desired SYN */
00056         CHECK_FAILED(find_tcp_packet(pcap_desc, &info->buddy_syn,
00057                 &info->direct_conn_status,NULL,NULL),ERROR_1);
00058 
00059         return SUCCESS;
00060 }
00061 
00062 errorcode capture_flooded_synack(peer_conn_info_t *info) {
00063 
00064         /* declare local variables */
00065         char errbuf[PCAP_ERRBUF_SIZE];
00066         pcap_t *pcap_desc = NULL;
00067         tcp_packet_info_t skeleton;
00068         unsigned char *payload = NULL;
00069         unsigned long payload_len = 0;
00070 
00071         /* error check arguments */
00072         CHECK_NOT_NULL(info,ERROR_NULL_ARG_1);
00073 
00074         /* do function */
00075 
00076         CHECK_FAILED(init_packet_capture(&pcap_desc,info->device,1000,
00077                 errbuf, PCAP_ERRBUF_SIZE), ERROR_1);
00078 
00079         /* fill in the syn ack info */
00080         skeleton.d_addr   = info->peer.ip;
00081         skeleton.d_port   = PORT_UNKNOWN;
00082         skeleton.s_addr   = info->buddy.ext_ip;
00083         skeleton.s_port   = info->buddy.ext_port;
00084         skeleton.ack_flag = FLAG_SET;
00085         skeleton.syn_flag = FLAG_SET;
00086 
00087         /* now loop checking packets for the desired SYN/ACK */
00088         CHECK_FAILED(find_tcp_packet(pcap_desc, &skeleton,
00089                 &info->bday.stop_synack_find,&payload,&payload_len), ERROR_1);
00090 
00091         DEBUG(DBG_BDAY,"DBAY:payload size is %u\n",(unsigned int)payload_len);
00092 
00093         if (payload == NULL)
00094                 return ERROR_1;
00095         if (payload_len != sizeof(port_t))
00096                 return ERROR_2;
00097 
00098         /* set the port value */
00099         memcpy(&info->bday.port,payload,sizeof(info->bday.port));
00100         info->bday.port_set = FLAG_SET;
00101 
00102         /* rebind the buddy socket to the new internal port */
00103         close(info->socks.buddy);
00104         CHECK_FAILED(bindSocket(skeleton.d_port,&info->socks.buddy),
00105                 ERROR_CALLED_FUNCTION);
00106 
00107         return SUCCESS;
00108 }
00109 
00110 errorcode init_packet_capture(pcap_t **pcap_desc, char *device, int timeout,
00111                                 char *errbuf, long errbuf_len) {
00112 
00113         /* declare local variables */
00114         char *filter = "tcp";
00115         struct bpf_program fp;
00116         bpf_u_int32 maskp;
00117         bpf_u_int32 netp;
00118 
00119         /* error check arguments */
00120         CHECK_NOT_NULL(pcap_desc,ERROR_NULL_ARG_1);
00121         CHECK_NOT_NULL(device,ERROR_NULL_ARG_2);
00122         CHECK_NOT_NULL(errbuf,ERROR_NULL_ARG_4);
00123         CHECK_GREATER_THAN(errbuf_len,PCAP_ERRBUF_SIZE-1,ERROR_ARG_5);
00124 
00125         /* do function */
00126         if ( pcap_lookupnet(device,&netp,&maskp,errbuf) < 0 ) {
00127                 DEBUG(DBG_SNIFF,
00128                         "SNIFF:did you forget to run this program as root?\n");
00129                 return ERROR_1;
00130         }
00131 
00132         if  ( (*pcap_desc=pcap_open_live(device,BUFSIZ,0,
00133                                         timeout,errbuf)) == NULL )
00134                 return ERROR_2;
00135 
00136         /* make sure the user is on ethernet (that is the only supported
00137          * data link layer right now */
00138         if ( pcap_datalink(*pcap_desc) != DLT_EN10MB)
00139                 return ERROR_2;
00140 
00141         /* compile the filter */
00142         if ( pcap_compile(*pcap_desc,&fp,filter,0,netp) < 0 )
00143                 return ERROR_4;
00144 
00145         /* set the filter */
00146         if ( pcap_setfilter(*pcap_desc,&fp) == -1 )
00147                 return ERROR_5;
00148 
00149         /* set pcap_next to be non-blocking */
00150         if ( pcap_setnonblock(*pcap_desc,1,errbuf) < 0 )
00151                 return ERROR_6;
00152 
00153         return SUCCESS;
00154 }
00155 
00156 errorcode find_tcp_packet(pcap_t *pcap_desc, tcp_packet_info_t *tcp_skeleton,
00157                         flag_t *break_flag, unsigned char **payload,
00158                         unsigned long *payload_len) {
00159 
00160         /* declare local variables */
00161         struct pcap_pkthdr hdr;
00162         const u_char *packet;
00163 
00164         /* error check arguments */
00165         CHECK_NOT_NULL(pcap_desc,ERROR_NULL_ARG_1);
00166         CHECK_NOT_NULL(tcp_skeleton,ERROR_NULL_ARG_2);
00167         CHECK_NOT_NULL(break_flag,ERROR_NULL_ARG_3);
00168 
00169         /* do function */
00170 
00171         /* loop as long as the brak_flag isn't set */
00172         while ( *break_flag == FLAG_UNSET) {
00173                 /* capture the next packet, if timeout occurs, then result is
00174                  * NULL */
00175                 if ( (packet=pcap_next(pcap_desc,&hdr)) != NULL) {
00176                         /* proces the packet, and if it is "the one" then
00177                          * return success */
00178                         if (!(FAILED(process_packet((unsigned char*) packet,
00179                                         tcp_skeleton,payload,payload_len)))) {
00180                                 return SUCCESS;
00181                         }
00182                 }
00183         }
00184 
00185         DEBUG(DBG_SNIFF,"SNIFF:could not find syn to buddy\n");
00186 
00187         return ERROR_2;
00188 }
00189 
00190 errorcode process_packet(unsigned char*packet,
00191                 tcp_packet_info_t *tcp_skeleton, unsigned char **payload,
00192                 unsigned long *payload_len) {
00193 
00194         /* declare local variables */
00195         struct ether_header *ether  = NULL; /* from net/ethernet.h */
00196         struct iphdr        *ip     = NULL; /* from linux/ip.h */
00197         struct tcphdr       *tcp    = NULL; /* from netinet/tcp.h */
00198         int ip_hdr_len              = 0;
00199 
00200         /* error check arguments */
00201         CHECK_NOT_NULL(packet,ERROR_NULL_ARG_1);
00202         CHECK_NOT_NULL(tcp_skeleton,ERROR_NULL_ARG_2);
00203 
00204         /* do function */
00205 
00206         /* align different structure pointers to correct location */
00207         ether = (struct ether_header*) (packet);
00208 
00209         ip    = (struct iphdr*) ((char*)ether + sizeof(struct ether_header));
00210         /* determine how long the ip hdr is (multiply by 4 because the ihl
00211          * field is in 32 bit words, but I want it in bytes */
00212         ip_hdr_len = 4 * (unsigned int) ip->ihl;
00213 
00214         tcp   = (struct tcphdr*) ( (char*)ip + ip_hdr_len);
00215 
00216         /*
00217         DEBUG(DBG_SNIFF,"RECEIVED PACKET:\n");
00218         DEBUG(DBG_SNIFF,"SNIFF:ip.s_addr:  %s\n",DBG_IP(ip->saddr));
00219         DEBUG(DBG_SNIFF,"SNIFF:ip.d_addr:  %s\n",DBG_IP(ip->daddr));
00220         DEBUG(DBG_SNIFF,"SNIFF:tcp.s_port: %d\n",DBG_PORT(tcp->th_sport));
00221         DEBUG(DBG_SNIFF,"SNIFF:tcp.d_port: %d\n",DBG_PORT(tcp->th_dport));
00222         DEBUG(DBG_SNIFF,"SNIFF:tcp ACK bit is %sset\n",
00223                 (tcp->th_flags&TH_ACK) ? "" : "not ");
00224         DEBUG(DBG_SNIFF,"SNIFF:tcp SYN bit is %sset\n",
00225                 (tcp->th_flags&TH_SYN) ? "" : "not ");
00226         DEBUG(DBG_SNIFF,"LOOKING FOR:\n");
00227         DEBUG(DBG_SNIFF,"SNIFF:skeleton.s_addr:  %s\n",
00228                 DBG_IP(tcp_skeleton->s_addr));
00229         DEBUG(DBG_SNIFF,"SNIFF:skeleton.d_addr:  %s\n",
00230                 DBG_IP(tcp_skeleton->d_addr));
00231         DEBUG(DBG_SNIFF,"SNIFF:skeleton.s_port: %d\n",
00232                 DBG_PORT(tcp_skeleton->s_port));
00233         DEBUG(DBG_SNIFF,"SNIFF:skeleton.d_port: %d\n",
00234                 DBG_PORT(tcp_skeleton->d_port));
00235         DEBUG(DBG_SNIFF,"SNIFF:skeleton ACK bit is %sset\n",
00236                 (tcp_skeleton->ack_flag==FLAG_SET) ? "" : "not ");
00237         DEBUG(DBG_SNIFF,"SNIFF:skeleton SYN bit is %sset\n",
00238                 (tcp_skeleton->syn_flag==FLAG_SET) ? "" : "not ");
00239         DEBUG(DBG_SNIFF,"\n");
00240         */
00241 
00242         /* if statement to check if this is the desired packet */
00243         if (    ( (ip->saddr     !=  tcp_skeleton->s_addr)   &&
00244                   (tcp_skeleton->s_addr != IP_UNKNOWN)     ) ||
00245                 ( (ip->daddr     !=  tcp_skeleton->d_addr)   &&
00246                   (tcp_skeleton->d_addr != IP_UNKNOWN)    ) ||
00247                 ( (tcp->th_sport !=  tcp_skeleton->s_port)   &&
00248                   (tcp_skeleton->s_port != PORT_UNKNOWN)   ) ||
00249                 ( (tcp->th_dport !=  tcp_skeleton->d_port)   &&
00250                   (tcp_skeleton->d_port != PORT_UNKNOWN)   ) ||
00251                 !BOOL_MATCH(tcp->th_flags&TH_ACK,
00252                         (tcp_skeleton->ack_flag==FLAG_SET)) ||
00253                 !BOOL_MATCH(tcp->th_flags&TH_SYN,
00254                         (tcp_skeleton->syn_flag==FLAG_SET))
00255            )  {
00256                 /* if here, at least one of the above didn't match */
00257                 return NOT_OK;
00258         }
00259 
00260         DEBUG(DBG_SNIFF,"SNIFF:matched packet\n");
00261 
00262         DEBUG(DBG_SNIFF,"SNIFF:ip.s_addr:  %s\n",DBG_IP(ip->saddr));
00263         DEBUG(DBG_SNIFF,"SNIFF:ip.d_addr:  %s\n",DBG_IP(ip->daddr));
00264         DEBUG(DBG_SNIFF,"SNIFF:tcp.s_port: %d\n",DBG_PORT(tcp->th_sport));
00265         DEBUG(DBG_SNIFF,"SNIFF:tcp.d_port: %d\n",DBG_PORT(tcp->th_dport));
00266 
00267         DEBUG(DBG_SNIFF,"SNIFF:tcp ACK bit is %sset\n",
00268                 (tcp->th_flags&TH_ACK) ? "" : "not ");
00269         DEBUG(DBG_SNIFF,"SNIFF:tcp SYN bit is %sset\n",
00270                 (tcp->th_flags&TH_SYN) ? "" : "not ");
00271 
00272 
00273         /* set the sequence number and ack number */
00274         tcp_skeleton->seq_num = tcp->th_seq;
00275         tcp_skeleton->ack_num = tcp->th_ack;
00276         tcp_skeleton->window  = tcp->th_win;
00277 
00278         /* set the other information */
00279         tcp_skeleton->s_addr = ip->saddr;
00280         tcp_skeleton->d_addr = ip->daddr;
00281         tcp_skeleton->s_port = tcp->th_sport;
00282         tcp_skeleton->d_port = tcp->th_dport;
00283 
00284         /* set the payload pointer */
00285         if (payload != NULL)
00286                 *payload = (unsigned char*) tcp + sizeof(struct tcphdr);
00287         if (payload_len != NULL)
00288                 *payload_len = ntohs(ip->tot_len) - sizeof(struct tcphdr) -
00289                                                         sizeof(struct iphdr);
00290 
00291 
00292         return SUCCESS;
00293 }
00294 

Generated on Wed Mar 30 23:20:47 2005 for NATBLASTER by  doxygen 1.3.9.1