00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <libnet.h>
00022 #include <pcap.h>
00023 #include <unistd.h>
00024 #include <errno.h>
00025 #include <sys/time.h>
00026 #include <stdio.h>
00027 #include <sys/types.h>
00028 #include <arpa/inet.h>
00029 #include <signal.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <netinet/in.h>
00033 #include <ctype.h>
00034 #include <time.h>
00035 #include <assert.h>
00036
00037 #include "tp_miscfunc.h"
00038 #include "traceproto.h"
00039 #include "config.h"
00040 #include "tp_as.h"
00041
00042 #ifdef HAVE_LIBCAP
00043 # include <sys/capability.h>
00044 #endif
00045
00046
00047
00048
00049
00050
00051 #ifdef HAVE_LIBDMALLOC
00052 #include <dmalloc.h>
00053 #endif
00054
00055
00056
00057
00058
00059 int parse_skips ( char * skip_ptr )
00060 {
00061 size_t c;
00062 char tmp[ 4 ];
00063 int tmp_c = 0;
00064
00065 behavior.skips = ( int * ) calloc ( behavior.max_ttl + 1, sizeof ( int ) );
00066 if ( behavior.skips == NULL )
00067 {
00068 printf ( "memory allocation error" );
00069 tixe ( tixe_cleanup, 1 );
00070 }
00071
00072 tixe_cleanup.skips_free = YES;
00073
00074
00075
00076
00077
00078
00079 memset ( & tmp, '\0', sizeof ( tmp ) );
00080 for ( c = 0; c < strlen ( skip_ptr ); c++ )
00081 {
00082 if ( isdigit ( skip_ptr[ c ] ) && tmp_c < 4 )
00083 {
00084 tmp[ tmp_c++ ] = skip_ptr[ c ];
00085 }
00086 else if ( isdigit ( skip_ptr[ c ] ) && tmp_c >= 4 )
00087 {
00088 return 1;
00089 }
00090 else if ( skip_ptr[ c ] == ',' )
00091 {
00092 tmp_c = atoi ( tmp );
00093 if ( tmp_c > 0 && tmp_c <= behavior.max_ttl )
00094 {
00095 behavior.skips[ tmp_c ] = 1;
00096 }
00097 else
00098 {
00099 return 1;
00100 }
00101 tmp_c = 0;
00102 memset ( & tmp, '\0', sizeof ( tmp ) );
00103 }
00104 else
00105 {
00106 return 1;
00107 }
00108 }
00109
00110
00111 if ( tmp_c != 0 )
00112 {
00113 tmp_c = atoi ( tmp );
00114 if ( tmp_c > 0 && tmp_c <= behavior.max_ttl )
00115 {
00116 behavior.skips[ tmp_c ] = 1;
00117 }
00118 else
00119 {
00120 return 1;
00121 }
00122 tmp_c = 0;
00123 memset ( & tmp, '\0', sizeof ( tmp ) );
00124 }
00125
00126 return 0;
00127 }
00128
00129
00130
00131
00132 void ctrl_c ( __attribute__((__unused__)) int unused )
00133 {
00134 behavior.do_audit_exit = YES;
00135 }
00136 void ctrl_z( __attribute__((__unused__)) int unused )
00137 {
00138 behavior.do_audit = YES;
00139 }
00140
00141
00142
00143
00144 double diff_time ( struct timeval * start, struct timeval * end )
00145 {
00146 register double diff;
00147
00148 diff = ( double )( end->tv_sec - start->tv_sec ) * 1000.0
00149 + ( double )( end->tv_usec - start->tv_usec ) / 1000.0;
00150
00151 return diff;
00152 }
00153
00154
00155
00156
00157 int do_filter( void )
00158 {
00159 char filter [ FILTERSIZE ];
00160 struct bpf_program compiled_filter;
00161 bpf_u_int32 netmask = 0;
00162
00163 if ( packet.protocol_number == IPPROTO_ICMP )
00164 {
00165 sprintf ( filter,
00166 behavior.filter_text,
00167 packet.ip_id,
00168 behavior.target );
00169 } else {
00170 sprintf ( filter,
00171 behavior.filter_text,
00172 behavior.target,
00173 packet.src_port,
00174 packet.dst_port,
00175 packet.ip_id );
00176 }
00177
00178 if ( debug.interface == YES )
00179 printf ( "debug: BPF filter: %s\n",
00180 filter );
00181
00182 if ( pcap_compile(
00183 state.psocket,
00184 & compiled_filter,
00185 filter,
00186 0,
00187 netmask ) == -1 )
00188 {
00189 printf("pcap error: %s\n", pcap_geterr( state.psocket ) );
00190 return 1;
00191 }
00192
00193 if ( pcap_setfilter(
00194 state.psocket,
00195 & compiled_filter ) != 0 )
00196 {
00197 printf("pcap error: %s\n", pcap_geterr( state.psocket ) );
00198 return 1;
00199 }
00200
00201 pcap_freecode ( & compiled_filter );
00202
00203 return 0;
00204 }
00205
00206
00207
00208
00209 int account_packet ( double return_time )
00210 {
00211
00212
00213
00214
00215 if ( return_time == ( double ) 0 )
00216 state.hop_record[ 0 ].lost_packets++;
00217 else
00218 state.hop_record[ 0 ].num_packets++;
00219
00220 if ( state.hop_record[ 0 ].min_time == ( double ) 0
00221 || state.hop_record[ 0 ].min_time > return_time )
00222 state.hop_record[ 0 ].min_time = return_time;
00223
00224 if ( state.hop_record[ 0 ].max_time < return_time )
00225 state.hop_record[ 0 ].max_time = return_time;
00226
00227 state.hop_record[ 0 ].ave_time =
00228 ( state.hop_record[ 0 ].ave_time
00229 * state.hop_record[ 0 ].num_packets
00230 + return_time )
00231 / ( state.hop_record[ 0 ].num_packets
00232 + 1 );
00233
00234
00235
00236
00237 state.hop_record[ state.current_hop ].distance = state.current_hop;
00238
00239
00240
00241
00242 if ( return_time == ( double ) 0 )
00243 {
00244 state.hop_record[ state.current_hop ].lost_packets++;
00245 return 0;
00246 }
00247 else
00248 state.hop_record[ state.current_hop ].num_packets++;
00249
00250 if ( state.hop_record[ state.current_hop ].min_time == (double)0
00251 || state.hop_record[ state.current_hop ].min_time > return_time )
00252 {
00253 state.hop_record[ state.current_hop ].min_time = return_time;
00254 }
00255
00256 if ( state.hop_record[ state.current_hop ].max_time < return_time )
00257 state.hop_record[ state.current_hop ].max_time = return_time;
00258
00259
00260
00261
00262 state.hop_record[ state.current_hop ].ave_time =
00263 ( state.hop_record[ state.current_hop ].ave_time
00264 * ( state.hop_record[ state.current_hop ].num_packets
00265 - 1 )
00266 + return_time )
00267 / ( state.hop_record[ state.current_hop ].num_packets );
00268
00269 return 1;
00270 }
00271
00272
00273
00274
00275
00276 void hop_audit( void )
00277 {
00278 int hop;
00279
00280 if ( behavior.account_level > TP_ACCOUNT_NONE )
00281 {
00282 printf ( "\nhop : min / ave / max : # packets : # lost\n" );
00283 }
00284
00285 if ( behavior.account_level == TP_ACCOUNT_FULL )
00286 {
00287 printf ( "-------------------------------------------------------\n" );
00288 for ( hop = behavior.min_ttl; hop <= behavior.max_ttl; hop++ )
00289 {
00290 if ( state.hop_record[ hop ].num_packets != 0
00291 || state.hop_record[ hop ].lost_packets != 0 )
00292 {
00293 printf ( "%3d : %#.5g / %#.5g / %#.5g : %3d packets : %3d lost\n",
00294 hop,
00295 state.hop_record[ hop ].min_time,
00296 state.hop_record[ hop ].ave_time,
00297 state.hop_record[ hop ].max_time,
00298 state.hop_record[ hop ].num_packets,
00299 state.hop_record[ hop ].lost_packets );
00300 }
00301
00302 }
00303 }
00304
00305 if ( behavior.account_level > TP_ACCOUNT_NONE )
00306 {
00307 printf ( "------------------------Total--------------------------\n" );
00308 if ( state.hop_record[ 0 ].num_packets != 0
00309 || state.hop_record[ 0 ].lost_packets != 0 )
00310 {
00311 printf ( "total %#.5g / %#.5g / %#.5g : %3d packets : %3d lost\n",
00312 state.hop_record[ 0 ].min_time,
00313 state.hop_record[ 0 ].ave_time,
00314 state.hop_record[ 0 ].max_time,
00315 state.hop_record[ 0 ].num_packets,
00316 state.hop_record[ 0 ].lost_packets );
00317 }
00318 printf ( "\n" );
00319 }
00320
00321 if ( behavior.do_audit_exit == YES )
00322 {
00323 printf ( "\n" );
00324 tixe ( tixe_cleanup, 0 );
00325 }
00326
00327 behavior.do_audit = NO;
00328 }
00329
00330
00331
00332
00333 int reg_name ( char * arg0 )
00334 {
00335 size_t c;
00336 state.prog = & arg0 [ 0 ];
00337 for ( c = 0; c < strlen ( arg0 ); c++ )
00338 {
00339 if ( arg0[ c ] == '/' )
00340 {
00341 state.prog = & arg0[ c+1 ];
00342 }
00343 }
00344
00345 return strlen ( state.prog );
00346 }
00347
00348
00349
00350
00351 void tixe ( struct cleanup clean_list, int exit_status )
00352 {
00353 if ( clean_list.payload_free == YES ) { free ( packet.payload ); }
00354 if ( clean_list.skips_free == YES ) { free ( behavior.skips ); }
00355 if ( clean_list.hop_record_free == YES ) { free ( state.hop_record ); }
00356 if ( clean_list.fake_psocket_free == YES ) { free ( state.fake_psocket ); }
00357
00358 if ( clean_list.libnet_cleanup == YES ) { libnet_destroy ( state.packet ); }
00359 if ( clean_list.pcap_cleanup == YES ) { pcap_close ( state.psocket ); }
00360
00361 #ifdef HAVE_GETADDRINFO
00362 if ( clean_list.addrinfo_cleanup == YES ) { freeaddrinfo( behavior.target_addrinfo_list_start ); }
00363 #endif
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 #ifdef HAVE_LIBDMALLOC
00374
00375 #endif
00376
00377 exit ( exit_status );
00378 }
00379
00380
00381
00382
00383 void version( void )
00384 {
00385 printf("%s version %s, released %s\n", PACKAGE, VERSION, RELEASE_DATE );
00386 }
00387
00388
00389
00390
00391
00392 u_char parse_flags ( char * user_flags )
00393 {
00394 int i, errors = 0;
00395 u_char packet_flags = '\0';
00396
00397 for ( i = strlen ( user_flags ); i > 0; i-- )
00398 {
00399 switch ( user_flags [ 0 ] )
00400 {
00401 case 'S':
00402 case 's':
00403 packet_flags |= TH_SYN;
00404 break;
00405 case 'A':
00406 case 'a':
00407 packet_flags |= TH_ACK;
00408 break;
00409 case 'R':
00410 case 'r':
00411 packet_flags |= TH_RST;
00412 break;
00413 case 'U':
00414 case 'u':
00415 packet_flags |= TH_URG;
00416 break;
00417 case 'p':
00418 case 'P':
00419 packet_flags |= TH_PUSH;
00420 break;
00421 case 'F':
00422 case 'f':
00423 packet_flags |= TH_FIN;
00424 break;
00425 case 'E':
00426 case 'e':
00427 packet_flags |= TH_ECE;
00428 break;
00429 case 'C':
00430 case 'c':
00431 packet_flags |= TH_CWR;
00432 break;
00433 default:
00434 errors++;
00435 break;
00436 }
00437 user_flags++;
00438 }
00439
00440 return packet_flags;
00441 }
00442
00443
00444
00445
00446
00447 int make_timestamp ( char * str_buf )
00448 {
00449 time_t epoch_time;
00450 struct tm * time_struct;
00451 char time_string [ TP_TIMESTAMP_LEN ];
00452 const char * month [ ] = {
00453 "Jan", "Feb", "Mar", "Apr",
00454 "May", "Jun", "Jul", "Aug",
00455 "Sep", "Oct", "Nov", "Dec" };
00456
00457 if ( ( epoch_time = time ( NULL ) ) == -1 )
00458 {
00459 perror ( "error determining time" );
00460 tixe ( tixe_cleanup, 1 );
00461 }
00462
00463 time_struct = localtime ( & epoch_time );
00464
00465 memset ( time_string, '\0', TP_TIMESTAMP_LEN );
00466
00467 if ( debug.timestamp == YES )
00468 printf ( "timestamp_style: %d\n", behavior.timestamp_style );
00469
00470 switch ( behavior.timestamp_style )
00471 {
00472 case TP_TIMESTAMP_US:
00473 snprintf ( time_string,
00474 TP_TIMESTAMP_LEN - 1,
00475 "%d/%0.2d/%d:%d:%d:%d",
00476 time_struct->tm_mon + 1,
00477 time_struct->tm_mday,
00478
00479 time_struct->tm_year + 1900,
00480 time_struct->tm_hour,
00481 time_struct->tm_min,
00482 time_struct->tm_sec );
00483 break;
00484 case TP_TIMESTAMP_DESCEND:
00485 snprintf ( time_string,
00486 TP_TIMESTAMP_LEN - 1,
00487 "%d/%d/%d:%d:%d:%d",
00488 time_struct->tm_year + 1900,
00489 time_struct->tm_mon + 1,
00490 time_struct->tm_mday,
00491 time_struct->tm_hour,
00492 time_struct->tm_min,
00493 time_struct->tm_sec );
00494 break;
00495 case TP_TIMESTAMP_EPOCH:
00496 snprintf ( time_string,
00497 TP_TIMESTAMP_LEN - 1,
00498 "%d",
00499 epoch_time );
00500 break;
00501 case TP_TIMESTAMP_STD:
00502 default:
00503 snprintf ( time_string,
00504 TP_TIMESTAMP_LEN - 1,
00505 "%0.2d/%s/%d:%d:%d:%d",
00506 time_struct->tm_mday,
00507 month [ time_struct->tm_mon ],
00508
00509 time_struct->tm_year + 1900,
00510 time_struct->tm_hour,
00511 time_struct->tm_min,
00512 time_struct->tm_sec );
00513 break;
00514 }
00515
00516 strncpy ( str_buf, time_string, TP_TIMESTAMP_LEN );
00517
00518 return strlen ( time_string );
00519 }
00520
00521
00522
00523
00524 u_char * tp_align ( const u_char * buf, unsigned int offset, unsigned int size )
00525 {
00526 unsigned char * new_buf;
00527 struct tp_align_ref * new_ref;
00528 struct tp_align_ref * ref_ptr;
00529
00530 new_buf = ( u_char * ) malloc ( size );
00531 assert(new_buf != NULL);
00532
00533
00534 if ( buf == NULL )
00535 {
00536 printf ( "error: reading from empty receive buffer\n" );
00537 tixe ( tixe_cleanup, 1 );
00538 }
00539
00540 memset ( new_buf, '\0', size );
00541 memcpy ( new_buf, buf + offset, size );
00542
00543 new_ref = ( struct tp_align_ref * ) malloc ( sizeof ( struct tp_align_ref ) );
00544 assert(new_ref != NULL);
00545 new_ref->next = NULL;
00546 new_ref->ref = new_buf;
00547 for ( ref_ptr = & tp_align_freelist;
00548 ref_ptr->next != NULL;
00549 ref_ptr = ref_ptr->next ) { ; }
00550 ref_ptr->next = new_ref;
00551
00552 if ( debug.memory == YES )
00553 {
00554 printf ( "debug: memory: allocated new_buf %p\n", new_buf );
00555 printf ( "debug: memory: allocated new_ref %p\n", (void *) new_ref );
00556 }
00557
00558 return new_buf;
00559 }
00560
00561
00562
00563
00564
00565 void dropexcesscapabilities( void )
00566 {
00567 #ifdef HAVE_LIBCAP
00568 cap_t cap_d = cap_init();
00569 cap_value_t cap_values[] = {
00570
00571 CAP_NET_RAW
00572 };
00573
00574 if (!cap_d) {
00575 fprintf(stderr, "Could not alloc cap struct\n");
00576 exit(-1);
00577 }
00578
00579 cap_clear(cap_d);
00580 cap_set_flag(cap_d, CAP_PERMITTED, 1, cap_values, CAP_SET);
00581 cap_set_flag(cap_d, CAP_EFFECTIVE, 1, cap_values, CAP_SET);
00582
00583 if (cap_set_proc(cap_d) != 0) {
00584 fprintf(stderr, "Could not set capabilities: %s\n", strerror(errno));
00585 exit(1);
00586 }
00587 cap_free(&cap_d);
00588 #endif
00589 }
00590
00591
00592
00593
00594
00595
00596 void parse_debug ( char * optarg )
00597 {
00598 size_t i;
00599
00600 for ( i = 0; i < strlen ( optarg ); i++ )
00601 {
00602 switch ( optarg [ i ] )
00603 {
00604 case 'a':
00605 printf ( "debug: all\n" );
00606 debug.loop = YES;
00607 debug.interface = YES;
00608 debug.send_buf = YES;
00609 debug.recv_buf = YES;
00610 debug.packet_length = YES;
00611 debug.memory = YES;
00612 break;
00613 case 'i':
00614 printf ( "debug: interface\n" );
00615 debug.interface = YES;
00616 break;
00617 case 'l':
00618 printf ( "debug: packet_length\n" );
00619 debug.packet_length = YES;
00620 break;
00621 case 'r':
00622 printf ( "debug: recv_buf\n" );
00623 debug.recv_buf = YES;
00624 break;
00625 case 's':
00626 printf ( "debug: send_buf\n" );
00627 debug.send_buf = YES;
00628 break;
00629 case 't':
00630 printf ( "debug: timestamp\n" );
00631 debug.timestamp = YES;
00632 break;
00633 case 'A':
00634 printf ( "debug: as_lookup\n" );
00635 debug.as_lookup = YES;
00636 break;
00637 case 'm':
00638 printf ( "debug: memory\n" );
00639 debug.memory = YES;
00640 break;
00641 default:
00642 printf ( "debug: invalid debug flag: %c\n", optarg [ i ] );
00643 break;
00644 }
00645 }
00646
00647 }
00648
00649
00650
00651
00652 void debug_packet ( const u_int8_t * const raw, const u_int bytes )
00653 {
00654 u_int i;
00655
00656
00657
00658 for ( i = 1; i <= bytes; i++ )
00659 {
00660 printf ( "%02x", raw [ i - 1 ] );
00661 if ( ( i % 2 ) == 0 ) { printf ( " " ); }
00662 if ( ( i % 16 ) == 0 ) { printf ( "\n" ); }
00663 }
00664 if ( ( i % 16 ) != 0 ) { printf ( "\n" ); }
00665
00666 return;
00667 }