"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "libntp/decodenetnum.c" between
ntp-4.2.8p14.tar.gz and ntp-4.2.8p15.tar.gz

About: NTP is the the Official Reference Implementation of the Network Time Protocol (NTP) that synchronize the clocks of computers over a network.

decodenetnum.c  (ntp-4.2.8p14):decodenetnum.c  (ntp-4.2.8p15)
skipping to change at line 16 skipping to change at line 16
#include <ctype.h> #include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H #ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#endif #endif
#include "ntp.h" #include "ntp.h"
#include "ntp_stdlib.h" #include "ntp_stdlib.h"
#include "ntp_assert.h"
#define PORTSTR(x) _PORTSTR(x) /* If the given string position points to a decimal digit, parse the
#define _PORTSTR(x) #x * number. If this is not possible, or the parsing did not consume the
* whole string, or if the result exceeds the maximum value, return the
static int * default value.
isnumstr( */
const char *s static unsigned long
_num_or_dflt(
char * sval,
unsigned long maxval,
unsigned long defval
) )
{ {
while (*s >= '0' && *s <= '9') char * ep;
++s; unsigned long num;
return !*s;
if (!(sval && isdigit(*(unsigned char*)sval)))
return defval;
num = strtoul(sval, &ep, 10);
if (!*ep && num <= maxval)
return num;
return defval;
}
/* If the given string position is not NULL and does not point to the
* terminator, replace the character with NUL and advance the pointer.
* Return the resulting position.
*/
static inline char*
_chop(
char * sp)
{
if (sp && *sp)
*sp++ = '\0';
return sp;
}
/* If the given string position points to the given char, advance the
* pointer and return the result. Otherwise, return NULL.
*/
static inline char*
_skip(
char * sp,
int ch)
{
if (sp && *(unsigned char*)sp == ch)
return (sp + 1);
return NULL;
} }
/* /*
* decodenetnum convert text IP address and port to sockaddr_u * decodenetnum convert text IP address and port to sockaddr_u
* *
* Returns 0 for failure, 1 for success. * Returns FALSE (->0) for failure, TRUE (->1) for success.
*/ */
int int
decodenetnum( decodenetnum(
const char *num, const char *num,
sockaddr_u *netnum sockaddr_u *net
) )
{ {
static const char * const servicename = "ntp"; /* Building a parser is more fun in Haskell, but here we go...
static const char * const serviceport = PORTSTR(NTP_PORT); *
* This works through 'inet_pton()' taking the brunt of the
struct addrinfo hints, *ai = NULL; * work, after some string manipulations to split off URI
int err; * brackets, ports and scope identifiers. The heuristics are
const char *host_str; * simple but must hold for all _VALID_ addresses. inet_pton()
const char *port_str; * will croak on bad ones later, but replicating the whole
char *pp; * parser logic to detect errors is wasteful.
char *np; */
char nbuf[80];
sockaddr_u netnum;
REQUIRE(num != NULL); char buf[64]; /* working copy of input */
char *haddr=buf;
unsigned int port=NTP_PORT, scope=0;
unsigned short afam=AF_UNSPEC;
if (strlen(num) >= sizeof(nbuf)) { /* copy input to working buffer with length check */
printf("length error\n"); if (strlcpy(buf, num, sizeof(buf)) >= sizeof(buf))
return FALSE; return FALSE;
}
port_str = servicename; /* Identify address family and possibly the port, if given. If
if ('[' != num[0]) { * this results in AF_UNSPEC, we will fail in the next step.
/* */
* to distinguish IPv6 embedded colons from a port if (*haddr == '[') {
* specification on an IPv4 address, assume all char * endp = strchr(++haddr, ']');
* legal IPv6 addresses have at least two colons. if (endp) {
*/ port = _num_or_dflt(_skip(_chop(endp), ':'),
pp = strchr(num, ':'); 0xFFFFu, port);
if (NULL == pp) afam = strchr(haddr, ':') ? AF_INET6 : AF_INET;
host_str = num; /* no colons */
else if (NULL != strchr(pp + 1, ':'))
host_str = num; /* two or more colons */
else { /* one colon */
strlcpy(nbuf, num, sizeof(nbuf));
host_str = nbuf;
pp = strchr(nbuf, ':');
*pp = '\0';
port_str = pp + 1;
} }
} else { } else {
host_str = np = nbuf; char *col = strchr(haddr, ':');
while (*++num && ']' != *num) char *dot = strchr(haddr, '.');
*np++ = *num; if (col == dot) {
*np = 0; /* no dot, no colon: bad! */
if (']' == num[0] && ':' == num[1] && '\0' != num[2]) afam = AF_UNSPEC;
port_str = &num[2]; } else if (!col) {
/* no colon, only dot: IPv4! */
afam = AF_INET;
} else if (!dot || col < dot) {
/* no dot or 1st colon before 1st dot: IPv6! */
afam = AF_INET6;
} else {
/* 1st dot before 1st colon: must be IPv4 with port */
afam = AF_INET;
port = _num_or_dflt(_chop(col), 0xFFFFu, port);
}
} }
if ( ! *host_str)
return FALSE;
if ( ! *port_str)
port_str = servicename;
ZERO(hints); /* Since we don't know about additional members in the address
hints.ai_flags |= Z_AI_NUMERICHOST; * structures, we wipe the result buffer thoroughly:
if (isnumstr(port_str)) */
hints.ai_flags |= Z_AI_NUMERICSERV; memset(&netnum, 0, sizeof(netnum));
err = getaddrinfo(host_str, port_str, &hints, &ai);
/* retry with default service name if the service lookup failed */ /* For AF_INET6, evaluate and remove any scope suffix. Have
if (err == EAI_SERVICE && strcmp(port_str, servicename)) { * inet_pton() do the real work for AF_INET and AF_INET6, bail
hints.ai_flags &= ~Z_AI_NUMERICSERV; * out otherwise:
port_str = servicename; */
err = getaddrinfo(host_str, port_str, &hints, &ai); switch (afam) {
} case AF_INET:
/* retry another time with default service port if the service lookup fai if (inet_pton(afam, haddr, &netnum.sa4.sin_addr) <= 0)
led */ return FALSE;
if (err == EAI_SERVICE && strcmp(port_str, serviceport)) { netnum.sa4.sin_port = htons((unsigned short)port);
hints.ai_flags |= Z_AI_NUMERICSERV; break;
port_str = serviceport;
err = getaddrinfo(host_str, port_str, &hints, &ai); case AF_INET6:
} scope = _num_or_dflt(_chop(strchr(haddr, '%')), 0xFFFFFFFFu, scop
if (err != 0) e);
return FALSE; if (inet_pton(afam, haddr, &netnum.sa6.sin6_addr) <= 0)
return FALSE;
netnum.sa6.sin6_port = htons((unsigned short)port);
netnum.sa6.sin6_scope_id = scope;
break;
INSIST(ai->ai_addrlen <= sizeof(*netnum)); case AF_UNSPEC:
ZERO(*netnum); default:
memcpy(netnum, ai->ai_addr, ai->ai_addrlen); return FALSE;
freeaddrinfo(ai); }
/* Collect the remaining pieces and feed the output, which was
* not touched so far:
*/
netnum.sa.sa_family = afam;
memcpy(net, &netnum, sizeof(netnum));
return TRUE; return TRUE;
} }
 End of changes. 14 change blocks. 
79 lines changed or deleted 124 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)