#include #if !defined(__OpenBSD__) #define __USE_GNU #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include 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 \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); }