Extend network-interface-list to return IPv6 and network info
Bug#38218 * src/process.c (Fnetwork_interface_list): Extend argument list to allow requesting full network info and/or IPv4/IPv6 info. (network_interface_list) [HAVE_GETIFADDRS]: Use getifaddrs to retrieve interface IP addresses. * src/process.h: Update prototype of network_interface_list. * src/w32.c (g_b_init_get_adapters_addresses): New init flag. (globals_of_w32): Initialize it. (GetAdaptersAddresses_Proc): New function typedef. (get_adapters_addresses): New wrapper function. (init_winsock): Load htonl and ntohl. (sys_htonl, sys_ntohl): New wrapper functions. (network_interface_list): Implement in terms of get_adapters_addresses. * nt/inc/sys/socket.h: Add sys_htonl and sys_ntohl prototypes. * etc/NEWS: Announce IPv4/IPv6 changes in network-interface-list. * doc/lispref/processes.texi (Misc Network): Document updated arglist and return values for network-interface-list.
This commit is contained in:
parent
5c3d0cf791
commit
650a514e99
7 changed files with 423 additions and 74 deletions
|
@ -2971,12 +2971,67 @@ non-@code{nil} if that particular network option is supported by
|
|||
on network connections. Note that they are supported only on some
|
||||
systems.
|
||||
|
||||
@defun network-interface-list
|
||||
This function returns a list describing the network interfaces
|
||||
of the machine you are using. The value is an alist whose
|
||||
elements have the form @code{(@var{name} . @var{address})}.
|
||||
@var{address} has the same form as the @var{local-address}
|
||||
and @var{remote-address} arguments to @code{make-network-process}.
|
||||
@defun network-interface-list &optional full family
|
||||
This function returns a list describing the network interfaces of the
|
||||
machine you are using. The value is an alist whose elements have the
|
||||
form @code{(@var{ifname} . @var{address})}. @var{ifname} is a string
|
||||
naming the interface, @var{address} has the same form as the
|
||||
@var{local-address} and @var{remote-address} arguments to
|
||||
@code{make-network-process}, i.e. a vector of integers. By default
|
||||
both IPv4 and IPv6 addresses are returned if possible.
|
||||
|
||||
Optional argument @var{full} non-@code{nil} means to instead return a
|
||||
list of one or more elements of the form @w{@code{(@var{ifname}
|
||||
@var{addr} @var{bcast} @var{netmask})}}. @var{ifname} is a non-unique
|
||||
string naming the interface. @var{addr}, @var{bcast}, and
|
||||
@var{netmask} are vectors of integers detailing the IP address,
|
||||
broadcast address, and network mask.
|
||||
|
||||
Optional argument @var{family} specified as symbol @code{ipv4} or
|
||||
@code{ipv6} restricts the returned information to IPv4 and IPv6
|
||||
addresses respectively, independently of the value of @var{full}.
|
||||
Speficying @code{ipv6} when IPv6 support is not available will result
|
||||
in an error being signaled.
|
||||
|
||||
Some examples:
|
||||
|
||||
@example
|
||||
(network-interface-list) @result{}
|
||||
(("vmnet8" .
|
||||
[172 16 76 1 0])
|
||||
("vmnet1" .
|
||||
[172 16 206 1 0])
|
||||
("lo0" .
|
||||
[65152 0 0 0 0 0 0 1 0])
|
||||
("lo0" .
|
||||
[0 0 0 0 0 0 0 1 0])
|
||||
("lo0" .
|
||||
[127 0 0 1 0]))
|
||||
@end example
|
||||
|
||||
@example
|
||||
(network-interface-list t) @result{}
|
||||
(("vmnet8"
|
||||
[172 16 76 1 0]
|
||||
[172 16 76 255 0]
|
||||
[255 255 255 0 0])
|
||||
("vmnet1"
|
||||
[172 16 206 1 0]
|
||||
[172 16 206 255 0]
|
||||
[255 255 255 0 0])
|
||||
("lo0"
|
||||
[65152 0 0 0 0 0 0 1 0]
|
||||
[65152 0 0 0 65535 65535 65535 65535 0]
|
||||
[65535 65535 65535 65535 0 0 0 0 0])
|
||||
("lo0"
|
||||
[0 0 0 0 0 0 0 1 0]
|
||||
[0 0 0 0 0 0 0 1 0]
|
||||
[65535 65535 65535 65535 65535 65535 65535 65535 0])
|
||||
("lo0"
|
||||
[127 0 0 1 0]
|
||||
[127 255 255 255 0]
|
||||
[255 0 0 0 0]))
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
@defun network-interface-info ifname
|
||||
|
@ -2996,6 +3051,8 @@ The layer 2 address (Ethernet MAC address, for instance).
|
|||
@item flags
|
||||
The current flags of the interface.
|
||||
@end table
|
||||
|
||||
Note that this function returns only IPv4 information.
|
||||
@end defun
|
||||
|
||||
@defun format-network-address address &optional omit-port
|
||||
|
|
5
etc/NEWS
5
etc/NEWS
|
@ -240,6 +240,11 @@ in addition to the decimal/hex/octal representation. Default nil.
|
|||
** New function 'network-lookup-address-info'.
|
||||
This does IPv4 and/or IPv6 address lookups on hostnames.
|
||||
|
||||
+++
|
||||
** 'network-interface-list' can now return IPv4 and IPv6 addresses.
|
||||
IPv4 and IPv6 addresses are now returned by default if available,
|
||||
optionally including netmask/broadcast address information.
|
||||
|
||||
---
|
||||
** Control of the threshold for using the 'distant-foreground' color.
|
||||
The threshold for color distance below which the 'distant-foreground'
|
||||
|
|
|
@ -228,21 +228,22 @@ host address is a localhost address, or in the same subnet as one
|
|||
of the local interfaces, this function returns nil. Non-nil
|
||||
otherwise."
|
||||
(let ((addresses (network-lookup-address-info host))
|
||||
(network-interface-list (network-interface-list))
|
||||
(network-interface-list (network-interface-list t))
|
||||
(off-net t))
|
||||
(when
|
||||
(or (and (functionp nsm-trust-local-network)
|
||||
(funcall nsm-trust-local-network))
|
||||
nsm-trust-local-network)
|
||||
(mapc
|
||||
(lambda (address)
|
||||
(lambda (ip)
|
||||
(mapc
|
||||
(lambda (iface)
|
||||
(let ((info (network-interface-info (car iface))))
|
||||
(lambda (info)
|
||||
(let ((local-ip (nth 1 info))
|
||||
(mask (nth 2 info)))
|
||||
(when
|
||||
(nsm-network-same-subnet (substring (car info) 0 -1)
|
||||
(substring (car (cddr info)) 0 -1)
|
||||
(substring address 0 -1))
|
||||
(nsm-network-same-subnet (substring local-ip 0 -1)
|
||||
(substring mask 0 -1)
|
||||
(substring ip 0 -1))
|
||||
(setq off-net nil))))
|
||||
network-interface-list))
|
||||
addresses))
|
||||
|
|
|
@ -92,6 +92,8 @@ typedef unsigned short uint16_t;
|
|||
#define connect sys_connect
|
||||
#define htons sys_htons
|
||||
#define ntohs sys_ntohs
|
||||
#define htonl sys_htonl
|
||||
#define ntohl sys_ntohl
|
||||
#define inet_addr sys_inet_addr
|
||||
#define gethostname sys_gethostname
|
||||
#define gethostbyname sys_gethostbyname
|
||||
|
@ -112,6 +114,8 @@ int sys_bind (int s, const struct sockaddr *addr, int namelen);
|
|||
int sys_connect (int s, const struct sockaddr *addr, int namelen);
|
||||
u_short sys_htons (u_short hostshort);
|
||||
u_short sys_ntohs (u_short netshort);
|
||||
u_long sys_htonl (u_long hostlong);
|
||||
u_long sys_ntohl (u_long netlong);
|
||||
unsigned long sys_inet_addr (const char * cp);
|
||||
int sys_gethostname (char * name, int namelen);
|
||||
struct hostent * sys_gethostbyname (const char * name);
|
||||
|
|
158
src/process.c
158
src/process.c
|
@ -4255,73 +4255,86 @@ usage: (make-network-process &rest ARGS) */)
|
|||
}
|
||||
|
||||
|
||||
#ifdef HAVE_NET_IF_H
|
||||
|
||||
#ifdef SIOCGIFCONF
|
||||
#ifdef HAVE_GETIFADDRS
|
||||
static Lisp_Object
|
||||
network_interface_list (void)
|
||||
network_interface_list (bool full, unsigned short match)
|
||||
{
|
||||
struct ifconf ifconf;
|
||||
struct ifreq *ifreq;
|
||||
void *buf = NULL;
|
||||
ptrdiff_t buf_size = 512;
|
||||
int s;
|
||||
Lisp_Object res;
|
||||
ptrdiff_t count;
|
||||
Lisp_Object res = Qnil;
|
||||
struct ifaddrs *ifap;
|
||||
|
||||
s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
if (s < 0)
|
||||
if (getifaddrs (&ifap) == -1)
|
||||
return Qnil;
|
||||
count = SPECPDL_INDEX ();
|
||||
record_unwind_protect_int (close_file_unwind, s);
|
||||
|
||||
do
|
||||
for (struct ifaddrs *it = ifap; it != NULL; it = it->ifa_next)
|
||||
{
|
||||
buf = xpalloc (buf, &buf_size, 1, INT_MAX, 1);
|
||||
ifconf.ifc_buf = buf;
|
||||
ifconf.ifc_len = buf_size;
|
||||
if (ioctl (s, SIOCGIFCONF, &ifconf))
|
||||
{
|
||||
emacs_close (s);
|
||||
xfree (buf);
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
while (ifconf.ifc_len == buf_size);
|
||||
int len;
|
||||
int addr_len;
|
||||
uint32_t *maskp;
|
||||
uint32_t *addrp;
|
||||
Lisp_Object elt = Qnil;
|
||||
|
||||
res = unbind_to (count, Qnil);
|
||||
ifreq = ifconf.ifc_req;
|
||||
while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len)
|
||||
{
|
||||
struct ifreq *ifq = ifreq;
|
||||
#ifdef HAVE_STRUCT_IFREQ_IFR_ADDR_SA_LEN
|
||||
#define SIZEOF_IFREQ(sif) \
|
||||
((sif)->ifr_addr.sa_len < sizeof (struct sockaddr) \
|
||||
? sizeof (*(sif)) : sizeof ((sif)->ifr_name) + (sif)->ifr_addr.sa_len)
|
||||
|
||||
int len = SIZEOF_IFREQ (ifq);
|
||||
#else
|
||||
int len = sizeof (*ifreq);
|
||||
/* BSD can allegedly return interfaces with a NULL address. */
|
||||
if (it->ifa_addr == NULL)
|
||||
continue;
|
||||
if (match && it->ifa_addr->sa_family != match)
|
||||
continue;
|
||||
if (it->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
DECLARE_POINTER_ALIAS (sin1, struct sockaddr_in, it->ifa_netmask);
|
||||
maskp = (uint32_t *)&sin1->sin_addr;
|
||||
DECLARE_POINTER_ALIAS (sin2, struct sockaddr_in, it->ifa_addr);
|
||||
addrp = (uint32_t *)&sin2->sin_addr;
|
||||
len = sizeof (struct sockaddr_in);
|
||||
addr_len = 1;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (it->ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
DECLARE_POINTER_ALIAS (sin6_1, struct sockaddr_in6, it->ifa_netmask);
|
||||
maskp = (uint32_t *) &sin6_1->sin6_addr;
|
||||
DECLARE_POINTER_ALIAS (sin6_2, struct sockaddr_in6, it->ifa_addr);
|
||||
addrp = (uint32_t *) &sin6_2->sin6_addr;
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
addr_len = 4;
|
||||
}
|
||||
#endif
|
||||
char namebuf[sizeof (ifq->ifr_name) + 1];
|
||||
ifreq = (struct ifreq *) ((char *) ifreq + len);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (ifq->ifr_addr.sa_family != AF_INET)
|
||||
continue;
|
||||
Lisp_Object addr = conv_sockaddr_to_lisp (it->ifa_addr, len);
|
||||
|
||||
memcpy (namebuf, ifq->ifr_name, 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);
|
||||
if (full)
|
||||
{
|
||||
elt = Fcons (conv_sockaddr_to_lisp (it->ifa_netmask, len), elt);
|
||||
/* There is an it->ifa_broadaddr field, but its contents are
|
||||
unreliable, so always calculate the broadcast address from
|
||||
the address and the netmask. */
|
||||
int i;
|
||||
uint32_t mask;
|
||||
for (i = 0; i < addr_len; i++)
|
||||
{
|
||||
mask = maskp[i];
|
||||
maskp[i] = (addrp[i] & mask) | ~mask;
|
||||
}
|
||||
elt = Fcons (conv_sockaddr_to_lisp (it->ifa_netmask, len), elt);
|
||||
elt = Fcons (addr, elt);
|
||||
}
|
||||
else
|
||||
{
|
||||
elt = addr;
|
||||
}
|
||||
res = Fcons (Fcons (build_string (it->ifa_name), elt), res);
|
||||
}
|
||||
#ifdef HAVE_FREEIFADDRS
|
||||
freeifaddrs (ifap);
|
||||
#endif
|
||||
|
||||
xfree (buf);
|
||||
return res;
|
||||
}
|
||||
#endif /* SIOCGIFCONF */
|
||||
#endif /* HAVE_GETIFADDRS */
|
||||
|
||||
#ifdef HAVE_NET_IF_H
|
||||
#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
|
||||
|
||||
struct ifflag_def {
|
||||
|
@ -4550,17 +4563,46 @@ network_interface_info (Lisp_Object ifname)
|
|||
#endif /* defined (HAVE_NET_IF_H) */
|
||||
|
||||
DEFUN ("network-interface-list", Fnetwork_interface_list,
|
||||
Snetwork_interface_list, 0, 0, 0,
|
||||
Snetwork_interface_list, 0, 2, 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'.
|
||||
Each element is cons of the form (IFNAME . IP) where IFNAME is a
|
||||
string containing the interface name, and IP is the network address in
|
||||
internal format; see the description of ADDRESS in
|
||||
`make-network-process'. The interface name is not guaranteed to be
|
||||
unique.
|
||||
|
||||
Optional parameter FULL non-nil means return all IP address info for
|
||||
each interface. Each element is then a list of the form
|
||||
(IFNAME IP BCAST MASK)
|
||||
where IFNAME is the interface name, IP the IP address,
|
||||
BCAST the broadcast address, and MASK the network mask.
|
||||
|
||||
Optional parameter FAMILY controls the type of addresses to return.
|
||||
The default of nil means both IPv4 and IPv6, symbol `ipv4' means IPv4
|
||||
only, symbol `ipv6' means IPv6 only.
|
||||
|
||||
See also `network-interface-info', which is limited to IPv4 only.
|
||||
|
||||
If the information is not available, return nil. */)
|
||||
(void)
|
||||
(Lisp_Object full, Lisp_Object family)
|
||||
{
|
||||
#if (defined HAVE_NET_IF_H && defined SIOCGIFCONF) || defined WINDOWSNT
|
||||
return network_interface_list ();
|
||||
#if defined HAVE_GETIFADDRS || defined WINDOWSNT
|
||||
unsigned short match;
|
||||
bool full_info = false;
|
||||
|
||||
if (! NILP (full))
|
||||
full_info = true;
|
||||
if (NILP (family))
|
||||
match = 0;
|
||||
else if (EQ (family, Qipv4))
|
||||
match = AF_INET;
|
||||
#ifdef AF_INET6
|
||||
else if (EQ (family, Qipv6))
|
||||
match = AF_INET6;
|
||||
#endif
|
||||
else
|
||||
error ("Unsupported address family");
|
||||
return network_interface_list (full_info, match);
|
||||
#else
|
||||
return Qnil;
|
||||
#endif
|
||||
|
|
|
@ -291,7 +291,7 @@ extern void catch_child_signal (void);
|
|||
extern void restore_nofile_limit (void);
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
extern Lisp_Object network_interface_list (void);
|
||||
extern Lisp_Object network_interface_list (bool full, unsigned short match);
|
||||
extern Lisp_Object network_interface_info (Lisp_Object);
|
||||
#endif
|
||||
|
||||
|
|
244
src/w32.c
244
src/w32.c
|
@ -227,6 +227,8 @@ typedef struct _REPARSE_DATA_BUFFER {
|
|||
#undef connect
|
||||
#undef htons
|
||||
#undef ntohs
|
||||
#undef htonl
|
||||
#undef ntohl
|
||||
#undef inet_addr
|
||||
#undef gethostname
|
||||
#undef gethostbyname
|
||||
|
@ -326,6 +328,7 @@ static BOOL g_b_init_set_file_security_a;
|
|||
static BOOL g_b_init_set_named_security_info_w;
|
||||
static BOOL g_b_init_set_named_security_info_a;
|
||||
static BOOL g_b_init_get_adapters_info;
|
||||
static BOOL g_b_init_get_adapters_addresses;
|
||||
static BOOL g_b_init_reg_open_key_ex_w;
|
||||
static BOOL g_b_init_reg_query_value_ex_w;
|
||||
static BOOL g_b_init_expand_environment_strings_w;
|
||||
|
@ -503,6 +506,12 @@ typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
|
|||
typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
|
||||
PIP_ADAPTER_INFO pAdapterInfo,
|
||||
PULONG pOutBufLen);
|
||||
typedef DWORD (WINAPI *GetAdaptersAddresses_Proc) (
|
||||
ULONG,
|
||||
ULONG,
|
||||
PVOID,
|
||||
PIP_ADAPTER_ADDRESSES,
|
||||
PULONG);
|
||||
|
||||
int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
|
||||
int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
|
||||
|
@ -1368,6 +1377,31 @@ get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
|
|||
return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen);
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
get_adapters_addresses (ULONG family, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen)
|
||||
{
|
||||
static GetAdaptersAddresses_Proc s_pfn_Get_Adapters_Addresses = NULL;
|
||||
HMODULE hm_iphlpapi = NULL;
|
||||
|
||||
if (is_windows_9x () == TRUE)
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
|
||||
if (g_b_init_get_adapters_addresses == 0)
|
||||
{
|
||||
g_b_init_get_adapters_addresses = 1;
|
||||
hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
|
||||
if (hm_iphlpapi)
|
||||
s_pfn_Get_Adapters_Addresses = (GetAdaptersAddresses_Proc)
|
||||
get_proc_addr (hm_iphlpapi, "GetAdaptersAddresses");
|
||||
}
|
||||
if (s_pfn_Get_Adapters_Addresses == NULL)
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
ULONG flags = GAA_FLAG_SKIP_ANYCAST
|
||||
| GAA_FLAG_SKIP_MULTICAST
|
||||
| GAA_FLAG_SKIP_DNS_SERVER;
|
||||
return s_pfn_Get_Adapters_Addresses (family, flags, NULL, pAdapterAddresses, pOutBufLen);
|
||||
}
|
||||
|
||||
static LONG WINAPI
|
||||
reg_open_key_ex_w (HKEY hkey, LPCWSTR lpSubKey, DWORD ulOptions,
|
||||
REGSAM samDesired, PHKEY phkResult)
|
||||
|
@ -7414,6 +7448,8 @@ int (PASCAL *pfn_WSACleanup) (void);
|
|||
|
||||
u_short (PASCAL *pfn_htons) (u_short hostshort);
|
||||
u_short (PASCAL *pfn_ntohs) (u_short netshort);
|
||||
u_long (PASCAL *pfn_htonl) (u_long hostlong);
|
||||
u_long (PASCAL *pfn_ntohl) (u_long netlong);
|
||||
unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
|
||||
int (PASCAL *pfn_gethostname) (char * name, int namelen);
|
||||
struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
|
||||
|
@ -7504,6 +7540,8 @@ init_winsock (int load_now)
|
|||
LOAD_PROC (shutdown);
|
||||
LOAD_PROC (htons);
|
||||
LOAD_PROC (ntohs);
|
||||
LOAD_PROC (htonl);
|
||||
LOAD_PROC (ntohl);
|
||||
LOAD_PROC (inet_addr);
|
||||
LOAD_PROC (gethostname);
|
||||
LOAD_PROC (gethostbyname);
|
||||
|
@ -7884,6 +7922,19 @@ sys_ntohs (u_short netshort)
|
|||
return (winsock_lib != NULL) ?
|
||||
pfn_ntohs (netshort) : netshort;
|
||||
}
|
||||
u_long
|
||||
sys_htonl (u_long hostlong)
|
||||
{
|
||||
return (winsock_lib != NULL) ?
|
||||
pfn_htonl (hostlong) : hostlong;
|
||||
}
|
||||
|
||||
u_long
|
||||
sys_ntohl (u_long netlong)
|
||||
{
|
||||
return (winsock_lib != NULL) ?
|
||||
pfn_ntohl (netlong) : netlong;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
sys_inet_addr (const char * cp)
|
||||
|
@ -9382,9 +9433,197 @@ network_interface_get_info (Lisp_Object ifname)
|
|||
}
|
||||
|
||||
Lisp_Object
|
||||
network_interface_list (void)
|
||||
network_interface_list (bool full, unsigned short match)
|
||||
{
|
||||
return network_interface_get_info (Qnil);
|
||||
ULONG ainfo_len = sizeof (IP_ADAPTER_ADDRESSES);
|
||||
ULONG family = match;
|
||||
IP_ADAPTER_ADDRESSES *adapter, *ainfo = xmalloc (ainfo_len);
|
||||
DWORD retval = get_adapters_addresses (family, ainfo, &ainfo_len);
|
||||
Lisp_Object res = Qnil;
|
||||
|
||||
if (retval == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
ainfo = xrealloc (ainfo, ainfo_len);
|
||||
retval = get_adapters_addresses (family, ainfo, &ainfo_len);
|
||||
}
|
||||
|
||||
if (retval != ERROR_SUCCESS)
|
||||
{
|
||||
xfree (ainfo);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* For the below, we need some winsock functions, so make sure
|
||||
the winsock DLL is loaded. If we cannot successfully load
|
||||
it, they will have no use of the information we provide,
|
||||
anyway, so punt. */
|
||||
if (!winsock_lib && !init_winsock (1))
|
||||
return res;
|
||||
|
||||
int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
|
||||
int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
|
||||
int tnl_count = 0;
|
||||
int if_num;
|
||||
char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
|
||||
static const char *ifmt[] = {
|
||||
"eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
|
||||
"lo%d", "ifx%d", "tunnel%d"
|
||||
};
|
||||
enum {
|
||||
NONE = -1,
|
||||
ETHERNET = 0,
|
||||
TOKENRING = 1,
|
||||
FDDI = 2,
|
||||
PPP = 3,
|
||||
SLIP = 4,
|
||||
WLAN = 5,
|
||||
LOOPBACK = 6,
|
||||
OTHER_IF = 7,
|
||||
TUNNEL = 8
|
||||
} ifmt_idx;
|
||||
|
||||
for (adapter = ainfo; adapter; adapter = adapter->Next)
|
||||
{
|
||||
|
||||
/* Present Unix-compatible interface names, instead of the
|
||||
Windows names, which are really GUIDs not readable by
|
||||
humans. */
|
||||
|
||||
switch (adapter->IfType)
|
||||
{
|
||||
case IF_TYPE_ETHERNET_CSMACD:
|
||||
ifmt_idx = ETHERNET;
|
||||
if_num = eth_count++;
|
||||
break;
|
||||
case IF_TYPE_ISO88025_TOKENRING:
|
||||
ifmt_idx = TOKENRING;
|
||||
if_num = tr_count++;
|
||||
break;
|
||||
case IF_TYPE_FDDI:
|
||||
ifmt_idx = FDDI;
|
||||
if_num = fddi_count++;
|
||||
break;
|
||||
case IF_TYPE_PPP:
|
||||
ifmt_idx = PPP;
|
||||
if_num = ppp_count++;
|
||||
break;
|
||||
case IF_TYPE_SLIP:
|
||||
ifmt_idx = SLIP;
|
||||
if_num = sl_count++;
|
||||
break;
|
||||
case IF_TYPE_IEEE80211:
|
||||
ifmt_idx = WLAN;
|
||||
if_num = wlan_count++;
|
||||
break;
|
||||
case IF_TYPE_SOFTWARE_LOOPBACK:
|
||||
ifmt_idx = LOOPBACK;
|
||||
if_num = lo_count++;
|
||||
break;
|
||||
case IF_TYPE_TUNNEL:
|
||||
ifmt_idx = TUNNEL;
|
||||
if_num = tnl_count++;
|
||||
break;
|
||||
default:
|
||||
ifmt_idx = OTHER_IF;
|
||||
if_num = ifx_count++;
|
||||
break;
|
||||
}
|
||||
sprintf (namebuf, ifmt[ifmt_idx], if_num);
|
||||
|
||||
IP_ADAPTER_UNICAST_ADDRESS *address;
|
||||
for (address = adapter->FirstUnicastAddress; address; address = address->Next)
|
||||
{
|
||||
int len;
|
||||
int addr_len;
|
||||
uint32_t *maskp;
|
||||
uint32_t *addrp;
|
||||
Lisp_Object elt = Qnil;
|
||||
struct sockaddr *ifa_addr = address->Address.lpSockaddr;
|
||||
|
||||
if (ifa_addr == NULL)
|
||||
continue;
|
||||
if (match && ifa_addr->sa_family != match)
|
||||
continue;
|
||||
|
||||
struct sockaddr_in ipv4;
|
||||
#ifdef AF_INET6
|
||||
struct sockaddr_in6 ipv6;
|
||||
#endif
|
||||
struct sockaddr *sin;
|
||||
|
||||
if (ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
ipv4.sin_family = AF_INET;
|
||||
ipv4.sin_port = 0;
|
||||
DECLARE_POINTER_ALIAS (sin_in, struct sockaddr_in, ifa_addr);
|
||||
addrp = (uint32_t *)&sin_in->sin_addr;
|
||||
maskp = (uint32_t *)&ipv4.sin_addr;
|
||||
sin = (struct sockaddr *)&ipv4;
|
||||
len = sizeof (struct sockaddr_in);
|
||||
addr_len = 1;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if (ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
ipv6.sin6_family = AF_INET6;
|
||||
ipv6.sin6_port = 0;
|
||||
DECLARE_POINTER_ALIAS (sin_in6, struct sockaddr_in6, ifa_addr);
|
||||
addrp = (uint32_t *)&sin_in6->sin6_addr;
|
||||
maskp = (uint32_t *)&ipv6.sin6_addr;
|
||||
sin = (struct sockaddr *)&ipv6;
|
||||
len = sizeof (struct sockaddr_in6);
|
||||
addr_len = 4;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
continue;
|
||||
|
||||
Lisp_Object addr = conv_sockaddr_to_lisp (ifa_addr, len);
|
||||
|
||||
if (full)
|
||||
{
|
||||
/* GetAdaptersAddress returns information in network
|
||||
byte order, so convert from host to network order
|
||||
when generating the netmask. */
|
||||
int i;
|
||||
ULONG numbits = address->OnLinkPrefixLength;
|
||||
for (i = 0; i < addr_len; i++)
|
||||
{
|
||||
if (numbits >= 32)
|
||||
{
|
||||
maskp[i] = -1U;
|
||||
numbits -= 32;
|
||||
}
|
||||
else if (numbits)
|
||||
{
|
||||
maskp[i] = sys_htonl (-1U << (32 - numbits));
|
||||
numbits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
maskp[i] = 0;
|
||||
}
|
||||
}
|
||||
elt = Fcons (conv_sockaddr_to_lisp (sin, len), elt);
|
||||
uint32_t mask;
|
||||
for (i = 0; i < addr_len; i++)
|
||||
{
|
||||
mask = maskp[i];
|
||||
maskp[i] = (addrp[i] & mask) | ~mask;
|
||||
|
||||
}
|
||||
elt = Fcons (conv_sockaddr_to_lisp (sin, len), elt);
|
||||
elt = Fcons (addr, elt);
|
||||
}
|
||||
else
|
||||
{
|
||||
elt = addr;
|
||||
}
|
||||
res = Fcons (Fcons (build_string (namebuf), elt), res);
|
||||
}
|
||||
}
|
||||
xfree (ainfo);
|
||||
return res;
|
||||
}
|
||||
|
||||
Lisp_Object
|
||||
|
@ -10099,6 +10338,7 @@ globals_of_w32 (void)
|
|||
g_b_init_set_named_security_info_w = 0;
|
||||
g_b_init_set_named_security_info_a = 0;
|
||||
g_b_init_get_adapters_info = 0;
|
||||
g_b_init_get_adapters_addresses = 0;
|
||||
g_b_init_reg_open_key_ex_w = 0;
|
||||
g_b_init_reg_query_value_ex_w = 0;
|
||||
g_b_init_expand_environment_strings_w = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue