From dd630f57c65931c3b6c5da8151193d73b2b768bd Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sat, 20 Oct 2012 16:22:14 +0000 Subject: Première version du client TZSP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2012-tzsp/trunk@2 147d2d3d-d0bd-48ea-923a-d90ac20f5906 --- pcap2tzsp.c | 304 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 pcap2tzsp.c (limited to 'pcap2tzsp.c') diff --git a/pcap2tzsp.c b/pcap2tzsp.c new file mode 100644 index 0000000..294ec32 --- /dev/null +++ b/pcap2tzsp.c @@ -0,0 +1,304 @@ + +/* Basics */ +#include +#include +#include + +/* Args parsing and basename() for usage */ +#include +#include + +/* UDP stuff */ +#include +#include +#include +#include +#include + +/* Packet capture stuff */ +#include +#include + +#define DEFAULT_FILTER "not ( udp and dst %s and port %s )" +#define DEFAULT_HOST "127.0.0.1" +#define DEFAULT_PORT "37008" +#define DEFAULT_SNAPLEN "64" + +#define UDP_SEND_BUFLEN 1500 +#define MAX_TZSP_PAYLOAD (1500-40-16) +#define MAX_BYTES_TO_CAPTURE (1500-40-16) + + +/* +TODO List + * Corriger bug du filtre par défaut qui capture qd même le traffic TZSP émis + * Utiliser le opt_snaplen réellement + * Resolution DNS host -> IP (c'est l'ip qu'il faut dans le filtre et pas le host !!) + * Stats nombre de packets loupés ? + * Implémenter une bwlimit en sortie (ptks/s et/ou bytes/s) + * Pkt timestamps sur 64bits (quel field prendre ?) + * Comparer les headers envoyés par un mikrotik avec /tool sniffer + * free() de tous les malloc(), calloc() et strdup() + * Graceful stop avec signal() + * Licence GPL +*/ + +/* Functions declaration */ +void capture_loop(char pcap_filter[]); +void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u_char * packet); + +/* Custom types definition */ +typedef struct _process_packet_args { + uint64_t pkt_count; + int udp_socket; + struct sockaddr_in udp_sockaddr; +} process_packet_args_t; + +/* Constants */ +const int sockaddr_len=sizeof(struct sockaddr_in); + + +/* Flags from commandline parsing */ +static int opt_verbose; +/* Option arguments from commandline parsing */ +static char *opt_iface=NULL; +static char *opt_host=NULL; +static char *opt_port=NULL; +static char *opt_snaplen=NULL; + + +void usage(char progname[]) { + printf("Usage : %s [--verbose] [--brief] [-i ] [-h ] [-p ] [custom_pcap_filter]\n", progname); + printf("\t : Interface name to capture from (Default : first available interface)\n"); + printf("\t : Host (or IPv4 address) for sending captured packet headers (Default : '%s')\n", DEFAULT_HOST); + printf("\t : Port for sending captured packet headers (Default '%s')\n", DEFAULT_PORT); + printf("\t : libpcap capture filter (Default '%s')\n", DEFAULT_FILTER); + exit(1); +} + +int main(int argc, char *argv[]) { + + /* Command line args parsing */ + int c,i,j,pcap_filter_len; + char *pcap_filter=NULL; + + while (1) { + static struct option long_options[] = { + /* These options set a flag. */ + {"verbose", no_argument, &opt_verbose, 1}, + {"brief", no_argument, &opt_verbose, 0}, + /* These options don't set a flag. + We distinguish them by their indices. */ + {"interface", required_argument, 0, 'i'}, + {"host", required_argument, 0, 'h'}, + {"port", required_argument, 0, 'p'}, + {"snaplen", required_argument, 0, 's'}, + {0, 0, 0, 0} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long(argc, argv, "i:h:p:s:", long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) break; + + switch (c) { + case 0: + /* If this option set a flag, do nothing else now. */ + if (long_options[option_index].flag != 0) break; + + //printf ("option %s", long_options[option_index].name); + //if (optarg) printf (" with arg %s", optarg); + //printf ("\n"); + + break; + case 'i': opt_iface= strdup(optarg); break; + case 'h': opt_host= strdup(optarg); break; + case 'p': opt_port= strdup(optarg); break; + case 's': opt_snaplen= strdup(optarg); break; + case '?': + /* getopt_long already printed an error message. */ + usage(basename(argv[0])); + break; + default: + abort(); + } + } + + // Assign default value if no user supplied value + if (opt_host==NULL) opt_host=strdup(DEFAULT_HOST); + if (opt_port==NULL) opt_port=strdup(DEFAULT_PORT); + if (opt_snaplen==NULL) opt_snaplen=strdup(DEFAULT_SNAPLEN); + // No default for opt_iface because will be choosen at runtime + + //if (verbose_flag) puts ("verbose flag is set"); + + /* Construct the pcap_filter */ + pcap_filter_len=0; + if (optind < argc) { + // Any remaining command line arguments is for pcap_filter + for (i=optind; ipkt_count++; + + if (old_tv_sec != pkthdr->ts.tv_sec) { + //printf("DEBUG : throughput=((double) %llu - %llu ) / ( %u - %u )\n", args->pkt_count, old_pkt_count, pkthdr->ts.tv_sec, old_tv_sec); + throughput=((double) args->pkt_count - old_pkt_count ) / (pkthdr->ts.tv_sec - old_tv_sec); + printf("\rPacket Count: %20llu (%8.1f pkt/s)", args->pkt_count, throughput); + fflush(stdout); + old_tv_sec=pkthdr->ts.tv_sec; + old_pkt_count= args->pkt_count; + } + + /* Variable fields for TZSP packet */ + ts=htonl((uint32_t) pkthdr->ts.tv_sec); /* TODO : this cast is bullshit ? */ + len=htons((uint16_t) pkthdr->len); + + /* TaZmen Sniffing Protocol (TZSP) packet forging */ + + //memset((char *) &buf, 0, UDP_SEND_BUFLEN); /* Buffer reset not useful for now */ + buf[0]=0x01; /* Version */ + buf[1]=0x01; /* Type == Packet for transmit */ + buf[2]=0x00; /* Encapsuled protocol (2 bytes) 0x0001 == Ethernet */ + buf[3]=0x01; + + buf[4]=0x0D; /* Tag type == TAG_TIMESTAMP */ + buf[5]=0x04; /* Tag length == 4 bytes */ + + /* buf[6,7,8,9] Timestamp on 4 bytes (network order) */ + memcpy(buf+6, &ts, 4); + + buf[10]=0x29; /* Tag type TAG_RX_FRAME_LENGTH */ + buf[11]=0x02; /* Tag length : 2 bytes */ + memcpy(buf+12,&len, 2); + + buf[14]=0x00; /* Tag type TAG PADDING (for alignement) */ + buf[15]=0x01; /* Tag type TAG END */ + + /* Raw packet copy */ + //TODO : assert that pkthdr->caplen < MAX_TZSP_PAYLOAD + 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"); + } +} + -- cgit v1.2.3