tp_packet.c

Go to the documentation of this file.
00001 /* vim: set tabstop=4: */
00002 /*
00003  * This file is part of TraceProto.
00004  * Copyright 2004-2005 Eric Hope and others; see the AUTHORS file for details.
00005  *
00006  * TraceProto is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * TraceProto is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with TraceProto; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00020 
00021 #include <libnet.h>
00022 #include <pcap.h>
00023 #include <unistd.h>
00024 #include <sys/time.h>
00025 #include <stdio.h>
00026 #include <sys/types.h>
00027 #include <arpa/inet.h>
00028 #include <stdlib.h>
00029 #include <ctype.h>
00030 #include <netdb.h>
00031 #include <netinet/in.h>
00032 
00033 #include "traceproto.h"
00034 #include "tp_miscfunc.h"
00035 #include "tp_packet.h"
00036 
00037 #ifdef HAVE_LIBDMALLOC
00038 #include <dmalloc.h>
00039 #endif /* HAVE_LIBDMALLOC */
00040 
00041 /*
00042  * builds the packet
00043  * called once per probe
00044  */
00045 void build_packet( void )
00046 {
00047         switch ( packet.protocol_number )
00048         {
00049         case IPPROTO_TCP:
00050                 state.tcp_h = libnet_build_tcp(
00051                         packet.src_port,
00052                         packet.dst_port,
00053                         libnet_get_prand(LIBNET_PRu32),  /* seq number */
00054                         libnet_get_prand(LIBNET_PRu32),  /* ack number */
00055                         packet.tcp_flags,                       /* SYN,ACK,etc */
00056                         1500,                              /* indow */
00057                         0,                                    /* checksum */
00058                         0,                                    /* urg */
00059                         LIBNET_TCP_H + behavior.payload_size,       /* length */
00060                         packet.payload,
00061                         behavior.payload_size,
00062                         state.packet,                           /* libnet thingie */
00063                         state.tcp_h );                  /* !0 = mod packet */
00064                 break;
00065         case IPPROTO_UDP:
00066                 state.udp_h = libnet_build_udp(
00067                         packet.src_port,
00068                         packet.dst_port,
00069                         LIBNET_UDP_H + behavior.payload_size,   /* length */
00070                         0,                                      /* checksum */
00071                         packet.payload,
00072                         behavior.payload_size,
00073                         state.packet,                           /* libnet thingie */
00074                         state.udp_h );
00075                 break;
00076         case IPPROTO_ICMP:
00077                 state.icmp_h = libnet_build_icmpv4_echo (
00078                         ICMP_ECHO,                              /* itype (8) */
00079                         0,                                      /* icode (0) */
00080                         0,                                      /* checksum */
00081                         libnet_get_prand ( LIBNET_PRu16 ),      /* ident */
00082                         libnet_get_prand ( LIBNET_PRu16 ),      /* sequence */
00083                         packet.payload,
00084                         behavior.payload_size,
00085                         state.packet,                           /* libnet thingie */
00086                         state.icmp_h );                         /* !0 = mod packet */
00087                 break;
00088         default:
00089                 printf ( "protocol error\n" );
00090                 tixe ( tixe_cleanup, 1 );
00091                 break;
00092         }
00093 }
00094 
00095 /*
00096  * if it's a tcp packet, take that portion
00097  * and sort it out
00098  */
00099 int parse_tcp_packet( const u_char * raw_packet )
00100 {
00101         struct libnet_tcp_hdr * tcp_hdr;
00102 
00103         if ( state.ip_hdr->ip_ttl >= 1 ) 
00104                 state.low_ttl = YES;
00105 
00106 /*      tcp_hdr = ( struct libnet_tcp_hdr * ) & raw_packet[ 0 ]; */
00107         tcp_hdr = ( struct libnet_tcp_hdr * ) tp_align ( raw_packet,
00108                                         0,
00109                                         sizeof ( struct libnet_tcp_hdr ) );
00110 
00111         account_packet ( state.trip_time );
00112 
00113         switch (  tcp_hdr->th_flags )
00114         {
00115         case ( TH_ACK | TH_RST ):
00116                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_ACKRST );
00117                 state.packet_match = TP_PACKET_DONE;
00118                 state.target_response = YES;
00119                 break;
00120         case ( TH_ACK | TH_SYN ):
00121                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_SYNACK );
00122                 state.packet_match = TP_PACKET_DONE;
00123                 state.target_response = YES;
00124                 break;
00125         case TH_SYN:
00126                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_SYN );
00127                 state.packet_match = TP_PACKET_DONE;
00128                 state.target_response = YES;
00129                 break;
00130         case ( TH_SYN | TH_ACK | TH_ECE | TH_CWR ):
00131                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_SEC );
00132                 state.packet_match = TP_PACKET_DONE;
00133                 state.target_response = YES;
00134                 break;
00135         case TH_RST:
00136                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_RST );
00137                 state.packet_match = TP_PACKET_DONE;
00138                 state.target_response = YES;
00139                 break;
00140         case TH_FIN:
00141                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_FIN );
00142                 state.packet_match = TP_PACKET_DONE;
00143                 state.target_response = YES;
00144                 break;
00145         case TH_ACK:
00146                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_ACK );
00147                 state.packet_match = TP_PACKET_DONE;
00148                 state.target_response = YES;
00149                 break;
00150         default:
00151                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_OTHER );
00152                 break;
00153         }
00154 
00155 
00156         return ( state.packet_match == TP_PACKET_NO ) ? 0 : 1;
00157 } /* end of parse_tcp_packet */
00158 
00159 
00160 
00161 
00162 /*
00163  * if it's a udp packet, take that portion
00164  * and sort it out
00165  */
00166 int parse_udp_packet( const u_char * raw_packet )
00167 {
00168         struct libnet_udp_hdr * udp_hdr;
00169 
00170         if ( state.ip_hdr->ip_ttl >= 1 ) 
00171                 state.low_ttl = YES;
00172 
00173 /*      udp_hdr = ( struct libnet_udp_hdr * ) & raw_packet[ 0 ]; */
00174         udp_hdr = ( struct libnet_udp_hdr * ) tp_align ( raw_packet,
00175                                         0,
00176                                         sizeof ( struct libnet_udp_hdr ) );
00177 
00178         account_packet ( state.trip_time );
00179 
00180         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_UDP );
00181         state.packet_match = TP_PACKET_DONE;
00182         state.target_response = YES;
00183 
00184         return ( state.packet_match == TP_PACKET_NO ) ? 0 : 1;
00185 } /* end of parse_udp_packet */
00186 
00187 
00188 
00189 /*
00190  * if it's an icmp packet, take that portion
00191  * and sort it out
00192  */
00193 int parse_icmp_packet( const u_char * raw_packet )
00194 {
00195         const struct libnet_icmpv4_hdr * icmp_hdr;
00196         const struct libnet_ipv4_hdr * icmp_payload;
00197 
00198         int icmp_payload_offset = 8;
00199 
00200         icmp_hdr = ( const struct libnet_icmpv4_hdr * ) & raw_packet [ 0 ];
00201         icmp_payload = ( const struct libnet_ipv4_hdr * ) & raw_packet [ icmp_payload_offset ];
00202 
00203         if ( icmp_payload->ip_id != tp_ntol ( packet.ip_id ) )
00204                 return ( state.packet_match == TP_PACKET_NO );
00205 
00206         account_packet ( state.trip_time );
00207 
00208         if ( icmp_hdr->icmp_type == ICMP_ECHOREPLY )
00209         {
00210                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_ECHOREPLY );
00211                 state.packet_match = TP_PACKET_MATCH;
00212                 state.target_response = YES;
00213         }
00214         else if ( icmp_hdr->icmp_type == ICMP_TIMXCEED )
00215         {
00216                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_TIMXCEED );
00217                 state.packet_match = TP_PACKET_MATCH;
00218         }
00219         else if ( icmp_hdr->icmp_type == ICMP_UNREACH )
00220         {
00221                 switch ( icmp_hdr->icmp_code )
00222                 {
00223                 case ICMP_UNREACH_PORT:
00224                         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_PORT_UNREACH );
00225                         state.packet_match = TP_PACKET_DONE;
00226                         state.target_response = YES;
00227                         break;
00228                 case ICMP_UNREACH_NET:
00229                         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_NET_UNREACH );
00230                         state.packet_match = TP_PACKET_DONE;
00231                         state.target_response = YES;
00232                         break;
00233                 case ICMP_UNREACH_HOST:
00234                         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_HOST_UNREACH );
00235                         state.packet_match = TP_PACKET_DONE;
00236                         state.target_response = YES;
00237                         break;
00238                 case ICMP_UNREACH_HOST_PROHIB:
00239                         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_HOST_UNREACH );
00240                         state.packet_match = TP_PACKET_DONE;
00241                         state.target_response = YES;
00242                         break;
00243                 case ICMP_UNREACH_NET_PROHIB:
00244                         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_NET_UNREACH );
00245                         state.packet_match = TP_PACKET_DONE;
00246                         state.target_response = YES;
00247                         break;
00248                 case ICMP_UNREACH_FILTER_PROHIB:
00249                         behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_PROHIB );
00250                         state.packet_match = TP_PACKET_DONE;
00251                         state.target_response = YES;
00252                         break;
00253                 default:
00254                         break;
00255                 }
00256         }
00257         else
00258         {
00259                 behavior.report( TP_OUT_HOP_INFO, & state.ip_hdr->ip_src, TP_TYPE_OTHER );
00260                 state.packet_match = TP_PACKET_MATCH;
00261         }
00262 
00263         return ( state.packet_match == TP_PACKET_NO ) ? 0 : 1;
00264 } /* end of parse_icmp_packet */
00265 
00266 
00267 /*
00268  * take the raw packet and do stuff with it
00269  * also figure out what it is
00270  */
00271 int parse_packet( u_char * raw_packet )
00272 {
00273         struct libnet_802_3_hdr * eth_hdr;
00274         int eth_offset, ipv4_offset;
00275 
00276         tp_align_freelist.next = NULL;
00277 
00278         if (  strncmp ( behavior.interface, "any", 3 ) == 0 )
00279                 eth_offset = LINUX_OFFSET + sizeof(struct libnet_802_3_hdr);
00280         else
00281                 eth_offset = sizeof(struct libnet_802_3_hdr);
00282 
00283         if ( debug.interface == YES )
00284                 printf ( "\ndebug: eth_offset is %d\n", eth_offset );
00285 
00286         ipv4_offset = eth_offset + sizeof( struct libnet_ipv4_hdr );
00287 /*
00288  * peel the ethernet and ip headers
00289  * off of the packet
00290  */
00291 /*      eth_hdr = ( struct libnet_802_3_hdr * ) raw_packet; */
00292         eth_hdr = ( struct libnet_802_3_hdr * ) tp_align ( raw_packet,
00293                                         0,
00294                                         sizeof ( struct libnet_802_3_hdr ) );
00295 
00296 /*      state.ip_hdr = ( struct libnet_ipv4_hdr * ) & raw_packet[ eth_offset ]; */
00297         state.ip_hdr = ( struct libnet_ipv4_hdr * ) tp_align ( raw_packet,
00298                                         eth_offset,
00299                                         sizeof ( struct libnet_ipv4_hdr ) );
00300 
00301         if ( state.ip_hdr->ip_ttl >= 1 ) 
00302                 state.low_ttl = YES;
00303 
00304         if ( debug.recv_buf == YES )
00305         {
00306                 printf ( "debug: recv buffer:\n" );
00307                 debug_packet ( raw_packet, 80 );
00308         }
00309 
00310         state.packet_match = TP_PACKET_NO;
00311 /*
00312  * now send it to the correct place
00313  */
00314         switch( state.ip_hdr->ip_p )
00315         {
00316         case IPPROTO_ICMP:
00317 /*              return parse_icmp_packet ( ( const u_char * ) & raw_packet [ ipv4_offset ] ); */
00318                 return parse_icmp_packet ( ( const u_char * ) tp_align ( raw_packet,
00319                                                         ipv4_offset,
00320                                                         sizeof ( struct libnet_icmpv4_hdr ) ) );
00321                 break;
00322         case IPPROTO_TCP:
00323 /*              return parse_tcp_packet ( ( const u_char * ) & raw_packet [ ipv4_offset ] ); */
00324                 return parse_tcp_packet ( ( const u_char * ) tp_align ( raw_packet,
00325                                                         ipv4_offset,
00326                                                         sizeof ( struct libnet_tcp_hdr ) ) );
00327                 break;
00328         case IPPROTO_UDP:
00329 /*              return parse_udp_packet ( ( const u_char * ) & raw_packet [ ipv4_offset ] ); */
00330                 return parse_udp_packet ( ( const u_char * ) tp_align ( raw_packet,
00331                                                         ipv4_offset,
00332                                                         sizeof ( struct libnet_udp_hdr ) ) );
00333                 break;
00334         default:
00335                 break;
00336         }
00337 
00338         return 0;
00339 } /* end of parse_packet */
00340 
00341 
00342 /*
00343  * Now to clean up after ourselves
00344  */
00345 void freelist_cleaner ( void )
00346 {
00347         struct tp_align_ref * ref_ptr, * ref_ptr_last;
00348 
00349         for ( ref_ptr = tp_align_freelist.next,
00350                 ref_ptr_last = NULL;
00351                 ref_ptr->next != NULL;
00352                 ref_ptr = ref_ptr->next )
00353         {
00354                 if ( debug.memory == YES )
00355                 {
00356                         printf ( "debug: memory: freeing ref %p\n", ref_ptr->ref );
00357                         printf ( "debug: memory: freeing last %p\n", (void *) ref_ptr_last );
00358                 }
00359 
00360                 free ( ref_ptr->ref );
00361                 if ( ref_ptr_last != NULL ) { free ( ref_ptr_last ); }
00362                 ref_ptr_last = ref_ptr;
00363         }
00364 
00365         /* and the last ones for good measure */
00366         if ( debug.memory == YES )
00367         {
00368                 printf ( "debug: memory: freeing ref %p\n", (void *) ref_ptr->ref );
00369                 printf ( "debug: memory: freeing last %p\n", (void *) ref_ptr_last );
00370         }
00371         free ( ref_ptr->ref );
00372         free ( ref_ptr_last );
00373 
00374         ref_ptr_last = ref_ptr;
00375         if ( debug.memory == YES )
00376                 printf ( "debug: memory: freeing last %p\n", (void *) ref_ptr_last );
00377         free ( ref_ptr_last );
00378 }
00379 
00380 
00381 /*
00382  * minor slight of hand to manipulate
00383  * the packet ip_id fields
00384  */
00385 int tp_ntol ( int n_order )
00386 {
00387         int tmp = n_order & 0xff;
00388         n_order = n_order >> 8;
00389         tmp = tmp << 8;
00390         n_order = n_order | tmp;
00391 
00392         return n_order;
00393 }
00394 
00395 /*
00396  * not really used at this point,
00397  * here for os that may not be as
00398  * good about send the resets for
00399  * raw sockets
00400  */
00401 int send_tcp_reset ( void )
00402 {
00403 
00404         state.tcp_h = libnet_build_tcp(
00405                 packet.src_port,
00406                 packet.dst_port,
00407                 libnet_get_prand ( LIBNET_PRu32 ),      /* seqnumber */
00408                 libnet_get_prand(LIBNET_PRu32),         /* acknumber */
00409                 TH_RST & TH_FIN,
00410                 1500,                                   /* indow */
00411                 0,                                      /* checksum */
00412                 0,                                      /* urg */
00413                 LIBNET_TCP_H + behavior.payload_size,   /* length */
00414                 packet.payload,
00415                 behavior.payload_size,
00416                 state.packet,                           /* libnet thingie */
00417                 state.tcp_h );                  /* !0 = modpacket */
00418 
00419         state.ip_h = libnet_build_ipv4(
00420                 LIBNET_IPV4_H,            /* IP hdr len */
00421                 0,                            /* tos */
00422                 packet.ip_id,               /* frag id */
00423                 packet.frag_bit,                /* frag offset */
00424                 state.current_hop,            /* ttl */
00425                 packet.protocol_number,
00426                 0,                            /* checksum */
00427                 packet.packed_src,            /* packed source */
00428                 packet.packed_target,      /* packed target */
00429                 NULL,                      /* payload */
00430                 0,                            /* payload size */
00431                 state.packet,
00432                 state.ip_h );
00433 
00434         if ( libnet_write( state.packet ) == -1 )
00435         {
00436                 return 1;
00437         }
00438         return 0;
00439 }
00440 
00441 /*
00442  * pick the correct interface to use for pcap and libnet
00443  */
00444 /********************
00445 char * find_interface ( )
00446 {
00447         return interface;
00448 }
00449 ********************/

Generated on Wed Sep 16 11:08:43 2009 for traceproto by  doxygen 1.5.4