Inspired by the traceroute / traceroute6 merge.
At least reduces the diff in the option parser :)
OK?

diff --git ping/ping.c ping/ping.c
index f5ccaca..4944f77 100644
--- ping/ping.c
+++ ping/ping.c
@@ -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 ping6/ping6.c ping6/ping6.c
index bedd559..9bc696f 100644
--- ping6/ping6.c
+++ ping6/ping6.c
@@ -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);
 


-- 
I'm not entirely sure you are real.

Reply via email to