summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorFlorian Obser <florian@cvs.openbsd.org>2015-11-29 22:41:21 +0000
committerFlorian Obser <florian@cvs.openbsd.org>2015-11-29 22:41:21 +0000
commitb732d07b4af673943ec65d4a177842c8af03b71f (patch)
treedc471acb835ce58a94f91fca8a40279dec611651 /sbin
parent1f17d2126d877f3f27823dcb3c671ecb766a17a0 (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.c52
-rw-r--r--sbin/ping6/ping6.c70
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);