- int len_ent = align (sizeof (*hp), ALIGNMENT);
- int len_name = align (strlen (hp->h_name) + 1, ALIGNMENT);
- int num_aliases = 1;
- int len_aliases = sizeof (char *);
- int num_addr_list = 1;
- int len_addr_list = sizeof (char *);
- int pos, i;
- char **sp;
- struct hostent *cp;
-
- for (sp = hp->h_aliases; *sp; sp++)
- {
- num_aliases++;
- len_aliases += align (strlen (*sp) + 1, ALIGNMENT)
- + sizeof (char *);
- }
-
- for (sp = hp->h_addr_list; *sp; sp++)
- {
- num_addr_list++;
- len_addr_list += align (hp->h_length, ALIGNMENT)
- + sizeof (char *);
- }
-
- cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases
- + len_addr_list);
-
- *cp = *hp;
- pos = len_ent;
- cp->h_name = (char *) &(((char *) cp) [pos]);
- strcpy (cp->h_name, hp->h_name);
-
- pos += len_name;
- cp->h_aliases = (char **) &(((char *) cp) [pos]);
- pos += num_aliases * sizeof (char *);
- for (sp = hp->h_aliases, i = 0; i < num_aliases; i++, sp++)
- if (*sp)
- {
- cp->h_aliases [i] = (char *) &(((char *) cp) [pos]);
- strcpy (cp->h_aliases [i], *sp);
- pos += align (strlen (*sp) + 1, ALIGNMENT);
- }
- else
- cp->h_aliases [i] = *sp;
-
- pos = len_ent + len_name + len_aliases;
- cp->h_addr_list = (char **) &(((char *) cp) [pos]);
- pos += num_addr_list * sizeof (char *);
- for (sp = hp->h_addr_list, i = 0; i < num_addr_list; i++, sp++)
- if (*sp)
- {
- cp->h_addr_list [i] = (char *) &(((char *) cp) [pos]);
- memcpy (cp->h_addr_list [i], *sp, hp->h_length);
- pos += align (hp->h_length, ALIGNMENT);
- }
- else
- cp->h_addr_list [i] = *sp;
-
- return cp;
+ struct addrinfo *ai = NULL;
+ struct addrinfo hint = {
+ /* don't return duplicates */
+ .ai_protocol = (int)IPPROTO_UDP,
+ .ai_flags = AI_NUMERICHOST,
+ .ai_family = AF_UNSPEC,
+ };
+ struct sockaddr_in sin;
+ int error, inet4;
+
+ /*
+ * Although getaddrinfo(3) is easier to use and supports
+ * IPv6, it recognizes incomplete addresses like "10.4"
+ * as valid AF_INET addresses. It also accepts presentation
+ * addresses that end with a blank.
+ *
+ * inet_pton(3) is much stricter. Use it to be certain we
+ * have a real AF_INET presentation address, before invoking
+ * getaddrinfo(3) to generate the full addrinfo list.
+ */
+ inet4 = 1;
+ if (inet_pton(AF_INET, paddr, &sin.sin_addr) == 0)
+ inet4 = 0;
+
+ error = getaddrinfo(paddr, NULL, &hint, &ai);
+ switch (error) {
+ case 0:
+ if (!inet4 && ai->ai_addr->sa_family == AF_INET) {
+ freeaddrinfo(ai);
+ break;
+ }
+ return ai;
+ case EAI_NONAME:
+ if (paddr == NULL)
+ xlog(D_GENERAL, "%s: passed a NULL presentation address",
+ __func__);
+ break;
+ case EAI_SYSTEM:
+ xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
+ __func__, paddr, errno);
+ break;
+ default:
+ xlog(D_GENERAL, "%s: failed to convert %s: %s",
+ __func__, paddr, gai_strerror(error));
+ break;
+ }
+
+ return NULL;