aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorJan Djärv2011-08-13 12:48:03 +0200
committerJan Djärv2011-08-13 12:48:03 +0200
commit377538cbcf8c1f0aab9b40ed2ff3df414904272f (patch)
tree9dfd855ba3e99732fd5d3f49096a5191c09233f3 /src/process.c
parent1bca59fe757d359e3c36d3de1c8ec19ed90be49c (diff)
downloademacs-377538cbcf8c1f0aab9b40ed2ff3df414904272f.tar.gz
emacs-377538cbcf8c1f0aab9b40ed2ff3df414904272f.zip
Fix network-interface-list|info on newer BSD derived OS:es.
* configure.in: Add header check: sys/socket.h, ifaddrs.h, net/if_dl.h. Check for getifaddrs and freeifaddrs. Check for sa_len in struct ifreq.ifr_addr (Bug#8477). * src/process.c: Include ifaddrs.h and net/if_dl.h if available (Bug#8477). (Fnetwork_interface_list): Allocate in increments of bytes instead of sizeof (struct ifreq). Iterate over ifconf.ifc_req by counting bytes (Bug#8477). Count bytes correctly when ifr_addr is a struct sockaddr. (struct ifflag_def): notrailers is smart on OSX. (Fnetwork_interface_info): Handle case when ifr_flags is negative. Get hardware address with getifaddrs if available.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c94
1 files changed, 82 insertions, 12 deletions
diff --git a/src/process.c b/src/process.c
index 236c27e5c3a..b3c295cecde 100644
--- a/src/process.c
+++ b/src/process.c
@@ -58,6 +58,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
58#include <net/if.h> 58#include <net/if.h>
59#endif /* HAVE_NET_IF_H */ 59#endif /* HAVE_NET_IF_H */
60 60
61#if defined(HAVE_IFADDRS_H)
62/* Must be after net/if.h */
63#include <ifaddrs.h>
64
65/* We only use structs from this header when we use getifaddrs. */
66#if defined(HAVE_NET_IF_DL_H)
67#include <net/if_dl.h>
68#endif
69
70#endif
71
61#ifdef NEED_BSDTTY 72#ifdef NEED_BSDTTY
62#include <bsdtty.h> 73#include <bsdtty.h>
63#endif 74#endif
@@ -3557,9 +3568,9 @@ format; see the description of ADDRESS in `make-network-process'. */)
3557 (void) 3568 (void)
3558{ 3569{
3559 struct ifconf ifconf; 3570 struct ifconf ifconf;
3560 struct ifreq *ifreqs = NULL; 3571 struct ifreq *ifreq;
3561 int ifaces = 0; 3572 void *buf = NULL;
3562 int buf_size, s; 3573 int buf_size = 512, s, i;
3563 Lisp_Object res; 3574 Lisp_Object res;
3564 3575
3565 s = socket (AF_INET, SOCK_STREAM, 0); 3576 s = socket (AF_INET, SOCK_STREAM, 0);
@@ -3567,20 +3578,19 @@ format; see the description of ADDRESS in `make-network-process'. */)
3567 return Qnil; 3578 return Qnil;
3568 3579
3569 again: 3580 again:
3570 ifaces += 25; 3581 buf_size *= 2;
3571 buf_size = ifaces * sizeof (ifreqs[0]); 3582 buf = xrealloc(buf, buf_size);
3572 ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size); 3583 if (!buf)
3573 if (!ifreqs)
3574 { 3584 {
3575 close (s); 3585 close (s);
3576 return Qnil; 3586 return Qnil;
3577 } 3587 }
3578 3588
3579 ifconf.ifc_len = buf_size; 3589 ifconf.ifc_buf = buf;
3580 ifconf.ifc_req = ifreqs;
3581 if (ioctl (s, SIOCGIFCONF, &ifconf)) 3590 if (ioctl (s, SIOCGIFCONF, &ifconf))
3582 { 3591 {
3583 close (s); 3592 close (s);
3593 xfree (buf);
3584 return Qnil; 3594 return Qnil;
3585 } 3595 }
3586 3596
@@ -3588,15 +3598,29 @@ format; see the description of ADDRESS in `make-network-process'. */)
3588 goto again; 3598 goto again;
3589 3599
3590 close (s); 3600 close (s);
3591 ifaces = ifconf.ifc_len / sizeof (ifreqs[0]);
3592 3601
3593 res = Qnil; 3602 res = Qnil;
3594 while (--ifaces >= 0) 3603 for (ifreq = ifconf.ifc_req;
3604 (char *) ifreq < (char *) (ifconf.ifc_req) + ifconf.ifc_len;
3605 )
3595 { 3606 {
3596 struct ifreq *ifq = &ifreqs[ifaces]; 3607 struct ifreq *ifq = ifreq;
3608#ifdef HAVE_STRUCT_IFREQ_IFR_ADDR_SA_LEN
3609#define SIZEOF_IFREQ(sif) \
3610 ((sif)->ifr_addr.sa_len < sizeof(struct sockaddr) ? \
3611 sizeof((*sif)) : sizeof ((sif)->ifr_name) + sif->ifr_addr.sa_len)
3612
3613 int len = SIZEOF_IFREQ (ifq);
3614#else
3615 int len = sizeof (*ifreq);
3616#endif
3597 char namebuf[sizeof (ifq->ifr_name) + 1]; 3617 char namebuf[sizeof (ifq->ifr_name) + 1];
3618 i += len;
3619 ifreq = (struct ifreq*) ((char*) ifreq + len);
3620
3598 if (ifq->ifr_addr.sa_family != AF_INET) 3621 if (ifq->ifr_addr.sa_family != AF_INET)
3599 continue; 3622 continue;
3623
3600 memcpy (namebuf, ifq->ifr_name, sizeof (ifq->ifr_name)); 3624 memcpy (namebuf, ifq->ifr_name, sizeof (ifq->ifr_name));
3601 namebuf[sizeof (ifq->ifr_name)] = 0; 3625 namebuf[sizeof (ifq->ifr_name)] = 0;
3602 res = Fcons (Fcons (build_string (namebuf), 3626 res = Fcons (Fcons (build_string (namebuf),
@@ -3605,6 +3629,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
3605 res); 3629 res);
3606 } 3630 }
3607 3631
3632 xfree (buf);
3608 return res; 3633 return res;
3609} 3634}
3610#endif /* SIOCGIFCONF */ 3635#endif /* SIOCGIFCONF */
@@ -3642,8 +3667,13 @@ static const struct ifflag_def ifflag_table[] = {
3642 { IFF_PROMISC, "promisc" }, 3667 { IFF_PROMISC, "promisc" },
3643#endif 3668#endif
3644#ifdef IFF_NOTRAILERS 3669#ifdef IFF_NOTRAILERS
3670#ifdef NS_IMPL_COCOA
3671 /* Really means smart, notrailers is obsolete */
3672 { IFF_NOTRAILERS, "smart" },
3673#else
3645 { IFF_NOTRAILERS, "notrailers" }, 3674 { IFF_NOTRAILERS, "notrailers" },
3646#endif 3675#endif
3676#endif
3647#ifdef IFF_ALLMULTI 3677#ifdef IFF_ALLMULTI
3648 { IFF_ALLMULTI, "allmulti" }, 3678 { IFF_ALLMULTI, "allmulti" },
3649#endif 3679#endif
@@ -3696,6 +3726,9 @@ FLAGS is the current flags of the interface. */)
3696 Lisp_Object elt; 3726 Lisp_Object elt;
3697 int s; 3727 int s;
3698 int any = 0; 3728 int any = 0;
3729#if defined(HAVE_GETIFADDRS)
3730 struct ifaddrs *ifap;
3731#endif
3699 3732
3700 CHECK_STRING (ifname); 3733 CHECK_STRING (ifname);
3701 3734
@@ -3714,6 +3747,12 @@ FLAGS is the current flags of the interface. */)
3714 const struct ifflag_def *fp; 3747 const struct ifflag_def *fp;
3715 int fnum; 3748 int fnum;
3716 3749
3750 /* If flags is smaller than int (i.e. short) it may have the high bit set
3751 due to IFF_MULTICAST. In that case, sign extending it into
3752 an int is wrong. */
3753 if (flags < 0 && sizeof (rq.ifr_flags) < sizeof (flags))
3754 flags = (unsigned short) rq.ifr_flags;
3755
3717 any = 1; 3756 any = 1;
3718 for (fp = ifflag_table; flags != 0 && fp->flag_sym; fp++) 3757 for (fp = ifflag_table; flags != 0 && fp->flag_sym; fp++)
3719 { 3758 {
@@ -3747,7 +3786,38 @@ FLAGS is the current flags of the interface. */)
3747 p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]); 3786 p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]);
3748 elt = Fcons (make_number (rq.ifr_hwaddr.sa_family), hwaddr); 3787 elt = Fcons (make_number (rq.ifr_hwaddr.sa_family), hwaddr);
3749 } 3788 }
3789#elif defined(HAVE_GETIFADDRS) && defined(LLADDR)
3790 if (getifaddrs (&ifap) != -1)
3791 {
3792 Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
3793 register struct Lisp_Vector *p = XVECTOR (hwaddr);
3794 struct ifaddrs *it;
3795
3796 for (it = ifap; it != NULL; it = it->ifa_next)
3797 {
3798 struct sockaddr_dl *sdl = (struct sockaddr_dl*) it->ifa_addr;
3799 unsigned char linkaddr[6];
3800 int n;
3801
3802 if (it->ifa_addr->sa_family != AF_LINK
3803 || strcmp (it->ifa_name, SSDATA (ifname)) != 0
3804 || sdl->sdl_alen != 6)
3805 continue;
3806
3807 memcpy (linkaddr, LLADDR(sdl), sdl->sdl_alen);
3808 for (n = 0; n < 6; n++)
3809 p->contents[n] = make_number (linkaddr[n]);
3810
3811 elt = Fcons (make_number (it->ifa_addr->sa_family), hwaddr);
3812 break;
3813 }
3814 }
3815#ifdef HAVE_FREEIFADDRS
3816 freeifaddrs (ifap);
3750#endif 3817#endif
3818
3819#endif /* HAVE_GETIFADDRS && LLADDR */
3820
3751 res = Fcons (elt, res); 3821 res = Fcons (elt, res);
3752 3822
3753 elt = Qnil; 3823 elt = Qnil;