summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/traceroute/traceroute.c247
-rw-r--r--usr.sbin/traceroute/traceroute.h68
-rw-r--r--usr.sbin/traceroute/worker.c112
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);