1 /* $NetBSD: decodenetnum.c,v 1.5 2016/01/08 21:35:38 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 REQUIRE(num != NULL); 41 42 if (strlen(num) >= sizeof(name)) { 43 return 0; 44 } 45 46 port_str = NULL; 47 if ('[' != num[0]) { 48 /* 49 * to distinguish IPv6 embedded colons from a port 50 * specification on an IPv4 address, assume all 51 * legal IPv6 addresses have at least two colons. 52 */ 53 pp = strchr(num, ':'); 54 if (NULL == pp) 55 cp = num; /* no colons */ 56 else if (NULL != strchr(pp + 1, ':')) 57 cp = num; /* two or more colons */ 58 else { /* one colon */ 59 strlcpy(name, num, sizeof(name)); 60 cp = name; 61 pp = strchr(cp, ':'); 62 *pp = '\0'; 63 port_str = pp + 1; 64 } 65 } else { 66 cp = num + 1; 67 np = name; 68 while (*cp && ']' != *cp) 69 *np++ = *cp++; 70 *np = 0; 71 if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) 72 port_str = &cp[2]; 73 cp = name; 74 } 75 ZERO(hints); 76 hints.ai_flags = Z_AI_NUMERICHOST; 77 err = getaddrinfo(cp, "ntp", &hints, &ai); 78 if (err != 0) 79 return 0; 80 INSIST(ai->ai_addrlen <= sizeof(*netnum)); 81 ZERO(*netnum); 82 memcpy(netnum, ai->ai_addr, ai->ai_addrlen); 83 freeaddrinfo(ai); 84 if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port)) 85 port = NTP_PORT; 86 SET_PORT(netnum, port); 87 return 1; 88 } 89