summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2012-10-21 16:05:19 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2012-10-21 16:05:19 +0000
commitd659ce6701878068bd475ef1f482c0a601b138bb (patch)
tree76043fe09a3fd50c975c3ad338b19fcca3c21107
parent87a0dd9a5fa0f673d95bd20ee3750af21243f10c (diff)
download2012-tzsp-d659ce6701878068bd475ef1f482c0a601b138bb.tar.gz
2012-tzsp-d659ce6701878068bd475ef1f482c0a601b138bb.tar.bz2
2012-tzsp-d659ce6701878068bd475ef1f482c0a601b138bb.zip
Partie UDP revampée (write() à la place de sendto() grace à l'utilisation de connect() en UDP...
Oui oui, c'est possible et normal. Résolution des noms avec getnameinfo(). Synthèse du filter par défaut en fonction de ça. Reste à tester avec un PC en IPv6 ! git-svn-id: file:///var/svn/2012-tzsp/trunk@10 147d2d3d-d0bd-48ea-923a-d90ac20f5906
-rw-r--r--pcap2tzsp.c155
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++;
}