1 /* $NetBSD: decodenetnum.c,v 1.1.1.3 2013/12/27 23:30:48 christos Exp $ */ 2 3 /* 4 * decodenetnum - return a net number (this is crude, but careful) 5 */ 6 #include <config.h> 7 #include <sys/types.h> 8 #include <ctype.h> 9 #ifdef HAVE_SYS_SOCKET_H 10 #include <sys/socket.h> 11 #endif 12 #ifdef HAVE_NETINET_IN_H 13 #include <netinet/in.h> 14 #endif 15 16 #include "ntp.h" 17 #include "ntp_stdlib.h" 18 #include "ntp_assert.h" 19 20 /* 21 * decodenetnum convert text IP address and port to sockaddr_u 22 * 23 * Returns 0 for failure, 1 for success. 24 */ 25 int 26 decodenetnum( 27 const char *num, 28 sockaddr_u *netnum 29 ) 30 { 31 struct addrinfo hints, *ai = NULL; 32 int err; 33 u_short port; 34 const char *cp; 35 const char *port_str; 36 char *pp; 37 char *np; 38 char name[80]; 39 40 NTP_REQUIRE(num != NULL); 41 NTP_REQUIRE(strlen(num) < sizeof(name)); 42 43 port_str = NULL; 44 if ('[' != num[0]) { 45 /* 46 * to distinguish IPv6 embedded colons from a port 47 * specification on an IPv4 address, assume all 48 * legal IPv6 addresses have at least two colons. 49 */ 50 pp = strchr(num, ':'); 51 if (NULL == pp) 52 cp = num; /* no colons */ 53 else if (NULL != strchr(pp + 1, ':')) 54 cp = num; /* two or more colons */ 55 else { /* one colon */ 56 strlcpy(name, num, sizeof(name)); 57 cp = name; 58 pp = strchr(cp, ':'); 59 *pp = '\0'; 60 port_str = pp + 1; 61 } 62 } else { 63 cp = num + 1; 64 np = name; 65 while (*cp && ']' != *cp) 66 *np++ = *cp++; 67 *np = 0; 68 if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) 69 port_str = &cp[2]; 70 cp = name; 71 } 72 ZERO(hints); 73 hints.ai_flags = Z_AI_NUMERICHOST; 74 err = getaddrinfo(cp, "ntp", &hints, &ai); 75 if (err != 0) 76 return 0; 77 NTP_INSIST(ai->ai_addrlen <= sizeof(*netnum)); 78 ZERO(*netnum); 79 memcpy(netnum, ai->ai_addr, ai->ai_addrlen); 80 freeaddrinfo(ai); 81 if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port)) 82 port = NTP_PORT; 83 SET_PORT(netnum, port); 84 return 1; 85 } 86