From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/1960 Path: news.gmane.org!not-for-mail From: Isaac Dunham Newsgroups: gmane.linux.lib.musl.general Subject: [RFC] get/freeifaddrs implementation ported from newlib Date: Wed, 19 Sep 2012 10:59:45 -0700 Message-ID: <20120919105945.594632f4.idunham@lavabit.com> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Multipart=_Wed__19_Sep_2012_10_59_45_-0700_6GvGV+KlFENi4a37" X-Trace: ger.gmane.org 1348077614 3892 80.91.229.3 (19 Sep 2012 18:00:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 19 Sep 2012 18:00:14 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-1961-gllmg-musl=m.gmane.org@lists.openwall.com Wed Sep 19 20:00:15 2012 Return-path: Envelope-to: gllmg-musl@plane.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1TEOZC-0001DT-2r for gllmg-musl@plane.gmane.org; Wed, 19 Sep 2012 20:00:06 +0200 Original-Received: (qmail 23889 invoked by uid 550); 19 Sep 2012 18:00:01 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 23878 invoked from network); 19 Sep 2012 18:00:00 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=lavabit; d=lavabit.com; b=tnYJ+Tb1v4yh9+oVBr5R3SEu+AyU6J5WMCG4Bh0rb0Dt7R15Vt6ON3KUlSz22jgs84xmiYiZnNPdZhgJNlSsKzBfnSfyt6GYby4av6NLht8YgSuVI8GECUWnj3ZdazPezHz4xDtMY+N0t0542K1UYPvHA+hSF3EGImRAd16/9iQ=; h=Date:From:To:Subject:Message-Id:X-Mailer:Mime-Version:Content-Type; X-Mailer: Sylpheed 3.0.2 (GTK+ 2.20.1; i486-pc-linux-gnu) Xref: news.gmane.org gmane.linux.lib.musl.general:1960 Archived-At: This is a multi-part message in MIME format. --Multipart=_Wed__19_Sep_2012_10_59_45_-0700_6GvGV+KlFENi4a37 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Hello, Here's a patch with getifaddrs & freeifaddrs. I don't consider it ready to push yet, but would like comments/improvements. The header is my own work, public domain; the C source is BSDi which is essentially the same as MIT. I based it on the newlib 1.16.0 version, with the macros removed. (newlib later removed getifaddrs either because it was not used or because it conditionally included a header with 4-clause BSD license; the code including that header has been removed). Testing: I could only test on i386 with ipv4; there's a note suggesting that inet4 on LP64 (for us, x86_64) may be broken. ipv6 should also be tested. The test is copy-pasted from getifaddrs(3). HTH, Isaac Dunham --Multipart=_Wed__19_Sep_2012_10_59_45_-0700_6GvGV+KlFENi4a37 Content-Type: text/x-diff; name="ifaddr.diff" Content-Disposition: attachment; filename="ifaddr.diff" Content-Transfer-Encoding: 7bit diff --git a/include/ifaddrs.h b/include/ifaddrs.h new file mode 100644 index 0000000..342d4bd --- /dev/null +++ b/include/ifaddrs.h @@ -0,0 +1,31 @@ +#ifndef _IFADDRS_H +#define _IFADDRS_H 1 + +struct ifaddrs { + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + union { + struct sockaddr *ifu_broadaddr; + struct sockaddr *ifu_dstaddr; + } ifa_ifu; + #define ifa_broadaddr ifa_ifu.ifu_broadaddr + #define ifa_dstaddr ifa_ifu.ifu_dstaddr + void *ifa_data; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int getifaddrs(struct ifaddrs **); + +void freeifaddrs(struct ifaddrs *); + +#ifdef __cpluplus +} +#endif + +#endif diff --git a/src/network/getifaddrs.c b/src/network/getifaddrs.c new file mode 100644 index 0000000..57920bb --- /dev/null +++ b/src/network/getifaddrs.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 1995, 1999 + * Berkeley Software Design, Inc. 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. + * + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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. + * + * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp + */ +/* + * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform + * try-and-error for region size. + */ + +#define _BSD_SOURCE +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(AF_LINK) +#define SA_LEN(sa) sizeof(struct sockaddr) +#endif + +#if !defined(SA_LEN) +#define SA_LEN(sa) sizeof(struct sockaddr) +#endif + +#define SALIGN (sizeof(long) - 1) +#define SA_RLEN(sa) (sizeof(struct sockaddr) ? ((sizeof(struct sockaddr) + SALIGN) & ~SALIGN) : (SALIGN + 1)) + +#ifndef ALIGNBYTES +/* + * On systems with a routing socket, ALIGNBYTES should match the value + * that the kernel uses when building the messages. + */ +#define ALIGNBYTES XXX +#endif +#ifndef ALIGN +#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES) +#endif + +int +getifaddrs(struct ifaddrs **pif) +{ + int icnt = 1; + int dcnt = 0; + int ncnt = 0; + struct ifaddrs *ifa, *ift; + char buf[1024]; + int m, sock; + struct ifconf ifc; + struct ifreq *ifr; + struct ifreq *lifr; + int i; + size_t len, alen; + char *data; + char *names; + + ifc.ifc_buf = buf; + ifc.ifc_len = sizeof(buf); + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return (-1); + i = ioctl(sock, SIOCGIFCONF, (char *)&ifc); + close(sock); + if (i < 0) + return (-1); + + ifr = ifc.ifc_req; + lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; + + while (ifr < lifr) { + struct sockaddr *sa; + + sa = &ifr->ifr_addr; + ++icnt; + dcnt += SA_RLEN(sa); + ncnt += sizeof(ifr->ifr_name) + 1; + + if (SA_LEN(sa) < sizeof(*sa)) + ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa)); + else + ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa)); + } + + if (icnt + dcnt + ncnt == 1) { + *pif = NULL; + free(buf); + return (0); + } + data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt); + if (data == NULL) { + free(buf); + return(-1); + } + + ifa = (struct ifaddrs *)(void *)data; + data += sizeof(struct ifaddrs) * icnt; + names = data + dcnt; + + memset(ifa, 0, sizeof(struct ifaddrs) * icnt); + ift = ifa; + + ifr = ifc.ifc_req; + lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; + + while (ifr < lifr) { + struct sockaddr *sa; + + ift->ifa_name = names; + names[sizeof(ifr->ifr_name)] = 0; + strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name)); + while (*names++) + ; + + ift->ifa_addr = (struct sockaddr *)data; + sa = &ifr->ifr_addr; + memcpy(data, sa, SA_LEN(sa)); + data += SA_RLEN(sa); + + ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa)); + ift = (ift->ifa_next = ift + 1); + } + if (--ift >= ifa) { + ift->ifa_next = NULL; + *pif = ifa; + } else { + *pif = NULL; + free(ifa); + } + return (0); +} + +void +freeifaddrs(struct ifaddrs *ifp) +{ + + free(ifp); +} --Multipart=_Wed__19_Sep_2012_10_59_45_-0700_6GvGV+KlFENi4a37 Content-Type: text/x-csrc; name="ifaddr-test.c" Content-Disposition: attachment; filename="ifaddr-test.c" Content-Transfer-Encoding: 7bit #include #include #include #include #include #include #include int main(int argc, char *argv[]) { struct ifaddrs *ifaddr, *ifa; int family, s; char host[NI_MAXHOST]; if (getifaddrs(&ifaddr) == -1) { perror("getifaddrs"); exit(EXIT_FAILURE); } /* Walk through linked list, maintaining head pointer so we can free list later */ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { family = ifa->ifa_addr->sa_family; /* Display interface name and family (including symbolic form of the latter for the common families) */ printf("%s address family: %d%s\n", ifa->ifa_name, family, (family == AF_PACKET) ? " (AF_PACKET)" : (family == AF_INET) ? " (AF_INET)" : (family == AF_INET6) ? " (AF_INET6)" : ""); /* For an AF_INET* interface address, display the address */ if (family == AF_INET || family == AF_INET6) { s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (s != 0) { printf("getnameinfo() failed: %s\n", gai_strerror(s)); exit(EXIT_FAILURE); } printf("\taddress: <%s>\n", host); } } freeifaddrs(ifaddr); exit(EXIT_SUCCESS); } --Multipart=_Wed__19_Sep_2012_10_59_45_-0700_6GvGV+KlFENi4a37--