diff options
Diffstat (limited to 'libntp/decodenetnum.c')
-rw-r--r-- | libntp/decodenetnum.c | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/libntp/decodenetnum.c b/libntp/decodenetnum.c index 746c855d8bd1..f265daebf9c6 100644 --- a/libntp/decodenetnum.c +++ b/libntp/decodenetnum.c @@ -1,39 +1,83 @@ /* * decodenetnum - return a net number (this is crude, but careful) */ +#include <config.h> #include <sys/types.h> #include <ctype.h> +#ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H #include <netinet/in.h> +#endif +#include "ntp.h" #include "ntp_stdlib.h" +#include "ntp_assert.h" +/* + * decodenetnum convert text IP address and port to sockaddr_u + * + * Returns 0 for failure, 1 for success. + */ int decodenetnum( const char *num, - struct sockaddr_storage *netnum + sockaddr_u *netnum ) { struct addrinfo hints, *ai = NULL; - register int err, i; - register const char *cp; + int err; + u_short port; + const char *cp; + const char *port_str; + char *pp; + char *np; char name[80]; - cp = num; + NTP_REQUIRE(num != NULL); + NTP_REQUIRE(strlen(num) < sizeof(name)); - if (*cp == '[') { - cp++; - for (i = 0; *cp != ']'; cp++, i++) - name[i] = *cp; - name[i] = '\0'; - num = name; + port_str = NULL; + if ('[' != num[0]) { + /* + * to distinguish IPv6 embedded colons from a port + * specification on an IPv4 address, assume all + * legal IPv6 addresses have at least two colons. + */ + pp = strchr(num, ':'); + if (NULL == pp) + cp = num; /* no colons */ + else if (NULL != strchr(pp + 1, ':')) + cp = num; /* two or more colons */ + else { /* one colon */ + strncpy(name, num, sizeof(name)); + name[sizeof(name) - 1] = '\0'; + cp = name; + pp = strchr(cp, ':'); + *pp = '\0'; + port_str = pp + 1; + } + } else { + cp = num + 1; + np = name; + while (*cp && ']' != *cp) + *np++ = *cp++; + *np = 0; + if (']' == cp[0] && ':' == cp[1] && '\0' != cp[2]) + port_str = &cp[2]; + cp = name; } - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_flags = AI_NUMERICHOST; - err = getaddrinfo(num, NULL, &hints, &ai); + ZERO(hints); + hints.ai_flags = Z_AI_NUMERICHOST; + err = getaddrinfo(cp, "ntp", &hints, &ai); if (err != 0) return 0; - memcpy(netnum, (struct sockaddr_storage *)ai->ai_addr, ai->ai_addrlen); + NTP_INSIST(ai->ai_addrlen <= sizeof(*netnum)); + memcpy(netnum, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); + if (NULL == port_str || 1 != sscanf(port_str, "%hu", &port)) + port = NTP_PORT; + SET_PORT(netnum, port); return 1; } |