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"
|
#include "precomp.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <iptypes.h>
|
||||||
#include <ws2ipdef.h>
|
#include <ws2ipdef.h>
|
||||||
#endif
|
#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
|
// 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
|
// In some cases, the interface will have multiple addresses, so we'll realloc
|
||||||
// this when necessary, but this will cover the common case.
|
// this when necessary, but this will cover the common case.
|
||||||
DWORD allocd_entries = 10;
|
DWORD allocd_entries = 20;
|
||||||
Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 10);
|
Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 20);
|
||||||
|
int prefixes[30];
|
||||||
|
int prefixes_cnt = 0;
|
||||||
|
|
||||||
DWORD mtu_bigendian;
|
DWORD mtu_bigendian;
|
||||||
DWORD interface_index_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;
|
LPSOCKADDR sockaddr;
|
||||||
|
|
||||||
|
@ -117,9 +123,15 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||||
ULONG outBufLen = 0;
|
ULONG outBufLen = 0;
|
||||||
DWORD (WINAPI *gaa)(DWORD, DWORD, void *, void *, void *);
|
DWORD (WINAPI *gaa)(DWORD, DWORD, void *, void *, void *);
|
||||||
|
|
||||||
// Use the larger version so we're guaranteed to have a large enough struct
|
// Use the newer version so we're guaranteed to have a large enough struct.
|
||||||
IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr;
|
// 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
|
do
|
||||||
{
|
{
|
||||||
|
@ -170,47 +182,75 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||||
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
|
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
|
||||||
tlv_cnt++;
|
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)
|
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.
|
sockaddr = pAddr->Address.lpSockaddr;
|
||||||
// Go ahead and allocate enough room for all of them.
|
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) {
|
if (allocd_entries < tlv_cnt+3) {
|
||||||
entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
|
entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3));
|
||||||
allocd_entries += 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) {
|
if (sockaddr->sa_family == AF_INET) {
|
||||||
entries[tlv_cnt].header.length = 4;
|
entries[tlv_cnt].header.length = 4;
|
||||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||||
if (pCurr->Length > 68) {
|
|
||||||
tlv_cnt++;
|
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
entries[tlv_cnt].header.length = 16;
|
entries[tlv_cnt].header.length = 16;
|
||||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||||
|
|
||||||
tlv_cnt++;
|
tlv_cnt++;
|
||||||
|
|
||||||
entries[tlv_cnt].header.length = sizeof(DWORD);
|
entries[tlv_cnt].header.length = sizeof(DWORD);
|
||||||
entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE;
|
entries[tlv_cnt].header.type = TLV_TYPE_IP6_SCOPE;
|
||||||
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
|
entries[tlv_cnt].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
|
||||||
|
|
||||||
if (pCurr->Length > 68) {
|
|
||||||
tlv_cnt++;
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
tlv_cnt++;
|
|
||||||
}
|
|
||||||
// Add the interface group
|
// Add the interface group
|
||||||
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
|
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
|
||||||
entries, tlv_cnt);
|
entries, tlv_cnt);
|
||||||
|
@ -225,7 +265,7 @@ DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else /* _WIN32 */
|
||||||
int get_interfaces_linux(Remote *remote, Packet *response) {
|
int get_interfaces_linux(Remote *remote, Packet *response) {
|
||||||
struct ifaces_list *ifaces = NULL;
|
struct ifaces_list *ifaces = NULL;
|
||||||
int i;
|
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_META_TYPE_GROUP, \
|
||||||
TLV_TYPE_EXTENSION_STDAPI, \
|
TLV_TYPE_EXTENSION_STDAPI, \
|
||||||
1423)
|
1423)
|
||||||
|
#define TLV_TYPE_IP_PREFIX \
|
||||||
|
MAKE_CUSTOM_TLV( \
|
||||||
|
TLV_META_TYPE_UINT, \
|
||||||
|
TLV_TYPE_EXTENSION_STDAPI, \
|
||||||
|
1424)
|
||||||
|
|
||||||
#define TLV_TYPE_IP \
|
#define TLV_TYPE_IP \
|
||||||
MAKE_CUSTOM_TLV( \
|
MAKE_CUSTOM_TLV( \
|
||||||
TLV_META_TYPE_RAW, \
|
TLV_META_TYPE_RAW, \
|
||||||
|
|
|
@ -60,6 +60,7 @@ class Config
|
||||||
response.each(TLV_TYPE_NETWORK_INTERFACE) { |iface|
|
response.each(TLV_TYPE_NETWORK_INTERFACE) { |iface|
|
||||||
addrs = []
|
addrs = []
|
||||||
netmasks = []
|
netmasks = []
|
||||||
|
scopes = []
|
||||||
while (a = iface.get_tlv_value(TLV_TYPE_IP, addrs.length))
|
while (a = iface.get_tlv_value(TLV_TYPE_IP, addrs.length))
|
||||||
# Netmasks aren't tightly associated with addresses, they're
|
# Netmasks aren't tightly associated with addresses, they're
|
||||||
# just thrown all together in the interface TLV ordered to
|
# 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,
|
# GroupTlv type for addresses containing an address, a netmask,
|
||||||
# and possibly a scope.
|
# and possibly a scope.
|
||||||
n = iface.get_tlv_value(TLV_TYPE_NETMASK, addrs.length)
|
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)
|
addrs << Rex::Socket.addr_ntoa(a)
|
||||||
netmasks << Rex::Socket.addr_ntoa(n) if n
|
|
||||||
end
|
end
|
||||||
ifaces << Interface.new(
|
ifaces << Interface.new(
|
||||||
:index => iface.get_tlv_value(TLV_TYPE_INTERFACE_INDEX),
|
:index => iface.get_tlv_value(TLV_TYPE_INTERFACE_INDEX),
|
||||||
|
@ -77,7 +90,8 @@ class Config
|
||||||
:mtu => iface.get_tlv_value(TLV_TYPE_INTERFACE_MTU),
|
:mtu => iface.get_tlv_value(TLV_TYPE_INTERFACE_MTU),
|
||||||
:flags => iface.get_tlv_value(TLV_TYPE_INTERFACE_FLAGS),
|
:flags => iface.get_tlv_value(TLV_TYPE_INTERFACE_FLAGS),
|
||||||
:addrs => addrs,
|
:addrs => addrs,
|
||||||
:netmasks => netmasks
|
:netmasks => netmasks,
|
||||||
|
:scopes => scopes
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ class Interface
|
||||||
self.flags = opts[:flags]
|
self.flags = opts[:flags]
|
||||||
self.addrs = opts[:addrs]
|
self.addrs = opts[:addrs]
|
||||||
self.netmasks = opts[:netmasks]
|
self.netmasks = opts[:netmasks]
|
||||||
|
self.scopes = opts[:scopes]
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -108,10 +109,6 @@ class Interface
|
||||||
#
|
#
|
||||||
attr_accessor :mac_name
|
attr_accessor :mac_name
|
||||||
#
|
#
|
||||||
# The subnet mask associated with the IPv6 interface.
|
|
||||||
#
|
|
||||||
attr_accessor :netmask6
|
|
||||||
#
|
|
||||||
# The MTU associated with the interface.
|
# The MTU associated with the interface.
|
||||||
#
|
#
|
||||||
attr_accessor :mtu
|
attr_accessor :mtu
|
||||||
|
@ -119,7 +116,14 @@ class Interface
|
||||||
# The flags associated with the interface.
|
# The flags associated with the interface.
|
||||||
#
|
#
|
||||||
attr_accessor :flags
|
attr_accessor :flags
|
||||||
|
#
|
||||||
|
# An Array of netmasks. This will have the same number of elements as #addrs
|
||||||
|
#
|
||||||
attr_accessor :netmasks
|
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; 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_NETMASK = TLV_META_TYPE_RAW | 1421
|
||||||
TLV_TYPE_GATEWAY = TLV_META_TYPE_RAW | 1422
|
TLV_TYPE_GATEWAY = TLV_META_TYPE_RAW | 1422
|
||||||
TLV_TYPE_NETWORK_ROUTE = TLV_META_TYPE_GROUP | 1423
|
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_IP = TLV_META_TYPE_RAW | 1430
|
||||||
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
||||||
|
|
Loading…
Reference in New Issue