Peter Selinger
2007-Jan-06 03:50 UTC
[Nut-upsdev] Re: [nut-commits] svn commit r708 - in trunk: . clients server
With the Ipv6 patch (r708), I get: upsclient.c: In function `upscli_connect': upsclient.c:469: `AI_ADDRCONFIG' undeclared (first use in this function) upsclient.c:469: (Each undeclared identifier is reported only once upsclient.c:469: for each function it appears in.) Even if it doesn't break IPv4 support, it may break portability, as IPv6 seems to require specific functions that are not as standardized as the IPv4 ones. For example it uses "struct addrinfo" and not "struct sockaddr_in". Moreover, it seems that my version of getaddrinfo() recognizes different flags than this patch assumes. Ideally the availability of IPv6 functions should be detected at configuration time. Unfortunately, the patch uses the new interface even for IPv4 support, so there is no easy way of enclosing the non-portable stuff in #ifdef's. Perhaps it would be better to develop this patch in a branch, and reverse the commit on the main branch until the portability issues are resolved? The ideal situation would be to enclose all the IPv6 stuff in #ifdef's, and leave the IPv4 stuff as it was before. -- Peter Arjen de Korte wrote:> > Author: adkorte-guest > Date: Fri Jan 5 21:06:59 2007 > New Revision: 708 > > Modified: > trunk/ChangeLog > trunk/clients/upsc.c > trunk/clients/upsclient.c > trunk/clients/upsclient.h > trunk/server/access.c > trunk/server/access.h > trunk/server/ctype.h > trunk/server/upsd.c > trunk/server/user.c > trunk/server/user.h > Log: > - added IPv6 support (Alioth Patches #304310) (IPv4 still seems to > work after applying this patch, but can't test IPv6) > > Any volunteers for testing IPv6 support? > > Modified: trunk/ChangeLog > =============================================================================> --- trunk/ChangeLog (original) > +++ trunk/ChangeLog Fri Jan 5 21:06:59 2007 > @@ -1,3 +1,8 @@ > +Fri Jan 5 19:57:46 UTC 2007 / Arjen de Korte <arjen@de-korte.org> > + > + - added IPv6 support (Alioth Patches #304310) (IPv4 still seems to > + work after applying this patch, but can't test IPv6) > + > Fri Jan 5 19:15:13 UTC 2007 / Arjen de Korte <arjen@de-korte.org> > > - data/cmdvartab: added ups.realpower, ups.realpower.nominal, > > Modified: trunk/clients/upsc.c > =============================================================================> --- trunk/clients/upsc.c (original) > +++ trunk/clients/upsc.c Fri Jan 5 21:06:59 2007 > @@ -25,6 +25,10 @@ > > #include "upsclient.h" > > +/* From IPv6 patch (doesn't seem to be used) > +static int opt_af = AF_UNSPEC; > + */ > + > static void help(const char *prog) > { > printf("Network UPS Tools upsc %s\n\n", UPS_VERSION); > > Modified: trunk/clients/upsclient.c > =============================================================================> --- trunk/clients/upsclient.c (original) > +++ trunk/clients/upsclient.c Fri Jan 5 21:06:59 2007 > @@ -38,6 +38,9 @@ > #define shutdown_how 2 > #endif > > +/* From IPv6 patch (doesn't seem to be used) > +extern int opt_af; > + */ > struct { > int flags; > const char *str; > @@ -421,8 +424,8 @@ > > int upscli_connect(UPSCONN *ups, const char *host, int port, int flags) > { > - struct sockaddr_in local, server; > - struct hostent *serv; > + struct addrinfo hints, *r, *rtmp; > + char *service; > > /* clear out any lingering junk */ > ups->fd = -1; > @@ -449,78 +452,86 @@ > return -1; > } > > - if ((serv = gethostbyname(host)) == (struct hostent *) NULL) { > - > - ups->upserror = UPSCLI_ERR_NOSUCHHOST; > + service = malloc (sizeof (char) * 6); > + if (service == NULL) { > + ups->upserror = UPSCLI_ERR_NOMEM; > return -1; > } > > - if ((ups->fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { > - ups->upserror = UPSCLI_ERR_SOCKFAILURE; > - ups->syserrno = errno; > + if (snprintf (service, 6, "%hu", (unsigned short int)port) < 1) { > return -1; > } > > - memset(&local, '\0', sizeof(struct sockaddr_in)); > - local.sin_family = AF_INET; > - local.sin_port = htons(INADDR_ANY); > - > - memset(&server, '\0', sizeof(struct sockaddr_in)); > - server.sin_family = AF_INET; > - server.sin_port = htons(port); > - > - memcpy(&server.sin_addr, serv->h_addr, serv->h_length); > - > - if (bind(ups->fd, (struct sockaddr *) &local, > - sizeof(struct sockaddr_in)) == -1) { > - ups->upserror = UPSCLI_ERR_BINDFAILURE; > - ups->syserrno = errno; > - close(ups->fd); > - ups->fd = -1; > + memset (&hints, 0, sizeof (struct addrinfo)); > + hints.ai_family = flags & UPSCLI_CONN_INET ? AF_INET : (flags & UPSCLI_CONN_INET6 ? AF_INET6 : AF_UNSPEC); > + hints.ai_socktype = SOCK_STREAM; > + hints.ai_protocol = IPPROTO_TCP; > + hints.ai_flags = AI_ADDRCONFIG; > > + if (getaddrinfo (host, service, &hints, &r) != 0) { > + ups->upserror = UPSCLI_ERR_NOSUCHHOST; > + free (service); > return -1; > } > + free (service); > > - if (connect(ups->fd, (struct sockaddr *) &server, > - sizeof(struct sockaddr_in)) == -1) { > - ups->upserror = UPSCLI_ERR_CONNFAILURE; > - ups->syserrno = errno; > - close(ups->fd); > - ups->fd = -1; > + for (rtmp = r; r != NULL; r = r->ai_next) { > + ups->fd = socket (r->ai_family, r->ai_socktype, r->ai_protocol); > + if (ups->fd < 0) { > + if (r->ai_next == NULL) { > + ups->upserror = UPSCLI_ERR_SOCKFAILURE; > + ups->syserrno = errno; > + break; > + } > + continue; > + } > > - return -1; > - } > + if (connect (ups->fd, r->ai_addr, r->ai_addrlen) == -1) { > + close (ups->fd); > + ups->fd = -1; > + if (r->ai_next == NULL) { > + ups->upserror = UPSCLI_ERR_CONNFAILURE; > + ups->syserrno = errno; > + break; > + } > + continue; > + } > + freeaddrinfo (rtmp); > > - /* don't use xstrdup for cleaner linking (fewer dependencies) */ > - ups->host = strdup(host); > + /* don't use xstrdup for cleaner linking (fewer dependencies) */ > + ups->host = strdup(host); > > - if (!ups->host) { > - close(ups->fd); > - ups->fd = -1; > + if (!ups->host) { > + close(ups->fd); > + ups->fd = -1; > > - ups->upserror = UPSCLI_ERR_NOMEM; > - return -1; > - } > + ups->upserror = UPSCLI_ERR_NOMEM; > + return -1; > + } > > - ups->port = port; > + ups->port = port; > > - if (flags & UPSCLI_CONN_TRYSSL) { > - upscli_sslinit(ups); > + if (flags & UPSCLI_CONN_TRYSSL) { > + upscli_sslinit(ups); > > - /* see if something made us die inside sslinit */ > - if (ups->upserror != 0) > - return -1; > - } > + /* see if something made us die inside sslinit */ > + if (ups->upserror != 0) > + return -1; > + } > > - if (flags & UPSCLI_CONN_REQSSL) { > - if (upscli_sslinit(ups) != 1) { > - ups->upserror = UPSCLI_ERR_SSLFAIL; > - upscli_closefd(ups); > - return -1; > + if (flags & UPSCLI_CONN_REQSSL) { > + if (upscli_sslinit(ups) != 1) { > + ups->upserror = UPSCLI_ERR_SSLFAIL; > + upscli_closefd(ups); > + return -1; > + } > } > + > + return 0; > } > + freeaddrinfo (rtmp); > > - return 0; > + return -1; > } > > /* map upsd error strings back to upsclient internal numbers */ > @@ -861,31 +872,48 @@ > > ptr = ap; > > - cp = strchr(ptr, ':'); > + if (*ptr != '[') { > + cp = strchr(ptr, ':'); > + if (cp) { > + *cp++ = '\0'; > + *hostname = strdup(ptr); > + > + if (!*hostname) { > + fprintf(stderr, "upscli_splitname: strdup failed\n"); > + return -1; > + } > > - if (cp) { > - *cp++ = '\0'; > - *hostname = strdup(ptr); > + ptr = cp; > + > + *port = strtol(ptr, (char **) NULL, 10); > > - if (!*hostname) { > - fprintf(stderr, "upscli_splitname: strdup failed\n"); > - return -1; > - } > + } else { > > - ptr = cp; > + *hostname = strdup(ptr); > > - *port = strtol(ptr, (char **) NULL, 10); > + if (!*hostname) { > + fprintf(stderr, "upscli_splitname: strdup failed\n"); > + return -1; > + } > > + *port = PORT; > + } > } else { > - > - *hostname = strdup(ptr); > - > - if (!*hostname) { > - fprintf(stderr, "upscli_splitname: strdup failed\n"); > + ptr++; > + cp = strchr(ptr, ']'); > + if (cp) { > + *cp = '\0'; > + *hostname = strdup (ptr); > + ptr = ++cp; > + cp = strchr (ptr, ':'); > + if (cp != NULL) > + *port = strtol (++cp, (char **)NULL, 10); > + else > + *port = PORT; > + } else { > + fprintf (stderr, "upscli_splitname: strchr(']') failed\n"); > return -1; > } > - > - *port = PORT; > } > > return 0; > > Modified: trunk/clients/upsclient.h > =============================================================================> --- trunk/clients/upsclient.h (original) > +++ trunk/clients/upsclient.h Fri Jan 5 21:06:59 2007 > @@ -148,6 +148,8 @@ > > #define UPSCLI_CONN_TRYSSL 0x0001 /* try SSL, OK if not supported */ > #define UPSCLI_CONN_REQSSL 0x0002 /* try SSL, fail if not supported */ > +#define UPSCLI_CONN_INET 0x0004 /* IPv4 only */ > +#define UPSCLI_CONN_INET6 0x0008 /* IPv6 only */ > > #ifdef __cplusplus > } > > Modified: trunk/server/access.c > =============================================================================> --- trunk/server/access.c (original) > +++ trunk/server/access.c Fri Jan 5 21:06:59 2007 > @@ -25,33 +25,72 @@ > #include "common.h" > #include "access.h" > > - struct acl_t *acl_head = NULL; > - struct access_t *access_head = NULL; > +struct acl_t *acl_head = NULL; > +struct access_t *access_head = NULL; > + > +/* > + * Stolen from privoxy code :] > + */ > +int mask_cmp (const struct sockaddr_storage* ip_addr, unsigned int prefix, const struct sockaddr_storage* net_addr) { > + switch (ip_addr->ss_family) { > + case AF_INET: > + return((((struct sockaddr_in*)ip_addr)->sin_addr.s_addr & htonl(prefix)) == ((struct sockaddr_in*)net_addr)->sin_addr.s_addr); > + break; > + case AF_INET6: > + if (AF_INET6 == net_addr->ss_family) { > + struct in6_addr ip, net; > + register unsigned char i; > + > + memcpy (&ip, &((struct sockaddr_in6 *)ip_addr)->sin6_addr, sizeof (struct in6_addr)); > + memcpy (&net, &((struct sockaddr_in6 *)net_addr)->sin6_addr, sizeof (struct in6_addr)); > + > + i = prefix/8; > + if (prefix%8) > + ip.s6_addr[i++] &= 0xff<<(8-(prefix%8)); > + for (; i < sizeof ip.s6_addr; i++) > + ip.s6_addr[i] = 0; > + > + return (memcmp (ip.s6_addr, net.s6_addr, sizeof ip.s6_addr)==0); > + } > + else if (AF_INET == net_addr->ss_family) { /* IPv4 mapped IPv6 */ > + struct in6_addr *ip6 = &((struct sockaddr_in6 *)ip_addr)->sin6_addr; > + struct in_addr *net = &((struct sockaddr_in *)net_addr)->sin_addr; > + > + if ((ip6->s6_addr32[3] & (u_int32_t)prefix) == net->s_addr && > +#if BYTE_ORDER == LITTLE_ENDIAN > + (ip6->s6_addr32[2] == (u_int32_t)0xffff0000) && > +#else > + (ip6->s6_addr32[2] == (u_int32_t)0x0000ffff) && > +#endif > + (ip6->s6_addr32[1] == 0) && (ip6->s6_addr32[0] == 0)) > + return(1); > + else > + return(0); > + } > + default: > + fatal_with_errno("mask_cmp: Unknown address family"); > + return(0); > + } > +} > > /* see if <addr> matches the acl <aclname> */ > -int acl_check(const char *aclname, const struct sockaddr_in *addr) > +int acl_check(const char *aclname, const struct sockaddr_storage *addr) > { > struct acl_t *tmp; > - int aclchk, addrchk; > > tmp = acl_head; > while (tmp != NULL) { > - if (!strcmp(tmp->name, aclname)) { > - aclchk = tmp->addr & tmp->mask; > - addrchk = ntohl(addr->sin_addr.s_addr) & tmp->mask; > - > - if (aclchk == addrchk) > - return 1; /* match */ > - } > - > + if (!strcmp(tmp->name, aclname)) > + if (mask_cmp (addr, tmp->mask, &tmp->addr)) > + return 1; > tmp = tmp->next; > } > - > + > return 0; /* not found */ > } > > /* return ACCEPT/REJECT based on source address */ > -int access_check(const struct sockaddr_in *addr) > +int access_check(const struct sockaddr_storage *addr) > { > struct access_t *tmp; > int ret; > @@ -108,21 +147,83 @@ > tmp = tmp->next; > } > > + /* memset (&saddr, 0, sizeof (struct sockaddr_storage)); */ > tmp = xmalloc(sizeof(struct acl_t)); > + memset (tmp, 0, sizeof (struct acl_t)); > tmp->name = xstrdup(aclname); > - tmp->addr = ntohl(inet_addr(addr)); > tmp->next = NULL; > > - /* must be a /nn CIDR type block */ > - if (strstr(mask, ".") == NULL) { > - if (atoi(mask) != 32) > - tmp->mask = ((unsigned int) ((1 << atoi(mask)) - 1) << > - (32 - atoi(mask))); > - else > - tmp->mask = 0xffffffff; /* avoid overflow from 2^32 */ > + if (*addr == '[') { > + struct sockaddr_in6 s6; > + char *stmp; > + > + stmp = strchr (addr, ']'); > + if (stmp == NULL) { > + free (tmp); > + fatal_with_errno("Expecting \']\' in \"%s\"", addr); > + } > + > + *stmp = '\0'; > + addr++; > + > + memset (&s6, 0, sizeof (struct sockaddr_in6)); > + s6.sin6_family = AF_INET6; > + > + if (inet_pton (AF_INET6, addr, &s6.sin6_addr) < 1) { > + free (tmp); > + fatal_with_errno("Invalid IPv6 address: \"%s\"", addr); > + } > + > + /* prefix */ > + tmp->mask = strtol (mask, NULL, 10); > + > + if (tmp->mask < 0 || tmp->mask > 128) { > + free (tmp); > + fatal_with_errno("Invalid IPv6 prefix"); > + } > + > + { register unsigned char i; > + i = (tmp->mask)/8; > + if ((tmp->mask)%8) > + s6.sin6_addr.s6_addr[i++] &= 0xff<<(8-((tmp->mask)%8)); > + for (; i < sizeof s6.sin6_addr.s6_addr; i++) > + s6.sin6_addr.s6_addr[i] = 0; > + } > + > + memcpy (&(tmp->addr), &s6, sizeof (struct sockaddr_in6)); > + /* tmp->addr.ss_len = sizeof (struct sockaddr_in6); */ > + tmp->addr.ss_family = AF_INET6; > + } else { > + struct sockaddr_in s4; > + > + /* mask */ > + if (inet_pton (AF_INET, mask, &s4.sin_addr) < 1) { > + /* must be a /nn CIDR type block */ > + tmp->mask = strtol (mask, NULL, 10); > + > + if (tmp->mask < 0 || tmp->mask > 32) { > + free (tmp); > + fatal_with_errno("Invalid CIDR type block: Must be > 0 && < 32"); > + } > + tmp->mask = 0xffffffff << (32 - tmp->mask); > + } else { > + tmp->mask = ntohl (s4.sin_addr.s_addr); > + } > + > + memset (&s4, 0, sizeof (struct sockaddr_in)); > + s4.sin_family = AF_INET; > + > + if (inet_pton (AF_INET, addr, &s4.sin_addr) < 1) { > + free (tmp); > + fatal_with_errno("Invalid IPv4 address: \"%s\"", addr); > + } > + > + s4.sin_addr.s_addr &= htonl (tmp->mask); > + > + memcpy (&(tmp->addr), &s4, sizeof (struct sockaddr_in)); > + /* tmp->addr.ss_len = sizeof (struct sockaddr_in); */ > + tmp->addr.ss_family = AF_INET; > } > - else > - tmp->mask = ntohl(inet_addr(mask)); > > if (last == NULL) /* first */ > acl_head = tmp; > > Modified: trunk/server/access.h > =============================================================================> --- trunk/server/access.h (original) > +++ trunk/server/access.h Fri Jan 5 21:06:59 2007 > @@ -26,8 +26,8 @@ > /* ACL structure */ > struct acl_t { > char *name; > - unsigned int addr; > - unsigned int mask; > + struct sockaddr_storage addr; > + unsigned int mask; /* prefix - if IPv6 */ > void *next; > }; > > @@ -38,8 +38,8 @@ > void *next; > }; > > -int acl_check(const char *aclname, const struct sockaddr_in *addr); > -int access_check(const struct sockaddr_in *addr); > +int acl_check(const char *aclname, const struct sockaddr_storage *addr); > +int access_check(const struct sockaddr_storage *addr); > void acl_add(const char *aclname, char *ipblock); > void access_add(int type, int numargs, const char **arg); > void acl_free(void); > > Modified: trunk/server/ctype.h > =============================================================================> --- trunk/server/ctype.h (original) > +++ trunk/server/ctype.h Fri Jan 5 21:06:59 2007 > @@ -32,7 +32,7 @@ > char *addr; > int fd; > int delete; /* set after a write fails */ > - struct sockaddr_in sock; > + struct sockaddr_storage sock; > char rq[SMALLBUF]; > size_t rqpos; > char *loginups; > > Modified: trunk/server/upsd.c > =============================================================================> --- trunk/server/upsd.c (original) > +++ trunk/server/upsd.c Fri Jan 5 21:06:59 2007 > @@ -26,6 +26,7 @@ > > #include <sys/un.h> > #include <sys/socket.h> > +#include <netdb.h> > > #ifdef HAVE_SSL > #include <openssl/err.h> > @@ -60,7 +61,11 @@ > static int listenfd, net_port = PORT; > > /* default is to listen on all local interfaces */ > -static struct in_addr listenaddr; > +static char *listenaddr = NULL; > + > +/* AF_ */ > + > +static int opt_af = AF_UNSPEC; > > /* signal handlers */ > static struct sigaction sa; > @@ -72,6 +77,20 @@ > /* set by signal handlers */ > static int reload_flag = 0, exit_flag = 0; > > +const char *inet_ntopW (struct sockaddr_storage *s) { > + static char str[40]; > + > + switch (s->ss_family) { > + case AF_INET: > + return inet_ntop (AF_INET, &(((struct sockaddr_in *)s)->sin_addr), str, 16); > + case AF_INET6: > + return inet_ntop (AF_INET6, &(((struct sockaddr_in6 *)s)->sin6_addr), str, 40); > + default: > + errno = EAFNOSUPPORT; > + return NULL; > + } > +} > + > /* return a pointer to the named ups if possible */ > upstype *get_ups_ptr(const char *name) > { > @@ -131,35 +150,61 @@ > /* create a listening socket for tcp connections */ > static void setuptcp(void) > { > - struct sockaddr_in server; > + struct addrinfo hints, *r, *rtmp; > + char *service; > int res, one = 1; > > - if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) > - fatal_with_errno("socket"); > - > - res = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void *) &one, > - sizeof(one)); > - > - if (res != 0) > - fatal_with_errno("setsockopt(SO_REUSEADDR)"); > - > - memset(&server, '\0', sizeof(server)); > - server.sin_addr = listenaddr; > - server.sin_family = AF_INET; > - server.sin_port = htons(net_port); > - > - if (bind(listenfd, (struct sockaddr *) &server, sizeof(server)) == -1) > - fatal_with_errno("Can't bind TCP port number %d", net_port); > + memset (&hints, 0, sizeof (struct addrinfo)); > + hints.ai_family = opt_af; > + hints.ai_flags = AI_PASSIVE; > + hints.ai_protocol = IPPROTO_TCP; > + hints.ai_socktype = SOCK_STREAM; > + > + service = xmalloc (sizeof (char) * 6); > + > + if (snprintf (service, 6, "%hu", (unsigned short int)net_port) < 1) > + fatal_with_errno("snprintf"); > + > + if (getaddrinfo (listenaddr, service, &hints, &r) != 0) { > + free (service); > + fatal_with_errno("getaddrinfo"); > + } > + free (service); > + > + for (rtmp = r; r != NULL; r = r->ai_next) { > + listenfd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); > + if (listenfd < 0) { > + if (r->ai_next == NULL) > + fatal_with_errno("socket"); > + continue; > + } > > - if ((res = fcntl(listenfd, F_GETFL, 0)) == -1) > - fatal_with_errno("fcntl(get)"); > + res = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one)); > + if (res != 0) > + fatal_with_errno("setsockopt(SO_REUSEADDR)"); > + > + if (bind (listenfd, r->ai_addr, r->ai_addrlen) == -1) { > + if (r->ai_next == NULL) > + fatal_with_errno("Can't bind TCP port number %u", net_port); > + close (listenfd); > + continue; > + } > > - if (fcntl(listenfd, F_SETFL, res | O_NDELAY) == -1) > - fatal_with_errno("fcntl(set)"); > + if ((res = fcntl(listenfd, F_GETFL, 0)) == -1) > + fatal_with_errno("fcntl(get)"); > > - if (listen(listenfd, 16)) > - fatal_with_errno("listen"); > + if (fcntl(listenfd, F_SETFL, res | O_NDELAY) == -1) > + fatal_with_errno("fcntl(set)"); > > + if (listen(listenfd, 16) == -1) { > + if (r->ai_next == NULL) > + fatal_with_errno("listen"); > + close (listenfd); > + continue; > + } > + break; > + } > + freeaddrinfo (rtmp); > return; > } > > @@ -412,7 +457,7 @@ > static void answertcp(void) > { > int acc; > - struct sockaddr_in csock; > + struct sockaddr_storage csock; > ctype *tmp, *last; > socklen_t clen; > > @@ -424,7 +469,7 @@ > > if (!access_check(&csock)) { > upslogx(LOG_NOTICE, "Rejecting TCP connection from %s", > - inet_ntoa(csock.sin_addr)); > + inet_ntopW(&csock)); > shutdown(acc, shutdown_how); > close(acc); > return; > @@ -439,10 +484,10 @@ > > tmp = xmalloc(sizeof(ctype)); > > - tmp->addr = xstrdup(inet_ntoa(csock.sin_addr)); > + tmp->addr = xstrdup(inet_ntopW(&csock)); > tmp->fd = acc; > tmp->delete = 0; > - memcpy(&tmp->sock, &csock, sizeof(struct sockaddr_in)); > + memcpy(&tmp->sock, &csock, sizeof(struct sockaddr_storage)); > > tmp->rqpos = 0; > memset(tmp->rq, '\0', sizeof(tmp->rq)); > @@ -463,7 +508,7 @@ > else > last->next = tmp; > > - upslogx(LOG_INFO, "Connection from %s", inet_ntoa(csock.sin_addr)); > + upslogx(LOG_INFO, "Connection from %s", tmp->addr); > } > > /* read tcp messages and handle them */ > @@ -668,6 +713,8 @@ > printf(" -r <dir> chroots to <dir>\n"); > printf(" -u <user> switch to <user> (if started as root)\n"); > printf(" -V display the version of this software\n"); > + printf(" -4 IPv4 only\n"); > + printf(" -6 IPv6 only\n"); > > exit(EXIT_SUCCESS); > } > @@ -737,13 +784,11 @@ > datapath = xstrdup(DATADIR); > > /* set up some things for later */ > - > - listenaddr.s_addr = INADDR_ANY; > snprintf(pidfn, sizeof(pidfn), "%s/upsd.pid", altpidpath()); > > printf("Network UPS Tools upsd %s\n", UPS_VERSION); > > - while ((i = getopt(argc, argv, "+hp:r:i:fu:Vc:D")) != EOF) { > + while ((i = getopt(argc, argv, "+h46p:r:i:fu:Vc:D")) != EOF) { > switch (i) { > case 'h': > help(progname); > @@ -752,8 +797,7 @@ > net_port = atoi(optarg); > break; > case 'i': > - if (!inet_aton(optarg, &listenaddr)) > - fatal_with_errno("Invalid IP address"); > + listenaddr = xstrdup(optarg); > break; > case 'r': > chroot_path = optarg; > @@ -784,6 +828,15 @@ > do_background = 0; > nut_debug_level++; > break; > + > + case '4': > + opt_af = AF_INET; > + break; > + > + case '6': > + opt_af = AF_INET6; > + break; > + > default: > help(progname); > break; > > Modified: trunk/server/user.c > =============================================================================> --- trunk/server/user.c (original) > +++ trunk/server/user.c Fri Jan 5 21:06:59 2007 > @@ -290,7 +290,7 @@ > users = NULL; > } > > -static int user_matchacl(ulist_t *user, const struct sockaddr_in *addr) > +static int user_matchacl(ulist_t *user, const struct sockaddr_storage *addr) > { > acllist *tmp; > > @@ -328,7 +328,7 @@ > return 0; /* fail */ > } > > -int user_checkinstcmd(const struct sockaddr_in *addr, > +int user_checkinstcmd(const struct sockaddr_storage *addr, > const char *un, const char *pw, const char *cmd) > { > ulist_t *tmp = users; > @@ -385,7 +385,7 @@ > return 0; /* fail */ > } > > -int user_checkaction(const struct sockaddr_in *addr, > +int user_checkaction(const struct sockaddr_storage *addr, > const char *un, const char *pw, const char *action) > { > ulist_t *tmp = users; > > Modified: trunk/server/user.h > =============================================================================> --- trunk/server/user.h (original) > +++ trunk/server/user.h Fri Jan 5 21:06:59 2007 > @@ -19,10 +19,10 @@ > > void user_load(void); > > -int user_checkinstcmd(const struct sockaddr_in *addr, > +int user_checkinstcmd(const struct sockaddr_storage *addr, > const char *un, const char *pw, const char *cmd); > > -int user_checkaction(const struct sockaddr_in *addr, > +int user_checkaction(const struct sockaddr_storage *addr, > const char *un, const char *pw, const char *action); > > void user_flush(void); > > _______________________________________________ > nut-commits mailing list > nut-commits@lists.alioth.debian.org > http://lists.alioth.debian.org/mailman/listinfo/nut-commits >
Arjen de Korte
2007-Jan-06 10:44 UTC
[Nut-upsdev] Re: [nut-commits] svn commit r708 - in trunk: . clients server
> With the Ipv6 patch (r708), I get: > > upsclient.c: In function `upscli_connect': > upsclient.c:469: `AI_ADDRCONFIG' undeclared (first use in this function) > upsclient.c:469: (Each undeclared identifier is reported only once > upsclient.c:469: for each function it appears in.)I got a report from Doug about similar problems in 'server/access.c'. It builds cleanly on my openSUSE 10.2 system however, so this looks like a portability problem.> Even if it doesn't break IPv4 support, it may break portability, as > IPv6 seems to require specific functions that are not as standardized > as the IPv4 ones. For example it uses "struct addrinfo" and not > "struct sockaddr_in". Moreover, it seems that my version of > getaddrinfo() recognizes different flags than this patch assumes.Point taken.> Ideally the availability of IPv6 functions should be detected at > configuration time. Unfortunately, the patch uses the new interface > even for IPv4 support, so there is no easy way of enclosing the > non-portable stuff in #ifdef's.I think if possible it is better to use one interface for both eventually. However, as you already indicated, it looks like the library functions involved are far from stable enough to be of general use now, so until that is the case, the old code should be the default.> Perhaps it would be better to develop this patch in a branch, and > reverse the commit on the main branch until the portability issues are > resolved? The ideal situation would be to enclose all the IPv6 stuff > in #ifdef's, and leave the IPv4 stuff as it was before.I prefer to keep it in the trunk, but enclosed in #ifdef's and hopefully with some kind of autodetection stuff to determine whether it is safe or not to use it. We should get as much feedback as possible on this, which is not going to happen if we put it on a sidetrack in branches (sadly enough, because there are a couple of nice developments there). I'll bring back the 'old' IPv4 stuff later today with #ifdef'ing to make the IPv6 code available. Best regards, Arjen -- Eindhoven - The Netherlands Key fingerprint - 66 4E 03 2C 9D B5 CB 9B 7A FE 7E C1 EE 88 BC 57
Peter Selinger
2007-Jan-06 20:33 UTC
[Nut-upsdev] Re: [nut-commits] svn commit r708 - in trunk: .
My list (netdb.h) ends after 3 items: /* Possible values for `ai_flags' field in `addrinfo' structure. */ # define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */ # define AI_CANONNAME 0x0002 /* Request for canonical name. */ # define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ -- Peter Arjen de Korte wrote:> > Peter Selinger wrote: > > > With the Ipv6 patch (r708), I get: > > > > upsclient.c: In function `upscli_connect': > > upsclient.c:469: `AI_ADDRCONFIG' undeclared (first use in this function) > > upsclient.c:469: (Each undeclared identifier is reported only once > > upsclient.c:469: for each function it appears in.) > > It's defined in <netdb.h> on my system (Linux/openSUSE 10.2): > > /* Possible values for `ai_flags' field in `addrinfo' structure. */ > # define AI_PASSIVE 0x0001 /* Socket address is intended for > `bind'. */ > # define AI_CANONNAME 0x0002 /* Request for canonical name. */ > # define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ > # define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ > # define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 > addresses. */ > # define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose > returned address type.. */ > # ifdef __USE_GNU > # define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded > in the current locale's character set) > before looking it up. */ > # define AI_CANONIDN 0x0080 /* Translate canonical name from IDN > format. */ > # define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode > code points. */ > # define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings > according to > STD3 rules. */ > # endif > # define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */ > > Apparently, there still is a long way to go before IPv6 is fully supported. > > Best regards, Arjen >
Arjen de Korte
2007-Jan-06 20:36 UTC
[Nut-upsdev] Re: [nut-commits] svn commit r708 - in trunk: . clients server
Peter Selinger wrote:> With the Ipv6 patch (r708), I get: > > upsclient.c: In function `upscli_connect': > upsclient.c:469: `AI_ADDRCONFIG' undeclared (first use in this function) > upsclient.c:469: (Each undeclared identifier is reported only once > upsclient.c:469: for each function it appears in.)It's defined in <netdb.h> on my system (Linux/openSUSE 10.2): /* Possible values for `ai_flags' field in `addrinfo' structure. */ # define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */ # define AI_CANONNAME 0x0002 /* Request for canonical name. */ # define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ # define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ # define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */ # define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose returned address type.. */ # ifdef __USE_GNU # define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded in the current locale's character set) before looking it up. */ # define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */ # define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode code points. */ # define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to STD3 rules. */ # endif # define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */ Apparently, there still is a long way to go before IPv6 is fully supported. Best regards, Arjen