char *get_interface_name_by_index(unsigned int fidx) { unsigned int i, idx; char errbuf[PCAP_ERRBUF_SIZE+4]; static char device_name[64]; // PKS, probably safe, due to snifferm mutex int if_error; struct ifaces_list *ifaces; pcap_if_t *interfaces, *int_iter; interfaces = int_iter = NULL; ifaces = NULL; idx = 1; memset(device_name, 0, sizeof(device_name)); if(pcap_findalldevs(&interfaces, errbuf) == -1) { dprintf("pcap_findalldevs failed, trying netlink_get_interfaces, errbuf was : %s", errbuf); if_error = netlink_get_interfaces(&ifaces); if(if_error) { dprintf("Error when retrieving interfaces info"); return NULL; } for (i = 0; i < ifaces->entries; i++) { if(fidx == ifaces->ifaces[i].index) { strncpy(device_name, ifaces->ifaces[i].name, sizeof(device_name)-1); break; } } } else { //pcap_findalldevs suceeded for(int_iter = interfaces; int_iter; int_iter = int_iter->next) { if(fidx == idx++) { strncpy(device_name, int_iter->name, sizeof(device_name)-1); break; } } } if(interfaces) { pcap_freealldevs(interfaces); } if (ifaces) { free(ifaces); } return device_name[0] ? device_name : NULL; }
#include "precomp.h" #ifdef _WIN32 #include <iptypes.h> #include <ws2ipdef.h> #endif #ifdef _WIN32 DWORD get_interfaces_windows_mib(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; Tlv entries[6]; PMIB_IPADDRTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPADDRROW) * 33; DWORD index; DWORD mtu_bigendian; DWORD interface_index_bigendian; MIB_IFROW iface; do { // Allocate memory for reading addresses into if (!(table = (PMIB_IPADDRTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the IP address table if (GetIpAddrTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate the entries for (index = 0; index < table->dwNumEntries; index++) { tlv_cnt = 0; interface_index_bigendian = htonl(table->table[index].dwIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_IP; entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwAddr; tlv_cnt++; entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_NETMASK; entries[tlv_cnt].buffer = (PUCHAR)&table->table[index].dwMask; tlv_cnt++; iface.dwIndex = table->table[index].dwIndex; // If interface information can get gotten, use it. if (GetIfEntry(&iface) == NO_ERROR) { entries[tlv_cnt].header.length = iface.dwPhysAddrLen; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)iface.bPhysAddr; tlv_cnt++; mtu_bigendian = htonl(iface.dwMtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; entries[tlv_cnt].buffer = (PUCHAR)&mtu_bigendian; tlv_cnt++; if (iface.bDescr) { entries[tlv_cnt].header.length = iface.dwDescrLen + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)iface.bDescr; tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (table) free(table); return result; } DWORD get_interfaces_windows(Remote *remote, Packet *response) { DWORD result = ERROR_SUCCESS; DWORD tlv_cnt; // 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 = 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 | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_ANYCAST; 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 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 { gaa = (DWORD (WINAPI *)(DWORD,DWORD,void*,void*,void*))GetProcAddress( GetModuleHandle("iphlpapi"), "GetAdaptersAddresses" ); if (!gaa) { result = get_interfaces_windows_mib(remote, response); 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) { tlv_cnt = 0; interface_index_bigendian = htonl(pCurr->IfIndex); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_INDEX; entries[tlv_cnt].buffer = (PUCHAR)&interface_index_bigendian; tlv_cnt++; entries[tlv_cnt].header.length = pCurr->PhysicalAddressLength; entries[tlv_cnt].header.type = TLV_TYPE_MAC_ADDR; entries[tlv_cnt].buffer = (PUCHAR)pCurr->PhysicalAddress; tlv_cnt++; entries[tlv_cnt].header.length = wcslen(pCurr->Description)*2 + 1; entries[tlv_cnt].header.type = TLV_TYPE_MAC_NAME; entries[tlv_cnt].buffer = (PUCHAR)pCurr->Description; tlv_cnt++; mtu_bigendian = htonl(pCurr->Mtu); entries[tlv_cnt].header.length = sizeof(DWORD); entries[tlv_cnt].header.type = TLV_TYPE_INTERFACE_MTU; 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) { 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; } if (pAddr->Length > 44) { // Then this is Vista+ and the OnLinkPrefixLength member // will be populated prefixes[prefixes_cnt] = htonl(pAddr->OnLinkPrefixLength); } if (pPrefix && 0 == prefixes[prefixes_cnt]) { // 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. free(entries); free(pAdapters); return get_interfaces_windows_mib(remote, response); } 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); 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); 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); tlv_cnt++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, tlv_cnt); } } while (0); if (entries) free(entries); if (pAdapters) free(pAdapters); return result; } #else /* _WIN32 */ int get_interfaces_linux(Remote *remote, Packet *response) { struct ifaces_list *ifaces = NULL; int i; int result; uint32_t interface_index_bigendian, mtu_bigendian; DWORD allocd_entries = 10; Tlv *entries = (Tlv *)malloc(sizeof(Tlv) * 10); dprintf("Grabbing interfaces"); result = netlink_get_interfaces(&ifaces); dprintf("Got 'em"); if (!result) { for (i = 0; i < ifaces->entries; i++) { int tlv_cnt = 0; int j = 0; dprintf("Building TLV for iface %d", i); 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[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++; mtu_bigendian = htonl(ifaces->ifaces[i].mtu); 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[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[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++; for (j = 0; j < ifaces->ifaces[i].addr_count; j++) { if (allocd_entries < tlv_cnt+3) { entries = realloc(entries, sizeof(Tlv) * (tlv_cnt+3)); allocd_entries += 3; } 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++; //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++; //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++; } } 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); if (entries) free(entries); return result; }
DWORD request_sniffer_interfaces(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); Tlv entries[8]; /* 0: Index 1: Name 2: Description 3: Type 4: MTU 5: Wireless? 6: Accessible? 7: DHCP? */ DWORD result = ERROR_SUCCESS; #ifdef _WIN32 HANDLE hCfg; unsigned int idx = 1; check_pssdk(); hCfg = MgrGetFirstAdapterCfg(hMgr); do { unsigned char *aname = (unsigned char *)AdpCfgGetAdapterNameA(hCfg); unsigned char *adesc = (unsigned char *)AdpCfgGetAdapterDescriptionA(hCfg); unsigned int ahand = htonl((unsigned int)hCfg); unsigned int atype = htonl(AdpCfgGetAdapterType(hCfg)); unsigned int amtu = htonl(AdpCfgGetMaxPacketSize(hCfg)); unsigned int aidx = htonl(idx); BOOL awireless = AdpCfgIsWireless(hCfg); BOOL ausable = AdpCfgGetAccessibleState(hCfg); BOOL adhcp = AdpCfgGetDhcpState(hCfg); memset(entries, 0, sizeof(entries)); dprintf("sniffer>> interface %d - %s - %s", idx, aname, adesc); entries[0].header.type = TLV_TYPE_UINT; entries[0].header.length = sizeof(unsigned int); entries[0].buffer = (PUCHAR)&aidx; entries[1].header.type = TLV_TYPE_STRING; entries[1].header.length = (DWORD)strlen(aname) + 1; entries[1].buffer = aname; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = (DWORD)strlen(adesc) + 1; entries[2].buffer = adesc; entries[3].header.type = TLV_TYPE_UINT; entries[3].header.length = sizeof(unsigned int); entries[3].buffer = (PUCHAR)&atype; entries[4].header.type = TLV_TYPE_UINT; entries[4].header.length = sizeof(unsigned int); entries[4].buffer = (PUCHAR)&amtu; entries[5].header.type = TLV_TYPE_BOOL; entries[5].header.length = sizeof(BOOL); entries[5].buffer = (PUCHAR)&awireless; entries[6].header.type = TLV_TYPE_BOOL; entries[6].header.length = sizeof(BOOL); entries[6].buffer = (PUCHAR)&ausable; entries[7].header.type = TLV_TYPE_BOOL; entries[7].header.length = sizeof(BOOL); entries[7].buffer = (PUCHAR)&adhcp; packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8); idx++; } while ((hCfg = MgrGetNextAdapterCfg(hMgr, hCfg)) != NULL); #else char errbuf[PCAP_ERRBUF_SIZE+4]; int aidx = htonl(1); // :~( struct ifaces_list *ifaces; uint32_t i; int aidx_bigendian; int mtu_bigendian; int yes_int = htonl(1); int no_int = 0; int mtu_int = htonl(1514); pcap_if_t *interfaces, *int_iter; interfaces = int_iter = NULL; ifaces = NULL; do { result = pcap_findalldevs(&interfaces, errbuf); if(!result) { // pcap_findalldevs suceeded for(int_iter = interfaces; int_iter; int_iter = int_iter->next) { entries[0].header.type = TLV_TYPE_UINT; entries[0].header.length = sizeof(unsigned int); entries[0].buffer = (PUCHAR)&aidx; entries[1].header.type = TLV_TYPE_STRING; entries[1].header.length = strlen(int_iter->name)+1; entries[1].buffer = (PUCHAR)int_iter->name; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = strlen(int_iter->name)+1; entries[2].buffer = (PUCHAR)int_iter->name; entries[3].header.type = TLV_TYPE_UINT; entries[3].header.length = sizeof(unsigned int); entries[3].buffer = (PUCHAR)&no_int; // xxx, get encapsulation type? entries[4].header.type = TLV_TYPE_UINT; entries[4].header.length = sizeof(unsigned int); entries[4].buffer = (PUCHAR)&mtu_int; // PKS :-( entries[5].header.type = TLV_TYPE_BOOL; entries[5].header.length = sizeof(BOOL); entries[5].buffer = (PUCHAR)&no_int; // check encaps options / crap entries[6].header.type = TLV_TYPE_BOOL; entries[6].header.length = sizeof(BOOL); entries[6].buffer = (PUCHAR)&yes_int; // sure, why not. entries[7].header.type = TLV_TYPE_BOOL; entries[7].header.length = sizeof(BOOL); entries[7].buffer = (PUCHAR)&no_int; // hrm. not worth it. packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8); aidx = htonl(ntohl(aidx)+1); // :~( } } else { dprintf("pcap_findalldevs() failed, trying netlink_get_interfaces now, errbuf was %s", errbuf); result = netlink_get_interfaces(&ifaces); if(result) { dprintf("Error when retrieving interfaces info"); break; } // netlink_get_interfaces suceeded for (i = 0; i < ifaces->entries; i++) { aidx_bigendian = htonl(ifaces->ifaces[i].index); entries[0].header.type = TLV_TYPE_UINT; entries[0].header.length = sizeof(uint32_t); entries[0].buffer = (PUCHAR)&aidx_bigendian; entries[1].header.type = TLV_TYPE_STRING; entries[1].header.length = strlen(ifaces->ifaces[i].name)+1; entries[1].buffer = (PUCHAR)ifaces->ifaces[i].name; entries[2].header.type = TLV_TYPE_STRING; entries[2].header.length = strlen(ifaces->ifaces[i].name)+1; entries[2].buffer = (PUCHAR)ifaces->ifaces[i].name; entries[3].header.type = TLV_TYPE_UINT; entries[3].header.length = sizeof(unsigned int); entries[3].buffer = (PUCHAR)&no_int; // xxx, get encapsulation type? mtu_bigendian = htonl(ifaces->ifaces[i].mtu); entries[4].header.type = TLV_TYPE_UINT; entries[4].header.length = sizeof(uint32_t); entries[4].buffer = (PUCHAR)&mtu_bigendian; entries[5].header.type = TLV_TYPE_BOOL; entries[5].header.length = sizeof(BOOL); entries[5].buffer = (PUCHAR)&no_int; // check encaps options / crap entries[6].header.type = TLV_TYPE_BOOL; entries[6].header.length = sizeof(BOOL); entries[6].buffer = (PUCHAR)&yes_int; // sure, why not. entries[7].header.type = TLV_TYPE_BOOL; entries[7].header.length = sizeof(BOOL); entries[7].buffer = (PUCHAR)&no_int; // hrm. not worth it. packet_add_tlv_group(response, TLV_TYPE_SNIFFER_INTERFACES, entries, 8); } } } while(0); if(ifaces) { free(ifaces); } if (interfaces) { pcap_freealldevs(interfaces); } #endif packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }