/* * This code is meant to either: * 1) Wait until the first packet received, or * 2) Wait until no packets are recieved for some timeout * by a particular pcap filter and then, in either case, exit. * Copyright 2003,2006 Alexey Toptygin * Released under GPL Version 2, June 1991 and WITHOUT ANY WARRANTY */ #include #include #include #include #include #include #define MY_SNAP 68 /* this is what tcpdump uses */ static int timeout_len; void cb_exit ( u_char *user, const struct pcap_pkthdr *header, const u_char *packet ) { exit ( 0 ); } void cb_resetalarm ( u_char *user, const struct pcap_pkthdr *header, const u_char *packet ) { alarm ( timeout_len ); } void alarm_handler ( int sig ) { exit ( 0 ); } pcap_t *init_pcap ( char *interface, char *filter_string ) { char errbuf[PCAP_ERRBUF_SIZE]; pcap_t *foo; struct bpf_program fp; bpf_u_int32 net, mask; errbuf[0] = 0; if ( !( foo = pcap_open_live ( interface, MY_SNAP, 1, 0, errbuf ) ) ) { fprintf ( stderr, "Could not open interface '%s'\n", interface ); exit ( 1 ); } if ( errbuf[0] ) { fprintf ( stderr, "Warning while opening interface '%s'\n%s\n", interface, errbuf ); errbuf[0] = 0; } if ( pcap_lookupnet ( interface, &net, &mask, errbuf ) ) { fprintf ( stderr, "Could not lookup interface '%s'\n%s\n", interface, errbuf ); goto err; } if ( pcap_compile ( foo, &fp, filter_string, 1, mask ) ) { fprintf ( stderr, "Could not compile filter expression:\n%s\n%s\n", filter_string, pcap_geterr ( foo ) ); goto err; } if ( pcap_setfilter ( foo, &fp ) ) { fprintf ( stderr, "Could not attach filter!\n%s\n", pcap_geterr ( foo ) ); pcap_freecode ( &fp ); goto err; } pcap_freecode ( &fp ); return foo; err: pcap_close ( foo ); exit ( 1 ); } void wait_packet ( char *interface, char *filter_string ) { pcap_t *foo = init_pcap ( interface, filter_string ); if ( pcap_loop ( foo, 1, &cb_exit, NULL ) ) { fprintf ( stderr, "pcap_loop returned error\n%s\n", pcap_geterr ( foo ) ); } pcap_close ( foo ); exit ( 1 ); } void wait_timeout ( char *interface, char *filter_string ) { pcap_t *foo = init_pcap ( interface, filter_string ); if ( SIG_ERR == signal ( SIGALRM, &alarm_handler ) ) { perror ( "Could not set signal handler" ); goto err; } alarm ( timeout_len ); if ( pcap_loop ( foo, -1, &cb_resetalarm, NULL ) ) { fprintf ( stderr, "pcap_loop returned error\n%s\n", pcap_geterr ( foo ) ); } err: pcap_close ( foo ); exit ( 1 ); } void print_usage ( char *self_name ) { fprintf ( stderr, "Usage: %s [ -t ] \n", self_name ); } int main ( int argc, char **argv ) { if ( argc < 3 ) goto err; if ( ! strncmp ( argv[1], "-t", 3 ) ) { if ( argc < 5 ) goto err; if ( ( timeout_len = atoi ( argv[2] ) ) <= 0 ) { fprintf ( stderr, "Invalid timeout value '%s'\n", argv[2] ); goto err; } wait_timeout ( argv[3], argv[4] ); } wait_packet ( argv[1], argv[2] ); err: print_usage ( argv[0] ); return 1; }