diff options
author | Florian Obser <florian@cvs.openbsd.org> | 2015-11-29 22:41:21 +0000 |
---|---|---|
committer | Florian Obser <florian@cvs.openbsd.org> | 2015-11-29 22:41:21 +0000 |
commit | b732d07b4af673943ec65d4a177842c8af03b71f (patch) | |
tree | dc471acb835ce58a94f91fca8a40279dec611651 /sbin | |
parent | 1f17d2126d877f3f27823dcb3c671ecb766a17a0 (diff) |
Reimplement source address selection. Inspired by the previous
traceroute / traceroute6 merge. Next step in unification.
OK benno@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ping/ping.c | 52 | ||||
-rw-r--r-- | sbin/ping6/ping6.c | 70 |
2 files changed, 65 insertions, 57 deletions
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c index f5ccaca8e9d..408feaabd69 100644 --- a/sbin/ping/ping.c +++ b/sbin/ping/ping.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ping.c,v 1.135 2015/11/29 12:32:10 florian Exp $ */ +/* $OpenBSD: ping.c,v 1.136 2015/11/29 22:41:20 florian Exp $ */ /* $NetBSD: ping.c,v 1.20 1995/08/11 22:37:58 cgd Exp $ */ /* @@ -110,7 +110,7 @@ int options; #define F_SO_DEBUG 0x0040 /* 0x0080 */ #define F_VERBOSE 0x0100 -#define F_SADDR 0x0200 +/* 0x0200 */ #define F_HDRINCL 0x0400 #define F_TTL 0x0800 #define F_AUD_RECV 0x2000 @@ -132,7 +132,6 @@ int mx_dup_ck = MAX_DUP_CHK; char rcvd_tbl[MAX_DUP_CHK / 8]; struct sockaddr_in whereto; /* who to ping */ -struct sockaddr_in whence; /* Which interface we come from */ unsigned int datalen = DEFDATALEN; int s; /* socket file descriptor */ u_char outpackhdr[IP_MAXPACKET]; /* Max packet size = 65535 */ @@ -186,11 +185,13 @@ int main(int argc, char *argv[]) { struct hostent *hp; + struct addrinfo hints, *res; + struct sockaddr_in from4; struct sockaddr_in *to; - struct in_addr saddr; int ch, i, optval = 1, packlen, preload, maxsize, df = 0, tos = 0; + int error; u_char *datap, *packet, ttl = MAXTTL, loop = 1; - char *target, hnamebuf[HOST_NAME_MAX+1]; + char *target, hnamebuf[HOST_NAME_MAX+1], *source = NULL; char rspace[3 + 4 * NROUTES + 1]; /* record route space */ socklen_t maxsizelen; const char *errstr; @@ -238,13 +239,7 @@ main(int argc, char *argv[]) break; case 'I': case 'S': /* deprecated */ - if (inet_aton(optarg, &saddr) == 0) { - if ((hp = gethostbyname(optarg)) == NULL) - errx(1, "bad interface address: %s", - optarg); - memcpy(&saddr, hp->h_addr, sizeof(saddr)); - } - options |= F_SADDR; + source = optarg; break; case 'i': /* wait between sending packets */ interval = strtod(optarg, NULL); @@ -360,16 +355,27 @@ main(int argc, char *argv[]) hostname = hnamebuf; } - if (options & F_SADDR) { + if (source) { if (IN_MULTICAST(ntohl(to->sin_addr.s_addr))) moptions |= MULTICAST_IF; else { - memset(&whence, 0, sizeof(whence)); - whence.sin_len = sizeof(whence); - whence.sin_family = AF_INET; - memcpy(&whence.sin_addr.s_addr, &saddr, sizeof(saddr)); - if (bind(s, (struct sockaddr *)&whence, - sizeof(whence)) < 0) + memset(&from4, 0, sizeof(from4)); + from4.sin_family = AF_INET; + if (inet_aton(source, &from4.sin_addr) == 0) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + if ((error = getaddrinfo(source, NULL, &hints, + &res))) + errx(1, "%s: %s", source, + gai_strerror(error)); + if (res->ai_addrlen != sizeof(from4)) + errx(1, "size of sockaddr mismatch"); + memcpy(&from4, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + } + if (bind(s, (struct sockaddr *)&from4, sizeof(from4)) + < 0) err(1, "bind"); } } @@ -426,8 +432,8 @@ main(int argc, char *argv[]) ip->ip_off = htons(df ? IP_DF : 0); ip->ip_ttl = ttl; ip->ip_p = IPPROTO_ICMP; - if (options & F_SADDR) - ip->ip_src = saddr; + if (source) + ip->ip_src = from4.sin_addr; else ip->ip_src.s_addr = INADDR_ANY; ip->ip_dst = to->sin_addr; @@ -457,8 +463,8 @@ main(int argc, char *argv[]) sizeof(ttl)) < 0) err(1, "setsockopt IP_MULTICAST_TTL"); if ((moptions & MULTICAST_IF) && - setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &saddr, - sizeof(saddr)) < 0) + setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &from4.sin_addr, + sizeof(from4.sin_addr)) < 0) err(1, "setsockopt IP_MULTICAST_IF"); /* diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index bedd5595043..3fcce1f5429 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ping6.c,v 1.142 2015/11/29 12:32:10 florian Exp $ */ +/* $OpenBSD: ping6.c,v 1.143 2015/11/29 22:41:20 florian Exp $ */ /* $KAME: ping6.c,v 1.163 2002/10/25 02:19:06 itojun Exp $ */ /* @@ -137,7 +137,7 @@ struct payload { #define F_QUIET 0x0010 #define F_SO_DEBUG 0x0040 #define F_VERBOSE 0x0100 -#define F_SRCADDR 0x4000 +/* 0x4000 */ #define F_HOSTNAME 0x10000 #define F_AUD_RECV 0x200000 #define F_AUD_MISS 0x400000 @@ -159,7 +159,7 @@ int mx_dup_ck = MAX_DUP_CHK; char rcvd_tbl[MAX_DUP_CHK / 8]; struct sockaddr_in6 dst; /* who to ping6 */ -struct sockaddr_in6 src; /* src addr of this packet */ + int datalen = DEFDATALEN; int s; /* socket file descriptor */ u_char outpack[MAXPACKETLEN]; @@ -220,12 +220,13 @@ main(int argc, char *argv[]) { struct addrinfo *res0; struct itimerval itimer; - struct sockaddr_in6 from; + struct sockaddr_in6 from, from6; struct addrinfo hints; int ch, i, maxsize, packlen, preload, optval, error; socklen_t maxsizelen; u_char *datap, *packet; char *e, *target; + char *source = NULL; const char *errstr; struct cmsghdr *scmsg = NULL; struct in6_pktinfo *pktinfo = NULL; @@ -278,23 +279,8 @@ main(int argc, char *argv[]) errx(1, "hoplimit is %s: %s", errstr, optarg); break; case 'I': - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */ - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_RAW; - hints.ai_protocol = IPPROTO_ICMPV6; - - error = getaddrinfo(optarg, NULL, &hints, &res0); - if (error) - errx(1, "invalid source address: %s", - gai_strerror(error)); - - if (res0->ai_family != AF_INET6 || res0->ai_addrlen != - sizeof(src)) - errx(1, "invalid source address"); - memcpy(&src, res0->ai_addr, sizeof(src)); - freeaddrinfo(res0); - options |= F_SRCADDR; + case 'S': /* deprecated */ + source = optarg; break; case 'i': /* wait between sending packets */ intval = strtod(optarg, &e); @@ -408,9 +394,25 @@ main(int argc, char *argv[]) freeaddrinfo(res0); /* set the source address if specified. */ - if ((options & F_SRCADDR) && - bind(s, (struct sockaddr *)&src, sizeof(src)) != 0) { - err(1, "bind"); + if (source) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */ + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_RAW; + hints.ai_protocol = IPPROTO_ICMPV6; + + error = getaddrinfo(source, NULL, &hints, &res0); + if (error) + errx(1, "invalid source address: %s", + gai_strerror(error)); + + if (res0->ai_family != AF_INET6 || res0->ai_addrlen != + sizeof(from6)) + errx(1, "invalid source address"); + memcpy(&from6, res0->ai_addr, sizeof(from6)); + freeaddrinfo(res0); + if (bind(s, (struct sockaddr *)&from6, sizeof(from6)) != 0) + err(1, "bind"); } /* @@ -535,21 +537,21 @@ main(int argc, char *argv[]) *(int *)(CMSG_DATA(scmsg)) = hoplimit; } - if (!(options & F_SRCADDR) && options & F_VERBOSE) { + if (!source && options & F_VERBOSE) { /* * get the source address. XXX since we revoked the root * privilege, we cannot use a raw socket for this. */ int dummy; - socklen_t len = sizeof(src); + socklen_t len = sizeof(from6); if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) err(1, "UDP socket"); - src.sin6_family = AF_INET6; - src.sin6_addr = dst.sin6_addr; - src.sin6_port = ntohs(DUMMY_PORT); - src.sin6_scope_id = dst.sin6_scope_id; + from6.sin6_family = AF_INET6; + from6.sin6_addr = dst.sin6_addr; + from6.sin6_port = ntohs(DUMMY_PORT); + from6.sin6_scope_id = dst.sin6_scope_id; if (pktinfo && setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO, @@ -571,10 +573,10 @@ main(int argc, char *argv[]) sizeof(rtableid)) < 0) err(1, "setsockopt(SO_RTABLE)"); - if (connect(dummy, (struct sockaddr *)&src, len) < 0) + if (connect(dummy, (struct sockaddr *)&from6, len) < 0) err(1, "UDP connect"); - if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0) + if (getsockname(dummy, (struct sockaddr *)&from6, &len) < 0) err(1, "getsockname"); close(dummy); @@ -601,8 +603,8 @@ main(int argc, char *argv[]) printf("PING6 %s (", hostname); if (options & F_VERBOSE) - printf("%s --> ", pr_addr((struct sockaddr *)&src, - sizeof(src))); + printf("%s --> ", pr_addr((struct sockaddr *)&from6, + sizeof(from6))); printf("%s): %d data bytes\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)), datalen); |