aboutsummaryrefslogtreecommitdiffstats
path: root/libglouglou
diff options
context:
space:
mode:
authorLaurent Ghigonis <laurent@p1sec.com>2012-12-16 16:04:41 +0100
committerLaurent Ghigonis <laurent@p1sec.com>2012-12-16 16:04:41 +0100
commitc33819056af9c8908068164a50ee98d6b78f66c0 (patch)
tree9a132bd70edba599e8c57497b683d4d63cd29cef /libglouglou
parentlink to libpcap and libdnet (diff)
downloadglouglou-c33819056af9c8908068164a50ee98d6b78f66c0.tar.xz
glouglou-c33819056af9c8908068164a50ee98d6b78f66c0.zip
work on traceroute, initialisation code is there now
Diffstat (limited to 'libglouglou')
-rw-r--r--libglouglou/examples/traceroute.c55
-rw-r--r--libglouglou/libggnet_traceroute.c121
-rw-r--r--libglouglou/libggnet_traceroute.h29
3 files changed, 186 insertions, 19 deletions
diff --git a/libglouglou/examples/traceroute.c b/libglouglou/examples/traceroute.c
index 9d3e218..080274f 100644
--- a/libglouglou/examples/traceroute.c
+++ b/libglouglou/examples/traceroute.c
@@ -1,11 +1,25 @@
+#include <sys/types.h>
+
+#if !defined(__OpenBSD__)
+#define __USE_GNU
+#define _GNU_SOURCE
+#endif
+
+#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <err.h>
+
#include <libggnet_traceroute.h>
+static void _droppriv(char *, int, char *);
static void _cb_traceroute(struct in_addr *,
struct ggnet_traceroute_req *, void *);
@@ -29,20 +43,21 @@ main(int argc, char *argv[])
ip.s_addr = ntohl(ip.s_addr);
bzero(&tv, sizeof(struct timeval));
- tv.tv_sec = 5;
+ tv.tv_sec = 10;
_ev_base = event_base_new();
- ggtr = ggnet_traceroute_new(_ev_base);
- ggnet_traceroute_reverse(ggtr, &ip, _cb_traceroute, NULL);
+ ggtr = ggnet_traceroute_new(_ev_base, "lo"); // XXX rm iface
+ _droppriv("nobody", 1, NULL); /* bad practise you should use dedicated user */
+ ggnet_traceroute_trace(ggtr, &ip, _cb_traceroute, NULL);
event_base_loopexit(_ev_base, &tv);
event_base_dispatch(_ev_base);
if (_answer) {
printf("%x:\n", ip.s_addr);
- LIST_FOREACH(&_route->hops, h, entry) {
- printf("%x (%d)\n", h->ip.s_addr, h->delay);
+ LIST_FOREACH(hop, &_route->hops, entry) {
+ printf("%x (%d)\n", hop->ip.s_addr, hop->delay);
}
} else {
printf("no answer\n");
@@ -50,9 +65,37 @@ main(int argc, char *argv[])
return 0;
}
+/* from libglouglou utils.c */
+static void
+_droppriv(char *user, int do_chroot, char *chroot_path)
+{
+ struct passwd *pw;
+
+ pw = getpwnam(user);
+ if (!pw)
+ err(1, "unknown user %s", user);
+ if (do_chroot) {
+ if (!chroot_path)
+ chroot_path = pw->pw_dir;
+ if (chroot(chroot_path) != 0)
+ err(1, "unable to chroot");
+ }
+ if (chdir("/") != 0)
+ err(1, "unable to chdir");
+ if (setgroups(1, &pw->pw_gid) == -1)
+ err(1, "setgroups() failed");
+ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
+ err(1, "setresgid failed");
+ if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
+ err(1, "setresuid() failed");
+ endpwent();
+ printf("droppriv done\n");
+}
+
+
static void
_cb_traceroute(struct in_addr *ip,
- struct ggnet_traceroute_req *route, void *data);
+ struct ggnet_traceroute_req *route, void *data)
{
_route = route;
_answer = 1;
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);
+}
diff --git a/libglouglou/libggnet_traceroute.h b/libglouglou/libggnet_traceroute.h
index 24aea02..0c19bea 100644
--- a/libglouglou/libggnet_traceroute.h
+++ b/libglouglou/libggnet_traceroute.h
@@ -1,6 +1,6 @@
-#include <event2/dns.h>
-#include <event2/util.h>
-#include <event2/event.h>
+#include <event.h>
+#include <dnet.h>
+#include <pcap.h>
#if defined(__OpenBSD__)
#include <sys/queue.h>
@@ -17,7 +17,11 @@ struct ggnet_traceroute_hop {
struct ggnet_traceroute_req {
LIST_ENTRY(ggnet_traceroute_req) entry;
- struct event *ev;
+ struct event *ev_recv;
+ struct event *ev_send;
+ struct addr ip;
+ struct addr srcip;
+ int hops_count;
LIST_HEAD(, ggnet_traceroute_hop) hops;
void (*cb_usr)(struct in_addr *, char *, void *);
void *data;
@@ -25,15 +29,20 @@ struct ggnet_traceroute_req {
struct ggnet_traceroute {
struct event_base *ev_base;
+ pcap_t *pcap;
+ ip_t *pkt_ip;
+ rand_t *pkt_rand;
+ int pcap_fd;
+ int pcap_dllen; /* datalink layer hdr len */
int req_pending;
- LIST_HEAD(, ggnet_traceroute_req) req_list; /* XXX for now unused. remove ? */
+ LIST_HEAD(, ggnet_traceroute_req) req_list;
};
-struct ggnet_traceroute *ggnet_traceroute_new(struct event_base *);
-void ggnet_traceroute_free(struct ggnet_dns *);
-struct ggnet_traceroute_req *ggnet_traceroute_trace(struct ggnet_traceroute *ggtr,
- struct in_iddr *ip,
+struct ggnet_traceroute *ggnet_traceroute_new(struct event_base *, char *);
+void ggnet_traceroute_free(struct ggnet_traceroute *);
+struct ggnet_traceroute_req *ggnet_traceroute_trace(struct ggnet_traceroute *,
+ struct in_addr *ip,
void (*cb_usr)(struct in_addr *, struct ggnet_traceroute_req *, void *),
- void *data)
+ void *);
void ggnet_traceroute_cancel(struct ggnet_traceroute *,
struct ggnet_traceroute_req *);