diff --git a/XFX.sln b/XFX.sln
index b5e6eee..b55d17f 100644
--- a/XFX.sln
+++ b/XFX.sln
@@ -21,6 +21,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libSystem.Windows", "src\li
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xnbbuild", "src\xnbbuild\xnbbuild.vcxproj", "{E5F1599D-C9FE-4EFB-97B6-13B46D4A1E35}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsocket", "libsocket\libsocket.vcxproj", "{FC85E968-A227-460F-858B-06A3581A65E0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -55,6 +57,10 @@ Global
{E5F1599D-C9FE-4EFB-97B6-13B46D4A1E35}.Debug|Win32.Build.0 = Debug|Win32
{E5F1599D-C9FE-4EFB-97B6-13B46D4A1E35}.Release|Win32.ActiveCfg = Release|Win32
{E5F1599D-C9FE-4EFB-97B6-13B46D4A1E35}.Release|Win32.Build.0 = Release|Win32
+ {FC85E968-A227-460F-858B-06A3581A65E0}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FC85E968-A227-460F-858B-06A3581A65E0}.Debug|Win32.Build.0 = Debug|Win32
+ {FC85E968-A227-460F-858B-06A3581A65E0}.Release|Win32.ActiveCfg = Release|Win32
+ {FC85E968-A227-460F-858B-06A3581A65E0}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/libsocket/libsocket.vcxproj b/libsocket/libsocket.vcxproj
new file mode 100644
index 0000000..272b019
--- /dev/null
+++ b/libsocket/libsocket.vcxproj
@@ -0,0 +1,66 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {FC85E968-A227-460F-858B-06A3581A65E0}
+ MakeFileProj
+
+
+
+ Makefile
+ true
+ v110
+
+
+ Makefile
+ false
+ v110
+
+
+
+
+
+
+
+
+
+
+
+
+ libsocket.a
+ WIN32;_DEBUG;$(NMakePreprocessorDefinitions)
+
+
+ libsocket.a
+ NDEBUG;WIN32;NDEBUG;$(NMakePreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libsocket/libsocket.vcxproj.filters b/libsocket/libsocket.vcxproj.filters
new file mode 100644
index 0000000..4c21f62
--- /dev/null
+++ b/libsocket/libsocket.vcxproj.filters
@@ -0,0 +1,58 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/libsocket/src/addr2ascii.c b/libsocket/src/addr2ascii.c
new file mode 100644
index 0000000..28c2fd0
--- /dev/null
+++ b/libsocket/src/addr2ascii.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 1996 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * $ANA: addr2ascii.c,v 1.1 1996/06/13 18:41:46 wollman Exp $
+ */
+
+#include
+__FBSDID("$FreeBSD: src/lib/libc/net/addr2ascii.c,v 1.2 2002/03/22 21:52:28 obrien Exp $");
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+/*-
+ * Convert a network address from binary to printable numeric format.
+ * This API is copied from INRIA's IPv6 implementation, but it is a
+ * bit bogus in two ways:
+ *
+ * 1) There is no value in passing both an address family and
+ * an address length; either one should imply the other,
+ * or we should be passing sockaddrs instead.
+ * 2) There should by contrast be /added/ a length for the buffer
+ * that we pass in, so that programmers are spared the need to
+ * manually calculate (read: ``guess'') the maximum length.
+ *
+ * Flash: the API is also the same in the NRL implementation, and seems to
+ * be some sort of standard, so we appear to be stuck with both the bad
+ * naming and the poor choice of arguments.
+ */
+char * addr2ascii(
+ int af,
+ const void *addrp,
+ int len, /* should be size_t XXX */
+ char *buf /* XXX should pass length of buffer */
+)
+{
+ static char staticbuf[64]; /* 64 for AF_LINK > 16 for AF_INET */
+
+ if (!buf)
+ buf = staticbuf;
+
+ switch(af)
+ {
+ case AF_INET:
+ if (len != sizeof(struct in_addr))
+ {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+ strcpy(buf, inet_ntoa(*(const struct in_addr *)addrp));
+ break;
+
+ case AF_LINK:
+ if (len != sizeof(struct sockaddr_dl))
+ {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+ strcpy(buf, link_ntoa((const struct sockaddr_dl *)addrp));
+ break;
+
+ default:
+ errno = EPROTONOSUPPORT;
+ return 0;
+ }
+
+ return buf;
+}
diff --git a/libsocket/src/ascii2addr.c b/libsocket/src/ascii2addr.c
new file mode 100644
index 0000000..3753f2e
--- /dev/null
+++ b/libsocket/src/ascii2addr.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright 1996 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * $ANA: ascii2addr.c,v 1.2 1996/06/13 18:46:02 wollman Exp $
+ */
+
+#include
+__FBSDID("$FreeBSD: src/lib/libc/net/ascii2addr.c,v 1.4 2002/03/22 21:52:28 obrien Exp $");
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+int ascii2addr(int af, const char *ascii, void *result)
+{
+ struct in_addr *ina;
+ char strbuf[4*sizeof("123")]; /* long enough for V4 only */
+
+ switch(af)
+ {
+ case AF_INET:
+ ina = (struct in_addr *)result;
+ strbuf[0] = '\0';
+ strncat(strbuf, ascii, (sizeof strbuf)-1);
+
+ if (inet_aton(strbuf, ina))
+ {
+ return sizeof(struct in_addr);
+ }
+
+ errno = EINVAL;
+ break;
+
+ case AF_LINK:
+ link_addr(ascii, result);
+ /* oops... no way to detect failure */
+ return sizeof(struct sockaddr_dl);
+
+ default:
+ errno = EPROTONOSUPPORT;
+ break;
+ }
+
+ return -1;
+}
diff --git a/libsocket/src/inet_addr.c b/libsocket/src/inet_addr.c
new file mode 100644
index 0000000..6ad6f96
--- /dev/null
+++ b/libsocket/src/inet_addr.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1983, 1990, 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.
+ * 4. 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 (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static const char rcsid[] = "$Id: inet_addr.c,v 1.4.18.1 2005/04/27 05:00:52 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+/* the algorithms only can deal with ASCII, so we optimize for it */
+#define USE_ASCII
+
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_addr.c,v 1.4 2007/06/03 17:20:26 ume Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include "port_after.h"
+
+/*%
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+in_addr_t /* XXX should be struct in_addr :( */
+inet_addr(const char *cp) {
+ struct in_addr val;
+
+ if (inet_aton(cp, &val))
+ return (val.s_addr);
+ return (INADDR_NONE);
+}
+
+/*%
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr) {
+ u_long val;
+ int base, n;
+ char c;
+ u_int8_t parts[4];
+ u_int8_t *pp = parts;
+ int digit;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit((unsigned char)c))
+ return (0);
+ val = 0; base = 10; digit = 0;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else {
+ base = 8;
+ digit = 1 ;
+ }
+ }
+ for (;;) {
+ if (isascii(c) && isdigit((unsigned char)c)) {
+ if (base == 8 && (c == '8' || c == '9'))
+ return (0);
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else if (base == 16 && isascii(c) &&
+ isxdigit((unsigned char)c)) {
+ val = (val << 4) |
+ (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
+ c = *++cp;
+ digit = 1;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xffU)
+ return (0);
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace((unsigned char)c)))
+ return (0);
+ /*
+ * Did we get a valid digit?
+ */
+ if (!digit)
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+ case 1: /*%< a -- 32 bits */
+ break;
+
+ case 2: /*%< a.b -- 8.24 bits */
+ if (val > 0xffffffU)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /*%< a.b.c -- 8.8.16 bits */
+ if (val > 0xffffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /*%< a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr != NULL)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_addr
+__weak_reference(__inet_addr, inet_addr);
+#undef inet_aton
+__weak_reference(__inet_aton, inet_aton);
+
+/*! \file */
diff --git a/libsocket/src/inet_lnaof.c b/libsocket/src/inet_lnaof.c
new file mode 100644
index 0000000..f31c178
--- /dev/null
+++ b/libsocket/src/inet_lnaof.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1983, 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.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_lnaof.c,v 1.4 2007/06/03 17:20:26 ume Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+#include
+
+#include "port_after.h"
+
+/*%
+ * Return the local network address portion of an
+ * internet address; handles class a/b/c network
+ * number formats.
+ */
+in_addr_t inet_lnaof(struct in_addr in)
+{
+ in_addr_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ {
+ return ((i) & IN_CLASSA_HOST);
+ }
+ else if (IN_CLASSB(i))
+ {
+ return ((i) & IN_CLASSB_HOST);
+ }
+ else
+ {
+ return ((i) & IN_CLASSC_HOST);
+ }
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_lnaof
+__weak_reference(__inet_lnaof, inet_lnaof);
+
+/*! \file */
diff --git a/libsocket/src/inet_makeaddr.c b/libsocket/src/inet_makeaddr.c
new file mode 100644
index 0000000..726b4d9
--- /dev/null
+++ b/libsocket/src/inet_makeaddr.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1983, 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.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_makeaddr.c,v 1.4 2007/06/03 17:20:26 ume Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+#include
+
+#include "port_after.h"
+
+/*%
+ * Formulate an Internet address from network + host. Used in
+ * building addresses stored in the ifnet structure.
+ */
+struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host)
+{
+ struct in_addr a;
+
+ if (net < 128U)
+ {
+ a.s_addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
+ }
+ else if (net < 65536U)
+ {
+ a.s_addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
+ }
+ else if (net < 16777216L)
+ {
+ a.s_addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
+ }
+ else
+ {
+ a.s_addr = net | host;
+ }
+
+ a.s_addr = htonl(a.s_addr);
+ return (a);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_makeaddr
+__weak_reference(__inet_makeaddr, inet_makeaddr);
+
+/*! \file */
diff --git a/libsocket/src/inet_net_ntop.c b/libsocket/src/inet_net_ntop.c
new file mode 100644
index 0000000..18baae9
--- /dev/null
+++ b/libsocket/src/inet_net_ntop.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.3.18.2 2006/06/20 02:51:32 marka Exp $";
+#endif
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_ntop.c,v 1.4 2007/06/03 17:20:26 ume Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4(const u_char *src, int bits, char *dst,
+ size_t size);
+static char * inet_net_ntop_ipv6(const u_char *src, int bits, char *dst,
+ size_t size);
+
+/*%
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ * convert network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char * inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*%
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+static char * inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
+{
+ char *odst = dst;
+ char *t;
+ u_int m;
+ int b;
+
+ if (bits < 0 || bits > 32)
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (bits == 0)
+ {
+ if (size < sizeof "0")
+ {
+ goto emsgsize;
+ }
+
+ *dst++ = '0';
+ size--;
+ *dst = '\0';
+ }
+
+ /* Format whole octets. */
+ for (b = bits / 8; b > 0; b--)
+ {
+ if (size <= sizeof "255.")
+ {
+ goto emsgsize;
+ }
+
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+
+ if (b > 1)
+ {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format partial octet. */
+ b = bits % 8;
+
+ if (b > 0)
+ {
+ if (size <= sizeof ".255")
+ {
+ goto emsgsize;
+ }
+
+ t = dst;
+
+ if (dst != odst)
+ {
+ *dst++ = '.';
+ }
+
+ m = ((1 << b) - 1) << (8 - b);
+ dst += SPRINTF((dst, "%u", *src & m));
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format CIDR /width. */
+ if (size <= sizeof "/32")
+ {
+ goto emsgsize;
+ }
+
+ dst += SPRINTF((dst, "/%u", bits));
+ return (odst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*%
+ * static char *
+ * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
+ * convert IPv6 network number from network to presentation format.
+ * generates CIDR style result always. Picks the shortest representation
+ * unless the IP is really IPv4.
+ * always prints specified number of bits (bits).
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Vadim Kogan (UCB), June 2001
+ * Original version (IPv4) by Paul Vixie (ISC), July 1996
+ */
+static char * inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
+{
+ u_int m;
+ int b;
+ int p;
+ int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
+ int i;
+ int is_ipv4 = 0;
+ unsigned char inbuf[16];
+ char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+ char *cp;
+ int words;
+ u_char *s;
+
+ if (bits < 0 || bits > 128)
+ {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ cp = outbuf;
+
+ if (bits == 0)
+ {
+ *cp++ = ':';
+ *cp++ = ':';
+ *cp = '\0';
+ }
+ else
+ {
+ /* Copy src to private buffer. Zero host part. */
+ p = (bits + 7) / 8;
+ memcpy(inbuf, src, p);
+ memset(inbuf + p, 0, 16 - p);
+ b = bits % 8;
+
+ if (b != 0)
+ {
+ m = ~0 << (8 - b);
+ inbuf[p-1] &= m;
+ }
+
+ s = inbuf;
+
+ /* how many words need to be displayed in output */
+ words = (bits + 15) / 16;
+
+ if (words == 1)
+ {
+ words = 2;
+ }
+
+ /* Find the longest substring of zero's */
+ zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
+
+ for (i = 0; i < (words * 2); i += 2)
+ {
+ if ((s[i] | s[i+1]) == 0)
+ {
+ if (tmp_zero_l == 0)
+ {
+ tmp_zero_s = i / 2;
+ }
+
+ tmp_zero_l++;
+ }
+ else
+ {
+ if (tmp_zero_l && zero_l < tmp_zero_l)
+ {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ tmp_zero_l = 0;
+ }
+ }
+ }
+
+ if (tmp_zero_l && zero_l < tmp_zero_l)
+ {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ }
+
+ if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
+ ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
+ ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
+ {
+ is_ipv4 = 1;
+ }
+
+ /* Format whole words. */
+ for (p = 0; p < words; p++)
+ {
+ if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l)
+ {
+ /* Time to skip some zeros */
+ if (p == zero_s)
+ {
+ *cp++ = ':';
+ }
+
+ if (p == words - 1)
+ {
+ *cp++ = ':';
+ }
+
+ s++;
+ s++;
+ continue;
+ }
+
+ if (is_ipv4 && p > 5)
+ {
+ *cp++ = (p == 6) ? ':' : '.';
+ cp += SPRINTF((cp, "%u", *s++));
+
+ /* we can potentially drop the last octet */
+ if (p != 7 || bits > 120)
+ {
+ *cp++ = '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ }
+ }
+ else
+ {
+ if (cp != outbuf)
+ {
+ *cp++ = ':';
+ }
+
+ cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
+ s += 2;
+ }
+ }
+ }
+ /* Format CIDR /width. */
+ sprintf(cp, "/%u", bits);
+
+ if (strlen(outbuf) + 1 > size)
+ {
+ goto emsgsize;
+ }
+
+ strcpy(dst, outbuf);
+
+ return (dst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_net_ntop
+__weak_reference(__inet_net_ntop, inet_net_ntop);
+
+/*! \file */
diff --git a/libsocket/src/inet_net_pton.c b/libsocket/src/inet_net_pton.c
new file mode 100644
index 0000000..b473293
--- /dev/null
+++ b/libsocket/src/inet_net_pton.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
+#endif
+
+/* the algorithms only can deal with ASCII, so we optimize for it */
+#define USE_ASCII
+
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_net_pton.c,v 1.4 2008/12/14 19:39:53 ume Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*%
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ * convert IPv4 network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not an IPv4 network specification.
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
+{
+ static const char xdigits[] = "0123456789abcdef";
+ static const char digits[] = "0123456789";
+ int n, ch, tmp = 0, dirty, bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X') &&
+ isascii((unsigned char)(src[1])) &&
+ isxdigit((unsigned char)(src[1])))
+ {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0U)
+ {
+ goto emsgsize;
+ }
+
+ dirty = 0;
+ src++; /*%< skip x or X. */
+
+ while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch))
+ {
+ if (isupper(ch))
+ {
+ ch = tolower(ch);
+ }
+ n = strchr(xdigits, ch) - xdigits;
+ assert(n >= 0 && n <= 15);
+
+ if (dirty == 0)
+ {
+ tmp = n;
+ }
+ else
+ {
+ tmp = (tmp << 4) | n;
+ }
+
+ if (++dirty == 2)
+ {
+ if (size-- <= 0U)
+ {
+ goto emsgsize;
+ }
+
+ *dst++ = (u_char) tmp;
+ dirty = 0;
+ }
+ }
+
+ if (dirty)
+ { /*%< Odd trailing nybble? */
+ if (size-- <= 0U)
+ {
+ goto emsgsize;
+ }
+
+ *dst++ = (u_char) (tmp << 4);
+ }
+ }
+ else if (isascii(ch) && isdigit(ch))
+ {
+ /* Decimal: eat dotted digit string. */
+ for (;;)
+ {
+ tmp = 0;
+
+ do
+ {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+
+ if (tmp > 255)
+ {
+ goto enoent;
+ }
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+
+ if (size-- <= 0U)
+ {
+ goto emsgsize;
+ }
+
+ *dst++ = (u_char) tmp;
+
+ if (ch == '\0' || ch == '/')
+ {
+ break;
+ }
+
+ if (ch != '.')
+ {
+ goto enoent;
+ }
+
+ ch = *src++;
+
+ if (!isascii(ch) || !isdigit(ch))
+ {
+ goto enoent;
+ }
+ }
+ }
+ else
+ {
+ goto enoent;
+ }
+
+ bits = -1;
+
+ if (ch == '/' && isascii((unsigned char)(src[0])) &&
+ isdigit((unsigned char)(src[0])) && dst > odst)
+ {
+ /* CIDR width specifier. Nothing can follow it. */
+ ch = *src++; /*%< Skip over the /. */
+ bits = 0;
+
+ do
+ {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ bits *= 10;
+ bits += n;
+
+ if (bits > 32)
+ {
+ goto enoent;
+ }
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+
+ if (ch != '\0')
+ {
+ goto enoent;
+ }
+ }
+
+ /* Firey death and destruction unless we prefetched EOS. */
+ if (ch != '\0')
+ {
+ goto enoent;
+ }
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ {
+ goto enoent;
+ }
+
+ /* If no CIDR spec was given, infer width from net class. */
+ if (bits == -1)
+ {
+ if (*odst >= 240) /*%< Class E */
+ {
+ bits = 32;
+ }
+ else if (*odst >= 224) /*%< Class D */
+ {
+ bits = 8;
+ }
+ else if (*odst >= 192) /*%< Class C */
+ {
+ bits = 24;
+ }
+ else if (*odst >= 128) /*%< Class B */
+ {
+ bits = 16;
+ }
+ else /*%< Class A */
+ {
+ bits = 8;
+ }
+
+ /* If imputed mask is narrower than specified octets, widen. */
+ if (bits < ((dst - odst) * 8))
+ {
+ bits = (dst - odst) * 8;
+ }
+
+ /*
+ * If there are no additional bits specified for a class D
+ * address adjust bits to 4.
+ */
+ if (bits == 8 && *odst == 224)
+ {
+ bits = 4;
+ }
+ }
+
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8))
+ {
+ if (size-- <= 0U)
+ {
+ goto emsgsize;
+ }
+
+ *dst++ = '\0';
+ }
+
+ return (bits);
+
+enoent:
+ errno = ENOENT;
+ return (-1);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int getbits(const char *src, int *bitsp)
+{
+ static const char digits[] = "0123456789";
+ int n;
+ int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+
+ while ((ch = *src++) != '\0')
+ {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+
+ if (pch != NULL)
+ {
+ if (n++ != 0 && val == 0) /*%< no leading zeros */
+ {
+ return (0);
+ }
+
+ val *= 10;
+ val += (pch - digits);
+
+ if (val > 128) /*%< range */
+ {
+ return (0);
+ }
+
+ continue;
+ }
+
+ return (0);
+ }
+
+ if (n == 0)
+ {
+ return (0);
+ }
+
+ *bitsp = val;
+ return (1);
+}
+
+static int getv4(const char *src, u_char *dst, int *bitsp)
+{
+ static const char digits[] = "0123456789";
+ u_char *odst = dst;
+ int n;
+ u_int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+
+ while ((ch = *src++) != '\0')
+ {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+
+ if (pch != NULL)
+ {
+ if (n++ != 0 && val == 0) /*%< no leading zeros */
+ {
+ return (0);
+ }
+
+ val *= 10;
+ val += (pch - digits);
+
+ if (val > 255) /*%< range */
+ {
+ return (0);
+ }
+
+ continue;
+ }
+
+ if (ch == '.' || ch == '/')
+ {
+ if (dst - odst > 3) /*%< too many octets? */
+ {
+ return (0);
+ }
+
+ *dst++ = val;
+
+ if (ch == '/')
+ {
+ return (getbits(src, bitsp));
+ }
+
+ val = 0;
+ n = 0;
+ continue;
+ }
+
+ return (0);
+ }
+
+ if (n == 0)
+ {
+ return (0);
+ }
+
+ if (dst - odst > 3) /*%< too many octets? */
+ {
+ return (0);
+ }
+
+ *dst++ = val;
+ return (1);
+}
+
+static int inet_net_pton_ipv6(const char *src, u_char *dst, size_t size)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int digits;
+ int bits;
+ size_t bytes;
+ int words;
+ int ipv4;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ {
+ if (*++src != ':')
+ {
+ goto enoent;
+ }
+ }
+
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ digits = 0;
+ bits = -1;
+ ipv4 = 0;
+
+ while ((ch = *src++) != '\0')
+ {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ {
+ pch = strchr((xdigits = xdigits_u), ch);
+ }
+
+ if (pch != NULL)
+ {
+ val <<= 4;
+ val |= (pch - xdigits);
+
+ if (++digits > 4)
+ {
+ goto enoent;
+ }
+
+ saw_xdigit = 1;
+ continue;
+ }
+
+ if (ch == ':')
+ {
+ curtok = src;
+
+ if (!saw_xdigit)
+ {
+ if (colonp)
+ {
+ goto enoent;
+ }
+
+ colonp = tp;
+ continue;
+ }
+ else if (*src == '\0')
+ {
+ goto enoent;
+ }
+
+ if (tp + NS_INT16SZ > endp)
+ {
+ return (0);
+ }
+
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ digits = 0;
+ val = 0;
+ continue;
+ }
+
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && getv4(curtok, tp, &bits) > 0)
+ {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ ipv4 = 1;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+
+ if (ch == '/' && getbits(src, &bits) > 0)
+ {
+ break;
+ }
+
+ goto enoent;
+ }
+
+ if (saw_xdigit)
+ {
+ if (tp + NS_INT16SZ > endp)
+ {
+ goto enoent;
+ }
+
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+
+ if (bits == -1)
+ {
+ bits = 128;
+ }
+
+ words = (bits + 15) / 16;
+
+ if (words < 2)
+ {
+ words = 2;
+ }
+
+ if (ipv4)
+ {
+ words = 8;
+ }
+
+ endp = tmp + 2 * words;
+
+ if (colonp != NULL)
+ {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ {
+ goto enoent;
+ }
+
+ for (i = 1; i <= n; i++)
+ {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+
+ tp = endp;
+ }
+
+ if (tp != endp)
+ {
+ goto enoent;
+ }
+
+ bytes = (bits + 7) / 8;
+
+ if (bytes > size)
+ {
+ goto emsgsize;
+ }
+
+ memcpy(dst, tmp, bytes);
+ return (bits);
+
+enoent:
+ errno = ENOENT;
+ return (-1);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+/*%
+ * int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int inet_net_pton(int af, const char *src, void *dst, size_t size)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ case AF_INET6:
+ return (inet_net_pton_ipv6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_net_pton
+__weak_reference(__inet_net_pton, inet_net_pton);
+
+/*! \file */
diff --git a/libsocket/src/inet_ntoa.c b/libsocket/src/inet_ntoa.c
new file mode 100644
index 0000000..b07c2ff
--- /dev/null
+++ b/libsocket/src/inet_ntoa.c
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 1983, 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.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: inet_ntoa.c,v 1.1.352.1 2005/04/27 05:00:54 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/inet_ntoa.c,v 1.6 2007/06/14 07:13:28 delphij Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "port_after.h"
+
+/*%
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+/*const*/ char * inet_ntoa(struct in_addr in)
+{
+ static char ret[18];
+
+ strcpy(ret, "[inet_ntoa error]");
+
+ (void)inet_ntop(AF_INET, &in, ret, sizeof ret);
+
+ return (ret);
+}
+
+#if 0
+char *
+inet_ntoa_r(struct in_addr in, char *buf, socklen_t size)
+{
+
+ (void) inet_ntop(AF_INET, &in, buf, size);
+ return (buf);
+}
+#endif
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_ntoa
+__weak_reference(__inet_ntoa, inet_ntoa);
+__weak_reference(__inet_ntoa_r, inet_ntoa_r);
+
+/*! \file */
diff --git a/libsocket/src/nsap_addr.c b/libsocket/src/nsap_addr.c
new file mode 100644
index 0000000..a31de36
--- /dev/null
+++ b/libsocket/src/nsap_addr.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nsap_addr.c,v 1.3.18.2 2005/07/28 07:38:08 marka Exp $";
+
+/* the algorithms only can deal with ASCII, so we optimize for it */
+#define USE_ASCII
+
+#endif /* LIBC_SCCS and not lint */
+#include
+__FBSDID("$FreeBSD: src/lib/libc/inet/nsap_addr.c,v 1.3 2007/06/03 17:20:26 ume Exp $");
+
+#include "port_before.h"
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+//#include
+
+#include "port_after.h"
+
+#include
+
+static char xtob(int c)
+{
+ return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int inet_nsap_addr(const char *ascii, u_char *binary, int maxlen)
+{
+ u_char c, nib;
+ u_int len = 0;
+
+ if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
+ {
+ return (0);
+ }
+
+ ascii += 2;
+
+ while ((c = *ascii++) != '\0' && len < (u_int)maxlen)
+ {
+ if (c == '.' || c == '+' || c == '/')
+ {
+ continue;
+ }
+
+ if (!isascii(c))
+ {
+ return (0);
+ }
+
+ if (islower(c))
+ {
+ c = toupper(c);
+ }
+
+ if (isxdigit(c))
+ {
+ nib = xtob(c);
+ c = *ascii++;
+
+ if (c != '\0')
+ {
+ c = toupper(c);
+
+ if (isxdigit(c))
+ {
+ *binary++ = (nib << 4) | xtob(c);
+ len++;
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ return (0);
+ }
+ }
+
+ return (len);
+}
+
+char * inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii)
+{
+ int nib;
+ int i;
+ char *tmpbuf = NULL;
+ char *start;
+
+ if (tmpbuf == NULL)
+ {
+ tmpbuf = (char *)malloc(255 * 3);
+
+ if (tmpbuf == NULL) return NULL;
+ }
+
+ if (ascii)
+ {
+ start = ascii;
+ }
+ else
+ {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ *ascii++ = '0';
+ *ascii++ = 'x';
+
+ if (binlen > 255)
+ {
+ binlen = 255;
+ }
+
+ for (i = 0; i < binlen; i++)
+ {
+ nib = *binary >> 4;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ nib = *binary++ & 0x0f;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+
+ if (((i % 2) == 0 && (i + 1) < binlen))
+ {
+ *ascii++ = '.';
+ }
+ }
+
+ *ascii = '\0';
+ return (start);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include .
+ */
+#undef inet_nsap_addr
+__weak_reference(__inet_nsap_addr, inet_nsap_addr);
+#undef inet_nsap_ntoa
+__weak_reference(__inet_nsap_ntoa, inet_nsap_ntoa);
+
+/*! \file */
diff --git a/libsocket/src/recv.c b/libsocket/src/recv.c
new file mode 100644
index 0000000..4911a69
--- /dev/null
+++ b/libsocket/src/recv.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)recv.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include
+__FBSDID("$FreeBSD: src/lib/libc/net/recv.c,v 1.4 2007/01/09 00:28:02 imp Exp $");
+
+#include "namespace.h"
+#include
+#include
+
+#include
+#include "un-namespace.h"
+
+#ifdef VARIANT_CANCELABLE
+ssize_t __recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
+#else /* !VARIANT_CANCELABLE */
+ssize_t __recvfrom_nocancel(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
+#endif /* VARIANT_CANCELABLE */
+
+ssize_t recv(int s, void *buf, size_t len, int flags)
+{
+#ifdef VARIANT_CANCELABLE
+ return (__recvfrom(s, buf, len, flags, NULL, 0));
+#else /* !VARIANT_CANCELABLE */
+ return (__recvfrom_nocancel(s, buf, len, flags, NULL, 0));
+#endif /* VARIANT_CANCELABLE */
+}
diff --git a/libsocket/src/send.c b/libsocket/src/send.c
new file mode 100644
index 0000000..fda610f
--- /dev/null
+++ b/libsocket/src/send.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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.
+ * 4. 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)send.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include
+__FBSDID("$FreeBSD: src/lib/libc/net/send.c,v 1.4 2007/01/09 00:28:02 imp Exp $");
+
+#include "namespace.h"
+#include
+#include
+
+#include
+#include "un-namespace.h"
+
+#ifdef VARIANT_CANCELABLE
+ssize_t __sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
+#else /* !VARIANT_CANCELABLE */
+ssize_t __sendto_nocancel(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
+#endif /* VARIANT_CANCELABLE */
+
+ssize_t send(int s, const void *msg, size_t len, int flags)
+{
+#ifdef VARIANT_CANCELABLE
+ return (__sendto(s, msg, len, flags, NULL, 0));
+#else /* !VARIANT_CANCELABLE */
+ return (__sendto_nocancel(s, msg, len, flags, NULL, 0));
+#endif /* VARIANT_CANCELABLE */
+}
diff --git a/libsocket/src/sockatmark.c b/libsocket/src/sockatmark.c
new file mode 100644
index 0000000..8663572
--- /dev/null
+++ b/libsocket/src/sockatmark.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002 William C. Fenner. 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 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: src/lib/libc/net/sockatmark.c,v 1.1 2002/12/13 22:22:55 fenner Exp $
+ */
+#include
+
+int sockatmark(int s)
+{
+ int atmark;
+
+ if (ioctl(s, SIOCATMARK, &atmark) == -1)
+ {
+ return -1;
+ }
+
+ return atmark;
+}
diff --git a/libsocket/src/sourcefilter.c b/libsocket/src/sourcefilter.c
new file mode 100644
index 0000000..88fba2b
--- /dev/null
+++ b/libsocket/src/sourcefilter.c
@@ -0,0 +1,442 @@
+/*-
+ * Copyright (c) 2007-2009 Bruce Simpson.
+ * 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 AUTHOR 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.
+ */
+
+#include
+__FBSDID("$FreeBSD: src/lib/libc/net/sourcefilter.c,v 1.5 2009/04/29 09:58:31 bms Exp $");
+
+#include "namespace.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "un-namespace.h"
+
+/*
+ * Advanced (Full-state) multicast group membership APIs [RFC3678]
+ * Currently this module assumes IPv4 support (INET) in the base system.
+ */
+#ifndef INET
+#define INET
+#endif
+
+union sockunion {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+#ifdef INET
+ struct sockaddr_in sin;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+};
+typedef union sockunion sockunion_t;
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * Internal: Map an IPv4 unicast address to an interface index.
+ * This is quite inefficient so it is recommended applications use
+ * the newer, more portable, protocol independent API.
+ */
+static uint32_t __inaddr_to_index(in_addr_t ifaddr)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifaddrs;
+ char *ifname;
+ int ifindex;
+ sockunion_t *psu;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ {
+ return (0);
+ }
+
+ ifindex = 0;
+ ifname = NULL;
+
+ /*
+ * Pass #1: Find the ifaddr entry corresponding to the
+ * supplied IPv4 address. We should really use the ifindex
+ * consistently for matches, however it is not available to
+ * us on this pass.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ psu = (sockunion_t *)ifa->ifa_addr;
+
+ if (psu && psu->ss.ss_family == AF_INET &&
+ psu->sin.sin_addr.s_addr == ifaddr)
+ {
+ ifname = ifa->ifa_name;
+ break;
+ }
+ }
+
+ if (ifname == NULL)
+ {
+ goto out;
+ }
+
+ /*
+ * Pass #2: Find the index of the interface matching the name
+ * we obtained from looking up the IPv4 ifaddr in pass #1.
+ * There must be a better way of doing this.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ psu = (sockunion_t *)ifa->ifa_addr;
+
+ if (psu && psu->ss.ss_family == AF_LINK &&
+ strcmp(ifa->ifa_name, ifname) == 0)
+ {
+ ifindex = psu->sdl.sdl_index;
+ break;
+ }
+ }
+
+ assert(ifindex != 0);
+
+out:
+ freeifaddrs(ifaddrs);
+ return (ifindex);
+}
+
+/*
+ * Set IPv4 source filter list in use on socket.
+ *
+ * Stubbed to setsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ */
+int setipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t fmode, uint32_t numsrc, struct in_addr *slist)
+{
+#ifdef INET
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ sockunion_t *psu, *tmpslist;
+ int err;
+ size_t i;
+ uint32_t ifindex;
+
+ assert(s != -1);
+
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+
+ if (ifindex == 0)
+ {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (numsrc != 0 || slist != NULL)
+ {
+ tmpslist = calloc(numsrc, sizeof(sockunion_t));
+
+ if (tmpslist == NULL)
+ {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ pina = slist;
+ psu = tmpslist;
+
+ for (i = 0; i < numsrc; i++, pina++, psu++)
+ {
+ psu->sin.sin_family = AF_INET;
+ psu->sin.sin_len = sizeof(struct sockaddr_in);
+ psu->sin.sin_addr = *pina;
+ }
+ }
+
+ err = setsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL)
+ {
+ free(tmpslist);
+ }
+
+ return (err);
+#else /* !INET */
+ return (EAFNOSUPPORT);
+#endif /* INET */
+}
+
+/*
+ * Get IPv4 source filter list in use on socket.
+ *
+ * Stubbed to getsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int getipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t *fmode, uint32_t *numsrc, struct in_addr *slist)
+{
+ sockunion_t *psu, *tmpslist;
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ int err;
+ size_t i;
+ uint32_t ifindex, onumsrc;
+
+ assert(s != -1);
+ assert(fmode != NULL);
+ assert(numsrc != NULL);
+
+ onumsrc = *numsrc;
+ *numsrc = 0;
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (onumsrc != 0 && slist == NULL))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+
+ if (ifindex == 0)
+ {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (onumsrc != 0 || slist != NULL)
+ {
+ tmpslist = calloc(onumsrc, sizeof(sockunion_t));
+
+ if (tmpslist == NULL)
+ {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ err = getsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL && *numsrc != 0)
+ {
+ pina = slist;
+ psu = tmpslist;
+
+ for (i = 0; i < MIN(onumsrc, *numsrc); i++, psu++)
+ {
+ if (psu->ss.ss_family != AF_INET)
+ continue;
+ *pina++ = psu->sin.sin_addr;
+ }
+
+ free(tmpslist);
+ }
+
+ return (err);
+}
+
+/*
+ * Set protocol-independent source filter list in use on socket.
+ */
+int
+setsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t fmode, uint32_t numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int level, optname;
+
+ if (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE)
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr))))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ memset(&msfr, 0, sizeof(msfr));
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = fmode;
+ msfr.msfr_nsrcs = numsrc;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+ msfr.msfr_srcs = slist; /* pointer */
+
+ return (_setsockopt(s, level, optname, &msfr, sizeof(msfr)));
+}
+
+/*
+ * Get protocol-independent source filter list in use on socket.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int err, level, nsrcs, optlen, optname;
+
+ if (interface == 0 || group == NULL || numsrc == NULL || fmode == NULL)
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ nsrcs = *numsrc;
+ *numsrc = 0;
+ *fmode = 0;
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family)
+ {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr))))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr))
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ break;
+ }
+
+ optlen = sizeof(struct __msfilterreq);
+ memset(&msfr, 0, optlen);
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = 0;
+ msfr.msfr_nsrcs = nsrcs;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+
+ /*
+ * msfr_srcs is a pointer to a vector of sockaddr_storage. It
+ * may be NULL. The kernel will always return the total number
+ * of filter entries for the group in msfr.msfr_nsrcs.
+ */
+ msfr.msfr_srcs = slist;
+ err = _getsockopt(s, level, optname, &msfr, &optlen);
+
+ if (err == 0)
+ {
+ *numsrc = msfr.msfr_nsrcs;
+ *fmode = msfr.msfr_fmode;
+ }
+
+ return (err);
+}