diff options
-rw-r--r-- | usr.sbin/traceroute/traceroute.c | 247 | ||||
-rw-r--r-- | usr.sbin/traceroute/traceroute.h | 68 | ||||
-rw-r--r-- | usr.sbin/traceroute/worker.c | 112 |
3 files changed, 241 insertions, 186 deletions
diff --git a/usr.sbin/traceroute/traceroute.c b/usr.sbin/traceroute/traceroute.c index b664dd71fa2..9debcb2610b 100644 --- a/usr.sbin/traceroute/traceroute.c +++ b/usr.sbin/traceroute/traceroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: traceroute.c,v 1.152 2017/05/28 10:00:00 benno Exp $ */ +/* $OpenBSD: traceroute.c,v 1.153 2017/05/28 10:01:52 benno Exp $ */ /* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */ /* @@ -258,9 +258,6 @@ #include "traceroute.h" -struct in_addr gateway[MAX_LSRR + 1]; - -int lsrrlen = 0; int32_t sec_perturb; int32_t usec_perturb; @@ -277,16 +274,7 @@ struct in6_pktinfo *rcvpktinfo; char *hostname; -u_short ident; u_int16_t srcport; -u_int16_t port = 32768+666;/* start udp dest port # for probe packets */ -u_char proto = IPPROTO_UDP; - -int verbose; -int curwaittime; /* time left to wait for response */ -int nflag; /* print addresses numerically */ -int dump; -int Aflag; /* lookup ASN */ int last_tos; void usage(int); @@ -297,9 +285,16 @@ int main(int argc, char *argv[]) { int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; - int ttl_flag = 0, incflag = 1, protoset = 0, sump = 0; - int ch, i, lsrr = 0, on = 1, probe, seq = 0, tos = 0, error, packetlen; - int rcvcmsglen, rcvsock4, rcvsock6, sndsock4, sndsock6, waittime; + + int ch, i; + int on = 1; + int probe; + int seq = 0; + int error; + int packetlen; + int rcvcmsglen; + int curwaittime; + int rcvsock4, rcvsock6, sndsock4, sndsock6; int v4sock_errno, v6sock_errno; struct addrinfo hints, *res; struct passwd *pw; @@ -312,35 +307,44 @@ main(int argc, char *argv[]) u_int32_t tmprnd; struct ip *ip = NULL; u_int8_t ttl; - char *ep, hbuf[NI_MAXHOST], *dest, *source = NULL; + char hbuf[NI_MAXHOST]; + char *dest; const char *errstr; long l; uid_t ouid, uid; gid_t gid; - u_int rtableid = 0; + socklen_t len; int headerlen; /* How long packet's header is */ - int nprobes = 3; - u_int8_t max_ttl = IPDEFTTL; - u_int8_t first_ttl = 1; - - int options = 0; /* socket options */ int xflag = 0; /* show ICMP extension header */ - int tflag = 0; /* tos flag was set */ int v6flag = 0; struct msghdr rcvmhdr; struct iovec rcviov[2]; + /* configuration defaults */ + struct tr_conf *conf; + if ((conf = calloc(1, sizeof(*conf))) == NULL) + err(1,NULL); + + conf->incflag = 1; + conf->first_ttl = 1; + conf->proto = IPPROTO_UDP; + conf->max_ttl = IPDEFTTL; + conf->nprobes = 3; + + /* start udp dest port # for probe packets */ + conf->port = 32768+666; + memset(&rcvmhdr, 0, sizeof(rcvmhdr)); memset(&rcviov, 0, sizeof(rcviov)); rcvsock4 = rcvsock6 = sndsock4 = sndsock6 = -1; v4sock_errno = v6sock_errno = 0; - waittime = 5 * 1000; + conf->waittime = 5 * 1000; if ((rcvsock6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) v6sock_errno = errno; @@ -407,83 +411,88 @@ main(int argc, char *argv[]) size = sizeof(i); if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0) == -1) err(1, "sysctl"); - max_ttl = i; + conf->max_ttl = i; while ((ch = getopt(argc, argv, v6flag ? "AcDdf:Ilm:np:q:Ss:w:vV:" : "AcDdf:g:Ilm:nP:p:q:Ss:t:V:vw:x")) != -1) switch (ch) { case 'A': - Aflag = 1; + conf->Aflag = 1; break; case 'c': - incflag = 0; + conf->incflag = 0; break; case 'd': - options |= SO_DEBUG; + conf->dflag = 1; break; case 'D': - dump = 1; + conf->dump = 1; break; case 'f': - first_ttl = strtonum(optarg, 1, max_ttl, &errstr); + conf->first_ttl = strtonum(optarg, 1, conf->max_ttl, + &errstr); if (errstr) - errx(1, "min ttl must be 1 to %u.", max_ttl); + errx(1, "min ttl must be 1 to %u.", + conf->max_ttl); break; case 'g': - if (lsrr >= MAX_LSRR) + if (conf->lsrr >= MAX_LSRR) errx(1, "too many gateways; max %d", MAX_LSRR); - if (inet_aton(optarg, &gateway[lsrr]) == 0) { + if (inet_aton(optarg, &conf->gateway[conf->lsrr]) == + 0) { hp = gethostbyname(optarg); if (hp == 0) errx(1, "unknown host %s", optarg); - memcpy(&gateway[lsrr], hp->h_addr, + memcpy(&conf->gateway[conf->lsrr], hp->h_addr, hp->h_length); } - if (++lsrr == 1) - lsrrlen = 4; - lsrrlen += 4; + if (++conf->lsrr == 1) + conf->lsrrlen = 4; + conf->lsrrlen += 4; break; case 'I': - if (protoset) + if (conf->protoset) errx(1, "protocol already set with -P"); - protoset = 1; - proto = IPPROTO_ICMP; + conf->protoset = 1; + conf->proto = IPPROTO_ICMP; break; case 'l': - ttl_flag = 1; + conf->ttl_flag = 1; break; case 'm': - max_ttl = strtonum(optarg, first_ttl, MAXTTL, &errstr); + conf->max_ttl = strtonum(optarg, conf->first_ttl, + MAXTTL, &errstr); if (errstr) - errx(1, "max ttl must be %u to %u.", first_ttl, - MAXTTL); + errx(1, "max ttl must be %u to %u.", + conf->first_ttl, MAXTTL); break; case 'n': - nflag = 1; + conf->nflag = 1; break; case 'p': - port = strtonum(optarg, 1, 65535, &errstr); + conf->port = strtonum(optarg, 1, 65535, &errstr); if (errstr) errx(1, "port must be >0, <65536."); break; case 'P': - if (protoset) + if (conf->protoset) errx(1, "protocol already set with -I"); - protoset = 1; - proto = strtonum(optarg, 1, IPPROTO_MAX - 1, &errstr); + conf->protoset = 1; + conf->proto = strtonum(optarg, 1, IPPROTO_MAX - 1, + &errstr); if (errstr) { struct protoent *pent; pent = getprotobyname(optarg); if (pent) - proto = pent->p_proto; + conf->proto = pent->p_proto; else errx(1, "proto must be >=1, or a " "name."); } break; case 'q': - nprobes = strtonum(optarg, 1, INT_MAX, &errstr); + conf->nprobes = strtonum(optarg, 1, INT_MAX, &errstr); if (errstr) errx(1, "nprobes must be >0."); break; @@ -492,15 +501,16 @@ main(int argc, char *argv[]) * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ - source = optarg; + conf->source = optarg; break; case 'S': - sump = 1; + conf->sump = 1; break; case 't': - if (!map_tos(optarg, &tos)) { + if (!map_tos(optarg, &conf->tos)) { if (strlen(optarg) > 1 && optarg[0] == '0' && optarg[1] == 'x') { + char *ep; errno = 0; ep = NULL; l = strtol(optarg, &ep, 16); @@ -508,38 +518,39 @@ main(int argc, char *argv[]) l < 0 || l > 255) errx(1, "illegal tos value %s", optarg); - tos = (int)l; + conf->tos = (int)l; } else { - tos = strtonum(optarg, 0, 255, &errstr); + conf->tos = strtonum(optarg, 0, 255, + &errstr); if (errstr) errx(1, "illegal tos value %s", optarg); } } - tflag = 1; - last_tos = tos; + conf->tflag = 1; + last_tos = conf->tos; break; case 'v': - verbose = 1; + conf->verbose = 1; break; case 'V': - rtableid = (unsigned int)strtonum(optarg, 0, + conf->rtableid = (unsigned int)strtonum(optarg, 0, RT_TABLEID_MAX, &errstr); if (errstr) errx(1, "rtable value is %s: %s", errstr, optarg); if (setsockopt(sndsock, SOL_SOCKET, SO_RTABLE, - &rtableid, sizeof(rtableid)) == -1) + &conf->rtableid, sizeof(conf->rtableid)) == -1) err(1, "setsockopt SO_RTABLE"); if (setsockopt(rcvsock, SOL_SOCKET, SO_RTABLE, - &rtableid, sizeof(rtableid)) == -1) + &conf->rtableid, sizeof(conf->rtableid)) == -1) err(1, "setsockopt SO_RTABLE"); break; case 'w': - waittime = strtonum(optarg, 2, INT_MAX, &errstr); + conf->waittime = strtonum(optarg, 2, INT_MAX, &errstr); if (errstr) errx(1, "wait must be >1 sec."); - waittime *= 1000; + conf->waittime *= 1000; break; case 'x': xflag = 1; @@ -555,7 +566,7 @@ main(int argc, char *argv[]) setvbuf(stdout, NULL, _IOLBF, 0); - ident = (getpid() & 0xffff) | 0x8000; + conf->ident = (getpid() & 0xffff) | 0x8000; tmprnd = arc4random(); sec_perturb = (tmprnd & 0x80000000) ? -(tmprnd & 0x7ff) : (tmprnd & 0x7ff); @@ -619,17 +630,17 @@ main(int argc, char *argv[]) switch (to->sa_family) { case AF_INET: - switch (proto) { + switch (conf->proto) { case IPPROTO_UDP: - headerlen = (sizeof(struct ip) + lsrrlen + + headerlen = (sizeof(struct ip) + conf->lsrrlen + sizeof(struct udphdr) + sizeof(struct packetdata)); break; case IPPROTO_ICMP: - headerlen = (sizeof(struct ip) + lsrrlen + + headerlen = (sizeof(struct ip) + conf->lsrrlen + sizeof(struct icmp) + sizeof(struct packetdata)); break; default: - headerlen = (sizeof(struct ip) + lsrrlen + + headerlen = (sizeof(struct ip) + conf->lsrrlen + sizeof(struct packetdata)); } @@ -652,36 +663,37 @@ main(int argc, char *argv[]) rcvmhdr.msg_controllen = 0; ip = (struct ip *)outpacket; - if (lsrr != 0) { + if (conf->lsrr != 0) { u_char *p = (u_char *)(ip + 1); *p++ = IPOPT_NOP; *p++ = IPOPT_LSRR; - *p++ = lsrrlen - 1; + *p++ = conf->lsrrlen - 1; *p++ = IPOPT_MINOFF; - gateway[lsrr] = to4.sin_addr; - for (i = 1; i <= lsrr; i++) { - memcpy(p, &gateway[i], sizeof(struct in_addr)); + conf->gateway[conf->lsrr] = to4.sin_addr; + for (i = 1; i <= conf->lsrr; i++) { + memcpy(p, &conf->gateway[i], + sizeof(struct in_addr)); p += sizeof(struct in_addr); } - ip->ip_dst = gateway[0]; + ip->ip_dst = conf->gateway[0]; } else ip->ip_dst = to4.sin_addr; ip->ip_off = htons(0); - ip->ip_hl = (sizeof(struct ip) + lsrrlen) >> 2; - ip->ip_p = proto; + ip->ip_hl = (sizeof(struct ip) + conf->lsrrlen) >> 2; + ip->ip_p = conf->proto; ip->ip_v = IPVERSION; - ip->ip_tos = tos; + ip->ip_tos = conf->tos; if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) err(6, "IP_HDRINCL"); - if (source) { + if (conf->source) { memset(&from4, 0, sizeof(from4)); from4.sin_family = AF_INET; - if (inet_aton(source, &from4.sin_addr) == 0) - errx(1, "unknown host %s", source); + if (inet_aton(conf->source, &from4.sin_addr) == 0) + errx(1, "unknown host %s", conf->source); ip->ip_src = from4.sin_addr; if (ouid != 0 && (ntohl(from4.sin_addr.s_addr) & 0xff000000U) == @@ -706,7 +718,7 @@ main(int argc, char *argv[]) * are prepended to the packet by the kernel */ packetlen = sizeof(struct ip6_hdr); - switch (proto) { + switch (conf->proto) { case IPPROTO_UDP: headerlen = sizeof(struct packetdata); packetlen += sizeof(struct udphdr); @@ -716,7 +728,7 @@ main(int argc, char *argv[]) sizeof(struct packetdata); break; default: - errx(1, "Unsupported proto: %hhu", proto); + errx(1, "Unsupported proto: %hhu", conf->proto); break; } @@ -748,7 +760,7 @@ main(int argc, char *argv[]) /* * Send UDP or ICMP */ - if (proto == IPPROTO_ICMP) { + if (conf->proto == IPPROTO_ICMP) { close(sndsock); sndsock = rcvsock; } @@ -757,13 +769,15 @@ main(int argc, char *argv[]) * Source selection */ memset(&from6, 0, sizeof(from6)); - if (source) { + if (conf->source) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_NUMERICHOST; - if ((error = getaddrinfo(source, "0", &hints, &res))) - errx(1, "%s: %s", source, gai_strerror(error)); + if ((error = getaddrinfo(conf->source, "0", &hints, + &res))) + errx(1, "%s: %s", conf->source, + gai_strerror(error)); if (res->ai_addrlen != sizeof(from6)) errx(1, "size of sockaddr mismatch"); memcpy(&from6, res->ai_addr, res->ai_addrlen); @@ -776,9 +790,9 @@ main(int argc, char *argv[]) nxt.sin6_port = htons(DUMMY_PORT); if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) err(1, "socket"); - if (rtableid > 0 && - setsockopt(dummy, SOL_SOCKET, SO_RTABLE, &rtableid, - sizeof(rtableid)) < 0) + if (conf->rtableid > 0 && + setsockopt(dummy, SOL_SOCKET, SO_RTABLE, + &conf->rtableid, sizeof(conf->rtableid)) < 0) err(1, "setsockopt(SO_RTABLE)"); if (connect(dummy, (struct sockaddr *)&nxt, nxt.sin6_len) < 0) @@ -805,7 +819,7 @@ main(int argc, char *argv[]) break; } - if (options & SO_DEBUG) { + if (conf->dflag) { (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, @@ -816,7 +830,7 @@ main(int argc, char *argv[]) sizeof(datalen)) < 0) err(6, "SO_SNDBUF"); - if (nflag && !Aflag) { + if (conf->nflag && !conf->Aflag) { if (pledge("stdio inet", NULL) == -1) err(1, "pledge"); } else { @@ -828,35 +842,37 @@ main(int argc, char *argv[]) sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) strlcpy(hbuf, "(invalid)", sizeof(hbuf)); fprintf(stderr, "%s to %s (%s)", __progname, hostname, hbuf); - if (source) - fprintf(stderr, " from %s", source); - fprintf(stderr, ", %u hops max, %d byte packets\n", max_ttl, packetlen); + if (conf->source) + fprintf(stderr, " from %s", conf->source); + fprintf(stderr, ", %u hops max, %d byte packets\n", conf->max_ttl, + packetlen); (void) fflush(stderr); - if (first_ttl > 1) - printf("Skipping %u intermediate hops\n", first_ttl - 1); + if (conf->first_ttl > 1) + printf("Skipping %u intermediate hops\n", conf->first_ttl - 1); - for (ttl = first_ttl; ttl && ttl <= max_ttl; ++ttl) { + for (ttl = conf->first_ttl; ttl && ttl <= conf->max_ttl; ++ttl) { int got_there = 0, unreachable = 0, timeout = 0, loss; in_addr_t lastaddr = 0; struct in6_addr lastaddr6; printf("%2u ", ttl); memset(&lastaddr6, 0, sizeof(lastaddr6)); - for (probe = 0, loss = 0; probe < nprobes; ++probe) { + for (probe = 0, loss = 0; probe < conf->nprobes; ++probe) { int cc; struct timeval t1, t2; gettime(&t1); - send_probe(++seq, ttl, incflag, to); - curwaittime = waittime; - while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { + send_probe(conf, ++seq, ttl, conf->incflag, to); + curwaittime = conf->waittime; + while ((cc = wait_for_reply(rcvsock, &rcvmhdr, + curwaittime))) { gettime(&t2); - i = packet_ok(to->sa_family, &rcvmhdr, cc, seq, - incflag); + i = packet_ok(conf, to->sa_family, &rcvmhdr, + cc, seq, conf->incflag); /* Skip wrong packet */ if (i == 0) { - curwaittime = waittime - + curwaittime = conf->waittime - ((t2.tv_sec - t1.tv_sec) * 1000 + (t2.tv_usec - t1.tv_usec) / 1000); if (curwaittime < 0) @@ -866,7 +882,7 @@ main(int argc, char *argv[]) if (to->sa_family == AF_INET) { ip = (struct ip *)packet; if (from4.sin_addr.s_addr != lastaddr) { - print(from, + print(conf, from, cc - (ip->ip_hl << 2), inet_ntop(AF_INET, &ip->ip_dst, hbuf, @@ -877,7 +893,8 @@ main(int argc, char *argv[]) } else if (to->sa_family == AF_INET6) { if (!IN6_ARE_ADDR_EQUAL( &from6.sin6_addr, &lastaddr6)) { - print(from, cc, rcvpktinfo ? + print(conf, from, cc, + rcvpktinfo ? inet_ntop( AF_INET6, &rcvpktinfo->ipi6_addr, hbuf, sizeof(hbuf)) : "?"); @@ -888,7 +905,7 @@ main(int argc, char *argv[]) to->sa_family); printf(" %g ms", deltaT(&t1, &t2)); - if (ttl_flag) + if (conf->ttl_flag) printf(" (%u)", v6flag ? rcvhlim : ip->ip_ttl); if (to->sa_family == AF_INET) { @@ -899,7 +916,7 @@ main(int argc, char *argv[]) break; } - if (tflag) + if (conf->tflag) check_tos(ip); } @@ -914,16 +931,16 @@ main(int argc, char *argv[]) printf(" *"); timeout++; loss++; - } else if (cc && probe == nprobes - 1 && - (xflag || verbose)) + } else if (cc && probe == conf->nprobes - 1 && + (xflag || conf->verbose)) print_exthdr(packet, cc); (void) fflush(stdout); } - if (sump) - printf(" (%d%% loss)", (loss * 100) / nprobes); + if (conf->sump) + printf(" (%d%% loss)", (loss * 100) / conf->nprobes); putchar('\n'); if (got_there || - (unreachable && (unreachable + timeout) >= nprobes)) + (unreachable && (unreachable + timeout) >= conf->nprobes)) break; } exit(0); diff --git a/usr.sbin/traceroute/traceroute.h b/usr.sbin/traceroute/traceroute.h index 2729ac30e9b..91a38fe76dd 100644 --- a/usr.sbin/traceroute/traceroute.h +++ b/usr.sbin/traceroute/traceroute.h @@ -1,4 +1,4 @@ -/* $OpenBSD: traceroute.h,v 1.2 2017/01/13 18:00:10 florian Exp $ */ +/* $OpenBSD: traceroute.h,v 1.3 2017/05/28 10:01:52 benno Exp $ */ /* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */ /* @@ -86,30 +86,68 @@ struct packetdata { u_int32_t usec; } __packed; -extern struct in_addr gateway[MAX_LSRR + 1]; -extern int lsrrlen; +struct tr_conf { + int verbose; + + u_short ident; + + int incflag; /* Do not inc the dest. port num */ + int dflag; /* set SO_DEBUG */ + int dump; + int Aflag; /* lookup ASN */ + int first_ttl; /* Set the first TTL or hop limit */ + + u_char proto; /* IP payload protocol to use */ + int protoset; + + int ttl_flag; /* display ttl on returned packet */ + u_int8_t max_ttl; /* Set the maximum TTL / hop limit */ + int nflag; /* print addresses numerically */ + + u_int16_t port; /* start udp dest port */ + int nprobes; + char *source; + int sump; + + int tos; + int tflag; /* tos value was set */ + + int last_tos; + + u_int rtableid; /* Set the routing table */ + + int waittime; /* time to wait for a response */ + + int lsrr; /* Loose Source Record Route */ + int lsrrlen; + struct in_addr gateway[MAX_LSRR + 1]; +}; + extern int32_t sec_perturb; extern int32_t usec_perturb; extern u_char packet[512]; extern u_char *outpacket; /* last inbound (icmp) packet */ -int wait_for_reply(int, struct msghdr *); +int wait_for_reply(int, struct msghdr *, int); void dump_packet(void); -void build_probe4(int, u_int8_t, int); -void build_probe6(int, u_int8_t, int, struct sockaddr *); -void send_probe(int, u_int8_t, int, struct sockaddr *); -struct udphdr *get_udphdr(struct ip6_hdr *, u_char *); -int packet_ok(int, struct msghdr *, int, int, int); -int packet_ok4(struct msghdr *, int, int, int); -int packet_ok6(struct msghdr *, int, int, int); +void build_probe4(struct tr_conf *, int, u_int8_t, int); +void build_probe6(struct tr_conf *, int, u_int8_t, int, + struct sockaddr *); +void send_probe(struct tr_conf *, int, u_int8_t, int, + struct sockaddr *); +struct udphdr *get_udphdr(struct tr_conf *, struct ip6_hdr *, u_char *); +int packet_ok(struct tr_conf *, int, struct msghdr *, int, int, + int); +int packet_ok4(struct tr_conf *, struct msghdr *, int, int, int); +int packet_ok6(struct tr_conf *, struct msghdr *, int, int, int); void icmp_code(int, int, int *, int *); void icmp4_code(int, int *, int *); void icmp6_code(int, int *, int *); void dump_packet(void); void print_exthdr(u_char *, int); void check_tos(struct ip*); -void print(struct sockaddr *, int, const char *); +void print(struct tr_conf *, struct sockaddr *, int, const char *); const char *inetname(struct sockaddr*); void print_asn(struct sockaddr_storage *); u_short in_cksum(u_short *, int); @@ -129,18 +167,12 @@ extern int datalen; /* How much data */ extern char *hostname; -extern u_short ident; extern u_int16_t srcport; -extern u_int16_t port; /* start udp dest port # for probe packets */ -extern u_char proto; #define ICMP_CODE 0; extern int verbose; -extern int curwaittime; /* time left to wait for response */ -extern int nflag; /* print addresses numerically */ extern int dump; -extern int Aflag; /* lookup ASN */ extern int last_tos; extern char *__progname; diff --git a/usr.sbin/traceroute/worker.c b/usr.sbin/traceroute/worker.c index ac13644eb5d..ccfddc1e359 100644 --- a/usr.sbin/traceroute/worker.c +++ b/usr.sbin/traceroute/worker.c @@ -1,4 +1,4 @@ -/* $OpenBSD: worker.c,v 1.2 2017/01/13 18:00:10 florian Exp $ */ +/* $OpenBSD: worker.c,v 1.3 2017/05/28 10:01:52 benno Exp $ */ /* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */ /* @@ -218,7 +218,7 @@ check_tos(struct ip *ip) } int -wait_for_reply(int sock, struct msghdr *mhdr) +wait_for_reply(int sock, struct msghdr *mhdr, int curwaittime) { struct pollfd pfd[1]; int cc = 0; @@ -249,35 +249,35 @@ dump_packet(void) } void -build_probe4(int seq, u_int8_t ttl, int iflag) +build_probe4(struct tr_conf *conf, int seq, u_int8_t ttl, int iflag) { struct ip *ip = (struct ip *)outpacket; u_char *p = (u_char *)(ip + 1); - struct udphdr *up = (struct udphdr *)(p + lsrrlen); - struct icmp *icmpp = (struct icmp *)(p + lsrrlen); + struct udphdr *up = (struct udphdr *)(p + conf->lsrrlen); + struct icmp *icmpp = (struct icmp *)(p + conf->lsrrlen); struct packetdata *op; struct timeval tv; ip->ip_len = htons(datalen); ip->ip_ttl = ttl; - ip->ip_id = htons(ident+seq); + ip->ip_id = htons(conf->ident+seq); - switch (proto) { + switch (conf->proto) { case IPPROTO_ICMP: icmpp->icmp_type = icmp_type; icmpp->icmp_code = ICMP_CODE; icmpp->icmp_seq = htons(seq); - icmpp->icmp_id = htons(ident); + icmpp->icmp_id = htons(conf->ident); op = (struct packetdata *)(icmpp + 1); break; case IPPROTO_UDP: - up->uh_sport = htons(ident); + up->uh_sport = htons(conf->ident); if (iflag) - up->uh_dport = htons(port+seq); + up->uh_dport = htons(conf->port+seq); else - up->uh_dport = htons(port); + up->uh_dport = htons(conf->port); up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - - lsrrlen)); + conf->lsrrlen)); up->uh_sum = 0; op = (struct packetdata *)(up + 1); break; @@ -305,17 +305,18 @@ build_probe4(int seq, u_int8_t ttl, int iflag) op->sec = htonl(tv.tv_sec + sec_perturb); op->usec = htonl((tv.tv_usec + usec_perturb) % 1000000); - if (proto == IPPROTO_ICMP && icmp_type == ICMP_ECHO) { + if (conf->proto == IPPROTO_ICMP && icmp_type == ICMP_ECHO) { icmpp->icmp_cksum = 0; icmpp->icmp_cksum = in_cksum((u_short *)icmpp, - datalen - sizeof(struct ip) - lsrrlen); + datalen - sizeof(struct ip) - conf->lsrrlen); if (icmpp->icmp_cksum == 0) icmpp->icmp_cksum = 0xffff; } } void -build_probe6(int seq, u_int8_t hops, int iflag, struct sockaddr *to) +build_probe6(struct tr_conf *conf, int seq, u_int8_t hops, int iflag, + struct sockaddr *to) { struct timeval tv; struct packetdata *op; @@ -327,18 +328,18 @@ build_probe6(int seq, u_int8_t hops, int iflag, struct sockaddr *to) warn("setsockopt IPV6_UNICAST_HOPS"); if (iflag) - ((struct sockaddr_in6*)to)->sin6_port = htons(port + seq); + ((struct sockaddr_in6*)to)->sin6_port = htons(conf->port + seq); else - ((struct sockaddr_in6*)to)->sin6_port = htons(port); + ((struct sockaddr_in6*)to)->sin6_port = htons(conf->port); gettime(&tv); - if (proto == IPPROTO_ICMP) { + if (conf->proto == IPPROTO_ICMP) { struct icmp6_hdr *icp = (struct icmp6_hdr *)outpacket; icp->icmp6_type = ICMP6_ECHO_REQUEST; icp->icmp6_code = 0; icp->icmp6_cksum = 0; - icp->icmp6_id = ident; + icp->icmp6_id = conf->ident; icp->icmp6_seq = htons(seq); op = (struct packetdata *)(outpacket + sizeof(struct icmp6_hdr)); @@ -351,23 +352,24 @@ build_probe6(int seq, u_int8_t hops, int iflag, struct sockaddr *to) } void -send_probe(int seq, u_int8_t ttl, int iflag, struct sockaddr *to) +send_probe(struct tr_conf *conf, int seq, u_int8_t ttl, int iflag, + struct sockaddr *to) { int i; switch (to->sa_family) { case AF_INET: - build_probe4(seq, ttl, iflag); + build_probe4(conf, seq, ttl, iflag); break; case AF_INET6: - build_probe6(seq, ttl, iflag, to); + build_probe6(conf, seq, ttl, iflag, to); break; default: errx(1, "unsupported AF: %d", to->sa_family); break; } - if (dump) + if (conf->dump) dump_packet(); i = sendto(sndsock, outpacket, datalen, 0, to, to->sa_len); @@ -424,14 +426,15 @@ pr_type(u_int8_t t) } int -packet_ok(int af, struct msghdr *mhdr, int cc, int seq, int iflag) +packet_ok(struct tr_conf *conf, int af, struct msghdr *mhdr, int cc, int seq, + int iflag) { switch (af) { case AF_INET: - return packet_ok4(mhdr, cc, seq, iflag); + return packet_ok4(conf, mhdr, cc, seq, iflag); break; case AF_INET6: - return packet_ok6(mhdr, cc, seq, iflag); + return packet_ok6(conf, mhdr, cc, seq, iflag); break; default: errx(1, "unsupported AF: %d", af); @@ -440,7 +443,7 @@ packet_ok(int af, struct msghdr *mhdr, int cc, int seq, int iflag) } int -packet_ok4(struct msghdr *mhdr, int cc,int seq, int iflag) +packet_ok4(struct tr_conf *conf, struct msghdr *mhdr, int cc,int seq, int iflag) { struct sockaddr_in *from = (struct sockaddr_in *)mhdr->msg_name; struct icmp *icp; @@ -453,7 +456,7 @@ packet_ok4(struct msghdr *mhdr, int cc,int seq, int iflag) ip = (struct ip *) buf; hlen = ip->ip_hl << 2; if (cc < hlen + ICMP_MINLEN) { - if (verbose) + if (conf->verbose) printf("packet too short (%d bytes) from %s\n", cc, inet_ntoa(from->sin_addr)); return (0); @@ -471,38 +474,39 @@ packet_ok4(struct msghdr *mhdr, int cc,int seq, int iflag) hip = &icp->icmp_ip; hlen = hip->ip_hl << 2; - switch (proto) { + switch (conf->proto) { case IPPROTO_ICMP: if (icmp_type == ICMP_ECHO && type == ICMP_ECHOREPLY && - icp->icmp_id == htons(ident) && + icp->icmp_id == htons(conf->ident) && icp->icmp_seq == htons(seq)) return (-2); /* we got there */ icmpp = (struct icmp *)((u_char *)hip + hlen); if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP && - icmpp->icmp_id == htons(ident) && + icmpp->icmp_id == htons(conf->ident) && icmpp->icmp_seq == htons(seq)) return (type == ICMP_TIMXCEED? -1 : code + 1); break; case IPPROTO_UDP: up = (struct udphdr *)((u_char *)hip + hlen); - if (hlen + 12 <= cc && hip->ip_p == proto && - up->uh_sport == htons(ident) && - ((iflag && up->uh_dport == htons(port + seq)) || - (!iflag && up->uh_dport == htons(port)))) + if (hlen + 12 <= cc && hip->ip_p == conf->proto && + up->uh_sport == htons(conf->ident) && + ((iflag && up->uh_dport == htons(conf->port + + seq)) || + (!iflag && up->uh_dport == htons(conf->port)))) return (type == ICMP_TIMXCEED? -1 : code + 1); break; default: /* this is some odd, user specified proto, * how do we check it? */ - if (hip->ip_p == proto) + if (hip->ip_p == conf->proto) return (type == ICMP_TIMXCEED? -1 : code + 1); } } - if (verbose) { + if (conf->verbose) { int i; in_addr_t *lp = (in_addr_t *)&icp->icmp_ip; @@ -517,7 +521,8 @@ packet_ok4(struct msghdr *mhdr, int cc,int seq, int iflag) } int -packet_ok6(struct msghdr *mhdr, int cc, int seq, int iflag) +packet_ok6(struct tr_conf *conf, struct msghdr *mhdr, int cc, int seq, + int iflag) { struct icmp6_hdr *icp; struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; @@ -526,10 +531,10 @@ packet_ok6(struct msghdr *mhdr, int cc, int seq, int iflag) struct cmsghdr *cm; int *hlimp; char hbuf[NI_MAXHOST]; - int useicmp = (proto == IPPROTO_ICMP); + int useicmp = (conf->proto == IPPROTO_ICMP); if (cc < sizeof(struct icmp6_hdr)) { - if (verbose) { + if (conf->verbose) { if (getnameinfo((struct sockaddr *)from, from->sin6_len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) strlcpy(hbuf, "invalid", sizeof(hbuf)); @@ -568,26 +573,27 @@ packet_ok6(struct msghdr *mhdr, int cc, int seq, int iflag) struct udphdr *up; hip = (struct ip6_hdr *)(icp + 1); - if ((up = get_udphdr(hip, (u_char *)(buf + cc))) == NULL) { - if (verbose) + if ((up = get_udphdr(conf, hip, (u_char *)(buf + cc))) == + NULL) { + if (conf->verbose) warnx("failed to get upper layer header"); return(0); } if (useicmp && - ((struct icmp6_hdr *)up)->icmp6_id == ident && + ((struct icmp6_hdr *)up)->icmp6_id == conf->ident && ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq)) return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); else if (!useicmp && up->uh_sport == htons(srcport) && - ((iflag && up->uh_dport == htons(port + seq)) || - (!iflag && up->uh_dport == htons(port)))) + ((iflag && up->uh_dport == htons(conf->port + seq)) || + (!iflag && up->uh_dport == htons(conf->port)))) return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1); } else if (useicmp && type == ICMP6_ECHO_REPLY) { - if (icp->icmp6_id == ident && + if (icp->icmp6_id == conf->ident && icp->icmp6_seq == htons(seq)) return (ICMP6_DST_UNREACH_NOPORT + 1); } - if (verbose) { + if (conf->verbose) { char sbuf[NI_MAXHOST], dbuf[INET6_ADDRSTRLEN]; u_int8_t *p; int i; @@ -618,21 +624,21 @@ packet_ok6(struct msghdr *mhdr, int cc, int seq, int iflag) } void -print(struct sockaddr *from, int cc, const char *to) +print(struct tr_conf *conf, struct sockaddr *from, int cc, const char *to) { char hbuf[NI_MAXHOST]; if (getnameinfo(from, from->sa_len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) strlcpy(hbuf, "invalid", sizeof(hbuf)); - if (nflag) + if (conf->nflag) printf(" %s", hbuf); else printf(" %s (%s)", inetname(from), hbuf); - if (Aflag) + if (conf->Aflag) print_asn((struct sockaddr_storage *)from); - if (verbose) + if (conf->verbose) printf(" %d bytes to %s", cc, to); } @@ -640,11 +646,11 @@ print(struct sockaddr *from, int cc, const char *to) * Increment pointer until find the UDP or ICMP header. */ struct udphdr * -get_udphdr(struct ip6_hdr *ip6, u_char *lim) +get_udphdr(struct tr_conf *conf, struct ip6_hdr *ip6, u_char *lim) { u_char *cp = (u_char *)ip6, nh; int hlen; - int useicmp = (proto == IPPROTO_ICMP); + int useicmp = (conf->proto == IPPROTO_ICMP); if (cp + sizeof(*ip6) >= lim) return(NULL); |