aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-10-16 18:44:02 +0300
committerEli Zaretskii2013-10-16 18:44:02 +0300
commit3dffe395916c0c075c1609c41e553d9f8e3690ea (patch)
treeeeaa2e377b897148fee2ed764c9e0fbb786dc9e1 /src
parentb911a94d7993508f8a53360a4be4651de30ea301 (diff)
downloademacs-3dffe395916c0c075c1609c41e553d9f8e3690ea.tar.gz
emacs-3dffe395916c0c075c1609c41e553d9f8e3690ea.zip
Implement network-interface-* functions for MS-Windows (bug #15610).
src/w32.c (network_interface_get_info, network_interface_list) (network_interface_info): New functions. (GetAdaptersInfo_Proc): New typedef. (get_adapters_info): New wrapper function. (globals_of_w32): Initialize g_b_init_get_adapters_info. src/process.h (network_interface_list, network_interface_info): New prototypes. src/process.c (conv_sockaddr_to_lisp): Now externally-visible. (Fnetwork_interface_list, Fnetwork_interface_info): Define for all systems. Return non-nil for systems that HAVE_NET_IF_H and for WINDOWSNT. Doc fix. (syms_of_process): Defsubr Snetwork_interface_list and Snetwork_interface_info unconditionally.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog16
-rw-r--r--src/process.c56
-rw-r--r--src/process.h4
-rw-r--r--src/w32.c292
4 files changed, 349 insertions, 19 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4874187b3c0..3b419af9e32 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,21 @@
12013-10-16 Eli Zaretskii <eliz@gnu.org> 12013-10-16 Eli Zaretskii <eliz@gnu.org>
2 2
3 * w32.c (network_interface_get_info, network_interface_list)
4 (network_interface_info): New functions. (Bug#15610)
5 (GetAdaptersInfo_Proc): New typedef.
6 (get_adapters_info): New wrapper function.
7 (globals_of_w32): Initialize g_b_init_get_adapters_info.
8
9 * process.h (network_interface_list, network_interface_info): New
10 prototypes.
11
12 * process.c (conv_sockaddr_to_lisp): Now externally-visible.
13 (Fnetwork_interface_list, Fnetwork_interface_info): Define for
14 all systems. Return non-nil for systems that HAVE_NET_IF_H and
15 for WINDOWSNT. Doc fix.
16 (syms_of_process): Defsubr Snetwork_interface_list and
17 Snetwork_interface_info unconditionally.
18
3 * menu.c (have_boxes): Fix redundant simulation of radio buttons 19 * menu.c (have_boxes): Fix redundant simulation of radio buttons
4 in NS GUI sessions. (Bug#15629) 20 in NS GUI sessions. (Bug#15629)
5 21
diff --git a/src/process.c b/src/process.c
index 2ed8a690193..cf9d5e265e1 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1958,7 +1958,7 @@ create_pty (Lisp_Object process)
1958/* Convert an internal struct sockaddr to a lisp object (vector or string). 1958/* Convert an internal struct sockaddr to a lisp object (vector or string).
1959 The address family of sa is not included in the result. */ 1959 The address family of sa is not included in the result. */
1960 1960
1961static Lisp_Object 1961Lisp_Object
1962conv_sockaddr_to_lisp (struct sockaddr *sa, int len) 1962conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
1963{ 1963{
1964 Lisp_Object address; 1964 Lisp_Object address;
@@ -3504,16 +3504,45 @@ usage: (make-network-process &rest ARGS) */)
3504} 3504}
3505 3505
3506 3506
3507#if defined (HAVE_NET_IF_H)
3508
3509#ifdef SIOCGIFCONF
3510DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0, 3507DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
3511 doc: /* Return an alist of all network interfaces and their network address. 3508 doc: /* Return an alist of all network interfaces and their network address.
3512Each element is a cons, the car of which is a string containing the 3509Each element is a cons, the car of which is a string containing the
3513interface name, and the cdr is the network address in internal 3510interface name, and the cdr is the network address in internal
3514format; see the description of ADDRESS in `make-network-process'. */) 3511format; see the description of ADDRESS in `make-network-process'.
3512
3513If the information is not available, return nil. */)
3515 (void) 3514 (void)
3516{ 3515{
3516#if (defined (HAVE_NET_IF_H) && defined (SIOCGIFCONF)) || defined (WINDOWSNT)
3517 return network_interface_list ();
3518#else
3519 return Qnil;
3520#endif
3521}
3522
3523DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0,
3524 doc: /* Return information about network interface named IFNAME.
3525The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS),
3526where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address,
3527NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and
3528FLAGS is the current flags of the interface.
3529
3530Data that is unavailable is returned as nil. */)
3531 (Lisp_Object ifname)
3532{
3533#if (defined (HAVE_NET_IF_H) && (defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS))) || defined (WINDOWSNT)
3534 return network_interface_info (ifname);
3535#else
3536 return Qnil;
3537#endif
3538}
3539
3540#if defined (HAVE_NET_IF_H)
3541
3542#ifdef SIOCGIFCONF
3543Lisp_Object
3544network_interface_list (void)
3545{
3517 struct ifconf ifconf; 3546 struct ifconf ifconf;
3518 struct ifreq *ifreq; 3547 struct ifreq *ifreq;
3519 void *buf = NULL; 3548 void *buf = NULL;
@@ -3654,13 +3683,8 @@ static const struct ifflag_def ifflag_table[] = {
3654 { 0, 0 } 3683 { 0, 0 }
3655}; 3684};
3656 3685
3657DEFUN ("network-interface-info", Fnetwork_interface_info, Snetwork_interface_info, 1, 1, 0, 3686Lisp_Object
3658 doc: /* Return information about network interface named IFNAME. 3687network_interface_info (Lisp_Object ifname)
3659The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS),
3660where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address,
3661NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and
3662FLAGS is the current flags of the interface. */)
3663 (Lisp_Object ifname)
3664{ 3688{
3665 struct ifreq rq; 3689 struct ifreq rq;
3666 Lisp_Object res = Qnil; 3690 Lisp_Object res = Qnil;
@@ -3802,7 +3826,7 @@ FLAGS is the current flags of the interface. */)
3802 3826
3803 return unbind_to (count, any ? res : Qnil); 3827 return unbind_to (count, any ? res : Qnil);
3804} 3828}
3805#endif 3829#endif /* !SIOCGIFADDR && !SIOCGIFHWADDR && !SIOCGIFFLAGS */
3806#endif /* defined (HAVE_NET_IF_H) */ 3830#endif /* defined (HAVE_NET_IF_H) */
3807 3831
3808/* Turn off input and output for process PROC. */ 3832/* Turn off input and output for process PROC. */
@@ -7293,14 +7317,8 @@ The variable takes effect when `start-process' is called. */);
7293 defsubr (&Sset_network_process_option); 7317 defsubr (&Sset_network_process_option);
7294 defsubr (&Smake_network_process); 7318 defsubr (&Smake_network_process);
7295 defsubr (&Sformat_network_address); 7319 defsubr (&Sformat_network_address);
7296#if defined (HAVE_NET_IF_H)
7297#ifdef SIOCGIFCONF
7298 defsubr (&Snetwork_interface_list); 7320 defsubr (&Snetwork_interface_list);
7299#endif
7300#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
7301 defsubr (&Snetwork_interface_info); 7321 defsubr (&Snetwork_interface_info);
7302#endif
7303#endif /* defined (HAVE_NET_IF_H) */
7304#ifdef DATAGRAM_SOCKETS 7322#ifdef DATAGRAM_SOCKETS
7305 defsubr (&Sprocess_datagram_address); 7323 defsubr (&Sprocess_datagram_address);
7306 defsubr (&Sset_process_datagram_address); 7324 defsubr (&Sset_process_datagram_address);
diff --git a/src/process.h b/src/process.h
index a9b15f03da4..163066f025f 100644
--- a/src/process.h
+++ b/src/process.h
@@ -240,4 +240,8 @@ extern void delete_write_fd (int fd);
240extern void catch_child_signal (void); 240extern void catch_child_signal (void);
241#endif 241#endif
242 242
243extern Lisp_Object network_interface_list (void);
244extern Lisp_Object network_interface_info (Lisp_Object);
245
246
243INLINE_HEADER_END 247INLINE_HEADER_END
diff --git a/src/w32.c b/src/w32.c
index c6b8dfed9dc..e26c6f46433 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -218,6 +218,8 @@ typedef struct _REPARSE_DATA_BUFFER {
218#undef recvfrom 218#undef recvfrom
219#undef sendto 219#undef sendto
220 220
221#include <iphlpapi.h> /* should be after winsock2.h */
222
221#include "w32.h" 223#include "w32.h"
222#include <dirent.h> 224#include <dirent.h>
223#include "w32common.h" 225#include "w32common.h"
@@ -296,6 +298,7 @@ static BOOL g_b_init_convert_sd_to_sddl;
296static BOOL g_b_init_convert_sddl_to_sd; 298static BOOL g_b_init_convert_sddl_to_sd;
297static BOOL g_b_init_is_valid_security_descriptor; 299static BOOL g_b_init_is_valid_security_descriptor;
298static BOOL g_b_init_set_file_security; 300static BOOL g_b_init_set_file_security;
301static BOOL g_b_init_get_adapters_info;
299 302
300/* 303/*
301 BEGIN: Wrapper functions around OpenProcessToken 304 BEGIN: Wrapper functions around OpenProcessToken
@@ -438,6 +441,9 @@ typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
438 LPTSTR *StringSecurityDescriptor, 441 LPTSTR *StringSecurityDescriptor,
439 PULONG StringSecurityDescriptorLen); 442 PULONG StringSecurityDescriptorLen);
440typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR); 443typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
444typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
445 PIP_ADAPTER_INFO pAdapterInfo,
446 PULONG pOutBufLen);
441 447
442 /* ** A utility function ** */ 448 /* ** A utility function ** */
443static BOOL 449static BOOL
@@ -1130,6 +1136,28 @@ convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
1130 return retval; 1136 return retval;
1131} 1137}
1132 1138
1139static DWORD WINAPI
1140get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
1141{
1142 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info = NULL;
1143 HMODULE hm_iphlpapi = NULL;
1144
1145 if (is_windows_9x () == TRUE)
1146 return ERROR_NOT_SUPPORTED;
1147
1148 if (g_b_init_get_adapters_info == 0)
1149 {
1150 g_b_init_get_adapters_info = 1;
1151 hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
1152 if (hm_iphlpapi)
1153 s_pfn_Get_Adapters_Info = (GetAdaptersInfo_Proc)
1154 GetProcAddress (hm_iphlpapi, "GetAdaptersInfo");
1155 }
1156 if (s_pfn_Get_Adapters_Info == NULL)
1157 return ERROR_NOT_SUPPORTED;
1158 return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen);
1159}
1160
1133 1161
1134 1162
1135/* Return 1 if P is a valid pointer to an object of size SIZE. Return 1163/* Return 1 if P is a valid pointer to an object of size SIZE. Return
@@ -7434,6 +7462,269 @@ sys_write (int fd, const void * buffer, unsigned int count)
7434 return nchars; 7462 return nchars;
7435} 7463}
7436 7464
7465
7466/* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
7467
7468extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, int);
7469
7470/* Return information about network interface IFNAME, or about all
7471 interfaces (if IFNAME is nil). */
7472static Lisp_Object
7473network_interface_get_info (Lisp_Object ifname)
7474{
7475 ULONG ainfo_len = sizeof (IP_ADAPTER_INFO);
7476 IP_ADAPTER_INFO *adapter, *ainfo = xmalloc (ainfo_len);
7477 DWORD retval = get_adapters_info (ainfo, &ainfo_len);
7478 Lisp_Object res = Qnil;
7479
7480 if (retval == ERROR_BUFFER_OVERFLOW)
7481 {
7482 ainfo = xrealloc (ainfo, ainfo_len);
7483 retval = get_adapters_info (ainfo, &ainfo_len);
7484 }
7485
7486 if (retval == ERROR_SUCCESS)
7487 {
7488 int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
7489 int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
7490 int if_num;
7491 struct sockaddr_in sa;
7492
7493 /* For the below, we need some winsock functions, so make sure
7494 the winsock DLL is loaded. If we cannot successfully load
7495 it, they will have no use of the information we provide,
7496 anyway, so punt. */
7497 if (!winsock_lib && !init_winsock (1))
7498 goto done;
7499
7500 for (adapter = ainfo; adapter; adapter = adapter->Next)
7501 {
7502 char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
7503 u_long ip_addr;
7504 /* Present Unix-compatible interface names, instead of the
7505 Windows names, which are really GUIDs not readable by
7506 humans. */
7507 static const char *ifmt[] = {
7508 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
7509 "lo", "ifx%d"
7510 };
7511 enum {
7512 NONE = -1,
7513 ETHERNET = 0,
7514 TOKENRING = 1,
7515 FDDI = 2,
7516 PPP = 3,
7517 SLIP = 4,
7518 WLAN = 5,
7519 LOOPBACK = 6,
7520 OTHER_IF = 7
7521 } ifmt_idx;
7522
7523 switch (adapter->Type)
7524 {
7525 case MIB_IF_TYPE_ETHERNET:
7526 /* Windows before Vista reports wireless adapters as
7527 Ethernet. Work around by looking at the Description
7528 string. */
7529 if (strstr (adapter->Description, "Wireless "))
7530 {
7531 ifmt_idx = WLAN;
7532 if_num = wlan_count++;
7533 }
7534 else
7535 {
7536 ifmt_idx = ETHERNET;
7537 if_num = eth_count++;
7538 }
7539 break;
7540 case MIB_IF_TYPE_TOKENRING:
7541 ifmt_idx = TOKENRING;
7542 if_num = tr_count++;
7543 break;
7544 case MIB_IF_TYPE_FDDI:
7545 ifmt_idx = FDDI;
7546 if_num = fddi_count++;
7547 break;
7548 case MIB_IF_TYPE_PPP:
7549 ifmt_idx = PPP;
7550 if_num = ppp_count++;
7551 break;
7552 case MIB_IF_TYPE_SLIP:
7553 ifmt_idx = SLIP;
7554 if_num = sl_count++;
7555 break;
7556 case IF_TYPE_IEEE80211:
7557 ifmt_idx = WLAN;
7558 if_num = wlan_count++;
7559 break;
7560 case MIB_IF_TYPE_LOOPBACK:
7561 if (lo_count < 0)
7562 {
7563 ifmt_idx = LOOPBACK;
7564 if_num = lo_count++;
7565 }
7566 else
7567 ifmt_idx = NONE;
7568 break;
7569 default:
7570 ifmt_idx = OTHER_IF;
7571 if_num = ifx_count++;
7572 break;
7573 }
7574 if (ifmt_idx == NONE)
7575 continue;
7576 sprintf (namebuf, ifmt[ifmt_idx], if_num);
7577
7578 sa.sin_family = AF_INET;
7579 ip_addr = sys_inet_addr (adapter->IpAddressList.IpAddress.String);
7580 if (ip_addr == INADDR_NONE)
7581 {
7582 /* Bogus address, skip this interface. */
7583 continue;
7584 }
7585 sa.sin_addr.s_addr = ip_addr;
7586 sa.sin_port = 0;
7587 if (NILP (ifname))
7588 res = Fcons (Fcons (build_string (namebuf),
7589 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
7590 sizeof (struct sockaddr))),
7591 res);
7592 else if (strcmp (namebuf, SSDATA (ifname)) == 0)
7593 {
7594 Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
7595 register struct Lisp_Vector *p = XVECTOR (hwaddr);
7596 Lisp_Object flags = Qnil;
7597 int n;
7598 u_long net_mask;
7599
7600 /* Flags. We guess most of them by type, since the
7601 Windows flags are different and hard to get by. */
7602 flags = Fcons (intern ("up"), flags);
7603 if (ifmt_idx == ETHERNET || ifmt_idx == WLAN)
7604 {
7605 flags = Fcons (intern ("broadcast"), flags);
7606 flags = Fcons (intern ("multicast"), flags);
7607 }
7608 flags = Fcons (intern ("running"), flags);
7609 if (ifmt_idx == PPP)
7610 {
7611 flags = Fcons (intern ("pointopoint"), flags);
7612 flags = Fcons (intern ("noarp"), flags);
7613 }
7614 if (adapter->HaveWins)
7615 flags = Fcons (intern ("WINS"), flags);
7616 if (adapter->DhcpEnabled)
7617 flags = Fcons (intern ("dynamic"), flags);
7618
7619 res = Fcons (flags, res);
7620
7621 /* Hardware address and its family. */
7622 for (n = 0; n < adapter->AddressLength; n++)
7623 p->u.contents[n] = make_number ((int) adapter->Address[n]);
7624 /* Windows does not support AF_LINK or AF_PACKET family
7625 of addresses. Use an arbitrary family number that is
7626 identical to what GNU/Linux returns. */
7627 res = Fcons (Fcons (make_number (1), hwaddr), res);
7628
7629 /* Network mask. */
7630 sa.sin_family = AF_INET;
7631 net_mask = sys_inet_addr (adapter->IpAddressList.IpMask.String);
7632 if (net_mask != INADDR_NONE)
7633 {
7634 sa.sin_addr.s_addr = net_mask;
7635 sa.sin_port = 0;
7636 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
7637 sizeof (struct sockaddr)),
7638 res);
7639 }
7640 else
7641 res = Fcons (Qnil, res);
7642
7643 sa.sin_family = AF_INET;
7644 if (ip_addr != INADDR_NONE)
7645 {
7646 /* Broadcast address is only reported by
7647 GetAdaptersAddresses, which is of limited
7648 availability. Generate it on our own. */
7649 u_long bcast_addr = (ip_addr & net_mask) | ~net_mask;
7650
7651 sa.sin_addr.s_addr = bcast_addr;
7652 sa.sin_port = 0;
7653 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
7654 sizeof (struct sockaddr)),
7655 res);
7656
7657 /* IP address. */
7658 sa.sin_addr.s_addr = ip_addr;
7659 sa.sin_port = 0;
7660 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
7661 sizeof (struct sockaddr)),
7662 res);
7663 }
7664 else
7665 res = Fcons (Qnil, Fcons (Qnil, res));
7666 }
7667 }
7668 /* GetAdaptersInfo is documented to not report loopback
7669 interfaces, so we generate one out of thin air. */
7670 if (!lo_count)
7671 {
7672 sa.sin_family = AF_INET;
7673 sa.sin_port = 0;
7674 if (NILP (ifname))
7675 {
7676 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
7677 res = Fcons (Fcons (build_string ("lo"),
7678 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
7679 sizeof (struct sockaddr))),
7680 res);
7681 }
7682 else if (strcmp (SSDATA (ifname), "lo") == 0)
7683 {
7684 res = Fcons (Fcons (intern ("running"),
7685 Fcons (intern ("loopback"),
7686 Fcons (intern ("up"), Qnil))), Qnil);
7687 /* 772 is what 3 different GNU/Linux systems report for
7688 the loopback interface. */
7689 res = Fcons (Fcons (make_number (772),
7690 Fmake_vector (make_number (6),
7691 make_number (0))),
7692 res);
7693 sa.sin_addr.s_addr = sys_inet_addr ("255.0.0.0");
7694 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
7695 sizeof (struct sockaddr)),
7696 res);
7697 sa.sin_addr.s_addr = sys_inet_addr ("0.0.0.0");
7698 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
7699 sizeof (struct sockaddr)),
7700 res);
7701 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
7702 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
7703 sizeof (struct sockaddr)),
7704 res);
7705 }
7706
7707 }
7708 }
7709
7710 done:
7711 xfree (ainfo);
7712 return res;
7713}
7714
7715Lisp_Object
7716network_interface_list (void)
7717{
7718 return network_interface_get_info (Qnil);
7719}
7720
7721Lisp_Object
7722network_interface_info (Lisp_Object ifname)
7723{
7724 return network_interface_get_info (ifname);
7725}
7726
7727
7437/* The Windows CRT functions are "optimized for speed", so they don't 7728/* The Windows CRT functions are "optimized for speed", so they don't
7438 check for timezone and DST changes if they were last called less 7729 check for timezone and DST changes if they were last called less
7439 than 1 minute ago (see http://support.microsoft.com/kb/821231). So 7730 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
@@ -7735,6 +8026,7 @@ globals_of_w32 (void)
7735 g_b_init_convert_sddl_to_sd = 0; 8026 g_b_init_convert_sddl_to_sd = 0;
7736 g_b_init_is_valid_security_descriptor = 0; 8027 g_b_init_is_valid_security_descriptor = 0;
7737 g_b_init_set_file_security = 0; 8028 g_b_init_set_file_security = 0;
8029 g_b_init_get_adapters_info = 0;
7738 num_of_processors = 0; 8030 num_of_processors = 0;
7739 /* The following sets a handler for shutdown notifications for 8031 /* The following sets a handler for shutdown notifications for
7740 console apps. This actually applies to Emacs in both console and 8032 console apps. This actually applies to Emacs in both console and