diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-04-24 21:40:36 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-04-24 21:40:36 +0000 |
commit | 42090a4d22f5c1213635160510f17b68ce84eb73 (patch) | |
tree | 16da453bd097457ef4e69be3480cfbe720cebe99 | |
parent | 22ed70ce27c4051e9a44bb6a89436e743b4e9de9 (diff) |
Don't return NULL in getconfigent() when an unresolvable hostname
or unsupported address family is specified. This simplifies the
hostname/address lookup loops and gets rid of the skip label.
Found by mpech@. OK deraadt@ and otto@
-rw-r--r-- | usr.sbin/inetd/inetd.8 | 13 | ||||
-rw-r--r-- | usr.sbin/inetd/inetd.c | 207 |
2 files changed, 91 insertions, 129 deletions
diff --git a/usr.sbin/inetd/inetd.8 b/usr.sbin/inetd/inetd.8 index a97cce77a88..0033aa5e3fa 100644 --- a/usr.sbin/inetd/inetd.8 +++ b/usr.sbin/inetd/inetd.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: inetd.8,v 1.25 2003/06/12 12:59:50 jmc Exp $ +.\" $OpenBSD: inetd.8,v 1.26 2004/04/24 21:40:35 millert Exp $ .\" Copyright (c) 1985, 1991 The Regents of the University of California. .\" All rights reserved. .\" @@ -192,11 +192,18 @@ and .Dq udp will be recognized as .Dq TCP or UDP over default IP version . -It is currently IPv4, but in the future it will be IPv6. +This is currently IPv4, but in the future it will be IPv6. If you need to specify IPv4 or IPv6 explicitly, use something like .Dq tcp4 or .Dq udp6 . +A +.Em protocol +of +.Dq unix +is used to specify a socket in the +.Ux +domain. .Pp The .Em wait/nowait @@ -377,7 +384,7 @@ command appeared in Support for Sun-RPC based services is modelled after that provided by SunOS 4.1. -IPv6 support and IPsec hack was made by KAME project, in 1999. +IPv6 support was added by the KAME project in 1999. .Sh BUGS Host address specifiers, while they make conceptual sense for RPC services, do not work entirely correctly. diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index b0598034dbe..4cd7165bcb6 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: inetd.c,v 1.116 2004/03/31 19:12:22 millert Exp $ */ +/* $OpenBSD: inetd.c,v 1.117 2004/04/24 21:40:35 millert Exp $ */ /* * Copyright (c) 1983,1991 The Regents of the University of California. @@ -36,8 +36,8 @@ char copyright[] = #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)inetd.c 5.30 (Berkeley) 6/3/91";*/ -static char rcsid[] = "$OpenBSD: inetd.c,v 1.116 2004/03/31 19:12:22 millert Exp $"; +/*static const char sccsid[] = "from: @(#)inetd.c 5.30 (Berkeley) 6/3/91";*/ +static const char rcsid[] = "$OpenBSD: inetd.c,v 1.117 2004/04/24 21:40:35 millert Exp $"; #endif /* not lint */ /* @@ -682,7 +682,7 @@ doconfig(void) if (matchconf(sep, cp)) break; add = 0; - if (sep != 0) { + if (sep != NULL) { int i; #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;} @@ -1162,12 +1162,9 @@ endconfig(void) struct servtab * getconfigent(void) { - struct servtab *sep; + struct servtab *sep, *tsep; + char *arg, *cp, *hostdelim, *s; int argc; - char *cp, *arg, *s; - char *hostdelim; - struct servtab *nsep; - struct servtab *psep; sep = (struct servtab *) malloc(sizeof(struct servtab)); if (sep == NULL) { @@ -1200,7 +1197,9 @@ more: if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { hostdelim[-1] = '\0'; sep->se_hostaddr = newstr(arg + 1); - } else + } else if (hostdelim == arg) + sep->se_hostaddr = newstr("*"); + else sep->se_hostaddr = newstr(arg); arg = hostdelim + 1; /* @@ -1242,10 +1241,29 @@ more: if (strcmp(sep->se_proto, "unix") == 0) { sep->se_family = AF_UNIX; + if (sep->se_hostaddr != NULL) { + syslog(LOG_WARNING, "%s/%s: %s: host address " + "specifiers are not supported in the UNIX domain", + sep->se_service, sep->se_proto, sep->se_hostaddr); + goto more; + } } else { + int s; + sep->se_family = AF_INET; if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') sep->se_family = AF_INET6; + + /* check if the family is supported */ + s = socket(sep->se_family, SOCK_DGRAM, 0); + if (s < 0) { + syslog(LOG_WARNING, "%s/%s: %s: the address family is " + "not supported by the kernel", sep->se_service, + sep->se_proto, sep->se_hostaddr); + goto more; + } + close(s); + if (strncmp(sep->se_proto, "rpc/", 4) == 0) { char *cp, *ccp; long l; @@ -1342,124 +1360,60 @@ more: sep->se_argv[argc++] = NULL; /* - * Now that we've processed the entire line, check if the hostname - * specifier was a comma separated list of hostnames. If so - * we'll make new entries for each address. + * Resolve each hostname in the se_hostaddr list (if any) + * and create a new entry for each resolved address. */ - while ((hostdelim = strrchr(sep->se_hostaddr, ',')) != NULL) { - nsep = dupconfig(sep); - - /* - * NULL terminate the hostname field of the existing entry, - * and make a dup for the new entry. - */ - *hostdelim++ = '\0'; - nsep->se_hostaddr = newstr(hostdelim); - - nsep->se_next = sep->se_next; - sep->se_next = nsep; - } - - nsep = sep; - while (nsep != NULL) { - nsep->se_checked = 1; - switch (nsep->se_family) { - case AF_INET: - case AF_INET6: - { - struct addrinfo hints, *res0, *res; - char *host, *port; - int error; - int s; - - /* check if the family is supported */ - s = socket(nsep->se_family, SOCK_DGRAM, 0); - if (s < 0) { - syslog(LOG_WARNING, - "%s/%s: %s: the address family is " - "not supported by the kernel", - nsep->se_service, nsep->se_proto, - nsep->se_hostaddr); - nsep->se_checked = 0; - goto skip; - } - close(s); + if (sep->se_hostaddr != NULL) { + struct addrinfo hints, *res0, *res; + char *host, *hostlist0, *hostlist, *port; + int error; + + hostlist = hostlist0 = sep->se_hostaddr; + sep->se_hostaddr = NULL; + sep->se_checked = -1; + while ((host = strsep(&hostlist, ",")) != NULL) { + if (*host == '\0') + continue; memset(&hints, 0, sizeof(hints)); - hints.ai_family = nsep->se_family; - hints.ai_socktype = nsep->se_socktype; + hints.ai_family = sep->se_family; + hints.ai_socktype = sep->se_socktype; hints.ai_flags = AI_PASSIVE; - if (!strcmp(nsep->se_hostaddr, "*")) - host = NULL; - else - host = nsep->se_hostaddr; port = "0"; /* XXX shortened IPv4 syntax is now forbidden */ - error = getaddrinfo(host, port, &hints, &res0); + error = getaddrinfo(strcmp(host, "*") ? host : NULL, + port, &hints, &res0); if (error) { syslog(LOG_ERR, "%s/%s: %s: %s", - nsep->se_service, nsep->se_proto, - nsep->se_hostaddr, - gai_strerror(error)); - nsep->se_checked = 0; - goto skip; + sep->se_service, sep->se_proto, + host, gai_strerror(error)); + continue; } for (res = res0; res; res = res->ai_next) { if (res->ai_addrlen > - sizeof(nsep->se_ctrladdr_storage)) - continue; - if (res == res0) { - memcpy(&nsep->se_ctrladdr_storage, - res->ai_addr, res->ai_addrlen); + sizeof(sep->se_ctrladdr_storage)) continue; - } - - psep = dupconfig(nsep); - psep->se_hostaddr = newstr(nsep->se_hostaddr); - psep->se_checked = 1; - memcpy(&psep->se_ctrladdr_storage, res->ai_addr, - res->ai_addrlen); - psep->se_ctrladdr_size = res->ai_addrlen; - /* - * Prepend to list, don't want to look up its - * hostname again. + * If sep is unused, store host in there. + * Otherwise, dup a new entry and prepend it. */ - psep->se_next = sep; - sep = psep; + if (sep->se_checked == -1) { + sep->se_checked = 0; + } else { + tsep = dupconfig(sep); + tsep->se_next = sep; + sep = tsep; + } + sep->se_hostaddr = newstr(host); + memcpy(&sep->se_ctrladdr_storage, + res->ai_addr, res->ai_addrlen); + sep->se_ctrladdr_size = res->ai_addrlen; } freeaddrinfo(res0); - break; - } - } -skip: - nsep = nsep->se_next; - } - - /* - * Finally, free any entries which failed the gethostbyname - * check. - */ - psep = NULL; - nsep = sep; - while (nsep != NULL) { - struct servtab *tsep; - - if (nsep->se_checked == 0) { - tsep = nsep; - if (psep == NULL) { - sep = nsep->se_next; - nsep = sep; - } else { - nsep = nsep->se_next; - psep->se_next = nsep; - } - freeconfig(tsep); - } else { - nsep->se_checked = 0; - psep = nsep; - nsep = nsep->se_next; } + free(hostlist0); + if (sep->se_checked == -1) + goto more; /* no resolvable names/addresses */ } return (sep); @@ -1470,21 +1424,22 @@ freeconfig(struct servtab *cp) { int i; - if (cp->se_hostaddr) - free(cp->se_hostaddr); - if (cp->se_service) - free(cp->se_service); - if (cp->se_proto) - free(cp->se_proto); - if (cp->se_user) - free(cp->se_user); - if (cp->se_group) - free(cp->se_group); - if (cp->se_server) - free(cp->se_server); - for (i = 0; i < MAXARGV; i++) - if (cp->se_argv[i]) - free(cp->se_argv[i]); + free(cp->se_hostaddr); + cp->se_hostaddr = NULL; + free(cp->se_service); + cp->se_service = NULL; + free(cp->se_proto); + cp->se_proto = NULL; + free(cp->se_user); + cp->se_user = NULL; + free(cp->se_group); + cp->se_group = NULL; + free(cp->se_server); + cp->se_server = NULL; + for (i = 0; i < MAXARGV; i++) { + free(cp->se_argv[i]); + cp->se_argv[i] = NULL; + } } char * |