diff options
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/gen/lockf.c | 11 | ||||
-rw-r--r-- | lib/libc/net/getaddrinfo.3 | 60 | ||||
-rw-r--r-- | lib/libc/net/getaddrinfo.c | 172 | ||||
-rw-r--r-- | lib/libc/net/name6.c | 7 | ||||
-rw-r--r-- | lib/libc/sys/clock_gettime.2 | 6 | ||||
-rw-r--r-- | lib/libc/sys/gettimeofday.2 | 4 |
6 files changed, 205 insertions, 55 deletions
diff --git a/lib/libc/gen/lockf.c b/lib/libc/gen/lockf.c index 2c567ba..c64a347 100644 --- a/lib/libc/gen/lockf.c +++ b/lib/libc/gen/lockf.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <fcntl.h> #include <unistd.h> #include "un-namespace.h" +#include "libc_private.h" int lockf(int filedes, int function, off_t size) @@ -62,9 +63,12 @@ lockf(int filedes, int function, off_t size) break; case F_TEST: fl.l_type = F_WRLCK; - if (_fcntl(filedes, F_GETLK, &fl) == -1) + if (((int (*)(int, int, ...)) + __libc_interposing[INTERPOS_fcntl])(filedes, F_GETLK, &fl) + == -1) return (-1); - if (fl.l_type == F_UNLCK || (fl.l_sysid == 0 && fl.l_pid == getpid())) + if (fl.l_type == F_UNLCK || (fl.l_sysid == 0 && + fl.l_pid == getpid())) return (0); errno = EAGAIN; return (-1); @@ -75,5 +79,6 @@ lockf(int filedes, int function, off_t size) /* NOTREACHED */ } - return (_fcntl(filedes, cmd, &fl)); + return (((int (*)(int, int, ...)) + __libc_interposing[INTERPOS_fcntl])(filedes, cmd, &fl)); } diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3 index 07fefc0..a8f8c25 100644 --- a/lib/libc/net/getaddrinfo.3 +++ b/lib/libc/net/getaddrinfo.3 @@ -18,7 +18,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 5, 2015 +.Dd December 21, 2015 .Dt GETADDRINFO 3 .Os .Sh NAME @@ -78,7 +78,7 @@ as defined by .Bd -literal struct addrinfo { int ai_flags; /* input flags */ - int ai_family; /* protocol family for socket */ + int ai_family; /* address family for socket */ int ai_socktype; /* socket type */ int ai_protocol; /* protocol for socket */ socklen_t ai_addrlen; /* length of socket-address */ @@ -94,12 +94,12 @@ The caller can supply the following structure elements in .Fa hints : .Bl -tag -width "ai_socktypeXX" .It Fa ai_family -The protocol family that should be used. +The address family that should be used. When .Fa ai_family is set to -.Dv PF_UNSPEC , -it means the caller will accept any protocol family supported by the +.Dv AF_UNSPEC , +it means the caller will accept any address family supported by the operating system. .It Fa ai_socktype Denotes the type of socket that is wanted: @@ -126,11 +126,13 @@ field to which the parameter points shall be set to zero or be the bitwise-inclusive OR of one or more of the values .Dv AI_ADDRCONFIG , +.Dv AI_ALL , .Dv AI_CANONNAME , .Dv AI_NUMERICHOST , -.Dv AI_NUMERICSERV +.Dv AI_NUMERICSERV , +.Dv AI_PASSIVE and -.Dv AI_PASSIVE . +.Dv AI_V4MAPPED . .Bl -tag -width "AI_CANONNAMEXX" .It Dv AI_ADDRCONFIG If the @@ -139,6 +141,25 @@ bit is set, IPv4 addresses shall be returned only if an IPv4 address is configured on the local system, and IPv6 addresses shall be returned only if an IPv6 address is configured on the local system. +.It Dv AI_ALL +If the +.Dv AI_ALL +flag is used with the +.Dv AI_V4MAPPED +flag, then +.Fn getaddrinfo +shall return all matching IPv6 and IPv4 addresses. +.Pp +For example, when using the DNS, queries are made for both AAAA records and A records, and +.Fn getaddrinfo +returns the combined results of both queries. +Any IPv4 addresses found are returned as IPv4-mapped IPv6 addresses. +.Pp +The +.Dv AI_ALL +flag without the +.Dv AI_V4MAPPED +flag is ignored. .It Dv AI_CANONNAME If the .Dv AI_CANONNAME @@ -203,6 +224,25 @@ loopback address if is the null pointer and .Dv AI_PASSIVE is not set. +.It Dv AI_V4MAPPED +If the +.Dv AI_V4MAPPED +flag is specified along with an ai_family of +.Dv AF_INET6 , +then +.Fn getaddrinfo +shall return IPv4-mapped IPv6 addresses on finding no matching IPv6 addresses ( +.Fa ai_addrlen +shall be 16). +.Pp +For example, when using the DNS, if no AAAA records are found then a query is made for A records and any found are returned as IPv4-mapped IPv6 addresses. +.Pp +The +.Dv AI_V4MAPPED +flag shall be ignored unless +.Fa ai_family +equals +.Dv AF_INET6 . .El .El .Pp @@ -221,7 +261,7 @@ behaves as if the caller provided a with .Fa ai_family set to -.Dv PF_UNSPEC +.Dv AF_UNSPEC and all other elements set to zero or .Dv NULL . .Pp @@ -333,7 +373,7 @@ int s; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); -hints.ai_family = PF_UNSPEC; +hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo("www.kame.net", "http", &hints, &res0); if (error) { @@ -376,7 +416,7 @@ int nsock; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); -hints.ai_family = PF_UNSPEC; +hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, "http", &hints, &res0); diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index 9bc2c9b..54ac329 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <nsswitch.h> #include "un-namespace.h" +#include "netdb_private.h" #include "libc_private.h" #ifdef NS_CACHING #include "nscache.h" @@ -451,6 +452,24 @@ getaddrinfo(const char *hostname, const char *servname, } /* + * RFC 3493: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They need to be ignored if specified in other + * occassions. + */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: +#ifdef INET6 + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; +#endif + case AI_ALL: + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + } + + /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed * for raw and other inet{,6} sockets. @@ -759,10 +778,9 @@ match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) memset(&key, 0, sizeof(key)); key.sin6_family = AF_INET6; key.sin6_len = sizeof(key); - key.sin6_addr.s6_addr[10] = 0xff; - key.sin6_addr.s6_addr[11] = 0xff; - memcpy(&key.sin6_addr.s6_addr[12], - &((struct sockaddr_in *)addr)->sin_addr, 4); + _map_v4v6_address( + (char *)&((struct sockaddr_in *)addr)->sin_addr, + (char *)&key.sin6_addr); break; default: return(NULL); @@ -842,6 +860,16 @@ set_source(struct ai_order *aio, struct policyhead *ph) if ((s = _socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC, ai.ai_protocol)) < 0) return; /* give up */ +#ifdef INET6 + if (ai.ai_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai.ai_addr; + int off = 0; + + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + (void)_setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + (char *)&off, sizeof(off)); + } +#endif if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0) goto cleanup; srclen = ai.ai_addrlen; @@ -1177,7 +1205,7 @@ explore_numeric(const struct addrinfo *pai, const char *hostname, const char *servname, struct addrinfo **res, const char *canonname) { const struct afd *afd; - struct addrinfo *ai; + struct addrinfo *ai, ai0; int error; char pton[PTON_MAX]; @@ -1201,8 +1229,17 @@ explore_numeric(const struct addrinfo *pai, const char *hostname, return 0; break; default: - if (inet_pton(afd->a_af, hostname, pton) != 1) - return 0; + if (inet_pton(afd->a_af, hostname, pton) != 1) { + if (pai->ai_family != AF_INET6 || + (pai->ai_flags & AI_V4MAPPED) != AI_V4MAPPED) + return 0; + if (inet_aton(hostname, (struct in_addr *)pton) != 1) + return 0; + afd = &afdl[N_INET]; + ai0 = *pai; + ai0.ai_family = AF_INET; + pai = &ai0; + } break; } @@ -1321,6 +1358,9 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) char *fp_str; int translate = 0; #endif +#ifdef INET6 + struct in6_addr mapaddr; +#endif #ifdef FAITH /* @@ -1358,6 +1398,14 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) } #endif +#ifdef INET6 + if (afd->a_af == AF_INET && (pai->ai_flags & AI_V4MAPPED) != 0) { + afd = &afdl[N_INET6]; + _map_v4v6_address(addr, (char *)&mapaddr); + addr = (char *)&mapaddr; + } +#endif + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); if (ai == NULL) @@ -2117,7 +2165,11 @@ getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, return sentinel.ai_next; } - RES_SET_H_ERRNO(res, NO_RECOVERY); + /* + * We could have walked a CNAME chain, but the ultimate target + * may not have what we looked for. + */ + RES_SET_H_ERRNO(res, ntohs(hp->ancount) > 0 ? NO_DATA : NO_RECOVERY); return NULL; } @@ -2191,7 +2243,7 @@ addr4sort(struct addrinfo *sentinel, res_state res) static int _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) { - struct addrinfo *ai; + struct addrinfo *ai, ai0; querybuf *buf, *buf2; const char *hostname; const struct addrinfo *pai; @@ -2221,6 +2273,13 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) return NS_NOTFOUND; } + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) { + ai0 = *pai; + ai0.ai_family = AF_UNSPEC; + pai = &ai0; + } + switch (pai->ai_family) { case AF_UNSPEC: q.name = hostname; @@ -2276,14 +2335,18 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) cur = cur->ai_next; } } - ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); - if (ai) - cur->ai_next = ai; + if (!ai || pai->ai_family != AF_UNSPEC || + (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) != AI_V4MAPPED) { + ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); + if (ai) + cur->ai_next = ai; + } free(buf); free(buf2); if (sentinel.ai_next == NULL) switch (res->res_h_errno) { case HOST_NOT_FOUND: + case NO_DATA: return NS_NOTFOUND; case TRY_AGAIN: return NS_TRYAGAIN; @@ -2360,6 +2423,9 @@ found: hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_flags = AI_NUMERICHOST; + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) + hints.ai_flags |= AI_V4MAPPED; error = getaddrinfo(addr, "0", &hints, &res0); if (error) goto again; @@ -2387,6 +2453,20 @@ found: return res0; } +static struct addrinfo * +_getht(FILE **hostf, const char *name, const struct addrinfo *pai, + struct addrinfo *cur) +{ + struct addrinfo *p; + + while ((p = _gethtent(hostf, name, pai)) != NULL) { + cur->ai_next = p; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + return (cur); +} + /*ARGSUSED*/ static int _files_getaddrinfo(void *rv, void *cb_data, va_list ap) @@ -2394,7 +2474,6 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap) const char *name; const struct addrinfo *pai; struct addrinfo sentinel, *cur; - struct addrinfo *p; FILE *hostf = NULL; name = va_arg(ap, char *); @@ -2404,11 +2483,19 @@ _files_getaddrinfo(void *rv, void *cb_data, va_list ap) cur = &sentinel; _sethtent(&hostf); - while ((p = _gethtent(&hostf, name, pai)) != NULL) { - cur->ai_next = p; - while (cur && cur->ai_next) - cur = cur->ai_next; - } + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) == AI_V4MAPPED) { + struct addrinfo ai0 = *pai; + + ai0.ai_flags &= ~AI_V4MAPPED; + cur = _getht(&hostf, name, &ai0, cur); + if (sentinel.ai_next == NULL) { + _sethtent(&hostf); + ai0.ai_flags |= AI_V4MAPPED; + cur = _getht(&hostf, name, &ai0, cur); + } + } else + cur = _getht(&hostf, name, pai, cur); _endhtent(&hostf); *((struct addrinfo **)rv) = sentinel.ai_next; @@ -2468,6 +2555,9 @@ nextline: hints = *pai; hints.ai_flags = AI_NUMERICHOST; + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) + hints.ai_flags |= AI_V4MAPPED; error = getaddrinfo(addr, NULL, &hints, &res0); if (error == 0) { for (res = res0; res; res = res->ai_next) { @@ -2515,15 +2605,46 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; + /* ipnodes.byname can hold both IPv4/v6 */ + r = yp_match(ypdomain, "ipnodes.byname", name, + (int)strlen(name), &ypbuf, &ypbuflen); + if (r == 0) { + ai = _yphostent(ypbuf, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + free(ypbuf); + } + + if (ai != NULL) { + struct sockaddr_in6 *sin6; + + switch (ai->ai_family) { + case AF_INET: + goto done; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)ai->ai_addr; + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + goto done; + break; + } + } + /* hosts.byname is only for IPv4 (Solaris8) */ - if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { + if (pai->ai_family == AF_UNSPEC || pai->ai_family == AF_INET || + ((pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) && + (ai == NULL || (pai->ai_flags & AI_ALL) == AI_ALL))) { r = yp_match(ypdomain, "hosts.byname", name, (int)strlen(name), &ypbuf, &ypbuflen); if (r == 0) { struct addrinfo ai4; ai4 = *pai; - ai4.ai_family = AF_INET; + if (pai->ai_family == AF_UNSPEC) + ai4.ai_family = AF_INET; ai = _yphostent(ypbuf, &ai4); if (ai) { cur->ai_next = ai; @@ -2534,16 +2655,7 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap) } } - /* ipnodes.byname can hold both IPv4/v6 */ - r = yp_match(ypdomain, "ipnodes.byname", name, - (int)strlen(name), &ypbuf, &ypbuflen); - if (r == 0) { - ai = _yphostent(ypbuf, pai); - if (ai) - cur->ai_next = ai; - free(ypbuf); - } - +done: if (sentinel.ai_next == NULL) { RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND); return NS_NOTFOUND; diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c index 97880a2..74d7380 100644 --- a/lib/libc/net/name6.c +++ b/lib/libc/net/name6.c @@ -795,10 +795,9 @@ match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head) memset(&key, 0, sizeof(key)); key.sin6_family = AF_INET6; key.sin6_len = sizeof(key); - key.sin6_addr.s6_addr[10] = 0xff; - key.sin6_addr.s6_addr[11] = 0xff; - memcpy(&key.sin6_addr.s6_addr[12], - &((struct sockaddr_in *)addr)->sin_addr, 4); + _map_v4v6_address( + (char *)&((struct sockaddr_in *)addr)->sin_addr, + (char *)&key.sin6_addr); break; default: return(NULL); diff --git a/lib/libc/sys/clock_gettime.2 b/lib/libc/sys/clock_gettime.2 index 583cc8f..b42432f 100644 --- a/lib/libc/sys/clock_gettime.2 +++ b/lib/libc/sys/clock_gettime.2 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 29, 2009 +.Dd December 20, 2015 .Dt CLOCK_GETTIME 2 .Os .Sh NAME @@ -136,10 +136,6 @@ The .Fa clock_id argument was not a valid value. -.It Bq Er EFAULT -The -.Fa *tp -argument address referenced invalid memory. .It Bq Er EPERM A user other than the super-user attempted to set the time. .El diff --git a/lib/libc/sys/gettimeofday.2 b/lib/libc/sys/gettimeofday.2 index 23cc059..888cbcd 100644 --- a/lib/libc/sys/gettimeofday.2 +++ b/lib/libc/sys/gettimeofday.2 @@ -28,7 +28,7 @@ .\" @(#)gettimeofday.2 8.2 (Berkeley) 5/26/95 .\" $FreeBSD$ .\" -.Dd May 26, 1995 +.Dd December 20, 2015 .Dt GETTIMEOFDAY 2 .Os .Sh NAME @@ -110,8 +110,6 @@ system call even when the system is secure. The following error codes may be set in .Va errno : .Bl -tag -width Er -.It Bq Er EFAULT -An argument address referenced invalid memory. .It Bq Er EPERM A user other than the super-user attempted to set the time. .El |