netresolv: Add support for AI_V4MAPPED in ai_flags in getaddrinfo
Ports over the following commits from FreeBSD: https://github.com/freebsd/freebsd-src/commit/b848a37d4eddb432629a799713cf6fb6f0fd8c3c https://github.com/freebsd/freebsd-src/commit/2cff354f1a56af10ad02164a9ee38c013ac80688 Fixes #14323. Change-Id: I40e6f0ee132eb2d17d8ec66ba0e28566e8695d18 Reviewed-on: https://review.haiku-os.org/c/haiku/+/10358 Haiku-Format: Haiku-format Bot <[email protected]> Tested-by: Commit checker robot <[email protected]> Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
committed by
Jérôme Duval
parent
763cfd171b
commit
902921a554
@@ -83,9 +83,9 @@ const char *hstrerror(int);
|
||||
#define AI_ADDRCONFIG 0x00000400
|
||||
#define AI_V4MAPPED 0x00000800
|
||||
|
||||
#define AI_MASK \
|
||||
(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG)
|
||||
|
||||
#define AI_MASK \
|
||||
(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG | AI_ALL \
|
||||
| AI_V4MAPPED)
|
||||
|
||||
/* getnameinfo */
|
||||
#if defined(_DEFAULT_SOURCE)
|
||||
|
||||
@@ -64,6 +64,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
getservent.c
|
||||
getservent_r.c
|
||||
hesiod.c
|
||||
map_v4v6.c
|
||||
nsdispatch.c
|
||||
nslexer.l
|
||||
nsparser.y
|
||||
|
||||
@@ -88,9 +88,10 @@ __RCSID("$NetBSD: getaddrinfo.c,v 1.119.2.1 2020/11/29 11:25:31 martin Exp $");
|
||||
|
||||
#include <FindDirectory.h>
|
||||
|
||||
#include <libutil.h>
|
||||
#include "netdb_private.h"
|
||||
#include "nsswitch.h"
|
||||
#include "servent.h"
|
||||
#include <libutil.h>
|
||||
|
||||
#ifndef RUMP_ACTION
|
||||
#ifdef __weak_alias
|
||||
@@ -136,17 +137,19 @@ static const struct afd {
|
||||
const char *a_addrany;
|
||||
const char *a_loopback;
|
||||
int a_scoped;
|
||||
} afdl [] = {
|
||||
} afdl[] = {
|
||||
#ifdef INET6
|
||||
{PF_INET6, sizeof(struct in6_addr),
|
||||
sizeof(struct sockaddr_in6),
|
||||
offsetof(struct sockaddr_in6, sin6_addr),
|
||||
in6_addrany, in6_loopback, 1},
|
||||
#define N_INET6 0
|
||||
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
|
||||
offsetof(struct sockaddr_in6, sin6_addr), in6_addrany, in6_loopback, 1},
|
||||
#define N_INET 1
|
||||
#define N_LOCAL 2
|
||||
#else
|
||||
#define N_INET 0
|
||||
#define N_LOCAL 1
|
||||
#endif
|
||||
{PF_INET, sizeof(struct in_addr),
|
||||
sizeof(struct sockaddr_in),
|
||||
offsetof(struct sockaddr_in, sin_addr),
|
||||
in_addrany, in_loopback, 0},
|
||||
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
|
||||
offsetof(struct sockaddr_in, sin_addr), in_addrany, in_loopback, 0},
|
||||
{0, 0, 0, 0, NULL, NULL, 0},
|
||||
};
|
||||
|
||||
@@ -522,6 +525,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;
|
||||
}
|
||||
|
||||
if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1)
|
||||
ERR(EAI_FAIL);
|
||||
|
||||
@@ -925,6 +946,17 @@ 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 SOCK_CLOEXEC == 0
|
||||
fcntl(s, F_SETFD, FD_CLOEXEC);
|
||||
#endif
|
||||
@@ -1308,7 +1340,7 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
|
||||
struct servent_data *svd)
|
||||
{
|
||||
const struct afd *afd;
|
||||
struct addrinfo *cur;
|
||||
struct addrinfo *cur, ai0;
|
||||
struct addrinfo sentinel;
|
||||
int error;
|
||||
char pton[PTON_MAX];
|
||||
@@ -1369,26 +1401,35 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (inet_pton(afd->a_af, hostname, pton) == 1) {
|
||||
if (pai->ai_family == afd->a_af ||
|
||||
pai->ai_family == PF_UNSPEC /*?*/) {
|
||||
GET_AI(cur->ai_next, afd, pton);
|
||||
GET_PORT(cur->ai_next, servname, svd);
|
||||
if ((pai->ai_flags & AI_CANONNAME)) {
|
||||
/*
|
||||
* Set the numeric address itself as
|
||||
* the canonical name, based on a
|
||||
* clarification in rfc2553bis-03.
|
||||
*/
|
||||
GET_CANONNAME(cur->ai_next, canonname);
|
||||
}
|
||||
while (cur->ai_next)
|
||||
cur = cur->ai_next;
|
||||
} else
|
||||
ERR(EAI_FAMILY); /*xxx*/
|
||||
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;
|
||||
}
|
||||
if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) {
|
||||
GET_AI(cur->ai_next, afd, pton);
|
||||
GET_PORT(cur->ai_next, servname, svd);
|
||||
if (pai->ai_flags & AI_CANONNAME) {
|
||||
/*
|
||||
* Set the numeric address itself as
|
||||
* the canonical name, based on a
|
||||
* clarification in rfc2553bis-03.
|
||||
*/
|
||||
GET_CANONNAME(cur->ai_next, canonname);
|
||||
}
|
||||
while (cur->ai_next)
|
||||
cur = cur->ai_next;
|
||||
} else {
|
||||
ERR(EAI_FAMILY); /*xxx*/
|
||||
}
|
||||
|
||||
|
||||
*res = sentinel.ai_next;
|
||||
return 0;
|
||||
@@ -1503,6 +1544,7 @@ allocaddrinfo(socklen_t addrlen)
|
||||
return ai;
|
||||
}
|
||||
|
||||
|
||||
static struct addrinfo *
|
||||
get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
|
||||
{
|
||||
@@ -1510,10 +1552,22 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
|
||||
struct addrinfo *ai;
|
||||
struct sockaddr *save;
|
||||
|
||||
#ifdef INET6
|
||||
struct in6_addr mapaddr;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(pai != NULL);
|
||||
_DIAGASSERT(afd != NULL);
|
||||
_DIAGASSERT(addr != NULL);
|
||||
|
||||
#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 = allocaddrinfo((socklen_t)afd->a_socklen);
|
||||
if (ai == NULL)
|
||||
return NULL;
|
||||
@@ -2097,10 +2151,13 @@ _dns_query(struct res_target *q, const struct addrinfo *pai,
|
||||
cur = cur->ai_next;
|
||||
}
|
||||
if (q2) {
|
||||
ai = getanswer(res, buf2, q2->n, q2->name, q2->qtype, pai);
|
||||
if (ai)
|
||||
cur->ai_next = ai;
|
||||
}
|
||||
if (!ai || pai->ai_family != AF_UNSPEC
|
||||
|| (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) != AI_V4MAPPED) {
|
||||
ai = getanswer(res, buf2, q2->n, q2->name, q2->qtype, pai);
|
||||
if (ai)
|
||||
cur->ai_next = ai;
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
free(buf2);
|
||||
return sentinel.ai_next;
|
||||
@@ -2245,7 +2302,7 @@ _dns_host_lookup(const char *name, const struct addrinfo *pai)
|
||||
static int
|
||||
_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
||||
{
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo ai0, *ai = NULL;
|
||||
const char *name, *servname;
|
||||
const struct addrinfo *pai;
|
||||
|
||||
@@ -2253,6 +2310,12 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
||||
pai = va_arg(ap, const struct addrinfo *);
|
||||
servname = va_arg(ap, char *);
|
||||
|
||||
if (pai->ai_family == AF_INET6 && (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) {
|
||||
ai0 = *pai;
|
||||
ai0.ai_family = AF_UNSPEC;
|
||||
pai = &ai0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try doing SRV lookup on service first.
|
||||
*/
|
||||
@@ -2370,6 +2433,10 @@ _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
|
||||
found:
|
||||
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)
|
||||
goto again;
|
||||
@@ -2387,6 +2454,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 +2475,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;
|
||||
#ifndef _REENTRANT
|
||||
static
|
||||
#endif
|
||||
@@ -2407,10 +2487,18 @@ _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);
|
||||
|
||||
@@ -2475,6 +2563,8 @@ 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) {
|
||||
@@ -2522,15 +2612,44 @@ _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;
|
||||
@@ -2541,16 +2660,7 @@ _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
||||
free(ypbuf);
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NS_NOTFOUND;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* ++Copyright++ 1985, 1988, 1993
|
||||
* -
|
||||
* Copyright (c) 1985, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "netdb_private.h"
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
typedef union {
|
||||
int32_t al;
|
||||
char ac;
|
||||
} align;
|
||||
|
||||
|
||||
void
|
||||
_map_v4v6_address(const char* src, char* dst)
|
||||
{
|
||||
/* Our caller may update in place. */
|
||||
memmove(&dst[12], src, NS_INADDRSZ);
|
||||
/* Mark this ipv6 addr as a mapped ipv4. */
|
||||
memset(&dst[10], 0xff, 2);
|
||||
memset(&dst[0], 0, 10);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*-
|
||||
* Copyright (C) 2005 The FreeBSD Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
void _map_v4v6_address(const char*, char*);
|
||||
Reference in New Issue
Block a user