From 04743ed9c532c972f51aae78b38473fb242a0c21 Mon Sep 17 00:00:00 2001 From: Tom Lint Date: Thu, 24 Jul 2014 17:27:55 +0200 Subject: [PATCH] Added skeleton libsocket project --- XFX.sln | 6 + libsocket/libsocket.vcxproj | 66 +++ libsocket/libsocket.vcxproj.filters | 58 +++ libsocket/src/addr2ascii.c | 99 +++++ libsocket/src/ascii2addr.c | 76 ++++ libsocket/src/inet_addr.c | 219 ++++++++++ libsocket/src/inet_lnaof.c | 74 ++++ libsocket/src/inet_makeaddr.c | 80 ++++ libsocket/src/inet_net_ntop.c | 342 ++++++++++++++++ libsocket/src/inet_net_pton.c | 614 ++++++++++++++++++++++++++++ libsocket/src/inet_ntoa.c | 82 ++++ libsocket/src/nsap_addr.c | 171 ++++++++ libsocket/src/recv.c | 56 +++ libsocket/src/send.c | 56 +++ libsocket/src/sockatmark.c | 39 ++ libsocket/src/sourcefilter.c | 442 ++++++++++++++++++++ 16 files changed, 2480 insertions(+) create mode 100644 libsocket/libsocket.vcxproj create mode 100644 libsocket/libsocket.vcxproj.filters create mode 100644 libsocket/src/addr2ascii.c create mode 100644 libsocket/src/ascii2addr.c create mode 100644 libsocket/src/inet_addr.c create mode 100644 libsocket/src/inet_lnaof.c create mode 100644 libsocket/src/inet_makeaddr.c create mode 100644 libsocket/src/inet_net_ntop.c create mode 100644 libsocket/src/inet_net_pton.c create mode 100644 libsocket/src/inet_ntoa.c create mode 100644 libsocket/src/nsap_addr.c create mode 100644 libsocket/src/recv.c create mode 100644 libsocket/src/send.c create mode 100644 libsocket/src/sockatmark.c create mode 100644 libsocket/src/sourcefilter.c 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); +}