Squashed commit of the following:
commit 8b4750d0dcbac0686f9403acdf5cab50c918212f Author: James Lee <egypt@metasploit.com> Date: Tue Mar 13 13:14:43 2012 -0600 Add bins for listing all addresses [Fixes #6476] commit 213dd92ebc9b706a45725e6515c7939d2edace0e Author: James Lee <egypt@metasploit.com> Date: Tue Mar 13 02:08:34 2012 -0600 Accept multiple addresses and netmasks [See #6476] commit 2e8bd3c3ecfb319bf9456485d2420bb5829b60cc Author: James Lee <egypt@metasploit.com> Date: Tue Mar 13 01:55:57 2012 -0600 Make inspecting meterpreter packets a little less painful Not sure why I originally thought there was no way to access extensions' constants before. A simple `require` makes it all happy. commit da367907cf579bd3aefaffbc84d2f96a41b85f00 Author: James Lee <egypt@metasploit.com> Date: Sun Mar 11 22:08:44 2012 -0600 Fix up Linux after changes for Windows commit ec9f04378b0155f69df95d4a94e62d33ce61977c Author: James Lee <egypt@metasploit.com> Date: Sun Mar 11 21:56:11 2012 -0600 Grab IPv6 addresses on Windows when possible Tries to GetProcAddress of GetAdaptersAddresses and falls back to the old GetIpAddrTable() function when it isn't available. This should work on XPSP1 and newer, albeit without netmasks on versions before Vista. Still trying to figure that one out. commit 1052ebdcf86114fbc03d1a37ab5d4c6a78e82daa Author: James Lee <egypt@metasploit.com> Date: Tue Mar 6 15:34:09 2012 -0700 Wrap Windows-specifc headers in ifdef commit f23f20587b3117c38a77e7e5a93d542411e9504f Author: James Lee <egypt@metasploit.com> Date: Tue Mar 6 14:36:34 2012 -0700 Handle multiple addrs on one iface on the ruby side commit d7207d075ac6462875d9da531cf20c175629a416 Author: James Lee <egypt@metasploit.com> Date: Mon Mar 5 21:57:39 2012 -0700 Adds IPv6 addrs to win32 get_interfaces response commit 11ae7e8a45bd56d25841ea8724377e0fb6789d72 Author: James Lee <egypt@metasploit.com> Date: Mon Mar 5 09:07:28 2012 -0700 Don't distinguish between 4 and 6. The client can figure it out from the length. commit 2c7490bdf3e4079f30857ee323d2ce23ab1bd9a5 Author: James Lee <egypt@metasploit.com> Date: Sun Mar 4 04:25:26 2012 -0700 Append to the list instead of assigning to it All addresses are being sent to the client now. Just need a way to parse them out correctly on the other side and meterpreter will be able to list all addresses on all interfaces on Linux. Next step is to allocate the proper number of TLVs to avoid good ol' stack smashes on systems with lots of addresses and then make sure we clean all the memory leaks. [See #6476] commit 73bba037ad968b922341c02459017afcc8407a76 Author: James Lee <egypt@metasploit.com> Date: Sun Mar 4 03:12:28 2012 -0700 Lay the groundwork for returning all addresses This commit only sends the last interface in the list, but it is looping through all of them as evidenced by the log, just need to make sure we're not overwriting as we go. [See #6476]unstable
parent
81248f35c4
commit
dd9ac8a6c0
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -37,16 +37,26 @@ typedef struct ___u128 {
|
|||
__u32 a4;
|
||||
}__u128;
|
||||
|
||||
struct iface_address {
|
||||
int family;
|
||||
union {
|
||||
__u32 addr;
|
||||
__u128 addr6;
|
||||
} ip;
|
||||
union {
|
||||
__u32 netmask;
|
||||
__u128 netmask6;
|
||||
} nm;
|
||||
};
|
||||
|
||||
struct iface_entry {
|
||||
unsigned char name[IFNAMSIZ+1];
|
||||
__u32 addr;
|
||||
__u32 netmask;
|
||||
unsigned char hwaddr[6];
|
||||
__u128 addr6;
|
||||
__u128 netmask6;
|
||||
uint32_t mtu;
|
||||
uint32_t index;
|
||||
unsigned char flags[FLAGS_LEN+1];
|
||||
int addr_count;
|
||||
struct iface_address *addr_list;
|
||||
};
|
||||
|
||||
struct ifaces_list {
|
||||
|
|
|
@ -1528,4 +1528,4 @@ DWORD packet_receive_via_http(Remote *remote, Packet **packet)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#include "precomp.h"
|
||||
|
||||
/*
|
||||
* Returns zero or more local interfaces to the requestor
|
||||
*/
|
||||
DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
||||
#ifdef _WIN32
|
||||
#include <ws2ipdef.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD get_interfaces_windows_mib(Remote *remote, Packet *response)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD entryCount;
|
||||
|
||||
#ifdef _WIN32
|
||||
Tlv entries[6];
|
||||
PMIB_IPADDRTABLE table = NULL;
|
||||
DWORD tableSize = sizeof(MIB_IPADDRROW) * 33;
|
||||
|
@ -35,26 +35,24 @@ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
|||
}
|
||||
|
||||
// Enumerate the entries
|
||||
for (index = 0;
|
||||
index < table->dwNumEntries;
|
||||
index++)
|
||||
for (index = 0; index < table->dwNumEntries; index++)
|
||||
{
|
||||
entryCount = 0;
|
||||
|
||||
interface_index_bigendian = htonl(table->table[index].dwIndex);
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_INTERFACE_INDEX;
|
||||
entries[entryCount].buffer = (PUCHAR)&interface_index_bigendian;
|
||||
entries[entryCount].header.type = TLV_TYPE_INTERFACE_INDEX;
|
||||
entries[entryCount].buffer = (PUCHAR)&interface_index_bigendian;
|
||||
entryCount++;
|
||||
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_IP;
|
||||
entries[entryCount].buffer = (PUCHAR)&table->table[index].dwAddr;
|
||||
entries[entryCount].header.type = TLV_TYPE_IP;
|
||||
entries[entryCount].buffer = (PUCHAR)&table->table[index].dwAddr;
|
||||
entryCount++;
|
||||
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_NETMASK;
|
||||
entries[entryCount].buffer = (PUCHAR)&table->table[index].dwMask;
|
||||
entries[entryCount].header.type = TLV_TYPE_NETMASK;
|
||||
entries[entryCount].buffer = (PUCHAR)&table->table[index].dwMask;
|
||||
entryCount++;
|
||||
|
||||
iface.dwIndex = table->table[index].dwIndex;
|
||||
|
@ -63,28 +61,28 @@ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
|||
if (GetIfEntry(&iface) == NO_ERROR)
|
||||
{
|
||||
entries[entryCount].header.length = iface.dwPhysAddrLen;
|
||||
entries[entryCount].header.type = TLV_TYPE_MAC_ADDR;
|
||||
entries[entryCount].buffer = (PUCHAR)iface.bPhysAddr;
|
||||
entries[entryCount].header.type = TLV_TYPE_MAC_ADDR;
|
||||
entries[entryCount].buffer = (PUCHAR)iface.bPhysAddr;
|
||||
entryCount++;
|
||||
|
||||
mtu_bigendian = htonl(iface.dwMtu);
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_INTERFACE_MTU;
|
||||
entries[entryCount].buffer = (PUCHAR)&mtu_bigendian;
|
||||
entries[entryCount].header.type = TLV_TYPE_INTERFACE_MTU;
|
||||
entries[entryCount].buffer = (PUCHAR)&mtu_bigendian;
|
||||
entryCount++;
|
||||
|
||||
if (iface.bDescr)
|
||||
{
|
||||
entries[entryCount].header.length = iface.dwDescrLen + 1;
|
||||
entries[entryCount].header.type = TLV_TYPE_MAC_NAME;
|
||||
entries[entryCount].buffer = (PUCHAR)iface.bDescr;
|
||||
entries[entryCount].header.type = TLV_TYPE_MAC_NAME;
|
||||
entries[entryCount].buffer = (PUCHAR)iface.bDescr;
|
||||
entryCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the interface group
|
||||
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
|
||||
entries, entryCount);
|
||||
entries, entryCount);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
@ -92,64 +90,249 @@ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
|||
if (table)
|
||||
free(table);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DWORD get_interfaces_windows(Remote *remote, Packet *response) {
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
DWORD entryCount;
|
||||
// Most of the time we'll need:
|
||||
// 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 mtu_bigendian;
|
||||
DWORD interface_index_bigendian;
|
||||
|
||||
ULONG flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_DNS_SERVER;
|
||||
|
||||
LPSOCKADDR sockaddr;
|
||||
|
||||
ULONG family = AF_UNSPEC;
|
||||
IP_ADAPTER_ADDRESSES *pAdapters = NULL;
|
||||
IP_ADAPTER_ADDRESSES *pCurr = NULL;
|
||||
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;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress(
|
||||
GetModuleHandle("iphlpapi"), "GetAdaptersAddresses"
|
||||
);
|
||||
if (!gaa) {
|
||||
result = get_interfaces_windows_mib(remote, response);
|
||||
|
||||
// --- DEBUG ---
|
||||
packet_add_tlv_uint(response, TLV_TYPE_EXIT_CODE, 666);
|
||||
// --- END DEBUG ---
|
||||
break;
|
||||
}
|
||||
|
||||
gaa(family, flags, NULL, pAdapters, &outBufLen);
|
||||
if (!(pAdapters = (IP_ADAPTER_ADDRESSES *)malloc(outBufLen)))
|
||||
{
|
||||
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||
break;
|
||||
}
|
||||
if (gaa(family, flags, NULL, pAdapters, &outBufLen))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
// Enumerate the entries
|
||||
for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next)
|
||||
{
|
||||
entryCount = 0;
|
||||
|
||||
interface_index_bigendian = htonl(pCurr->IfIndex);
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_INTERFACE_INDEX;
|
||||
entries[entryCount].buffer = (PUCHAR)&interface_index_bigendian;
|
||||
entryCount++;
|
||||
|
||||
entries[entryCount].header.length = pCurr->PhysicalAddressLength;
|
||||
entries[entryCount].header.type = TLV_TYPE_MAC_ADDR;
|
||||
entries[entryCount].buffer = (PUCHAR)pCurr->PhysicalAddress;
|
||||
entryCount++;
|
||||
|
||||
entries[entryCount].header.length = wcslen(pCurr->Description)*2 + 1;
|
||||
entries[entryCount].header.type = TLV_TYPE_MAC_NAME;
|
||||
entries[entryCount].buffer = (PUCHAR)pCurr->Description;
|
||||
entryCount++;
|
||||
|
||||
mtu_bigendian = htonl(pCurr->Mtu);
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_INTERFACE_MTU;
|
||||
entries[entryCount].buffer = (PUCHAR)&mtu_bigendian;
|
||||
entryCount++;
|
||||
|
||||
|
||||
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.
|
||||
if (allocd_entries < entryCount+3) {
|
||||
entries = realloc(entries, sizeof(Tlv) * (entryCount+3));
|
||||
allocd_entries += 3;
|
||||
}
|
||||
|
||||
sockaddr = pAddr->Address.lpSockaddr;
|
||||
if (sockaddr->sa_family == AF_INET) {
|
||||
entries[entryCount].header.length = 4;
|
||||
entries[entryCount].header.type = TLV_TYPE_IP;
|
||||
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||
if (pCurr->Length > 68) {
|
||||
|
||||
// --- DEBUG ---
|
||||
packet_add_tlv_uint(response, TLV_TYPE_EXIT_CODE, 1337);
|
||||
// --- END DEBUG ---
|
||||
|
||||
|
||||
entryCount++;
|
||||
entries[entryCount].header.length = 4;
|
||||
entries[entryCount].header.type = TLV_TYPE_NETMASK;
|
||||
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr);
|
||||
}
|
||||
} else {
|
||||
entries[entryCount].header.length = 16;
|
||||
entries[entryCount].header.type = TLV_TYPE_IP;
|
||||
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||
|
||||
entryCount++;
|
||||
entries[entryCount].header.length = sizeof(DWORD);
|
||||
entries[entryCount].header.type = TLV_TYPE_IP6_SCOPE;
|
||||
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id);
|
||||
|
||||
if (pCurr->Length > 68) {
|
||||
entryCount++;
|
||||
entries[entryCount].header.length = 16;
|
||||
entries[entryCount].header.type = TLV_TYPE_NETMASK;
|
||||
entries[entryCount].buffer = (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr);
|
||||
}
|
||||
|
||||
}
|
||||
entryCount++;
|
||||
}
|
||||
// Add the interface group
|
||||
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE,
|
||||
entries, entryCount);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (entries)
|
||||
free(entries);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
int get_interfaces_linux(Remote *remote, Packet *response) {
|
||||
struct ifaces_list *ifaces = NULL;
|
||||
int i;
|
||||
int if_error;
|
||||
int result;
|
||||
uint32_t interface_index_bigendian, mtu_bigendian;
|
||||
Tlv entries[9];
|
||||
// wild guess, should probably malloc
|
||||
Tlv entries[39];
|
||||
|
||||
if_error = netlink_get_interfaces(&ifaces);
|
||||
dprintf("Grabbing interfaces");
|
||||
result = netlink_get_interfaces(&ifaces);
|
||||
dprintf("Got 'em");
|
||||
|
||||
if (if_error) {
|
||||
result = if_error;
|
||||
} else {
|
||||
if (!result) {
|
||||
for (i = 0; i < ifaces->entries; i++) {
|
||||
int tlv_cnt = 0;
|
||||
int j = 0;
|
||||
dprintf("Building TLV for iface %d", i);
|
||||
|
||||
entries[0].header.length = strlen(ifaces->ifaces[i].name)+1;
|
||||
entries[0].header.type = TLV_TYPE_MAC_NAME;
|
||||
entries[0].buffer = (PUCHAR)ifaces->ifaces[i].name;
|
||||
entries[tlv_cnt].header.length = strlen(ifaces->ifaces[i].name)+1;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].name;
|
||||
tlv_cnt++;
|
||||
|
||||
entries[1].header.length = 6;
|
||||
entries[1].header.type = TLV_TYPE_MAC_ADDR;
|
||||
entries[1].buffer = (PUCHAR)ifaces->ifaces[i].hwaddr;
|
||||
entries[tlv_cnt].header.length = 6;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].hwaddr;
|
||||
tlv_cnt++;
|
||||
|
||||
entries[2].header.length = sizeof(__u32);
|
||||
entries[2].header.type = TLV_TYPE_IP;
|
||||
entries[2].buffer = (PUCHAR)&ifaces->ifaces[i].addr;
|
||||
for (j = 0; j < ifaces->ifaces[i].addr_count; j++) {
|
||||
if (ifaces->ifaces[i].addr_list[j].family == AF_INET) {
|
||||
dprintf("ip addr for %s", ifaces->ifaces[i].name);
|
||||
entries[tlv_cnt].header.length = sizeof(__u32);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].ip.addr;
|
||||
tlv_cnt++;
|
||||
|
||||
entries[3].header.length = sizeof(__u32);
|
||||
entries[3].header.type = TLV_TYPE_NETMASK;
|
||||
entries[3].buffer = (PUCHAR)&ifaces->ifaces[i].netmask;
|
||||
//dprintf("netmask for %s", ifaces->ifaces[i].name);
|
||||
entries[tlv_cnt].header.length = sizeof(__u32);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].nm.netmask;
|
||||
tlv_cnt++;
|
||||
} else {
|
||||
dprintf("-- ip six addr for %s", ifaces->ifaces[i].name);
|
||||
entries[tlv_cnt].header.length = sizeof(__u128);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_IP;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].ip.addr6;
|
||||
tlv_cnt++;
|
||||
|
||||
entries[4].header.length = sizeof(__u128);
|
||||
entries[4].header.type = TLV_TYPE_IP6;
|
||||
entries[4].buffer = (PUCHAR)&ifaces->ifaces[i].addr6;
|
||||
|
||||
entries[5].header.length = sizeof(__u128);
|
||||
entries[5].header.type = TLV_TYPE_NETMASK6;
|
||||
entries[5].buffer = (PUCHAR)&ifaces->ifaces[i].netmask6;
|
||||
//dprintf("netmask6 for %s", ifaces->ifaces[i].name);
|
||||
entries[tlv_cnt].header.length = sizeof(__u128);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_NETMASK;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&ifaces->ifaces[i].addr_list[j].nm.netmask6;
|
||||
tlv_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
mtu_bigendian = htonl(ifaces->ifaces[i].mtu);
|
||||
entries[6].header.length = sizeof(uint32_t);
|
||||
entries[6].header.type = TLV_TYPE_INTERFACE_MTU;
|
||||
entries[6].buffer = (PUCHAR)&mtu_bigendian;
|
||||
entries[tlv_cnt].header.length = sizeof(uint32_t);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian;
|
||||
tlv_cnt++;
|
||||
|
||||
entries[7].header.length = strlen(ifaces->ifaces[i].flags)+1;
|
||||
entries[7].header.type = TLV_TYPE_INTERFACE_FLAGS;
|
||||
entries[7].buffer = (PUCHAR)ifaces->ifaces[i].flags;
|
||||
entries[tlv_cnt].header.length = strlen(ifaces->ifaces[i].flags)+1;
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_FLAGS;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)ifaces->ifaces[i].flags;
|
||||
tlv_cnt++;
|
||||
|
||||
interface_index_bigendian = htonl(ifaces->ifaces[i].index);
|
||||
entries[8].header.length = sizeof(uint32_t);
|
||||
entries[8].header.type = TLV_TYPE_INTERFACE_INDEX;
|
||||
entries[8].buffer = (PUCHAR)&interface_index_bigendian;
|
||||
|
||||
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, 9);
|
||||
entries[tlv_cnt].header.length = sizeof(uint32_t);
|
||||
entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX;
|
||||
entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian;
|
||||
tlv_cnt++;
|
||||
|
||||
dprintf("Adding TLV to group");
|
||||
packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt);
|
||||
dprintf("done Adding TLV to group");
|
||||
}
|
||||
}
|
||||
|
||||
if (ifaces)
|
||||
free(ifaces);
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Returns zero or more local interfaces to the requestor
|
||||
*/
|
||||
DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
||||
{
|
||||
Packet *response = packet_create_response(packet);
|
||||
DWORD result = ERROR_SUCCESS;
|
||||
|
||||
#ifdef _WIN32
|
||||
result = get_interfaces_windows(remote, response);
|
||||
#else
|
||||
result = get_interfaces_linux(remote, response);
|
||||
#endif
|
||||
|
||||
// Transmit the response if valid
|
||||
|
@ -159,5 +342,3 @@ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -355,26 +355,6 @@
|
|||
TLV_META_TYPE_GROUP, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1423)
|
||||
#define TLV_TYPE_SUBNET6 \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1424)
|
||||
#define TLV_TYPE_NETMASK6 \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1425)
|
||||
#define TLV_TYPE_GATEWAY6 \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1426)
|
||||
#define TLV_TYPE_NETWORK_ROUTE6 \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_GROUP, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1427)
|
||||
#define TLV_TYPE_IP \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
|
@ -395,9 +375,9 @@
|
|||
TLV_META_TYPE_GROUP, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1433)
|
||||
#define TLV_TYPE_IP6 \
|
||||
#define TLV_TYPE_IP6_SCOPE \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_RAW, \
|
||||
TLV_META_TYPE_RAW, \
|
||||
TLV_TYPE_EXTENSION_STDAPI, \
|
||||
1434)
|
||||
|
||||
|
|
|
@ -158,8 +158,8 @@ int netlink_parse(int fd, int seq, netlink_cb_t callback, void *data)
|
|||
}
|
||||
|
||||
for(nh = (struct nlmsghdr *)(buf); NLMSG_OK(nh, len); nh = (struct nlmsghdr *) NLMSG_NEXT(nh, len)) {
|
||||
dprintf("buf = %p, nh = %p", buf, nh);
|
||||
dprintf("nh->nlmsg_type = %d", nh->nlmsg_type);
|
||||
//dprintf("buf = %p, nh = %p", buf, nh);
|
||||
//dprintf("nh->nlmsg_type = %d", nh->nlmsg_type);
|
||||
|
||||
if(nh->nlmsg_type == NLMSG_DONE) {
|
||||
end = 1;
|
||||
|
@ -168,12 +168,12 @@ int netlink_parse(int fd, int seq, netlink_cb_t callback, void *data)
|
|||
|
||||
if(nh->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *me = (struct nlmsgerr *) NLMSG_DATA (nh);
|
||||
dprintf("in NLMSG_ERROR handling.. me = %p");
|
||||
dprintf("me->error = %d", me->error);
|
||||
//dprintf("in NLMSG_ERROR handling.. me = %p", me);
|
||||
//dprintf("me->error = %d", me->error);
|
||||
if(me->error) {
|
||||
dprintf("so, we have: nlmsg_len: %d, nlmsg_type: %d, nlmsg_flags: %d, nlmsg_seq: %d, nlmsg_pid: %d",
|
||||
me->msg.nlmsg_len, me->msg.nlmsg_type, me->msg.nlmsg_flags,
|
||||
me->msg.nlmsg_seq, me->msg.nlmsg_pid);
|
||||
//dprintf("so, we have: nlmsg_len: %d, nlmsg_type: %d, nlmsg_flags: %d, nlmsg_seq: %d, nlmsg_pid: %d",
|
||||
// me->msg.nlmsg_len, me->msg.nlmsg_type, me->msg.nlmsg_flags,
|
||||
// me->msg.nlmsg_seq, me->msg.nlmsg_pid);
|
||||
|
||||
if(me->msg.nlmsg_seq == seq) {
|
||||
dprintf("Hum. kernel doesn't like our message :~(");
|
||||
|
@ -188,7 +188,7 @@ int netlink_parse(int fd, int seq, netlink_cb_t callback, void *data)
|
|||
|
||||
//
|
||||
|
||||
dprintf("[%s] dispatching into callback", __FUNCTION__);
|
||||
dprintf("dispatching into callback");
|
||||
|
||||
status = callback(nh, data);
|
||||
|
||||
|
@ -262,7 +262,7 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
dprintf("Adjusted rm at +4");
|
||||
}
|
||||
|
||||
dprintf("rtm_family : 0x%x , rtm_dst_len : 0x%x, rtm_src_len : 0x%x",rm->rtm_family, rm->rtm_dst_len, rm->rtm_src_len);
|
||||
//dprintf("rtm_family : 0x%x , rtm_dst_len : 0x%x, rtm_src_len : 0x%x",rm->rtm_family, rm->rtm_dst_len, rm->rtm_src_len);
|
||||
// print directly connected routes
|
||||
if(rm->rtm_type != RTN_UNICAST && rm->rtm_type != RTN_LOCAL) {
|
||||
dprintf("got %d instead of RTN_UNICAST (%d) or RTN_LOCAL (%d)", rm->rtm_type, RTN_UNICAST,RTN_LOCAL);
|
||||
|
@ -289,7 +289,7 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
else
|
||||
is_ipv6 = 1;
|
||||
|
||||
dprintf("nh->nlmsg_len: %d, NLMSG_LENGTH(sizeof(..)): %d, is_ipv6 : %d", nh->nlmsg_len, NLMSG_LENGTH(sizeof(struct rtmsg)),is_ipv6);
|
||||
//dprintf("nh->nlmsg_len: %d, NLMSG_LENGTH(sizeof(..)): %d, is_ipv6 : %d", nh->nlmsg_len, NLMSG_LENGTH(sizeof(struct rtmsg)),is_ipv6);
|
||||
|
||||
len = nh->nlmsg_len - NLMSG_LENGTH (sizeof(struct rtmsg));
|
||||
if(len <= 0) {
|
||||
|
@ -297,12 +297,12 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
dprintf("RTA_DST=%d, RTA_SRC=%d, RTA_GATEWAY=%d, RTA_PREFSRC=%d, RTA_OIF=%d, RTA_PRIORITY=%d", RTA_DST, RTA_SRC, RTA_GATEWAY, RTA_PREFSRC,RTA_OIF, RTA_PRIORITY);
|
||||
//dprintf("RTA_DST=%d, RTA_SRC=%d, RTA_GATEWAY=%d, RTA_PREFSRC=%d, RTA_OIF=%d, RTA_PRIORITY=%d", RTA_DST, RTA_SRC, RTA_GATEWAY, RTA_PREFSRC,RTA_OIF, RTA_PRIORITY);
|
||||
|
||||
|
||||
dprintf("rtm_table : %d, RT_TABLE_UNSPEC=%d, RT_TABLE_DEFAULT =%d, RT_TABLE_MAIN=%d,RT_TABLE_LOCAL=%d", rm->rtm_table,RT_TABLE_UNSPEC, RT_TABLE_DEFAULT , RT_TABLE_MAIN, RT_TABLE_LOCAL);
|
||||
//dprintf("rtm_table : %d, RT_TABLE_UNSPEC=%d, RT_TABLE_DEFAULT =%d, RT_TABLE_MAIN=%d,RT_TABLE_LOCAL=%d", rm->rtm_table,RT_TABLE_UNSPEC, RT_TABLE_DEFAULT , RT_TABLE_MAIN, RT_TABLE_LOCAL);
|
||||
|
||||
dprintf("rtm_type : %d, RTN_UNICAST=%d, RTN_LOCAL=%d", rm->rtm_type,RTN_UNICAST, RTN_LOCAL);
|
||||
//dprintf("rtm_type : %d, RTN_UNICAST=%d, RTN_LOCAL=%d", rm->rtm_type,RTN_UNICAST, RTN_LOCAL);
|
||||
// okay, so.
|
||||
//
|
||||
|
||||
|
@ -310,11 +310,11 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
{
|
||||
if (is_ipv6) {
|
||||
what6 = (unsigned char *) RTA_DATA(ra);
|
||||
dprintf("ra @ %p, type = %d, length = %d, payload = %d, payload data = %08x %08x %08x %08x", ra, ra->rta_type, ra->rta_len, RTA_PAYLOAD(ra), *(__u32 *)what6, *(__u32 *)(what6+4), *(__u32 *)(what6+8), *(__u32 *)(what6+12));
|
||||
//dprintf("ra @ %p, type = %d, length = %d, payload = %d, payload data = %08x %08x %08x %08x", ra, ra->rta_type, ra->rta_len, RTA_PAYLOAD(ra), *(__u32 *)what6, *(__u32 *)(what6+4), *(__u32 *)(what6+8), *(__u32 *)(what6+12));
|
||||
}
|
||||
else {
|
||||
what = (__u32 *) RTA_DATA(ra);
|
||||
dprintf("ra @ %p, type = %d, length = %d, payload = %d, payload data = %08x", ra, ra->rta_type, ra->rta_len, RTA_PAYLOAD(ra), *what);
|
||||
//dprintf("ra @ %p, type = %d, length = %d, payload = %d, payload data = %08x", ra, ra->rta_type, ra->rta_len, RTA_PAYLOAD(ra), *what);
|
||||
}
|
||||
|
||||
switch(ra->rta_type) {
|
||||
|
@ -341,7 +341,7 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
dprintf("and while you're here, rtm_dst_len = %d", rm->rtm_dst_len);
|
||||
//dprintf("and while you're here, rtm_dst_len = %d", rm->rtm_dst_len);
|
||||
|
||||
if (is_ipv6) {
|
||||
// if netmask is FFFFFFFF FFFFFFFF 00000000 00000000 (/64), netmask6.a1 and netmask6.a2 == 0xffffffff, and nestmask6.a3 and .a4 == 0
|
||||
|
@ -387,11 +387,11 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
|
||||
strncpy(re6->interface, int_name, IFNAMSIZ);
|
||||
re6->metric = metric;
|
||||
dprintf("re6->dest6 = %08x %08x %08x %08x, re6->netmask6 = %08x %08x %08x %08x, re6->nexthop6 = %08x %08x %08x %08x, interface = %s, metric = %d",
|
||||
re6->dest6.a1,re6->dest6.a2,re6->dest6.a3,re6->dest6.a4,
|
||||
re6->netmask6.a1,re6->netmask6.a2,re6->netmask6.a3,re6->netmask6.a4,
|
||||
re6->nexthop6.a1,re6->nexthop6.a2,re6->nexthop6.a3,re6->nexthop6.a4,
|
||||
re6->interface,re6->metric);
|
||||
//dprintf("re6->dest6 = %08x %08x %08x %08x, re6->netmask6 = %08x %08x %08x %08x, re6->nexthop6 = %08x %08x %08x %08x, interface = %s, metric = %d",
|
||||
// re6->dest6.a1,re6->dest6.a2,re6->dest6.a3,re6->dest6.a4,
|
||||
// re6->netmask6.a1,re6->netmask6.a2,re6->netmask6.a3,re6->netmask6.a4,
|
||||
// re6->nexthop6.a1,re6->nexthop6.a2,re6->nexthop6.a3,re6->nexthop6.a4,
|
||||
// re6->interface,re6->metric);
|
||||
tmp6->entries++;
|
||||
|
||||
*table_v6 = tmp6;
|
||||
|
@ -414,7 +414,7 @@ int netlink_parse_routing_table(struct nlmsghdr *nh, void *data)
|
|||
strncpy(re->interface, int_name, IFNAMSIZ);
|
||||
re->metric = metric;
|
||||
|
||||
dprintf("re->dest = %08x, re->netmask = %08x, re->nexthop = %08x, interface = %s, metric = %d", re->dest, re->netmask, re->nexthop,re->interface,re->metric);
|
||||
//dprintf("re->dest = %08x, re->netmask = %08x, re->nexthop = %08x, interface = %s, metric = %d", re->dest, re->netmask, re->nexthop,re->interface,re->metric);
|
||||
tmp->entries++;
|
||||
|
||||
*table_v4 = tmp;
|
||||
|
@ -531,7 +531,7 @@ int netlink_parse_interface_link(struct nlmsghdr *nh, void *data)
|
|||
iface = (unsigned char *)iface + 4;
|
||||
dprintf("Adjusted iface at +4");
|
||||
}
|
||||
dprintf("ifi_family : 0x%x , ifi_type : 0x%x, ifi_index : 0x%x",iface->ifi_family, iface->ifi_type, iface->ifi_index);
|
||||
//dprintf("ifi_family : 0x%x , ifi_type : 0x%x, ifi_index : 0x%x",iface->ifi_family, iface->ifi_type, iface->ifi_index);
|
||||
len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));
|
||||
memset(&iface_tmp, 0, sizeof(iface_tmp));
|
||||
|
||||
|
@ -642,8 +642,7 @@ int netlink_parse_interface_address(struct nlmsghdr *nh, void *data)
|
|||
{
|
||||
struct ifaces_list ** iface_list = ( struct ifaces_list **) data;
|
||||
struct iface_entry * iff;
|
||||
struct iface_entry * iff_tmp;
|
||||
struct ifaces_list *tmp;
|
||||
struct ifaces_list * iface_list_tmp;
|
||||
struct iface_entry iface_tmp;
|
||||
|
||||
struct ifaddrmsg *iaddr;
|
||||
|
@ -652,6 +651,11 @@ int netlink_parse_interface_address(struct nlmsghdr *nh, void *data)
|
|||
uint32_t newsize;
|
||||
unsigned char is_ipv6;
|
||||
|
||||
struct iface_address *addr_tmp;
|
||||
|
||||
// strictly for debugging
|
||||
char addr_str[64];
|
||||
|
||||
iaddr = NLMSG_DATA(nh);
|
||||
// stumbled upon an old system with 4 bytes padding between nlmsghdr and ifaddrmsg, try to detect it
|
||||
if (!likely_ifaddrmsg(iaddr)) {
|
||||
|
@ -659,7 +663,6 @@ int netlink_parse_interface_address(struct nlmsghdr *nh, void *data)
|
|||
dprintf("Adjusted iaddr at +4");
|
||||
}
|
||||
|
||||
dprintf("ifa_family : 0x%x , ifa_prefixlen : 0x%x, ifa_flags : 0x%x, ifa_scope : 0x%x",iaddr->ifa_family, iaddr->ifa_prefixlen, iaddr->ifa_flags, iaddr->ifa_scope);
|
||||
len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*iaddr));
|
||||
|
||||
if (iaddr->ifa_family == AF_INET6)
|
||||
|
@ -667,127 +670,111 @@ int netlink_parse_interface_address(struct nlmsghdr *nh, void *data)
|
|||
else if (iaddr->ifa_family == AF_INET)
|
||||
is_ipv6 = 0;
|
||||
else {
|
||||
dprintf("Got iaddr->ifa_family : %d which is unknown (iaddr->ifa_index : %d)", iaddr->ifa_family, iaddr->ifa_index);
|
||||
//dprintf("Got iaddr->ifa_family : %d which is unknown (iaddr->ifa_index : %d)", iaddr->ifa_family, iaddr->ifa_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&iface_tmp, 0, sizeof(iface_tmp));
|
||||
iface_tmp.index = iaddr->ifa_index;
|
||||
|
||||
dprintf("-------------------------------------");
|
||||
for (attribute = IFA_RTA(iaddr); RTA_OK(attribute, len); attribute = RTA_NEXT(attribute, len))
|
||||
{
|
||||
dprintf("Start of loop, attribute->rta_type = %d", attribute->rta_type);
|
||||
switch(attribute->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
// Make room for a new address
|
||||
iface_tmp.addr_count++;
|
||||
iface_tmp.addr_list = realloc(iface_tmp.addr_list, sizeof(struct iface_address) * iface_tmp.addr_count);
|
||||
addr_tmp = &iface_tmp.addr_list[iface_tmp.addr_count-1];
|
||||
if (is_ipv6)
|
||||
memcpy(&iface_tmp.addr6, (unsigned char *) RTA_DATA(attribute), sizeof(__u128));
|
||||
else
|
||||
iface_tmp.addr = *(__u32 *) RTA_DATA(attribute);
|
||||
{
|
||||
addr_tmp->family = AF_INET6;
|
||||
memcpy(&addr_tmp->ip.addr6, (unsigned char *) RTA_DATA(attribute), sizeof(__u128));
|
||||
} else {
|
||||
addr_tmp->family = AF_INET;
|
||||
addr_tmp->ip.addr = *(__u32 *) RTA_DATA(attribute);
|
||||
}
|
||||
address_calculate_netmask(addr_tmp, iaddr->ifa_prefixlen);
|
||||
|
||||
inet_ntop(addr_tmp->family, &addr_tmp->ip, addr_str, sizeof(addr_str));
|
||||
dprintf("Interface: %s", addr_str);
|
||||
inet_ntop(addr_tmp->family, &addr_tmp->nm, addr_str, sizeof(addr_str));
|
||||
dprintf("Netmask: %s", addr_str);
|
||||
break;
|
||||
|
||||
case IFA_LABEL:
|
||||
strncpy(iface_tmp.name, (unsigned char *) RTA_DATA(attribute), IFNAMSIZ);
|
||||
dprintf("Copied name %s", iface_tmp.name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dprintf("-------------------------------------");
|
||||
}
|
||||
|
||||
dprintf("and while you're here, iaddr->ifa_prefixlen = %d", iaddr->ifa_prefixlen);
|
||||
|
||||
if (is_ipv6) {
|
||||
// if netmask is FFFFFFFF FFFFFFFF 00000000 00000000 (/64), netmask6.a1 and netmask6.a2 == 0xffffffff, and nestmask6.a3 and .a4 == 0
|
||||
// netmask6 is set to 0 at the beginning of the function, no need to reset the values to 0 if it is needed
|
||||
// XXX really ugly, but works
|
||||
if (iaddr->ifa_prefixlen >= 96) {
|
||||
iface_tmp.netmask6.a4 = (1 << (iaddr->ifa_prefixlen-96))-1;
|
||||
iface_tmp.netmask6.a1 = iface_tmp.netmask6.a2 = iface_tmp.netmask6.a3 = 0xffffffff;
|
||||
}
|
||||
else if (iaddr->ifa_prefixlen >= 64) {
|
||||
iface_tmp.netmask6.a3 = (1 << (iaddr->ifa_prefixlen-64))-1;
|
||||
iface_tmp.netmask6.a1 = iface_tmp.netmask6.a2 = 0xffffffff;
|
||||
}
|
||||
else if (iaddr->ifa_prefixlen >= 32) {
|
||||
iface_tmp.netmask6.a2 = (1 << (iaddr->ifa_prefixlen-32))-1;
|
||||
iface_tmp.netmask6.a1 = 0xffffffff;
|
||||
}
|
||||
else
|
||||
iface_tmp.netmask6.a1 = (1 << iaddr->ifa_prefixlen)-1;
|
||||
}
|
||||
else {
|
||||
if (iaddr->ifa_prefixlen == 32)
|
||||
iface_tmp.netmask = 0xffffffff;
|
||||
else
|
||||
iface_tmp.netmask = ((1 << iaddr->ifa_prefixlen) - 1);
|
||||
|
||||
}
|
||||
dprintf("Exited loop");
|
||||
|
||||
/*
|
||||
* try to find the iface by index and name
|
||||
* an IP alias (eth0:0 for instance) will have the same index but not the same name/label
|
||||
* no alias when getting IPv6 address, so just search using the index
|
||||
* An IP alias (eth0:0 for instance) will have the same index but not the
|
||||
* same name/label. There are no aliases when getting IPv6 address, so
|
||||
* just search using the index.
|
||||
*/
|
||||
if (is_ipv6) {
|
||||
iff = find_iface_by_index(*iface_list, iaddr->ifa_index);
|
||||
iff = find_iface_by_index(*iface_list, iface_tmp.index);
|
||||
if (iff == NULL) {
|
||||
dprintf("Cannot find iface with index %d", iaddr->ifa_index);
|
||||
dprintf("Cannot find iface with index %d", iface_tmp.index);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
iff = find_iface_by_index_and_name(*iface_list, iaddr->ifa_index, iface_tmp.name);
|
||||
iff = find_iface_by_index_and_name(*iface_list, iface_tmp.index, iface_tmp.name);
|
||||
|
||||
if (iff == NULL) {
|
||||
dprintf("[%s] %s an alias?", __FUNCTION__, iface_tmp.name);
|
||||
// didn't find this name, probably an alias such as eth0:0
|
||||
iff = find_iface_by_index(*iface_list, iaddr->ifa_index);
|
||||
/* Now we're dealing with an IPv4 alias such as eth0:0. With a regular
|
||||
* interface, the mac address, mtu, flags, etc. would already have been
|
||||
* initialized when we did the RTM_GETLINK request. Since an alias
|
||||
* doesn't count as a physical interface, that didn't happen, so copy
|
||||
* all of the parent interface's info to this one.
|
||||
*/
|
||||
dprintf("%s an alias?", iface_tmp.name);
|
||||
iff = find_iface_by_index(*iface_list, iface_tmp.index);
|
||||
if (iff == NULL) {
|
||||
dprintf("Cannot find iface with index %d", iaddr->ifa_index);
|
||||
dprintf("Cannot find iface with index %d", iface_tmp.index);
|
||||
return 0;
|
||||
}
|
||||
// found it, copy the data to save it
|
||||
// old MAC addr and MTU
|
||||
memcpy(iface_tmp.hwaddr, iff->hwaddr, 6);
|
||||
iface_tmp.mtu = iff->mtu;
|
||||
iface_tmp.index = iff->index;
|
||||
memcpy(&iface_tmp.addr6, &iff->addr6, sizeof(__u128));
|
||||
memcpy(&iface_tmp.netmask6, &iff->netmask6, sizeof(__u128));
|
||||
strncpy(iface_tmp.flags, iff->flags, FLAGS_LEN);
|
||||
// allocate new one
|
||||
|
||||
// expand the list to accomodate the new one
|
||||
newsize = sizeof(struct ifaces_list);
|
||||
newsize += ((*iface_list)->entries + 1) * sizeof(struct iface_entry);
|
||||
iface_list_tmp = realloc(*iface_list, newsize);
|
||||
|
||||
tmp = realloc(*iface_list, newsize);
|
||||
|
||||
if(tmp == NULL) {
|
||||
if(iface_list_tmp == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
iff = &(tmp->ifaces[tmp->entries]);
|
||||
iff = &(iface_list_tmp->ifaces[iface_list_tmp->entries]);
|
||||
memset(iff, 0, sizeof(struct iface_entry));
|
||||
// copy back saved data in new iface_entry
|
||||
memcpy(iff->hwaddr, iface_tmp.hwaddr, 6);
|
||||
iff->mtu = iface_tmp.mtu;
|
||||
iff->index = iface_tmp.index;
|
||||
memcpy(&iff->addr6, &iface_tmp.addr6, sizeof(__u128));
|
||||
memcpy(&iff->netmask6, &iface_tmp.netmask6, sizeof(__u128));
|
||||
|
||||
strncpy(iff->flags, iface_tmp.flags, FLAGS_LEN);
|
||||
// copy new name
|
||||
strncpy(iff->name, iface_tmp.name, IFNAMSIZ);
|
||||
|
||||
tmp->entries++;
|
||||
*iface_list = tmp;
|
||||
}
|
||||
//now, iff points to a iface_entry, just copy add/addr6 and netmask/netmask6
|
||||
if (is_ipv6) {
|
||||
memcpy(&iff->addr6, &iface_tmp.addr6, sizeof(__u128));
|
||||
memcpy(&iff->netmask6, &iface_tmp.netmask6, sizeof(__u128));
|
||||
}
|
||||
else {
|
||||
iff->addr = iface_tmp.addr;
|
||||
iff->netmask = iface_tmp.netmask;
|
||||
iface_list_tmp->entries++;
|
||||
*iface_list = iface_list_tmp;
|
||||
}
|
||||
|
||||
dprintf("iff->index = %d, iff->name = %s, iff->addr = %08x, iff->netmask = %08x, iff->addr6 = %08x %08x %08x %08x, iff->netmask6 = %08x %08x %08x %08x",
|
||||
iff->index, iff->name, iff->addr, iff->netmask,
|
||||
iff->addr6.a1,iff->addr6.a2,iff->addr6.a3,iff->addr6.a4, iff->netmask6.a1,iff->netmask6.a2,iff->netmask6.a3,iff->netmask6.a4);
|
||||
inet_ntop(addr_tmp->family, &addr_tmp->ip, addr_str, sizeof(addr_str));
|
||||
dprintf("Appending: %s", addr_str);
|
||||
iface_entry_append_address(iff, &iface_tmp.addr_list[0]);
|
||||
dprintf("iff->addr_count = %d; iface_tmp.addr_count = %d", iff->addr_count, iface_tmp.addr_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -836,7 +823,7 @@ int netlink_get_interfaces(struct ifaces_list **iface_list)
|
|||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
// for each interface created before, will get the IPv4 / IPv6 addr
|
||||
status = netlink_parse(fd, seq, netlink_parse_interface_address, iface_list);
|
||||
status = netlink_parse(fd, seq, netlink_parse_interface_address, iface_list);
|
||||
close(fd);
|
||||
if(status != 0) {
|
||||
if (*iface_list)
|
||||
|
@ -848,3 +835,42 @@ int netlink_get_interfaces(struct ifaces_list **iface_list)
|
|||
return status;
|
||||
|
||||
}
|
||||
|
||||
void address_calculate_netmask(struct iface_address *address, int ifa_prefixlen) {
|
||||
|
||||
if (address->family == AF_INET6) {
|
||||
// if netmask is FFFFFFFF FFFFFFFF 00000000 00000000 (/64), netmask6.a1 and netmask6.a2 == 0xffffffff, and nestmask6.a3 and .a4 == 0
|
||||
// netmask6 is set to 0 at the beginning of the function, no need to reset the values to 0 if it is needed
|
||||
// XXX really ugly, but works
|
||||
if (ifa_prefixlen >= 96) {
|
||||
address->nm.netmask6.a4 = (1 << (ifa_prefixlen-96))-1;
|
||||
address->nm.netmask6.a1 = address->nm.netmask6.a2 = address->nm.netmask6.a3 = 0xffffffff;
|
||||
}
|
||||
else if (ifa_prefixlen >= 64) {
|
||||
address->nm.netmask6.a3 = (1 << (ifa_prefixlen-64))-1;
|
||||
address->nm.netmask6.a1 = address->nm.netmask6.a2 = 0xffffffff;
|
||||
}
|
||||
else if (ifa_prefixlen >= 32) {
|
||||
address->nm.netmask6.a2 = (1 << (ifa_prefixlen-32))-1;
|
||||
address->nm.netmask6.a1 = 0xffffffff;
|
||||
}
|
||||
else
|
||||
address->nm.netmask6.a1 = (1 << ifa_prefixlen)-1;
|
||||
}
|
||||
else {
|
||||
if (ifa_prefixlen == 32)
|
||||
address->nm.netmask = 0xffffffff;
|
||||
else
|
||||
address->nm.netmask = ((1 << ifa_prefixlen) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void iface_entry_append_address(struct iface_entry *iface, struct iface_address *address) {
|
||||
iface->addr_count++;
|
||||
iface->addr_list = realloc(iface->addr_list, sizeof(struct iface_address) * iface->addr_count);
|
||||
dprintf("Realloc'd %p", iface->addr_list);
|
||||
|
||||
memcpy(&iface->addr_list[iface->addr_count-1], address, sizeof(struct iface_address));
|
||||
}
|
||||
|
||||
|
|
|
@ -312,18 +312,18 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
|||
|
||||
# Try to match our visible IP to a real interface
|
||||
# TODO: Deal with IPv6 addresses
|
||||
found = ifaces.find {|i| i.ip == shost }
|
||||
found = !!(ifaces.find {|i| i.addrs.find {|a| p a; a == shost } })
|
||||
nhost = nil
|
||||
hobj = nil
|
||||
|
||||
if Rex::Socket.is_ipv4?(shost) and not found
|
||||
|
||||
# Try to find an interface with a default route
|
||||
default_routes = routes.select{ |r| r.subnet == "0.0.0.0" }
|
||||
default_routes = routes.select{ |r| r.subnet == "0.0.0.0" || r.subnet == "::" }
|
||||
default_routes.each do |r|
|
||||
ifaces.each do |i|
|
||||
cidr = Rex::Socket.net2bitmask( i.netmask ) rescue "/32"
|
||||
rang = Rex::Socket::RangeWalker.new( "#{i.ip}/#{cidr}" ) rescue nil
|
||||
bits = Rex::Socket.net2bitmask( i.netmask ) rescue 32
|
||||
rang = Rex::Socket::RangeWalker.new( "#{i.ip}/#{bits}" ) rescue nil
|
||||
if rang and rang.include?( r.gateway )
|
||||
nhost = i.ip
|
||||
break
|
||||
|
|
|
@ -58,16 +58,27 @@ class Config
|
|||
response = client.send_request(request)
|
||||
|
||||
response.each(TLV_TYPE_NETWORK_INTERFACE) { |iface|
|
||||
addrs = []
|
||||
netmasks = []
|
||||
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
|
||||
# match up. This could be done better by creating another
|
||||
# GroupTlv type for addresses containing an address, a netmask,
|
||||
# and possibly a scope.
|
||||
n = iface.get_tlv_value(TLV_TYPE_NETMASK, addrs.length)
|
||||
addrs << Rex::Socket.addr_ntoa(a)
|
||||
netmasks << Rex::Socket.addr_ntoa(n) if n
|
||||
end
|
||||
ifaces << Interface.new(
|
||||
iface.get_tlv_value(TLV_TYPE_INTERFACE_INDEX),
|
||||
iface.get_tlv_value(TLV_TYPE_IP),
|
||||
iface.get_tlv_value(TLV_TYPE_NETMASK),
|
||||
iface.get_tlv_value(TLV_TYPE_MAC_ADDRESS),
|
||||
iface.get_tlv_value(TLV_TYPE_MAC_NAME),
|
||||
iface.get_tlv_value(TLV_TYPE_IP6),
|
||||
iface.get_tlv_value(TLV_TYPE_NETMASK6),
|
||||
iface.get_tlv_value(TLV_TYPE_INTERFACE_MTU),
|
||||
iface.get_tlv_value(TLV_TYPE_INTERFACE_FLAGS))
|
||||
:index => iface.get_tlv_value(TLV_TYPE_INTERFACE_INDEX),
|
||||
:mac_addr => iface.get_tlv_value(TLV_TYPE_MAC_ADDRESS),
|
||||
:mac_name => iface.get_tlv_value(TLV_TYPE_MAC_NAME),
|
||||
:mtu => iface.get_tlv_value(TLV_TYPE_INTERFACE_MTU),
|
||||
:flags => iface.get_tlv_value(TLV_TYPE_INTERFACE_FLAGS),
|
||||
:addrs => addrs,
|
||||
:netmasks => netmasks
|
||||
)
|
||||
}
|
||||
|
||||
return ifaces
|
||||
|
|
|
@ -27,16 +27,14 @@ class Interface
|
|||
# Returns a logical interface and initializes it to the supplied
|
||||
# parameters.
|
||||
#
|
||||
def initialize(index, ip, netmask, mac_addr, mac_name, ip6=nil, netmask6=nil, mtu=nil, flags=nil)
|
||||
self.index = index || -1
|
||||
self.ip = (ip ? IPAddr.ntop(ip) : nil)
|
||||
self.netmask = (netmask ? IPAddr.ntop(netmask) : nil)
|
||||
self.mac_addr = mac_addr
|
||||
self.mac_name = mac_name
|
||||
self.ip6 = (ip6 ? IPAddr.new_ntoh(ip6).to_s : nil)
|
||||
self.netmask6 = (netmask6 ? IPAddr.new_ntoh(netmask6).to_s : nil)
|
||||
self.mtu = mtu
|
||||
self.flags = flags
|
||||
def initialize(opts={})
|
||||
self.index = opts[:index] || -1
|
||||
self.mac_addr = opts[:mac_addr]
|
||||
self.mac_name = opts[:mac_name]
|
||||
self.mtu = opts[:mtu]
|
||||
self.flags = opts[:flags]
|
||||
self.addrs = opts[:addrs]
|
||||
self.netmasks = opts[:netmasks]
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -54,11 +52,22 @@ class Interface
|
|||
macocts[3], macocts[4], macocts[5])],
|
||||
["MTU" , mtu ],
|
||||
["Flags" , flags ],
|
||||
["IPv4 Address" , ((ip and ip != "0.0.0.0") ? ip : nil) ],
|
||||
["IPv4 Netmask" , netmask ],
|
||||
["IPv6 Address" , ((ip6 and ip6 != "::") ? ip6 : nil) ],
|
||||
["IPv6 Netmask" , ((netmask6 and netmask6 != "::") ? netmask6 : nil) ],
|
||||
]
|
||||
|
||||
# If all went as planned, addrs and netmasks will have the same number
|
||||
# of elements and be properly ordered such that they match up
|
||||
# correctly.
|
||||
addr_masks = addrs.zip(netmasks)
|
||||
|
||||
addr_masks.select { |a| Rex::Socket.is_ipv4?(a[0]) }.each { |a|
|
||||
info << [ "IPv4 Address", a[0] ]
|
||||
info << [ "IPv4 Netmask", a[1] ]
|
||||
}
|
||||
addr_masks.select { |a| Rex::Socket.is_ipv6?(a[0]) }.each { |a|
|
||||
info << [ "IPv6 Address", a[0] ]
|
||||
info << [ "IPv6 Netmask", a[1] ]
|
||||
}
|
||||
|
||||
pad = info.map{|i| i[0] }.max_by{|k|k.length}.length
|
||||
|
||||
ret = sprintf(
|
||||
|
@ -76,17 +85,20 @@ class Interface
|
|||
end
|
||||
|
||||
#
|
||||
# The indedx of the interface.
|
||||
# The first address associated with this Interface
|
||||
#
|
||||
def ip
|
||||
addrs.first
|
||||
end
|
||||
|
||||
#
|
||||
# The index of the interface.
|
||||
#
|
||||
attr_accessor :index
|
||||
#
|
||||
# The IP address bound to the interface.
|
||||
# An Array of IP addresses bound to the Interface.
|
||||
#
|
||||
attr_accessor :ip
|
||||
#
|
||||
# The subnet mask associated with the interface.
|
||||
#
|
||||
attr_accessor :netmask
|
||||
attr_accessor :addrs
|
||||
#
|
||||
# The physical (MAC) address of the NIC.
|
||||
#
|
||||
|
@ -96,10 +108,6 @@ class Interface
|
|||
#
|
||||
attr_accessor :mac_name
|
||||
#
|
||||
# The IPv6 address bound to the interface.
|
||||
#
|
||||
attr_accessor :ip6
|
||||
#
|
||||
# The subnet mask associated with the IPv6 interface.
|
||||
#
|
||||
attr_accessor :netmask6
|
||||
|
@ -111,6 +119,7 @@ class Interface
|
|||
# The flags associated with the interface.
|
||||
#
|
||||
attr_accessor :flags
|
||||
attr_accessor :netmasks
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
||||
|
|
|
@ -51,17 +51,12 @@ 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_SUBNET6 = TLV_META_TYPE_RAW | 1424
|
||||
TLV_TYPE_NETMASK6 = TLV_META_TYPE_RAW | 1425
|
||||
TLV_TYPE_GATEWAY6 = TLV_META_TYPE_RAW | 1426
|
||||
TLV_TYPE_NETWORK_ROUTE6 = TLV_META_TYPE_GROUP | 1427
|
||||
|
||||
|
||||
TLV_TYPE_IP = TLV_META_TYPE_RAW | 1430
|
||||
TLV_TYPE_MAC_ADDRESS = TLV_META_TYPE_RAW | 1431
|
||||
TLV_TYPE_MAC_NAME = TLV_META_TYPE_STRING | 1432
|
||||
TLV_TYPE_NETWORK_INTERFACE = TLV_META_TYPE_GROUP | 1433
|
||||
TLV_TYPE_IP6 = TLV_META_TYPE_RAW | 1434
|
||||
TLV_TYPE_IP6_SCOPE = TLV_META_TYPE_RAW | 1434
|
||||
|
||||
TLV_TYPE_SUBNET_STRING = TLV_META_TYPE_STRING | 1440
|
||||
TLV_TYPE_NETMASK_STRING = TLV_META_TYPE_STRING | 1441
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/tlv'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
|
@ -129,13 +131,14 @@ class Tlv
|
|||
|
||||
def inspect
|
||||
utype = type ^ TLV_META_TYPE_COMPRESSED
|
||||
group = false
|
||||
meta = case (utype & TLV_META_MASK)
|
||||
when TLV_META_TYPE_STRING; "STRING"
|
||||
when TLV_META_TYPE_UINT; "INT"
|
||||
when TLV_META_TYPE_RAW; "RAW"
|
||||
when TLV_META_TYPE_BOOL; "BOOL"
|
||||
when TLV_META_TYPE_QWORD; "QWORD"
|
||||
when TLV_META_TYPE_GROUP; "GROUP"
|
||||
when TLV_META_TYPE_GROUP; group=true; "GROUP"
|
||||
when TLV_META_TYPE_COMPLEX; "COMPLEX"
|
||||
else; 'unknown-meta-type'
|
||||
end
|
||||
|
@ -175,16 +178,33 @@ class Tlv
|
|||
when TLV_TYPE_MIGRATE_PAYLOAD; "MIGRATE-PAYLOAD"
|
||||
when TLV_TYPE_MIGRATE_ARCH; "MIGRATE-ARCH"
|
||||
|
||||
# Extension classes don't exist yet, so can't use their constants
|
||||
# here.
|
||||
#when Extensions::Stdapi::TLV_TYPE_IP; 'ip-address'
|
||||
when Extensions::Stdapi::TLV_TYPE_NETWORK_INTERFACE; 'network-interface'
|
||||
when Extensions::Stdapi::TLV_TYPE_IP; 'ip-address'
|
||||
when Extensions::Stdapi::TLV_TYPE_NETMASK; 'netmask'
|
||||
when Extensions::Stdapi::TLV_TYPE_MAC_ADDRESS; 'mac-address'
|
||||
when Extensions::Stdapi::TLV_TYPE_MAC_NAME; 'interface-name'
|
||||
when Extensions::Stdapi::TLV_TYPE_IP6_SCOPE; 'address-scope'
|
||||
when Extensions::Stdapi::TLV_TYPE_INTERFACE_MTU; 'interface-mtu'
|
||||
when Extensions::Stdapi::TLV_TYPE_INTERFACE_FLAGS; 'interface-flags'
|
||||
when Extensions::Stdapi::TLV_TYPE_INTERFACE_INDEX; 'interface-index'
|
||||
|
||||
else; "unknown-#{type}"
|
||||
end
|
||||
val = value.inspect
|
||||
if val.length > 50
|
||||
val = val[0,50] + ' ..."'
|
||||
end
|
||||
"#<#{self.class} type=#{stype} #{self.class.to_s =~ /Packet/ ? "tlvs=#{@tlvs.inspect}" : "meta=#{meta} value=#{val}"} >"
|
||||
group ||= (self.class.to_s =~ /Packet/)
|
||||
if group
|
||||
tlvs_inspect = "tlvs=[\n"
|
||||
@tlvs.each { |t|
|
||||
tlvs_inspect << " #{t.inspect}\n"
|
||||
}
|
||||
tlvs_inspect << "]"
|
||||
else
|
||||
tlvs_inspect = "meta=#{meta} value=#{val}"
|
||||
end
|
||||
"#<#{self.class} type=#{stype} #{tlvs_inspect}>"
|
||||
end
|
||||
|
||||
##
|
||||
|
|
Loading…
Reference in New Issue