154359Sroberto/* 254359Sroberto * decodenetnum - return a net number (this is crude, but careful) 354359Sroberto */ 4285612Sdelphij#include <config.h> 554359Sroberto#include <sys/types.h> 654359Sroberto#include <ctype.h> 7285612Sdelphij#ifdef HAVE_SYS_SOCKET_H 854359Sroberto#include <sys/socket.h> 9285612Sdelphij#endif 10285612Sdelphij#ifdef HAVE_NETINET_IN_H 1154359Sroberto#include <netinet/in.h> 12285612Sdelphij#endif 1354359Sroberto 14285612Sdelphij#include "ntp.h" 1554359Sroberto#include "ntp_stdlib.h" 16285612Sdelphij#include "ntp_assert.h" 1754359Sroberto 18285612Sdelphij/* 19285612Sdelphij * decodenetnum convert text IP address and port to sockaddr_u 20285612Sdelphij * 21285612Sdelphij * Returns 0 for failure, 1 for success. 22285612Sdelphij */ 2354359Srobertoint 2454359Srobertodecodenetnum( 2554359Sroberto const char *num, 26285612Sdelphij sockaddr_u *netnum 2754359Sroberto ) 2854359Sroberto{ 29132451Sroberto struct addrinfo hints, *ai = NULL; 30285612Sdelphij int err; 31285612Sdelphij u_short port; 32285612Sdelphij const char *cp; 33285612Sdelphij const char *port_str; 34285612Sdelphij char *pp; 35285612Sdelphij char *np; 36132451Sroberto char name[80]; 3754359Sroberto 38289997Sglebius REQUIRE(num != NULL); 3954359Sroberto 40289997Sglebius if (strlen(num) >= sizeof(name)) { 41289997Sglebius return 0; 42289997Sglebius } 43289997Sglebius 44285612Sdelphij port_str = NULL; 45285612Sdelphij if ('[' != num[0]) { 46285612Sdelphij /* 47285612Sdelphij * to distinguish IPv6 embedded colons from a port 48285612Sdelphij * specification on an IPv4 address, assume all 49285612Sdelphij * legal IPv6 addresses have at least two colons. 50285612Sdelphij */ 51285612Sdelphij pp = strchr(num, ':'); 52285612Sdelphij if (NULL == pp) 53285612Sdelphij cp = num; /* no colons */ 54285612Sdelphij else if (NULL != strchr(pp + 1, ':')) 55285612Sdelphij cp = num; /* two or more colons */ 56285612Sdelphij else { /* one colon */ 57285612Sdelphij strlcpy(name, num, sizeof(name)); 58285612Sdelphij cp = name; 59285612Sdelphij pp = strchr(cp, ':'); 60285612Sdelphij *pp = '\0'; 61285612Sdelphij port_str = pp + 1; 62285612Sdelphij } 63285612Sdelphij } else { 64285612Sdelphij cp = num + 1; 65285612Sdelphij np = name; 66285612Sdelphij while (*cp && ']' != *cp) 67285612Sdelphij *np++ = *cp++; 68285612Sdelphij *np = 0; 69285612Sdelphij if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) 70285612Sdelphij port_str = &cp[2]; 71285612Sdelphij cp = name; 7254359Sroberto } 73285612Sdelphij ZERO(hints); 74285612Sdelphij hints.ai_flags = Z_AI_NUMERICHOST; 75285612Sdelphij err = getaddrinfo(cp, "ntp", &hints, &ai); 76132451Sroberto if (err != 0) 77132451Sroberto return 0; 78289997Sglebius INSIST(ai->ai_addrlen <= sizeof(*netnum)); 79285612Sdelphij ZERO(*netnum); 80285612Sdelphij memcpy(netnum, ai->ai_addr, ai->ai_addrlen); 81132451Sroberto freeaddrinfo(ai); 82285612Sdelphij if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port)) 83285612Sdelphij port = NTP_PORT; 84285612Sdelphij SET_PORT(netnum, port); 8554359Sroberto return 1; 8654359Sroberto} 87