Return network prefixes when available
Solves #6525 on Vista+. Win2k still works using the old MIB method (which doesn't support ipv6). Win2k3 and XP are still busted for unknown reasons.unstable
parent
916f23fe4e
commit
9aaf6af072
Binary file not shown.
|
@ -1,6 +1,7 @@
|
|||
#include "precomp.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <iptypes.h>
|
||||
#include <ws2ipdef.h>
|
||||
#endif
|
||||
|
||||
|
@ -101,13 +102,18 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
|||
// index, name (description), MAC addr, mtu, flags, IP addr, netmask, maybe scope id
|
||||
// In some cases, the interface will have multiple addresses, so we'll realloc
|
||||
// this when necessary, but this will cover the common case.
|
||||
DWORD allocd_entries = 10;
|
||||
Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 10);
|
||||
DWORD allocd_entries = 20;
|
||||
Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 20);
|
||||
int prefixes[30];
|
||||
int prefixes_cnt = 0;
|
||||
|
||||
DWORD mtu_bigendian;
|
||||
DWORD interface_index_bigendian;
|
||||
|
||||
ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER;
|
||||
ULONG flags = GAA_FLAG_INCLUDE_PREFIX
|
||||
| GAA_FLAG_SKIP_DNS_SERVER
|
||||
| GAA_FLAG_SKIP_MULTICAST
|
||||
| GAA_FLAG_SKIP_ANYCAST;
|
||||
|
||||
LPSOCKADDR sockaddr;
|
||||
|
||||
|
@ -117,9 +123,15 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
|||
ULONG outBufLen = 0;
|
||||
DWORD (WINAPI *gaa)(DWORD, DWORD, void *, void *, void *);
|
||||
|
||||
// Use the larger version so we're guaranteed to have a large enough struct
|
||||
IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr;
|
||||
|
||||
// Use the newer version so we're guaranteed to have a large enough struct.
|
||||
// Unfortunately, using these probably means it won't compile on older
|
||||
// versions of Visual Studio. =(
|
||||
IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr = NULL;
|
||||
IP_ADAPTER_UNICAST_ADDRESS_LH *pPref = NULL;
|
||||
// IP_ADAPTER_PREFIX is only defined if NTDDI_VERSION > NTDDI_WINXP
|
||||
// Since we request older versions of things, we have to be explicit
|
||||
// when using newer structs.
|
||||
IP_ADAPTER_PREFIX_XP *pPrefix = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -170,46 +182,74 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
|||
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
|
||||
tlv_cnt++;
|
||||
|
||||
if (pCurr->Length > 68) {
|
||||
// Then this is a Longhorn struct version and it contains the
|
||||
// FirstPrefix member, save it for later in case we don't have
|
||||
// an OnLinkPrefixLength
|
||||
pPrefix = pCurr->FirstPrefix;
|
||||
}
|
||||
|
||||
for (pAddr = (void*)pCurr->FirstUnicastAddress; pAddr; pAddr = (void*)pAddr->Next)
|
||||
{
|
||||
// This loop can add up to three Tlv's - one for address, one for scope_id, one for netmask.
|
||||
// Go ahead and allocate enough room for all of them.
|
||||
sockaddr = pAddr->Address.lpSockaddr;
|
||||
if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family) {
|
||||
// Skip interfaces that aren't IP
|
||||
continue;
|
||||
}
|
||||
|
||||
// This loop can add up to three Tlv's - one for address, one
|
||||
// for scope_id, one for netmask. Go ahead and allocate enough
|
||||
// room for all of them.
|
||||
if (allocd_entries < tlv_cnt+3) {
|
||||
entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
|
||||
allocd_entries += 3;
|
||||
}
|
||||
|
||||
sockaddr = pAddr->Address.lpSockaddr;
|
||||
if (pAddr->Length > 44) {
|
||||
// Then this is Vista+ and the OnLinkPrefixLength member
|
||||
// will be populated
|
||||
pPrefix = NULL;
|
||||
prefixes[prefixes_cnt] = htonl(pAddr->OnLinkPrefixLength);
|
||||
} else if (pPrefix) {
|
||||
// Otherwise, we have to walk the FirstPrefix linked list
|
||||
prefixes[prefixes_cnt] = htonl(pPrefix->PrefixLength);
|
||||
pPrefix = pPrefix->Next;
|
||||
} else {
|
||||
// This is XP SP0 and as far as I can tell, we have no way
|
||||
// of determining the netmask short of bailing on
|
||||
// this method and falling back to MIB, which doesn't
|
||||
// return IPv6 addresses. Older versions (e.g. NT4, 2k)
|
||||
// don't have GetAdapterAddresses, so they will have fallen
|
||||
// through earlier to the MIB implementation.
|
||||
}
|
||||
packet_add_tlv_uint(response, TLV_TYPE_EXIT_CODE, prefixes[prefixes_cnt]);
|
||||
|
||||
if (prefixes[prefixes_cnt]) {
|
||||
entries[tlv_cnt].header.length = 4;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP_PREFIX;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&prefixes[prefixes_cnt];
|
||||
tlv_cnt++;
|
||||
prefixes_cnt++;
|
||||
}
|
||||
|
||||
if (sockaddr->sa_family == AF_INET) {
|
||||
entries[tlv_cnt].header.length = 4;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||
if (pCurr->Length > 68) {
|
||||
tlv_cnt++;
|
||||
entries[tlv_cnt].header.length = 4;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||
}
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||
tlv_cnt++;
|
||||
|
||||
} else {
|
||||
entries[tlv_cnt].header.length = 16;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||
tlv_cnt++;
|
||||
|
||||
entries[tlv_cnt].header.length = sizeof(DWORD);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
|
||||
|
||||
if (pCurr->Length > 68) {
|
||||
tlv_cnt++;
|
||||
entries[tlv_cnt].header.length = 16;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||
}
|
||||
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
|
||||
tlv_cnt++;
|
||||
}
|
||||
tlv_cnt++;
|
||||
|
||||
}
|
||||
// Add the interface group
|
||||
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
|
||||
|
@ -225,7 +265,7 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
|||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* _WIN32 */
|
||||
int get_interfaces_linux(Remote *remote, Packet *response) {
|
||||
struct ifaces_list *ifaces = NULL;
|
||||
int i;
|
||||
|
@ -341,3 +381,5 @@ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -355,6 +355,12 @@
|
|||
TLV_META_TYPE_GROUP, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1423)
|
||||
#define TLV_TYPE_IP_PREFIX \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_UINT, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1424)
|
||||
|
||||
#define TLV_TYPE_IP \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
|
|
|
@ -60,6 +60,7 @@ class Config
|
|||
response.each(TLV_TYPE_NETWORK_INTERFACE) { |iface|
|
||||
addrs = []
|
||||
netmasks = []
|
||||
scopes = []
|
||||
while (a = iface.get_tlv_value(TLV_TYPE_IP, addrs.length))
|
||||
# Netmasks aren't tightly associated with addresses, they're
|
||||
# just thrown all together in the interface TLV ordered to
|
||||
|
@ -67,8 +68,20 @@ class Config
|
|||
# GroupTlv type for addresses containing an address, a netmask,
|
||||
# and possibly a scope.
|
||||
n = iface.get_tlv_value(TLV_TYPE_NETMASK, addrs.length)
|
||||
if (n.nil?)
|
||||
# Some systems can't report a netmask, only a network
|
||||
# prefix, so figure out the netmask from that.
|
||||
n = iface.get_tlv_value(TLV_TYPE_IP_PREFIX, addrs.length)
|
||||
if n
|
||||
n = Rex::Socket.bit2netmask(n, !!(a.length == 16))
|
||||
end
|
||||
else
|
||||
n = Rex::Socket.addr_ntoa(n)
|
||||
end
|
||||
s = iface.get_tlv_value(TLV_TYPE_IP6_SCOPE, addrs.length)
|
||||
scopes[addrs.length] = s if s
|
||||
netmasks[addrs.length] = n if n
|
||||
addrs << Rex::Socket.addr_ntoa(a)
|
||||
netmasks << Rex::Socket.addr_ntoa(n) if n
|
||||
end
|
||||
ifaces << Interface.new(
|
||||
:index => iface.get_tlv_value(TLV_TYPE_INTERFACE_INDEX),
|
||||
|
@ -77,7 +90,8 @@ class Config
|
|||
:mtu => iface.get_tlv_value(TLV_TYPE_INTERFACE_MTU),
|
||||
:flags => iface.get_tlv_value(TLV_TYPE_INTERFACE_FLAGS),
|
||||
:addrs => addrs,
|
||||
:netmasks => netmasks
|
||||
:netmasks => netmasks,
|
||||
:scopes => scopes
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class Interface
|
|||
self.flags = opts[:flags]
|
||||
self.addrs = opts[:addrs]
|
||||
self.netmasks = opts[:netmasks]
|
||||
self.scopes = opts[:scopes]
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -108,10 +109,6 @@ class Interface
|
|||
#
|
||||
attr_accessor :mac_name
|
||||
#
|
||||
# The subnet mask associated with the IPv6 interface.
|
||||
#
|
||||
attr_accessor :netmask6
|
||||
#
|
||||
# The MTU associated with the interface.
|
||||
#
|
||||
attr_accessor :mtu
|
||||
|
@ -119,7 +116,14 @@ class Interface
|
|||
# The flags associated with the interface.
|
||||
#
|
||||
attr_accessor :flags
|
||||
#
|
||||
# An Array of netmasks. This will have the same number of elements as #addrs
|
||||
#
|
||||
attr_accessor :netmasks
|
||||
#
|
||||
# An Array of IPv6 address scopes. This will have the same number of elements as #addrs
|
||||
#
|
||||
attr_accessor :scopes
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
||||
|
|
|
@ -51,6 +51,7 @@ TLV_TYPE_SUBNET = TLV_META_TYPE_RAW | 1420
|
|||
TLV_TYPE_NETMASK = TLV_META_TYPE_RAW | 1421
|
||||
TLV_TYPE_GATEWAY = TLV_META_TYPE_RAW | 1422
|
||||
TLV_TYPE_NETWORK_ROUTE = TLV_META_TYPE_GROUP | 1423
|
||||
TLV_TYPE_IP_PREFIX = TLV_META_TYPE_UINT | 1424
|
||||
|
||||
TLV_TYPE_IP = TLV_META_TYPE_RAW | 1430
|
||||
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
||||
|
|
Loading…
Reference in New Issue