DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags) { DWORD ret = NO_ERROR; if (!ppIpNetTable) ret = ERROR_INVALID_PARAMETER; else { DWORD numEntries = getNumArpEntries(); DWORD size = sizeof(MIB_IPNETTABLE); PMIB_IPNETTABLE table; if (numEntries > 1) size += (numEntries - 1) * sizeof(MIB_IPNETROW); table = HeapAlloc(heap, flags, size); #if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP) if (table) { int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO}; #define MIB_LEN (sizeof(mib) / sizeof(mib[0])) size_t needed; char *buf, *lim, *next; struct rt_msghdr *rtm; struct sockaddr_inarp *sinarp; struct sockaddr_dl *sdl; *ppIpNetTable = table; table->dwNumEntries = 0; if (sysctl (mib, MIB_LEN, NULL, &needed, NULL, 0) == -1) { ERR ("failed to get size of arp table\n"); return ERROR_NOT_SUPPORTED; } buf = HeapAlloc (GetProcessHeap (), 0, needed); if (!buf) return ERROR_OUTOFMEMORY; if (sysctl (mib, MIB_LEN, buf, &needed, NULL, 0) == -1) { ERR ("failed to get arp table\n"); HeapFree (GetProcessHeap (), 0, buf); return ERROR_NOT_SUPPORTED; } lim = buf + needed; next = buf; while(next < lim) { rtm = (struct rt_msghdr *)next; sinarp=(struct sockaddr_inarp *)(rtm + 1); sdl = (struct sockaddr_dl *)((char *)sinarp + ROUNDUP(sinarp->sin_len)); if(sdl->sdl_alen) /* arp entry */ { DWORD byte = strtoul(&sdl->sdl_data[sdl->sdl_alen], NULL, 16); memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_IPNETROW)); table->table[table->dwNumEntries].dwAddr = sinarp->sin_addr.s_addr; table->table[table->dwNumEntries].dwIndex = sdl->sdl_index; table->table[table->dwNumEntries].dwPhysAddrLen = sdl->sdl_alen; table->table[table->dwNumEntries].bPhysAddr[ table->table[table->dwNumEntries].dwPhysAddrLen++] = byte & 0x0ff; if(rtm->rtm_rmx.rmx_expire == 0) table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC; else if(sinarp->sin_other & SIN_PROXY) table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER; else if(rtm->rtm_rmx.rmx_expire != 0) table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC; else table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_INVALID; table->dwNumEntries++; } next += rtm->rtm_msglen; } HeapFree (GetProcessHeap (), 0, buf); } else ret = ERROR_OUTOFMEMORY; return ret; #endif if (table) { FILE *fp; *ppIpNetTable = table; table->dwNumEntries = 0; /* get from /proc/net/arp, no error if can't */ fp = fopen("/proc/net/arp", "r"); if (fp) { char buf[512] = { 0 }, *ptr; /* skip header line */ ptr = fgets(buf, sizeof(buf), fp); while (ptr && table->dwNumEntries < numEntries) { ptr = fgets(buf, sizeof(buf), fp); if (ptr) { char *endPtr; memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_IPNETROW)); table->table[table->dwNumEntries].dwAddr = inet_addr(ptr); while (ptr && *ptr && !isspace(*ptr)) ptr++; if (ptr && *ptr) { strtoul(ptr, &endPtr, 16); /* hw type (skip) */ ptr = endPtr; } if (ptr && *ptr) { DWORD flags = strtoul(ptr, &endPtr, 16); #ifdef ATF_COM if (flags & ATF_COM) table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC; else #endif #ifdef ATF_PERM if (flags & ATF_PERM) table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC; else #endif table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER; ptr = endPtr; } while (ptr && *ptr && isspace(*ptr)) ptr++; while (ptr && *ptr && !isspace(*ptr)) { DWORD byte = strtoul(ptr, &endPtr, 16); if (endPtr && *endPtr) { endPtr++; table->table[table->dwNumEntries].bPhysAddr[ table->table[table->dwNumEntries].dwPhysAddrLen++] = byte & 0x0ff; } ptr = endPtr; } if (ptr && *ptr) { strtoul(ptr, &endPtr, 16); /* mask (skip) */ ptr = endPtr; } getInterfaceIndexByName(ptr, &table->table[table->dwNumEntries].dwIndex); table->dwNumEntries++; } } fclose(fp); } else ret = ERROR_NOT_SUPPORTED; } else ret = ERROR_OUTOFMEMORY; } return ret; }
PMIB_IPNETTABLE getArpTable(void) { DWORD numEntities, returnSize; TDIEntityID *entitySet; HANDLE tcpFile; int i, totalNumber, TmpIdx, CurrIdx = 0; NTSTATUS status; PMIB_IPNETTABLE IpArpTable = NULL; PMIB_IPNETROW AdapterArpTable = NULL; TRACE("called.\n"); totalNumber = getNumArpEntries(); status = openTcpFile( &tcpFile ); if( !NT_SUCCESS(status) ) { TRACE("failure: %08x\n", (int)status ); return 0; } IpArpTable = HeapAlloc ( GetProcessHeap(), 0, sizeof(DWORD) + (sizeof(MIB_IPNETROW) * totalNumber) ); if (!IpArpTable) { closeTcpFile(tcpFile); return NULL; } status = tdiGetEntityIDSet( tcpFile, &entitySet, &numEntities ); for( i = 0; i < numEntities; i++ ) { if( isInterface( &entitySet[i] ) && hasArp( tcpFile, &entitySet[i] ) ) { status = tdiGetSetOfThings( tcpFile, INFO_CLASS_PROTOCOL, INFO_TYPE_PROVIDER, IP_MIB_ARPTABLE_ENTRY_ID, AT_ENTITY, entitySet[i].tei_instance, 0, sizeof(MIB_IPNETROW), (PVOID *)&AdapterArpTable, &returnSize ); if( status == STATUS_SUCCESS ) { for( TmpIdx = 0; TmpIdx < returnSize; TmpIdx++, CurrIdx++ ) IpArpTable->table[CurrIdx] = AdapterArpTable[TmpIdx]; tdiFreeThingSet( AdapterArpTable ); } } } closeTcpFile( tcpFile ); tdiFreeThingSet( entitySet ); IpArpTable->dwNumEntries = CurrIdx; return IpArpTable; }