diff options
Diffstat (limited to 'libglouglou/examples/traceroute.c')
-rw-r--r-- | libglouglou/examples/traceroute.c | 103 |
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); +} |