diff options
Diffstat (limited to 'libglouglou/libggnet_traceroute.c')
-rw-r--r-- | libglouglou/libggnet_traceroute.c | 121 |
1 files changed, 118 insertions, 3 deletions
diff --git a/libglouglou/libggnet_traceroute.c b/libglouglou/libggnet_traceroute.c index 3b8e6ed..f00fd72 100644 --- a/libglouglou/libggnet_traceroute.c +++ b/libglouglou/libggnet_traceroute.c @@ -8,10 +8,31 @@ * All rights reserved. */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/types.h> + +#include <netinet/in.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "libggnet_traceroute.h" + +static void _req_free(struct ggnet_traceroute_req *); +static void _cb_recv(evutil_socket_t, short, void *); +static void _cb_send(evutil_socket_t, short, void *); +static int pcap_dloff(pcap_t *); // XXX move to libggnet_utils ? + struct ggnet_traceroute * -ggnet_traceroute_new(struct event_base *ev_base) +ggnet_traceroute_new(struct event_base *ev_base, char *iface) { struct ggnet_traceroute *ggtr; + char ebuff[PCAP_ERRBUF_SIZE]; ggtr = calloc(1, sizeof(struct ggnet_traceroute)); if (!ggtr) { @@ -19,18 +40,47 @@ ggnet_traceroute_new(struct event_base *ev_base) exit(1); } ggtr->ev_base = ev_base; - return ggdns; + ggtr->pkt_ip = ip_open(); + if (!ggtr->pkt_ip) { + printf("ip_open() failed\n"); + ggnet_traceroute_free(ggtr); + return NULL; + } + ggtr->pkt_rand = rand_open(); + + + /* XXX get iface from route_open, route_get and pcap_lookupnet. + * will need to do so in ggnet_traceroute_trace() so user privs, so will need + * to prefetch the routes / interfaces, maybe */ + + ggtr->pcap = pcap_open_live(iface, 1500, 1, 500, ebuff); + if (ggtr->pcap == NULL) + err(1, "pcap_open_live()"); + ggtr->pcap_dllen = pcap_dloff(ggtr->pcap); + ggtr->pcap_fd = pcap_fileno(ggtr->pcap); + + return ggtr; } void ggnet_traceroute_free(struct ggnet_traceroute *ggtr) { + struct ggnet_traceroute_req *req; + + if (ggtr->pcap) + pcap_close(ggtr->pcap); + if (ggtr->pkt_ip) + ip_close(ggtr->pkt_ip); + if (ggtr->pkt_rand) + rand_close(ggtr->pkt_rand); + LIST_FOREACH(req, &ggtr->req_list, entry) + _req_free(req); free(ggtr); } struct ggnet_traceroute_req * ggnet_traceroute_trace(struct ggnet_traceroute *ggtr, - struct in_iddr *ip, + struct in_addr *ip, void (*cb_usr)(struct in_addr *, struct ggnet_traceroute_req *, void *), void *data) { @@ -42,6 +92,16 @@ ggnet_traceroute_trace(struct ggnet_traceroute *ggtr, exit(1); } + addr_aton("127.0.0.1", &req->srcip); + addr_aton("127.0.0.1", &req->ip); + + req->ev_recv = event_new(ggtr->ev_base, + ggtr->pcap_fd, EV_READ, _cb_recv, req); + event_add(req->ev_recv, NULL); + req->ev_send = event_new(ggtr->ev_base, + ggtr->pcap_fd, EV_WRITE, _cb_send, req); + event_add(req->ev_send, NULL); + LIST_INSERT_HEAD(&ggtr->req_list, req, entry); return req; } @@ -52,5 +112,60 @@ ggnet_traceroute_cancel(struct ggnet_traceroute *ggtr, { LIST_REMOVE(req, entry); ggtr->req_pending--; + _req_free(req); +} + +static void +_req_free(struct ggnet_traceroute_req *req) +{ + if (req->ev_recv) + event_free(req->ev_recv); + if (req->ev_send) + event_free(req->ev_send); free(req); } + +static void +_cb_recv(evutil_socket_t fd, short what, void *arg) +{ + struct ggnet_traceroute_req *req; + + req = arg; + printf("cbggnet_traceroute cb_recv %s\n", addr_ntoa(&req->ip)); +} + +static void +_cb_send(evutil_socket_t fd, short what, void *arg) +{ + struct ggnet_traceroute_req *req; + + req = arg; + printf("cbggnet_traceroute cb_send %s\n", addr_ntoa(&req->ip)); +} + +static int +pcap_dloff(pcap_t *pd) +{ + int i; + + i = pcap_datalink(pd); + + switch (i) { + case DLT_EN10MB: + i = 14; + break; + case DLT_IEEE802: + i = 22; + break; + case DLT_FDDI: + i = 21; + break; + case DLT_NULL: + i = 4; + break; + default: + i = -1; + break; + } + return (i); +} |