1/* $NetBSD: decodenetnum.c,v 1.1.1.2 2012/01/31 21:24:16 kardel 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 */ 25int 26decodenetnum( 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 strncpy(name, num, sizeof(name)); 57 name[sizeof(name) - 1] = '\0'; 58 cp = name; 59 pp = strchr(cp, ':'); 60 *pp = '\0'; 61 port_str = pp + 1; 62 } 63 } else { 64 cp = num + 1; 65 np = name; 66 while (*cp && ']' != *cp) 67 *np++ = *cp++; 68 *np = 0; 69 if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) 70 port_str = &cp[2]; 71 cp = name; 72 } 73 ZERO(hints); 74 hints.ai_flags = Z_AI_NUMERICHOST; 75 err = getaddrinfo(cp, "ntp", &hints, &ai); 76 if (err != 0) 77 return 0; 78 NTP_INSIST(ai->ai_addrlen <= sizeof(*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