Mercurial > emacs
changeset 52503:256a27a47af1
[HAVE_SOCKETS]: Include sys/ioctl.h and net/if.h.
(Fnetwork_interface_list, Fget_network_interface_info): New defuns.
(syms_of_process): Defsubr them.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Sat, 13 Sep 2003 23:34:33 +0000 |
parents | 9afe1154d52b |
children | cd1293e6665e |
files | src/process.c |
diffstat | 1 files changed, 245 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/process.c Sat Sep 13 23:33:41 2003 +0000 +++ b/src/process.c Sat Sep 13 23:34:33 2003 +0000 @@ -98,6 +98,17 @@ #include <bsdtty.h> #endif +/* Can we use SIOCGIFCONF and/or SIOCGIFADDR */ +#ifdef HAVE_SOCKETS +#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) +/* sys/ioctl.h may have been included already */ +#ifndef SIOCGIFADDR +#include <sys/ioctl.h> +#endif +#include <net/if.h> +#endif +#endif + #ifdef IRIS #include <sys/sysmacros.h> /* for "minor" */ #endif /* not IRIS */ @@ -3356,6 +3367,234 @@ } #endif /* HAVE_SOCKETS */ + +#ifdef HAVE_SOCKETS + +#ifdef 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 +interface name, and the cdr is the network address in internal +format; see the description of ADDRESS in 'make-network-process'. */) + () +{ + struct ifconf ifconf; + struct ifreq *ifreqs = NULL; + int ifaces = 0; + int buf_size, s; + Lisp_Object res; + + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) + return Qnil; + + again: + ifaces += 25; + buf_size = ifaces * sizeof(ifreqs[0]); + ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size); + if (!ifreqs) + { + close (s); + return Qnil; + } + + ifconf.ifc_len = buf_size; + ifconf.ifc_req = ifreqs; + if (ioctl (s, SIOCGIFCONF, &ifconf)) + { + close (s); + return Qnil; + } + + if (ifconf.ifc_len == buf_size) + goto again; + + close (s); + ifaces = ifconf.ifc_len / sizeof (ifreqs[0]); + + res = Qnil; + while (--ifaces >= 0) + { + struct ifreq *ifq = &ifreqs[ifaces]; + char namebuf[sizeof (ifq->ifr_name) + 1]; + if (ifq->ifr_addr.sa_family != AF_INET) + continue; + bcopy (ifq->ifr_name, namebuf, sizeof (ifq->ifr_name)); + namebuf[sizeof (ifq->ifr_name)] = 0; + res = Fcons (Fcons (build_string (namebuf), + conv_sockaddr_to_lisp (&ifq->ifr_addr, + sizeof (struct sockaddr))), + res); + } + + return res; +} +#endif + +#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) + +struct ifflag_def { + int flag_bit; + char *flag_sym; +}; + +static struct ifflag_def ifflag_table[] = { +#ifdef IFF_UP + { IFF_UP, "up" }, +#endif +#ifdef IFF_BROADCAST + { IFF_BROADCAST, "broadcast" }, +#endif +#ifdef IFF_DEBUG + { IFF_DEBUG, "debug" }, +#endif +#ifdef IFF_LOOPBACK + { IFF_LOOPBACK, "loopback" }, +#endif +#ifdef IFF_POINTOPOINT + { IFF_POINTOPOINT, "pointopoint" }, +#endif +#ifdef IFF_RUNNING + { IFF_RUNNING, "running" }, +#endif +#ifdef IFF_NOARP + { IFF_NOARP, "noarp" }, +#endif +#ifdef IFF_PROMISC + { IFF_PROMISC, "promisc" }, +#endif +#ifdef IFF_NOTRAILERS + { IFF_NOTRAILERS, "notrailers" }, +#endif +#ifdef IFF_ALLMULTI + { IFF_ALLMULTI, "allmulti" }, +#endif +#ifdef IFF_MASTER + { IFF_MASTER, "master" }, +#endif +#ifdef IFF_SLAVE + { IFF_SLAVE, "slave" }, +#endif +#ifdef IFF_MULTICAST + { IFF_MULTICAST, "multicast" }, +#endif +#ifdef IFF_PORTSEL + { IFF_PORTSEL, "portsel" }, +#endif +#ifdef IFF_AUTOMEDIA + { IFF_AUTOMEDIA, "automedia" }, +#endif +#ifdef IFF_DYNAMIC + { IFF_DYNAMIC, "dynamic" }, +#endif + { 0, 0 } +}; + +DEFUN ("get-network-interface-info", Fget_network_interface_info, Sget_network_interface_info, 1, 1, 0, + doc: /* Return information about network interface named IFNAME. +The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS), +where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address, +NETMASK is the layer 3 network mask, HWADDR is the layer 2 addres, and +FLAGS is the current flags of the interface. */) + (ifname) + Lisp_Object ifname; +{ + struct ifreq rq; + Lisp_Object res = Qnil; + Lisp_Object elt; + int s; + int any = 0; + + CHECK_STRING (ifname); + + bzero (rq.ifr_name, sizeof rq.ifr_name); + strncpy (rq.ifr_name, SDATA (ifname), sizeof (rq.ifr_name)); + + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) + return Qnil; + + elt = Qnil; +#ifdef SIOCGIFFLAGS + if (ioctl (s, SIOCGIFFLAGS, &rq) == 0) + { + 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); + } + } + } +#endif + res = Fcons (elt, res); + + elt = Qnil; +#ifdef SIOCGIFHWADDR + if (ioctl (s, SIOCGIFHWADDR, &rq) == 0) + { + Lisp_Object hwaddr = Fmake_vector (6, Qnil); + register struct Lisp_Vector *p = XVECTOR (hwaddr); + int n; + + any++; + for (n = 0; n < 6; n++) + p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]); + elt = Fcons (XINT (rq.ifr_hwaddr.sa_family), hwaddr); + } +#endif + res = Fcons (elt, res); + + elt = Qnil; +#ifdef SIOCGIFNETMASK + if (ioctl (s, SIOCGIFNETMASK, &rq) == 0) + { + any++; + elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask)); + } +#endif + res = Fcons (elt, res); + + elt = Qnil; +#ifdef SIOCGIFBRDADDR + if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0) + { + any++; + elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof (rq.ifr_broadaddr)); + } +#endif + res = Fcons (elt, res); + + elt = Qnil; +#ifdef SIOCGIFADDR + if (ioctl (s, SIOCGIFADDR, &rq) == 0) + { + any++; + elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr)); + } +#endif + res = Fcons (elt, res); + + close (s); + + return any ? res : Qnil; +} +#endif +#endif /* HAVE_SOCKETS */ + void deactivate_process (proc) Lisp_Object proc; @@ -6467,6 +6706,12 @@ defsubr (&Sset_network_process_options); defsubr (&Smake_network_process); defsubr (&Sformat_network_address); +#ifdef SIOCGIFCONF + defsubr (&Snetwork_interface_list); +#endif +#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS) + defsubr (&Sget_network_interface_info); +#endif #endif /* HAVE_SOCKETS */ #ifdef DATAGRAM_SOCKETS defsubr (&Sprocess_datagram_address);