int NET_TCP_LISTEN(AGENT_REQUEST *request, AGENT_RESULT *result) { MIB_TCPTABLE *pTcpTable = NULL; DWORD dwSize, dwRetVal; int i, ret = SYSINFO_RET_FAIL; unsigned short port; char *port_str; if (1 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } port_str = get_rparam(request, 0); if (NULL == port_str || SUCCEED != is_ushort(port_str, &port)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter.")); return SYSINFO_RET_FAIL; } dwSize = sizeof(MIB_TCPTABLE); pTcpTable = (MIB_TCPTABLE *)zbx_malloc(pTcpTable, dwSize); /* Make an initial call to GetTcpTable to get the necessary size into the dwSize variable */ if (ERROR_INSUFFICIENT_BUFFER == (dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE))) pTcpTable = (MIB_TCPTABLE *)zbx_realloc(pTcpTable, dwSize); /* Make a second call to GetTcpTable to get the actual data we require */ if (NO_ERROR == (dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE))) { for (i = 0; i < (int)pTcpTable->dwNumEntries; i++) { if (MIB_TCP_STATE_LISTEN == pTcpTable->table[i].dwState && port == ntohs((u_short)pTcpTable->table[i].dwLocalPort)) { SET_UI64_RESULT(result, 1); break; } } ret = SYSINFO_RET_OK; } else { zabbix_log(LOG_LEVEL_DEBUG, "GetTcpTable failed with error: %s", strerror_from_system(dwRetVal)); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain system information: %s", strerror_from_system(dwRetVal))); goto clean; } if (!ISSET_UI64(result)) SET_UI64_RESULT(result, 0); clean: zbx_free(pTcpTable); return ret; }
PortSet PortsManager::GetNowPorts() { PortSet newPorts; PMIB_TCPTABLE pTcpTable; DWORD dwSize = 0; DWORD dwRetVal = 0; unsigned short *port_ptr; DWORD i; /* Get size required by GetTcpTable() */ if (GetTcpTable(NULL, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { pTcpTable = (MIB_TCPTABLE *) malloc (dwSize); } /* Get actual data using GetTcpTable() */ if ((dwRetVal = GetTcpTable(pTcpTable, &dwSize, 0)) == NO_ERROR) { if (pTcpTable->dwNumEntries > 0) { for (i=0; i<pTcpTable->dwNumEntries; i++) { //addr_ptr = (char *)&pTcpTable->table[i].dwLocalAddr; //port_ptr = (unsigned short *)&pTcpTable->table[i].dwLocalPort; //addr_ptr = (char *)&pTcpTable->table[i].dwRemoteAddr; port_ptr = (unsigned short *)&pTcpTable->table[i].dwRemotePort; DWORD state = pTcpTable->table[i].dwState; newPorts.insert(Port(*port_ptr, state)); } } } free(pTcpTable); return newPorts; }
//---------------------------------------------------------------------------- // Wrapper to GetTcpTable() //---------------------------------------------------------------------------- DWORD MyGetTcpTable(PMIB_TCPTABLE& pTcpTable, BOOL fOrder) { DWORD status = NO_ERROR; DWORD statusRetry = NO_ERROR; DWORD dwActualSize = 0; // query for buffer size needed status = GetTcpTable(pTcpTable, &dwActualSize, fOrder); if (status == NO_ERROR) { printf("No error\n"); return status; } else if (status == ERROR_INSUFFICIENT_BUFFER) { // need more space pTcpTable = (PMIB_TCPTABLE) malloc(dwActualSize); assert(pTcpTable); statusRetry = GetTcpTable(pTcpTable, &dwActualSize, fOrder); return statusRetry; } else { return status; } }
int NET_TCP_LISTEN(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result) { MIB_TCPTABLE *pTcpTable = NULL; DWORD dwSize, dwRetVal; int i, ret = SYSINFO_RET_FAIL; unsigned short port; char tmp[8]; assert(result); init_result(result); if (num_param(param) > 1) return SYSINFO_RET_FAIL; if (0 != get_param(param, 1, tmp, sizeof(tmp))) return SYSINFO_RET_FAIL; if (SUCCEED != is_ushort(tmp, &port)) return SYSINFO_RET_FAIL; dwSize = sizeof(MIB_TCPTABLE); pTcpTable = (MIB_TCPTABLE *)zbx_malloc(pTcpTable, dwSize); /* Make an initial call to GetTcpTable to get the necessary size into the dwSize variable */ if (ERROR_INSUFFICIENT_BUFFER == (dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE))) pTcpTable = (MIB_TCPTABLE *)zbx_realloc(pTcpTable, dwSize); /* Make a second call to GetTcpTable to get the actual data we require */ if (NO_ERROR == (dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE))) { for (i = 0; i < (int)pTcpTable->dwNumEntries; i++) { if (MIB_TCP_STATE_LISTEN == pTcpTable->table[i].dwState && port == ntohs((u_short)pTcpTable->table[i].dwLocalPort)) { SET_UI64_RESULT(result, 1); break; } } ret = SYSINFO_RET_OK; } else { zabbix_log(LOG_LEVEL_DEBUG, "GetTcpTable failed with error: %s", strerror_from_system(dwRetVal)); goto clean; } if (!ISSET_UI64(result)) SET_UI64_RESULT(result, 0); clean: zbx_free(pTcpTable); return ret; }
HRESULT AdbUtils::GetPortState(ULONG nPort, ULONG *nStateID) { MIB_TCPTABLE TcpTable[100]; DWORD nSize = sizeof(TcpTable); if (NO_ERROR == GetTcpTable(&TcpTable[0], &nSize, TRUE)) { DWORD nCount = TcpTable[0].dwNumEntries; if (nCount > 0) { for (DWORD i=0; i<nCount; i++) { MIB_TCPROW TcpRow = TcpTable[0].table[i]; DWORD temp1 = TcpRow.dwLocalPort; int temp2 = temp1 / 256 + (temp1 % 256) * 256; if (temp2 == nPort) { *nStateID = TcpRow.dwState; return S_OK; } } } return S_FALSE; } return S_FALSE; }
int GetValidPort(){ int port; HINSTANCE hdll; int CurrentUsePort[1000] = {0}; int portnum = 0, i = 0; unsigned long table_len; MIB_TCPTABLE tcp_table; MIB_UDPTABLE udp_table; port=0; DWORD (*GetTcpTable)(PMIB_TCPTABLE,PDWORD,bool); DWORD (*GetUdpTable)(PMIB_UDPTABLE,PDWORD,bool); hdll=LoadLibrary("iphlpapi.dll"); if(!hdll) return port; (FARPROC &)GetTcpTable=GetProcAddress(hdll,"GetTcpTable"); (FARPROC &)GetUdpTable=GetProcAddress(hdll,"GetUdpTable"); if(GetTcpTable){ TRACE("get tcp table\r\n"); table_len=(unsigned long)sizeof(tcp_table); GetTcpTable(&tcp_table,(PDWORD)&table_len,false); } if(GetUdpTable){ TRACE("get udp table\r\n"); table_len=sizeof(MIB_UDPTABLE); //GetUdpTable(&udp_table,&table_len,1); } FreeLibrary(hdll); return port; }
int tcpTable_load(netsnmp_cache *cache, void *vmagic) { PMIB_TCPTABLE pTcpTable = NULL; DWORD dwActualSize = 0; DWORD status = NO_ERROR; /* * query for the buffer size needed */ status = GetTcpTable(pTcpTable, &dwActualSize, TRUE); if (status == ERROR_INSUFFICIENT_BUFFER) { pTcpTable = (PMIB_TCPTABLE) malloc(dwActualSize); if (pTcpTable != NULL) { /* * Get the sorted TCP table */ status = GetTcpTable(pTcpTable, &dwActualSize, TRUE); } } if (status == NO_ERROR) { int i; DEBUGMSGTL(("mibII/tcpTable", "Loaded TCP Table (WIN32)\n")); tcp_size = pTcpTable->dwNumEntries -1; /* entries are counted starting with 0 */ tcp_head = pTcpTable->table; /* * Count the number of established connections * Probably not actually necessary for Windows */ for (i = 0; i < tcp_size; i++) { if (tcp_head[i].dwState == 5 /* established */ || tcp_head[i].dwState == 8 /* closeWait */ ) tcp_estab++; } return 0; } DEBUGMSGTL(("mibII/tcpTable", "Failed to load TCP Table (win32)\n")); if (pTcpTable) free(pTcpTable); return -1; }
VOID ShowTcpTable() { PMIB_TCPTABLE tcpTable; DWORD error, dwSize; DWORD i; CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN]; CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN]; CHAR Host[ADDRESSLEN]; CHAR Remote[ADDRESSLEN]; /* Get the table of TCP endpoints */ dwSize = sizeof (MIB_TCPTABLE); /* Should also work when we get new connections between 2 GetTcpTable() * calls: */ do { tcpTable = (PMIB_TCPTABLE) HeapAlloc(GetProcessHeap(), 0, dwSize); error = GetTcpTable(tcpTable, &dwSize, TRUE); if ( error != NO_ERROR ) HeapFree(GetProcessHeap(), 0, tcpTable); } while ( error == ERROR_INSUFFICIENT_BUFFER ); if (error != NO_ERROR) { printf("Failed to snapshot TCP endpoints.\n"); DoFormatMessage(error); exit(EXIT_FAILURE); } /* Dump the TCP table */ for (i = 0; i < tcpTable->dwNumEntries; i++) { /* If we aren't showing all connections, only display established, close wait * and time wait. This is the default output for netstat */ if (bDoShowAllCons || (tcpTable->table[i].dwState == MIB_TCP_STATE_ESTAB) || (tcpTable->table[i].dwState == MIB_TCP_STATE_CLOSE_WAIT) || (tcpTable->table[i].dwState == MIB_TCP_STATE_TIME_WAIT)) { /* I've split this up so it's easier to follow */ GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN); GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN); GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, HOSTNAMELEN); GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, PORTNAMELEN); sprintf(Host, "%s:%s", HostIp, HostPort); sprintf(Remote, "%s:%s", RemoteIp, RemotePort); _tprintf(_T(" %-6s %-22s %-22s %s\n"), _T("TCP"), Host, Remote, TcpState[tcpTable->table[i].dwState]); } } HeapFree(GetProcessHeap(), 0, tcpTable); }
static void NETSTAT_tcp_table(void) { PMIB_TCPTABLE table; DWORD err, size, i; WCHAR HostIp[MAX_HOSTNAME_LEN], HostPort[32]; WCHAR RemoteIp[MAX_HOSTNAME_LEN], RemotePort[32]; WCHAR Host[MAX_HOSTNAME_LEN + 32]; WCHAR Remote[MAX_HOSTNAME_LEN + 32]; size = sizeof(MIB_TCPTABLE); do { table = (PMIB_TCPTABLE)HeapAlloc(GetProcessHeap(), 0, size); err = GetTcpTable(table, &size, TRUE); if (err != NO_ERROR) HeapFree(GetProcessHeap(), 0, table); } while (err == ERROR_INSUFFICIENT_BUFFER); if (err) return; for (i = 0; i < table->dwNumEntries; i++) { if ((table->table[i].u.dwState == MIB_TCP_STATE_CLOSE_WAIT) || (table->table[i].u.dwState == MIB_TCP_STATE_ESTAB) || (table->table[i].u.dwState == MIB_TCP_STATE_TIME_WAIT)) { NETSTAT_host_name(table->table[i].dwLocalAddr, HostIp); NETSTAT_port_name(table->table[i].dwLocalPort, HostPort); NETSTAT_host_name(table->table[i].dwRemoteAddr, RemoteIp); NETSTAT_port_name(table->table[i].dwRemotePort, RemotePort); sprintfW(Host, fmtcolon, HostIp, HostPort); sprintfW(Remote, fmtcolon, RemoteIp, RemotePort); NETSTAT_wprintf(fmttcpout, tcpW, Host, Remote, tcpstatesW[table->table[i].u.dwState]); } } HeapFree(GetProcessHeap(), 0, table); }
BOOL AdbUtils::PortUsedTCP(ULONG uPort) { MIB_TCPTABLE TcpTable[100]; DWORD nSize = sizeof(TcpTable); if (NO_ERROR == GetTcpTable(&TcpTable[0], &nSize, TRUE)) { DWORD nCount = TcpTable[0].dwNumEntries; if (nCount > 0) { for (DWORD i=0; i<nCount; i++) { MIB_TCPROW TcpRow = TcpTable[0].table[i]; DWORD temp1 = TcpRow.dwLocalPort; int temp2 = temp1 / 256 + (temp1 % 256) * 256; if (temp2 == uPort) { return TRUE; } } } return FALSE; } return FALSE; }
/* * retrieve tcp table for win 2000 and NT4 ? */ DWORD windows_get_tcp_table_win2000_down(struct connection_table **table_connection) { PMIB_TCPTABLE pTcpTable = NULL; struct connection_entry * current_connection; DWORD dwSize = 0; DWORD dwRetVal = 0; DWORD result = ERROR_SUCCESS; DWORD i, state; do { dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE); dprintf("[NETSTAT TCP] need %d bytes",dwSize); /* Get the size required by GetTcpTable() */ if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) { pTcpTable = (MIB_TCPTABLE *) malloc (dwSize); } else if (dwRetVal != NO_ERROR) { result = ERROR_NOT_SUPPORTED; break; } if ((dwRetVal = GetTcpTable(pTcpTable, &dwSize, TRUE)) == NO_ERROR) { dprintf("[NETSTAT] found %d tcp connections", pTcpTable->dwNumEntries); for (i = 0 ; i < pTcpTable->dwNumEntries ; i++) { // check available memory and allocate if necessary if (check_and_allocate(table_connection) == ERROR_NOT_ENOUGH_MEMORY) { free(pTcpTable); return ERROR_NOT_ENOUGH_MEMORY; } current_connection = &(*table_connection)->table[(*table_connection)->entries]; current_connection->type = AF_INET; current_connection->local_addr.addr = pTcpTable->table[i].dwLocalAddr; current_connection->remote_addr.addr = pTcpTable->table[i].dwRemoteAddr; current_connection->local_port = ntohs((u_short)(pTcpTable->table[i].dwLocalPort & 0x0000ffff)); // if socket is in LISTEN, remote_port is garbage, force value to 0 if (pTcpTable->table[i].dwState == MIB_TCP_STATE_LISTEN) current_connection->remote_port = 0; else current_connection->remote_port = ntohs((u_short)(pTcpTable->table[i].dwRemotePort & 0x0000ffff)); state = pTcpTable->table[i].dwState; if ((state <= 0) || (state > 12)) state = 13; // points to UNKNOWN in the state array strncpy(current_connection->state, tcp_connection_states[state], sizeof(current_connection->state)); strncpy(current_connection->protocol, "tcp", sizeof(current_connection->protocol)); // force program_name to "-" strncpy(current_connection->program_name, "-", sizeof(current_connection->program_name)); (*table_connection)->entries++; } free(pTcpTable); } else { // GetTcpTable failed result = GetLastError(); break; } } while (0) ; return result; }
void FillTcpTable(HWND hwnd) { MIB_TCPTABLE *tcpTable = (MIB_TCPTABLE*)malloc(sizeof(MIB_TCPTABLE)); HWND listView = GetDlgItem(hwnd, TCP_LIST); LVITEM item; memset(&item, 0, sizeof(item)); item.mask = LVIF_TEXT; item.cchTextMax = 256; struct in_addr IpAddr; TCHAR szLocalAddr[128]; TCHAR szLocalPort[6]; TCHAR szRemoteAddr[128]; TCHAR szRemotePort[6]; size_t num; DWORD expSize = sizeof(MIB_TCPTABLE); if(GetTcpTable(tcpTable, &expSize, TRUE) == ERROR_INSUFFICIENT_BUFFER) { free(tcpTable); tcpTable = (MIB_TCPTABLE*)malloc(expSize); } if(GetTcpTable(tcpTable, &expSize, TRUE) != NO_ERROR) { MessageBox(NULL, TEXT("Error retrieving TCP table!"), NULL, 0); } else { SendMessage(listView, LVM_DELETEALLITEMS, 0, 0); for(int i = 0; i < (int)tcpTable->dwNumEntries; ++i) { item.iItem = i; item.iSubItem = 0; switch(tcpTable->table[i].dwState) { case MIB_TCP_STATE_CLOSED: item.pszText = TEXT("CLOSED"); break; case MIB_TCP_STATE_LISTEN: item.pszText = TEXT("LISTEN"); break; case MIB_TCP_STATE_SYN_SENT: item.pszText = TEXT("SYN-SENT"); break; case MIB_TCP_STATE_SYN_RCVD: item.pszText = TEXT("SYN-RECEIVED"); break; case MIB_TCP_STATE_ESTAB: item.pszText = TEXT("ESTABLISHED"); break; case MIB_TCP_STATE_FIN_WAIT1: item.pszText = TEXT("FIN-WAIT-1"); break; case MIB_TCP_STATE_FIN_WAIT2: item.pszText = TEXT("FIN-WAIT-2"); break; case MIB_TCP_STATE_CLOSE_WAIT: item.pszText = TEXT("CLOSE-WAIT"); break; case MIB_TCP_STATE_CLOSING: item.pszText = TEXT("CLOSING"); break; case MIB_TCP_STATE_LAST_ACK: item.pszText = TEXT("LAST-ACK"); break; case MIB_TCP_STATE_TIME_WAIT: item.pszText = TEXT("TIME-WAIT"); break; case MIB_TCP_STATE_DELETE_TCB: item.pszText = TEXT("DELETE-TCB"); break; default: item.pszText = TEXT("UNKNOWN"); break; } SendMessage(listView, LVM_INSERTITEM, i, (LPARAM)&item); IpAddr.S_un.S_addr = (u_long)tcpTable->table[i].dwLocalAddr; mbstowcs_s(&num, szLocalAddr, inet_ntoa(IpAddr), 128); item.iSubItem = 1; item.pszText = szLocalAddr; SendMessage(listView, LVM_SETITEM, i, (LPARAM)&item); _itow_s((u_short)tcpTable->table[i].dwLocalPort, szLocalPort, 6, 10); item.iSubItem = 2; item.pszText = szLocalPort; SendMessage(listView, LVM_SETITEM, i, (LPARAM)&item); IpAddr.S_un.S_addr = (u_long)tcpTable->table[i].dwRemoteAddr; mbstowcs_s(&num, szRemoteAddr, inet_ntoa(IpAddr), 128); item.iSubItem = 3; item.pszText = szRemoteAddr; SendMessage(listView, LVM_SETITEM, i, (LPARAM)&item); _itow_s((u_short)tcpTable->table[i].dwRemotePort, szRemotePort, 6, 10); item.iSubItem = 4; item.pszText = szRemotePort; SendMessage(listView, LVM_SETITEM, i, (LPARAM)&item); } } if(tcpTable) { free(tcpTable); } }
DWORD WINAPI WsControl(DWORD protocol, DWORD action, LPVOID pRequestInfo, LPDWORD pcbRequestInfoLen, LPVOID pResponseInfo, LPDWORD pcbResponseInfoLen) { /* Get the command structure into a pointer we can use, rather than void */ TDIObjectID *pcommand = pRequestInfo; /* validate input parameters. Error codes are from winerror.h, not from * winsock.h. pcbResponseInfoLen is apparently allowed to be NULL for some * commands, since winipcfg.exe fails if we ensure it's non-NULL in every * case. */ if (protocol != IPPROTO_TCP) return ERROR_INVALID_PARAMETER; if (!pcommand) return ERROR_INVALID_PARAMETER; if (!pcbRequestInfoLen) return ERROR_INVALID_ACCESS; if (*pcbRequestInfoLen < sizeof(TDIObjectID)) return ERROR_INVALID_ACCESS; if (!pResponseInfo) return ERROR_INVALID_PARAMETER; if (pcommand->toi_type != INFO_TYPE_PROVIDER) return ERROR_INVALID_PARAMETER; TRACE (" WsControl TOI_ID=>0x%lx<, {TEI_ENTITY=0x%lx, TEI_INSTANCE=0x%lx}, TOI_CLASS=0x%lx, TOI_TYPE=0x%lx\n", pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance, pcommand->toi_class, pcommand->toi_type ); switch (action) { case WSCNTL_TCPIP_QUERY_INFO: { if (pcommand->toi_class != INFO_CLASS_GENERIC && pcommand->toi_class != INFO_CLASS_PROTOCOL) { ERR("Unexpected class %ld for WSCNTL_TCPIP_QUERY_INFO\n", pcommand->toi_class); return ERROR_BAD_ENVIRONMENT; } switch (pcommand->toi_id) { /* ENTITY_LIST_ID gets the list of "entity IDs", where an entity may represent an interface, or a datagram service, or address translation, or other fun things. Typically an entity ID represents a class of service, which is further queried for what type it is. Different types will then have more specific queries defined. */ case ENTITY_LIST_ID: { TDIEntityID *baseptr = pResponseInfo; DWORD numInt, i, ifTable, spaceNeeded; PMIB_IFTABLE table; if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (pcommand->toi_class != INFO_CLASS_GENERIC) { FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx\n", pcommand->toi_class); return (ERROR_BAD_ENVIRONMENT); } GetNumberOfInterfaces(&numInt); spaceNeeded = sizeof(TDIEntityID) * (numInt * 2 + 3); if (*pcbResponseInfoLen < spaceNeeded) return (ERROR_LOCK_VIOLATION); ifTable = 0; GetIfTable(NULL, &ifTable, FALSE); table = HeapAlloc( GetProcessHeap(), 0, ifTable ); if (!table) return ERROR_NOT_ENOUGH_MEMORY; GetIfTable(table, &ifTable, FALSE); spaceNeeded = sizeof(TDIEntityID) * (table->dwNumEntries + 4); if (*pcbResponseInfoLen < spaceNeeded) { HeapFree( GetProcessHeap(), 0, table ); return ERROR_LOCK_VIOLATION; } memset(baseptr, 0, spaceNeeded); for (i = 0; i < table->dwNumEntries; i++) { /* Return IF_GENERIC and CL_NL_ENTITY on every interface, and * AT_ENTITY, CL_TL_ENTITY, and CO_TL_ENTITY on the first * interface. MS returns them only on the loopback interface, * but it doesn't seem to matter. */ if (i == 0) { baseptr->tei_entity = CO_TL_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; baseptr->tei_entity = CL_TL_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; baseptr->tei_entity = AT_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; } baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; baseptr->tei_entity = IF_GENERIC; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; } *pcbResponseInfoLen = spaceNeeded; HeapFree( GetProcessHeap(), 0, table ); break; } /* Returns MIB-II statistics for an interface */ case ENTITY_TYPE_ID: switch (pcommand->toi_entity.tei_entity) { case IF_GENERIC: if (pcommand->toi_class == INFO_CLASS_GENERIC) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; *((ULONG *)pResponseInfo) = IF_MIB; *pcbResponseInfoLen = sizeof(ULONG); } else if (pcommand->toi_class == INFO_CLASS_PROTOCOL) { MIB_IFROW row; DWORD index = pcommand->toi_entity.tei_instance, ret; DWORD size = sizeof(row) - sizeof(row.wszName) - sizeof(row.bDescr); if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (*pcbResponseInfoLen < size) return (ERROR_LOCK_VIOLATION); row.dwIndex = index; ret = GetIfEntry(&row); if (ret != NO_ERROR) { /* FIXME: Win98's arp.exe insists on querying index 1 for * its MIB-II stats, regardless of the tei_instances * returned in the ENTITY_LIST query above. If the query * fails, arp.exe fails. So, I do this hack return value * if index is 1 and the query failed just to get arp.exe * to continue. */ if (index == 1) return NO_ERROR; ERR ("Error retrieving data for interface index %u\n", index); return ret; } size = sizeof(row) - sizeof(row.wszName) - sizeof(row.bDescr) + row.dwDescrLen; if (*pcbResponseInfoLen < size) return (ERROR_LOCK_VIOLATION); memcpy(pResponseInfo, &row.dwIndex, size); *pcbResponseInfoLen = size; } break; /* Returns address-translation related data. In our case, this is * ARP. */ case AT_ENTITY: if (pcommand->toi_class == INFO_CLASS_GENERIC) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; *((ULONG *)pResponseInfo) = AT_ARP; *pcbResponseInfoLen = sizeof(ULONG); } else if (pcommand->toi_class == INFO_CLASS_PROTOCOL) { PMIB_IPNETTABLE table; DWORD size; PULONG output = pResponseInfo; if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (*pcbResponseInfoLen < sizeof(ULONG) * 2) return (ERROR_LOCK_VIOLATION); GetIpNetTable(NULL, &size, FALSE); table = HeapAlloc( GetProcessHeap(), 0, size ); if (!table) return ERROR_NOT_ENOUGH_MEMORY; GetIpNetTable(table, &size, FALSE); /* FIXME: I don't understand the meaning of the ARP output * very well, but it seems to indicate how many ARP entries * exist. I don't know whether this should reflect the * number per interface, as I'm only testing with a single * interface. So, I lie and say all ARP entries exist on * a single interface--the first one that appears in the * ARP table. */ *(output++) = table->dwNumEntries; *output = table->table[0].dwIndex; HeapFree( GetProcessHeap(), 0, table ); *pcbResponseInfoLen = sizeof(ULONG) * 2; } break; /* Returns connectionless network layer statistics--in our case, * this is IP. */ case CL_NL_ENTITY: if (pcommand->toi_class == INFO_CLASS_GENERIC) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; *((ULONG *)pResponseInfo) = CL_NL_IP; *pcbResponseInfoLen = sizeof(ULONG); } else if (pcommand->toi_class == INFO_CLASS_PROTOCOL) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (*pcbResponseInfoLen < sizeof(MIB_IPSTATS)) return ERROR_LOCK_VIOLATION; GetIpStatistics(pResponseInfo); *pcbResponseInfoLen = sizeof(MIB_IPSTATS); } break; /* Returns connectionless transport layer statistics--in our case, * this is UDP. */ case CL_TL_ENTITY: if (pcommand->toi_class == INFO_CLASS_GENERIC) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; *((ULONG *)pResponseInfo) = CL_TL_UDP; *pcbResponseInfoLen = sizeof(ULONG); } else if (pcommand->toi_class == INFO_CLASS_PROTOCOL) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (*pcbResponseInfoLen < sizeof(MIB_UDPSTATS)) return ERROR_LOCK_VIOLATION; GetUdpStatistics(pResponseInfo); *pcbResponseInfoLen = sizeof(MIB_UDPSTATS); } break; /* Returns connection-oriented transport layer statistics--in our * case, this is TCP. */ case CO_TL_ENTITY: if (pcommand->toi_class == INFO_CLASS_GENERIC) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; *((ULONG *)pResponseInfo) = CO_TL_TCP; *pcbResponseInfoLen = sizeof(ULONG); } else if (pcommand->toi_class == INFO_CLASS_PROTOCOL) { if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (*pcbResponseInfoLen < sizeof(MIB_TCPSTATS)) return ERROR_LOCK_VIOLATION; GetTcpStatistics(pResponseInfo); *pcbResponseInfoLen = sizeof(MIB_TCPSTATS); } break; default: ERR("Unknown entity %ld for ENTITY_TYPE_ID query\n", pcommand->toi_entity.tei_entity); } break; /* This call returns the IP address, subnet mask, and broadcast * address for an interface. If there are multiple IP addresses for * the interface with the given index, returns the "first" one. */ case IP_MIB_ADDRTABLE_ENTRY_ID: { DWORD index = pcommand->toi_entity.tei_instance; PMIB_IPADDRROW baseIPInfo = pResponseInfo; PMIB_IPADDRTABLE table; DWORD tableSize, i; if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; if (*pcbResponseInfoLen < sizeof(MIB_IPADDRROW)) return (ERROR_LOCK_VIOLATION); /* get entire table, because there isn't an exported function that gets just one entry. */ tableSize = 0; GetIpAddrTable(NULL, &tableSize, FALSE); table = HeapAlloc( GetProcessHeap(), 0, tableSize ); if (!table) return ERROR_NOT_ENOUGH_MEMORY; GetIpAddrTable(table, &tableSize, FALSE); for (i = 0; i < table->dwNumEntries; i++) { if (table->table[i].dwIndex == index) { TRACE("Found IP info for tei_instance 0x%x:\n", index); TRACE("IP 0x%08x, mask 0x%08x\n", table->table[i].dwAddr, table->table[i].dwMask); *baseIPInfo = table->table[i]; break; } } HeapFree( GetProcessHeap(), 0, table ); *pcbResponseInfoLen = sizeof(MIB_IPADDRROW); break; } case IP_MIB_TABLE_ENTRY_ID: { switch (pcommand->toi_entity.tei_entity) { /* This call returns the routing table. * No official documentation found, even the name of the command is unknown. * Work is based on * http://www.cyberport.com/~tangent/programming/winsock/articles/wscontrol.html * and testings done with winipcfg.exe, route.exe and ipconfig.exe. * pcommand->toi_entity.tei_instance seems to be the interface number * but route.exe outputs only the information for the last interface * if only the routes for the pcommand->toi_entity.tei_instance * interface are returned. */ case CL_NL_ENTITY: { DWORD routeTableSize, numRoutes, ndx, ret; PMIB_IPFORWARDTABLE table; IPRouteEntry *winRouteTable = pResponseInfo; if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; ret = GetIpForwardTable(NULL, &routeTableSize, FALSE); if (ret != ERROR_INSUFFICIENT_BUFFER) return ret; numRoutes = (routeTableSize - sizeof(MIB_IPFORWARDTABLE)) / sizeof(MIB_IPFORWARDROW) + 1; if (*pcbResponseInfoLen < sizeof(IPRouteEntry) * numRoutes) return (ERROR_LOCK_VIOLATION); table = HeapAlloc( GetProcessHeap(), 0, routeTableSize ); if (!table) return ERROR_NOT_ENOUGH_MEMORY; ret = GetIpForwardTable(table, &routeTableSize, FALSE); if (ret != NO_ERROR) { HeapFree( GetProcessHeap(), 0, table ); return ret; } memset(pResponseInfo, 0, sizeof(IPRouteEntry) * numRoutes); for (ndx = 0; ndx < table->dwNumEntries; ndx++) { winRouteTable->ire_addr = table->table[ndx].dwForwardDest; winRouteTable->ire_index = table->table[ndx].dwForwardIfIndex; winRouteTable->ire_metric = table->table[ndx].dwForwardMetric1; /* winRouteTable->ire_option4 = winRouteTable->ire_option5 = winRouteTable->ire_option6 = */ winRouteTable->ire_gw = table->table[ndx].dwForwardNextHop; /* winRouteTable->ire_option8 = winRouteTable->ire_option9 = winRouteTable->ire_option10 = */ winRouteTable->ire_mask = table->table[ndx].dwForwardMask; /* winRouteTable->ire_option12 = */ winRouteTable++; } /* calculate the length of the data in the output buffer */ *pcbResponseInfoLen = sizeof(IPRouteEntry) * table->dwNumEntries; HeapFree( GetProcessHeap(), 0, table ); } break; case AT_ARP: { DWORD arpTableSize, numEntries, ret; PMIB_IPNETTABLE table; if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; ret = GetIpNetTable(NULL, &arpTableSize, FALSE); if (ret != ERROR_INSUFFICIENT_BUFFER) return ret; numEntries = (arpTableSize - sizeof(MIB_IPNETTABLE)) / sizeof(MIB_IPNETROW) + 1; if (*pcbResponseInfoLen < sizeof(MIB_IPNETROW) * numEntries) return (ERROR_LOCK_VIOLATION); table = HeapAlloc( GetProcessHeap(), 0, arpTableSize ); if (!table) return ERROR_NOT_ENOUGH_MEMORY; ret = GetIpNetTable(table, &arpTableSize, FALSE); if (ret != NO_ERROR) { HeapFree( GetProcessHeap(), 0, table ); return ret; } if (*pcbResponseInfoLen < sizeof(MIB_IPNETROW) * table->dwNumEntries) { HeapFree( GetProcessHeap(), 0, table ); return ERROR_LOCK_VIOLATION; } memcpy(pResponseInfo, table->table, sizeof(MIB_IPNETROW) * table->dwNumEntries); /* calculate the length of the data in the output buffer */ *pcbResponseInfoLen = sizeof(MIB_IPNETROW) * table->dwNumEntries; HeapFree( GetProcessHeap(), 0, table ); } break; case CO_TL_ENTITY: { DWORD tcpTableSize, numEntries, ret; PMIB_TCPTABLE table; DWORD i; if (!pcbResponseInfoLen) return ERROR_BAD_ENVIRONMENT; ret = GetTcpTable(NULL, &tcpTableSize, FALSE); if (ret != ERROR_INSUFFICIENT_BUFFER) return ret; numEntries = (tcpTableSize - sizeof(MIB_TCPTABLE)) / sizeof(MIB_TCPROW) + 1; if (*pcbResponseInfoLen < sizeof(MIB_TCPROW) * numEntries) return (ERROR_LOCK_VIOLATION); table = HeapAlloc( GetProcessHeap(), 0, tcpTableSize ); if (!table) return ERROR_NOT_ENOUGH_MEMORY; ret = GetTcpTable(table, &tcpTableSize, FALSE); if (ret != NO_ERROR) { HeapFree( GetProcessHeap(), 0, table ); return ret; } if (*pcbResponseInfoLen < sizeof(MIB_TCPROW) * table->dwNumEntries) { HeapFree( GetProcessHeap(), 0, table ); return ERROR_LOCK_VIOLATION; } for (i = 0; i < table->dwNumEntries; i++) { USHORT sPort; sPort = ntohs((USHORT)table->table[i].dwLocalPort); table->table[i].dwLocalPort = (DWORD)sPort; sPort = ntohs((USHORT)table->table[i].dwRemotePort); table->table[i].dwRemotePort = (DWORD)sPort; } memcpy(pResponseInfo, table->table, sizeof(MIB_TCPROW) * table->dwNumEntries); /* calculate the length of the data in the output buffer */ *pcbResponseInfoLen = sizeof(MIB_TCPROW) * table->dwNumEntries; HeapFree( GetProcessHeap(), 0, table ); } break; default: { FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx\n", pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance, pcommand->toi_class); return (ERROR_BAD_ENVIRONMENT); } } } break; default: { FIXME ("Command ID Not Supported -> toi_id=0x%lx, toi_entity={tei_entity=0x%lx, tei_instance=0x%lx}, toi_class=0x%lx\n", pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance, pcommand->toi_class); return (ERROR_BAD_ENVIRONMENT); } } break; } case WSCNTL_TCPIP_ICMP_ECHO: { unsigned int addr = *(unsigned int*)pRequestInfo; #if 0 int timeout= *(unsigned int*)(inbuf+4); short x1 = *(unsigned short*)(inbuf+8); short sendbufsize = *(unsigned short*)(inbuf+10); char x2 = *(unsigned char*)(inbuf+12); char ttl = *(unsigned char*)(inbuf+13); char service = *(unsigned char*)(inbuf+14); char type= *(unsigned char*)(inbuf+15); /* 0x2: don't fragment*/ #endif FIXME("(ICMP_ECHO) to 0x%08x stub\n", addr); break; } default: FIXME("Protocol Not Supported -> protocol=0x%x, action=0x%x, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n", protocol, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen); return (WSAEOPNOTSUPP); } return (WSCTL_SUCCESS); }
EIF_INTEGER posix_gettcptable(EIF_POINTER pTcpTable, EIF_POINTER pwdSize, EIF_BOOLEAN bOrder) { return GetTcpTable (pTcpTable, pwdSize, bOrder); }