aboutsummaryrefslogtreecommitdiffstats
path: root/libglouglou/libggnet_traceroute.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglouglou/libggnet_traceroute.c')
-rw-r--r--libglouglou/libggnet_traceroute.c121
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);
+}