From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Alex Plotnick Newsgroups: gmane.emacs.devel Subject: Patch for network-interface-{list,info} Date: Sun, 16 Nov 2003 15:17:21 -0500 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: <9230.36090466685$1069014067@news.gmane.org> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1069014067 3263 80.91.224.253 (16 Nov 2003 20:21:07 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sun, 16 Nov 2003 20:21:07 +0000 (UTC) Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Sun Nov 16 21:21:04 2003 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1ALTOJ-0007mU-00 for ; Sun, 16 Nov 2003 21:21:03 +0100 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.35 #1 (Debian)) id 1ALTOJ-0008Qu-00 for ; Sun, 16 Nov 2003 21:21:03 +0100 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.24) id 1ALUJs-0006jY-Sp for emacs-devel@quimby.gnus.org; Sun, 16 Nov 2003 16:20:32 -0500 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.24) id 1ALUIw-0006Om-1a for emacs-devel@gnu.org; Sun, 16 Nov 2003 16:19:34 -0500 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.24) id 1ALUIO-0005zk-7c for emacs-devel@gnu.org; Sun, 16 Nov 2003 16:19:31 -0500 Original-Received: from [204.127.202.56] (helo=sccrmhc12.comcast.net) by monty-python.gnu.org with esmtp (Exim 4.24) id 1ALUIN-0005tL-4c for emacs-devel@gnu.org; Sun, 16 Nov 2003 16:18:59 -0500 Original-Received: from milo.localdomain (pcp04988064pcs.benslm01.pa.comcast.net[68.81.104.105]) by comcast.net (sccrmhc12) with ESMTP id <2003111620172101200s3ht0e>; Sun, 16 Nov 2003 20:17:21 +0000 Original-Received: from Dora.local. (gateway.localdomain [192.168.0.1]) by milo.localdomain (Postfix) with ESMTP id A9597144893E for ; Sun, 16 Nov 2003 15:17:20 -0500 (EST) Original-To: emacs-devel@gnu.org User-Agent: Gnus/5.1002 (Gnus v5.10.2) Emacs/21.3.50 (darwin) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.2 Precedence: list List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:17846 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:17846 I noticed that the functions `network-interface-info' and `network-interface-list' did not work on Darwin 6.8 (Mac OS X 10.2.8). After some investigation, I determined that they probably would not work on some other BSDs as well. The following patch addresses some of the issues. The use of ioctl(SIOCGIFCONF) to fetch the list of network interfaces is prone to some interesting problems. In particular, the size of the returned structures (struct ifreq) is not constant on some systems (e.g., Darwin), making the buffer resizing and list iteration somewhat tricky. My patch fixes these errors, and the SIOCGIFCONF now works properly under both GNU/Linux and Darwin. However, it seems to be preferable to just use getifaddrs() when available, as it's a much cleaner interface. To my mind, it's tempting to get rid of the SIOCGIFCONF code all together, but I've left it in for now. In the case of `network-interface-info', certain of the requested ioctl()s are non-existent on Darwin (and, again, presumably on some other BSDs); in particular, SIOCGIFNETMASK and SIOCGIFHWADDR. I've got some code that uses getifaddrs() to fetch all of this info (instead of doing separate ioctl() calls), but have not included it in this patch. If people think this is the correct way to go, I'll send it on. (For those that care: the downside of this is the difference between the link-layer sockaddrs on BSD (struct sockaddr_dl) and Linux (struct sockaddr_ll).) Comments, suggestions, bug-fixes, and test reports are all welcome. -- Alex Plotnick Index: configure.in =================================================================== RCS file: /cvsroot/emacs/emacs/configure.in,v retrieving revision 1.356 diff -u -r1.356 configure.in --- configure.in 23 Sep 2003 12:39:44 -0000 1.356 +++ configure.in 16 Nov 2003 20:05:24 -0000 @@ -1516,7 +1516,9 @@ [#include ]) AC_CHECK_MEMBERS([struct ifreq.ifr_flags, struct ifreq.ifr_hwaddr, struct ifreq.ifr_netmask, struct ifreq.ifr_broadaddr, - struct ifreq.ifr_addr], , ,[#include ]) + struct ifreq.ifr_addr], , ,[#include +#include +#include ]) dnl checks for compiler characteristics @@ -2298,7 +2300,7 @@ rename closedir mkdir rmdir sysinfo \ random lrand48 bcopy bcmp logb frexp fmod rint cbrt ftime res_init setsid \ strerror fpathconf select mktime euidaccess getpagesize tzset setlocale \ -utimes setrlimit setpgid getcwd getwd shutdown getaddrinfo \ +utimes setrlimit setpgid getcwd getwd shutdown getaddrinfo getifaddrs \ __fpending mblen mbrlen mbsinit strsignal setitimer ualarm index rindex \ sendto recvfrom getsockopt setsockopt getsockname getpeername \ gai_strerror mkstemp getline getdelim mremap memmove fsync bzero \ Index: src/process.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/process.c,v retrieving revision 1.416 diff -u -r1.416 process.c --- src/process.c 27 Sep 2003 00:25:40 -0000 1.416 +++ src/process.c 16 Nov 2003 20:05:26 -0000 @@ -109,6 +109,10 @@ #endif #endif +#ifdef HAVE_GETIFADDRS +#include +#endif + #ifdef IRIS #include /* for "minor" */ #endif /* not IRIS */ @@ -3353,7 +3357,7 @@ #if defined(HAVE_SOCKETS) && defined(HAVE_NET_IF_H) && defined(HAVE_SYS_IOCTL_H) -#ifdef SIOCGIFCONF +#if defined(HAVE_GETIFADDRS) || defined(SIOCGIFCONF) DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0, doc: /* Return an alist of all network interfaces and their network address. Each element is a cons, the car of which is a string containing the @@ -3361,58 +3365,89 @@ format; see the description of ADDRESS in `make-network-process'. */) () { + Lisp_Object res = Qnil; +#ifdef HAVE_GETIFADDRS + struct ifaddrs *ifap, *ifa; + + if (getifaddrs (&ifap) != 0) + return Qnil; + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) + { + char namebuf[sizeof (ifa->ifa_name) + 1]; + if (ifa->ifa_addr->sa_family != AF_INET) + continue; + bcopy (ifa->ifa_name, namebuf, sizeof (ifa->ifa_name)); + namebuf[sizeof (ifa->ifa_name)] = 0; + res = Fcons (Fcons (build_string (namebuf), + conv_sockaddr_to_lisp (ifa->ifa_addr, + sizeof (struct sockaddr))), + res); + } + freeifaddrs(ifap); + +#else /* defined(SIOCGIFCONF) */ struct ifconf ifconf; - struct ifreq *ifreqs = NULL; - int ifaces = 0; + struct ifreq *ifrp, *ifend, *ifnext; + char *buf = NULL; int buf_size, s; - Lisp_Object res; - s = socket (AF_INET, SOCK_STREAM, 0); + s = socket (AF_INET, SOCK_DGRAM, 0); if (s < 0) return Qnil; + buf_size = 0; again: - ifaces += 25; - buf_size = ifaces * sizeof(ifreqs[0]); - ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size); - if (!ifreqs) + buf_size += 1024; + buf = (char *) xrealloc (buf, buf_size); + if (!buf) { close (s); return Qnil; } ifconf.ifc_len = buf_size; - ifconf.ifc_req = ifreqs; - if (ioctl (s, SIOCGIFCONF, &ifconf)) + ifconf.ifc_buf = buf; + bzero (buf, buf_size); + if (ioctl (s, SIOCGIFCONF, &ifconf) == -1) { close (s); + xfree (buf); return Qnil; } - if (ifconf.ifc_len == buf_size) + if (buf_size - ifconf.ifc_len < sizeof (struct ifreq)) goto again; close (s); - ifaces = ifconf.ifc_len / sizeof (ifreqs[0]); - res = Qnil; - while (--ifaces >= 0) +#ifdef _SIZEOF_ADDR_IFREQ +#define sizeof_ifreq(IFREQ) _SIZEOF_ADDR_IFREQ (IFREQ) +#else +#define sizeof_ifreq(IFREQ) sizeof (struct ifreq) +#endif + + ifrp = (struct ifreq *) buf; + ifend = (struct ifreq *)(buf + ifconf.ifc_len); + for ( ; ifrp < ifend; ifrp = ifnext) { - struct ifreq *ifq = &ifreqs[ifaces]; - char namebuf[sizeof (ifq->ifr_name) + 1]; - if (ifq->ifr_addr.sa_family != AF_INET) + ifnext = (struct ifreq *) ((char *) ifrp + sizeof_ifreq (*ifrp)); + char namebuf[sizeof (ifrp->ifr_name) + 1]; + if (ifrp->ifr_addr.sa_family != AF_INET) continue; - bcopy (ifq->ifr_name, namebuf, sizeof (ifq->ifr_name)); - namebuf[sizeof (ifq->ifr_name)] = 0; + bcopy (ifrp->ifr_name, namebuf, sizeof (ifrp->ifr_name)); + namebuf[sizeof (ifrp->ifr_name)] = 0; res = Fcons (Fcons (build_string (namebuf), - conv_sockaddr_to_lisp (&ifq->ifr_addr, + conv_sockaddr_to_lisp (&ifrp->ifr_addr, sizeof (struct sockaddr))), res); } + xfree (buf); +#endif /* SIOCGIFCONF */ return res; } -#endif /* SIOCGIFCONF */ +#endif /* defined(HAVE_GETIFADDRS) || defined(SIOCGIFCONF) */ #if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) @@ -3473,6 +3508,29 @@ { 0, 0 } }; +static Lisp_Object +conv_ifflags_to_lisp (flags) + short int flags; +{ + Lisp_Object obj = Qnil; + struct ifflag_def *fp; + int fnum; + + for (fp = ifflag_table; fp->flag_bit && fp->flag_sym; fp++) + { + if (flags & fp->flag_bit) + { + obj = Fcons (intern (fp->flag_sym), obj); + flags -= fp->flag_bit; + } + } + for (fnum = 0; flags && fnum < 16; fnum++) + if (flags & (1 << fnum)) + obj = Fcons (make_number (fnum), obj); + + return obj; +} + DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, doc: /* Return information about network interface named IFNAME. The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), @@ -3499,35 +3557,17 @@ elt = Qnil; #if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ_IFR_FLAGS) - if (ioctl (s, SIOCGIFFLAGS, &rq) == 0) + if (ioctl (s, SIOCGIFFLAGS, &rq) != -1) { - int flags = rq.ifr_flags; - struct ifflag_def *fp; - int fnum; - any++; - for (fp = ifflag_table; flags != 0 && fp; fp++) - { - if (flags & fp->flag_bit) - { - elt = Fcons (intern (fp->flag_sym), elt); - flags -= fp->flag_bit; - } - } - for (fnum = 0; flags && fnum < 32; fnum++) - { - if (flags & (1 << fnum)) - { - elt = Fcons (make_number (fnum), elt); - } - } + elt = conv_ifflags_to_lisp (rq.ifr_flags); } #endif res = Fcons (elt, res); elt = Qnil; #if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR) - if (ioctl (s, SIOCGIFHWADDR, &rq) == 0) + if (ioctl (s, SIOCGIFHWADDR, &rq) != -1) { Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil); register struct Lisp_Vector *p = XVECTOR (hwaddr); @@ -3543,7 +3583,7 @@ elt = Qnil; #if defined(SIOCGIFNETMASK) && defined(ifr_netmask) - if (ioctl (s, SIOCGIFNETMASK, &rq) == 0) + if (ioctl (s, SIOCGIFNETMASK, &rq) != -1) { any++; elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask)); @@ -3553,7 +3593,7 @@ elt = Qnil; #if defined(SIOCGIFBRDADDR) && defined(HAVE_STRUCT_IFREQ_IFR_BROADADDR) - if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0) + if (ioctl (s, SIOCGIFBRDADDR, &rq) != -1) { any++; elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof (rq.ifr_broadaddr)); @@ -3563,7 +3603,7 @@ elt = Qnil; #if defined(SIOCGIFADDR) && defined(HAVE_STRUCT_IFREQ_IFR_ADDR) - if (ioctl (s, SIOCGIFADDR, &rq) == 0) + if (ioctl (s, SIOCGIFADDR, &rq) != -1) { any++; elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr));