diff options
-rw-r--r-- | pcap2tzsp.c | 155 |
1 files changed, 106 insertions, 49 deletions
diff --git a/pcap2tzsp.c b/pcap2tzsp.c index 8ec9e9f..e84f5bf 100644 --- a/pcap2tzsp.c +++ b/pcap2tzsp.c @@ -13,11 +13,12 @@ #include <libgen.h> /* UDP stuff */ -#include <arpa/inet.h> -#include <netinet/in.h> +/*#include <arpa/inet.h> +#include <netinet/in.h> no longer used */ #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> +#include <netdb.h> /* Name resolution */ /* Packet capture stuff */ #include <pcap.h> @@ -28,7 +29,7 @@ /* Option default values (as strings) */ #define DEFAULT_FILTER "not ( icmp[icmptype]=icmp-unreach or (udp and dst %s and port %s) )" -#define DEFAULT_HOST "127.0.0.1" +#define DEFAULT_HOST "localhost" #define DEFAULT_PORT "37008" #define DEFAULT_SNAPLEN "70" @@ -43,18 +44,20 @@ #define MIN_BYTES_TO_CAPTURE 16 #define MAX_BYTES_TO_CAPTURE (1500-20-8-16) - +/* Max len of a numerical form of host address 39 chars in IPv6 */ +#define NI_MAXHOST_NUMERIC 40 /* TODO List * Resolution DNS host -> IP (c'est l'ip qu'il faut dans le filtre et pas le host !!) * Implémenter une bwlimit en sortie (ptks/s et/ou bytes/s) - * TZSP over IPv6 + * TZSP over IPv6 (le filter doit avoir le dst qui va bien , pas le nom, l'adresse) * getopts -v et --help * Licence GPL */ /* Functions declaration */ -void capture_loop(char pcap_filter[]); +int make_dgram_socket(char host[], char service[], int hint_flags, char **resolved_address); +void start_capture_loop(char *pcap_filter); void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u_char * packet); /* Custom types definition */ @@ -62,13 +65,9 @@ typedef struct _process_packet_args { /* Types like in libpcap because I don't want to mess around hours */ u_int captured_pkt_count; u_int sent_pkt_count; - int udp_socket; - struct sockaddr_in udp_sockaddr; + int socket; } process_packet_args_t; -/* Constants */ -const int sockaddr_len=sizeof(struct sockaddr_in); - /* Flags from commandline parsing */ static int opt_verbose; @@ -182,40 +181,91 @@ int main(int argc, char *argv[]) { j+=sprintf(pcap_filter+j, "%s", argv[i]); } } - } else { - // Else, use the default filter (skip the TZSP packet flow to host:port) - pcap_filter_len = strlen(DEFAULT_FILTER) -4 + strlen(opt_host) + strlen(opt_port) + 1; - pcap_filter=calloc(pcap_filter_len+1, sizeof(char)); - j=sprintf(pcap_filter, DEFAULT_FILTER, opt_host, opt_port); } - //printf ("Capture filter will be : '%s' (pcap_filter_len-j==%i)\n", pcap_filter, pcap_filter_len-j); - signal(SIGINT, sig_handler); /* Run the capture loop */ - capture_loop(pcap_filter); - - free(pcap_filter); + start_capture_loop(pcap_filter); free(opt_host); free(opt_port); free(opt_snaplen); if (opt_iface!=NULL) free(opt_iface); + if (pcap_filter!=NULL) free(pcap_filter); return 0; } +int make_dgram_socket(char host[], char service[], int hint_flags, char **resolved_address) { + + /* Code taken from Client program example of getaddrinfo(3) manpage */ + + struct addrinfo hints; + struct addrinfo *result, *rp; + char hbuf[NI_MAXHOST_NUMERIC]; + int sfd, s; + + /* Obtain address(es) matching host/port */ -void capture_loop(char pcap_filter[]) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = hint_flags | AI_CANONNAME; + hints.ai_protocol = 0; /* Any protocol */ + + s = getaddrinfo(host, service, &hints, &result); + if (s != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); + exit(EXIT_FAILURE); + } + + /* getaddrinfo() returns a list of address structures. + Try each address until we successfully connect(2). + If socket(2) (or connect(2)) fails, we (close the socket + and) try the next address. */ + + for (rp = result; rp != NULL; rp = rp->ai_next) { + sfd = socket(rp->ai_family, rp->ai_socktype, + rp->ai_protocol); + if (sfd == -1) + continue; + + if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + break; /* Success */ + + close(sfd); + } + + if (rp == NULL) { /* No address succeeded */ + freeaddrinfo(result); + return -1; + } + + /* This part was not in the example as is */ + if ( resolved_address != NULL) { + /* If wanted, return numerical form of the choosen host address */ + if ( getnameinfo(rp->ai_addr, rp->ai_addrlen, hbuf, + NI_MAXHOST_NUMERIC, NULL, 0, NI_NUMERICHOST) == 0 ) { + *resolved_address=strdup(hbuf); + } + } + + freeaddrinfo(result); /* No longer needed */ + return sfd; +} + + +void start_capture_loop(char *pcap_filter) { //Global for signal handling //pcap_t *pcap_handle = NULL; + char *resolved_address=NULL; static char *pcap_device=NULL; char pcap_errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program pcap_filter_prog; struct pcap_stat stat; process_packet_args_t process_packet_args; - int snaplen; + int snaplen, hints_flags, pcap_filter_len, pcap_filter_synthetised=0; memset(pcap_errbuf,0,PCAP_ERRBUF_SIZE); memset(&process_packet_args,0,sizeof(process_packet_args_t)); @@ -237,16 +287,15 @@ void capture_loop(char pcap_filter[]) { exit(12); } - /* Already done : memset((char *) &(process_packet_args.udp_sockaddr), 0, sockaddr_len); */ - process_packet_args.udp_sockaddr.sin_family = AF_INET; - process_packet_args.udp_sockaddr.sin_port = htons(atoi(opt_port)); - if (inet_aton(opt_host, &(process_packet_args.udp_sockaddr.sin_addr))==0) { - fprintf(stderr, "inet_aton : Impossible de parser l'IP %s\n",opt_host); - exit(11); + /* UDP socket creation */ + hints_flags=AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED; + if (opt_verbose) printf("Opening socket for sending TZSP to %s:%s\n", opt_host, opt_port); + if ( ( process_packet_args.socket = make_dgram_socket(opt_host, opt_port, hints_flags, &resolved_address) ) == -1 ) { + fprintf(stderr, "ERROR : Couldn't make a socket to %s:%s\n", opt_host, opt_port); + exit(10); } - - /* Initialisation pcap */ + /* pcap init */ if (opt_verbose) printf("Opening device %s for capturing\n", pcap_device); /* Open device in promiscuous mode */ @@ -255,12 +304,25 @@ void capture_loop(char pcap_filter[]) { exit(21); } + if (pcap_filter==NULL) { + pcap_filter_synthetised=1; + // Synthethise a default filter that skip the TZSP packet flow to host:port + pcap_filter_len = strlen(DEFAULT_FILTER) -4 + strlen(resolved_address) + strlen(opt_port) + 1; + pcap_filter=calloc(pcap_filter_len, sizeof(char)); + //XXX pos=snprintf(pcap_filter, pcap_filter_len, DEFAULT_FILTER, resolved_address, opt_port); + /*res=*/ (void)sprintf(pcap_filter, DEFAULT_FILTER, resolved_address, opt_port); + //printf ("DEBUG : Capture filter will be : '%s' (pcap_filter_len-res==%i)\n", pcap_filter, pcap_filter_len-res); + } + free(resolved_address); + if (opt_verbose) printf("Compiling the following capture filter : '%s'\n", pcap_filter); if ( pcap_compile(pcap_handle,&pcap_filter_prog,pcap_filter,1,PCAP_NETMASK_UNKNOWN) == -1 ) { fprintf(stderr,"ERROR : %s\n", pcap_geterr(pcap_handle) ); exit(22); } + if (pcap_filter_synthetised) free(pcap_filter); + if ( pcap_setfilter(pcap_handle,&pcap_filter_prog) == -1 ) { fprintf(stderr,"ERROR : %s\n", pcap_geterr(pcap_handle) ); exit(23); @@ -268,13 +330,6 @@ void capture_loop(char pcap_filter[]) { pcap_freecode(&pcap_filter_prog); - /* Initialisation socket UDP */ - process_packet_args.udp_socket=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (process_packet_args.udp_socket==-1) { - perror("socket"); - exit(10); - } - /* Loop forever & call process_packet() for every received packet */ if ( pcap_loop(pcap_handle, -1, process_packet, (u_char *)&process_packet_args) == -1) { fprintf(stderr, "ERROR: %s\n", pcap_geterr(pcap_handle) ); @@ -292,7 +347,8 @@ void capture_loop(char pcap_filter[]) { stat.ps_recv, stat.ps_drop); pcap_close(pcap_handle); - close(process_packet_args.udp_socket); + close(process_packet_args.socket); + //XXX freeaddrinfo(target_addrinfo); } @@ -304,12 +360,12 @@ void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u static time_t old_tv_sec=0; static u_int old_captured_pkt_count=0; - int res; + int res, tzsp_len; double throughput; - uint32_t ts; /* In network byte order */ //uint32_t pkt_num; /* In network byte order */ - uint16_t len; /* In network byte order */ + uint32_t field_ts; /* In network byte order */ + uint16_t field_len; /* In network byte order */ char buf[UDP_SEND_BUFLEN]; /* struct timespec ts_reqsleep; For simulation */ @@ -332,8 +388,8 @@ void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u //TODO : bwlimit HERE (not before, no after) /* Variable fields for TZSP packet */ - ts=htonl((uint32_t) pkthdr->ts.tv_sec); /* TODO : this cast is bullshit ? */ - len=htons((uint16_t) pkthdr->len); + field_ts=htonl((uint32_t) pkthdr->ts.tv_sec); /* TODO : this cast is bullshit ? */ + field_len=htons((uint16_t) pkthdr->len); //pkt_num=htons((uint32_t) args->captured_pkt_count); /* TaZmen Sniffing Protocol (TZSP) packet forging */ @@ -348,7 +404,7 @@ void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u buf[5]=0x04; /* Tag length == 4 bytes */ /* buf[6,7,8,9] Timestamp on 4 bytes (network order) */ - memcpy(buf+6, &ts, 4); + memcpy(buf+6, &field_ts, 4); /* Wireshark don't dissect that */ //buf[10]=0x28; /* Tag type TAG_PACKET_COUNT */ @@ -357,7 +413,7 @@ void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u buf[10]=0x29; /* Tag type TAG_RX_FRAME_LENGTH */ buf[11]=0x02; /* Tag length == 2 bytes */ - memcpy(buf+12,&len, 2); + memcpy(buf+12, &field_len, 2); buf[14]=0x00; /* Tag type TAG PADDING (for alignement) */ buf[15]=0x01; /* Tag type TAG END */ @@ -367,9 +423,10 @@ void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u memcpy(buf+16,packet, pkthdr->caplen); /* TZSP packet sending (over the UDP socket) */ - res=sendto(args->udp_socket, buf, 16+pkthdr->caplen, 0, (struct sockaddr *)&(args->udp_sockaddr), sockaddr_len); - if (res==-1) { - fprintf(stderr, "sendto() error\n"); + tzsp_len=16+pkthdr->caplen; + res=write(args->socket, buf, tzsp_len); + if (res != tzsp_len) { + fprintf(stderr, "write() on UDP socket error (written %i of %i bytes)\n", res, tzsp_len); } else { args->sent_pkt_count++; } |