Index: sbin/ping/ping.c =================================================================== --- sbin/ping/ping.c +++ sbin/ping/ping.c @@ -160,7 +160,8 @@ static int mx_dup_ck = MAX_DUP_CHK; static char rcvd_tbl[MAX_DUP_CHK / 8]; -static struct sockaddr_in whereto; /* who to ping */ +static struct addrinfo *whereto; /* who to ping */ +static struct in_addr wheretoaddr; static int datalen = DEFDATALEN; static int maxpayload; static int ssend; /* send socket file descriptor */ @@ -169,8 +170,6 @@ static char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */ static char BSPACE = '\b'; /* characters written for flood */ static char DOT = '.'; -static char *hostname; -static char *shostname; static int ident; /* process id to identify our packets */ static int uid; /* cached uid for micro-optimization */ static u_char icmp_type = ICMP_ECHO; @@ -206,6 +205,8 @@ static cap_channel_t *capdns; +static struct addrinfo *get_addr(const char *, char *, size_t); + static void fill(char *, char *); static u_short in_cksum(u_short *, int); static cap_channel_t *capdns_setup(void); @@ -226,7 +227,8 @@ int main(int argc, char *const *argv) { - struct sockaddr_in from, sock_in; + struct sockaddr_in from; + struct addrinfo *sock_in; struct in_addr ifaddr; struct timeval last, intvl; struct iovec iov; @@ -236,21 +238,19 @@ size_t sz; u_char *datap, packet[IP_MAXPACKET] __aligned(4); char *ep, *source, *target, *payload; - struct hostent *hp; #ifdef IPSEC_POLICY_IPSEC char *policy_in, *policy_out; #endif - struct sockaddr_in *to; double t; u_long alarmtimeout, ultmp; int almost_done, ch, df, hold, i, icmp_len, mib[4], preload; int ssend_errno, srecv_errno, tos, ttl; char ctrl[CMSG_SPACE(sizeof(struct timeval))]; - char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN]; #ifdef IP_OPTIONS char rspace[MAX_IPOPTLEN]; /* record route space */ #endif unsigned char loop, mttl; + char wheretoip[NI_MAXHOST]; payload = source = NULL; #ifdef IPSEC_POLICY_IPSEC @@ -561,51 +561,15 @@ } capdns = capdns_setup(); if (source) { - bzero((char *)&sock_in, sizeof(sock_in)); - sock_in.sin_family = AF_INET; - if (inet_aton(source, &sock_in.sin_addr) != 0) { - shostname = source; - } else { - hp = cap_gethostbyname2(capdns, source, AF_INET); - if (!hp) - errx(EX_NOHOST, "cannot resolve %s: %s", - source, hstrerror(h_errno)); - - sock_in.sin_len = sizeof sock_in; - if ((unsigned)hp->h_length > sizeof(sock_in.sin_addr) || - hp->h_length < 0) - errx(1, "gethostbyname2: illegal address"); - memcpy(&sock_in.sin_addr, hp->h_addr_list[0], - sizeof(sock_in.sin_addr)); - (void)strncpy(snamebuf, hp->h_name, - sizeof(snamebuf) - 1); - snamebuf[sizeof(snamebuf) - 1] = '\0'; - shostname = snamebuf; - } - if (bind(ssend, (struct sockaddr *)&sock_in, sizeof sock_in) == - -1) + sock_in = get_addr(source, NULL, 0); + if (bind(ssend, sock_in->ai_addr, sock_in->ai_addrlen) == -1) err(1, "bind"); } - bzero(&whereto, sizeof(whereto)); - to = &whereto; - to->sin_family = AF_INET; - to->sin_len = sizeof *to; - if (inet_aton(target, &to->sin_addr) != 0) { - hostname = target; - } else { - hp = cap_gethostbyname2(capdns, target, AF_INET); - if (!hp) - errx(EX_NOHOST, "cannot resolve %s: %s", - target, hstrerror(h_errno)); - - if ((unsigned)hp->h_length > sizeof(to->sin_addr)) - errx(1, "gethostbyname2 returned an illegal address"); - memcpy(&to->sin_addr, hp->h_addr_list[0], sizeof to->sin_addr); - (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); - hnamebuf[sizeof(hnamebuf) - 1] = '\0'; - hostname = hnamebuf; - } + whereto = get_addr(target, wheretoip, sizeof(wheretoip)); + wheretoaddr = ((struct sockaddr_in *)&whereto->ai_addr)->sin_addr; + if (connect(ssend, whereto->ai_addr, whereto->ai_addrlen) != 0) + err(1, "connect"); /* From now on we will use only reverse DNS lookups. */ if (capdns != NULL) { @@ -616,17 +580,14 @@ err(1, "unable to limit access to system.dns service"); } - if (connect(ssend, (struct sockaddr *)&whereto, sizeof(whereto)) != 0) - err(1, "connect"); - if (options & F_FLOOD && options & F_INTERVAL) errx(EX_USAGE, "-f and -i: incompatible options"); - if (options & F_FLOOD && IN_MULTICAST(ntohl(to->sin_addr.s_addr))) + if (options & F_FLOOD && IN_MULTICAST(ntohl(wheretoaddr.s_addr))) errx(EX_USAGE, "-f flag cannot be used with multicast destination"); - if (options & (F_MIF | F_NOLOOP | F_MTTL) - && !IN_MULTICAST(ntohl(to->sin_addr.s_addr))) + if (options & (F_MIF | F_NOLOOP | F_MTTL) && + !IN_MULTICAST(ntohl(wheretoaddr.s_addr))) errx(EX_USAGE, "-I, -L, -T flags cannot be used with unicast destination"); @@ -697,8 +658,12 @@ ip->ip_off = htons(df ? IP_DF : 0); ip->ip_ttl = ttl; ip->ip_p = IPPROTO_ICMP; - ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY; - ip->ip_dst = to->sin_addr; + ip->ip_src.s_addr = INADDR_ANY; + if (source) { + ip->ip_src.s_addr = + ((struct sockaddr_in *)&sock_in->ai_addr)->sin_addr.s_addr; + } + ip->ip_dst = wheretoaddr; } if (options & F_NUMERIC) @@ -816,11 +781,10 @@ if (cap_rights_limit(ssend, &rights) < 0 && errno != ENOSYS) err(1, "cap_rights_limit ssend setsockopt"); - if (to->sin_family == AF_INET) { - (void)printf("PING %s (%s)", hostname, - inet_ntoa(to->sin_addr)); + if (whereto->ai_family == AF_INET) { + (void)printf("PING %s (%s)", whereto->ai_canonname, wheretoip); if (source) - (void)printf(" from %s", shostname); + (void)printf(" from %s", sock_in->ai_canonname); if (sweepmax) (void)printf(": (%d ... %d) data bytes\n", sweepmin, sweepmax); @@ -830,9 +794,10 @@ } else { if (sweepmax) (void)printf("PING %s: (%d ... %d) data bytes\n", - hostname, sweepmin, sweepmax); + whereto->ai_canonname, sweepmin, sweepmax); else - (void)printf("PING %s: %d data bytes\n", hostname, datalen); + (void)printf("PING %s: %d data bytes\n", + whereto->ai_canonname, datalen); } /* @@ -985,6 +950,35 @@ exit(0); /* Make the compiler happy */ } + +static struct addrinfo * +get_addr(const char *host, char *ipstr, size_t iplen) +{ + struct addrinfo hints, *addr; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_flags = AI_CANONNAME; + + error = cap_getaddrinfo(capdns, host, NULL, &hints, &addr); + if (error != 0) { + errx(EX_NOHOST, "cannot resolve %s: %s", + host, gai_strerror(error)); + } + + if (ipstr != NULL) { + error = cap_getnameinfo(capdns, addr->ai_addr, addr->ai_addrlen, + ipstr, iplen, NULL, 0, NI_NUMERICHOST); + if (error != 0) { + errx(EX_NOHOST, "cannot resolve %s: %s", + host, gai_strerror(error)); + } + } + + return (addr); +} + /* * stopit -- * Set the global bit that causes the main loop to quit. @@ -1068,7 +1062,7 @@ warn("sendto"); } else { warn("%s: partial write: %d of %d bytes", - hostname, i, cc); + whereto->ai_canonname, i, cc); } } ntransmitted++; @@ -1245,7 +1239,7 @@ if (((options & F_VERBOSE) && uid == 0) || (!(options & F_QUIET2) && - (oip->ip_dst.s_addr == whereto.sin_addr.s_addr) && + (oip->ip_dst.s_addr == wheretoaddr.s_addr) && (oip->ip_p == IPPROTO_ICMP) && (oicmp->icmp_type == ICMP_ECHO) && (oicmp->icmp_id == ident))) { @@ -1444,7 +1438,7 @@ (void)signal(SIGALRM, SIG_IGN); (void)putchar('\n'); (void)fflush(stdout); - (void)printf("--- %s ping statistics ---\n", hostname); + (void)printf("--- %s ping statistics ---\n", whereto->ai_canonname); (void)printf("%ld packets transmitted, ", ntransmitted); (void)printf("%ld packets received, ", nreceived); if (nrepeats)