aboutsummaryrefslogtreecommitdiffstats
path: root/libglouglou/examples/traceroute.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglouglou/examples/traceroute.c')
-rw-r--r--libglouglou/examples/traceroute.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/libglouglou/examples/traceroute.c b/libglouglou/examples/traceroute.c
new file mode 100644
index 0000000..080274f
--- /dev/null
+++ b/libglouglou/examples/traceroute.c
@@ -0,0 +1,103 @@
+#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 *);
+
+struct event_base *_ev_base;
+struct ggnet_traceroute_req *_route = NULL;
+int _answer = 0;
+
+int
+main(int argc, char *argv[])
+{
+ struct ggnet_traceroute *ggtr;
+ struct ggnet_traceroute_hop *hop;
+ struct in_addr ip;
+ struct timeval tv;
+
+ if (argc < 2) {
+ printf("usage: traceroute <ip>\n");
+ exit(1);
+ }
+ inet_aton(argv[1], &ip);
+ ip.s_addr = ntohl(ip.s_addr);
+
+ bzero(&tv, sizeof(struct timeval));
+ tv.tv_sec = 10;
+
+ _ev_base = event_base_new();
+
+ 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(hop, &_route->hops, entry) {
+ printf("%x (%d)\n", hop->ip.s_addr, hop->delay);
+ }
+ } else {
+ printf("no answer\n");
+ }
+ 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)
+{
+ _route = route;
+ _answer = 1;
+ event_base_loopexit(_ev_base, NULL);
+}