diff --git a/dlls/wsock32/socket.c b/dlls/wsock32/socket.c index 7a2025fd5e2..b61e26dde47 100644 --- a/dlls/wsock32/socket.c +++ b/dlls/wsock32/socket.c @@ -2,6 +2,7 @@ * WSOCK32 specific functions * * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka. + * Copyright (C) 2003 Juan Lang. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -81,22 +82,21 @@ INT WINAPI WS1_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *o * From: "Peter Rindfuss" * Date: 1997/08/17 * - * WSCNTL_TCPIP_QUERY_INFO option is partially implemeted based + * The WSCNTL_TCPIP_QUERY_INFO option is partially implemented based * on observing the behaviour of WsControl with an app in * Windows 98. It is not fully implemented, and there could * be (are?) errors due to incorrect assumptions made. * * * WsControl returns WSCTL_SUCCESS on success. - * STATUS_BUFFER_TOO_SMALL is returned if the output buffer length - * (*pcbResponseInfoLen) is too small, otherwise errors return -1. - * - * It doesn't seem to generate errors that can be retrieved by - * WSAGetLastError(). + * ERROR_LOCK_VIOLATION is returned if the output buffer length + * (*pcbResponseInfoLen) is too small. This is an unusual error code, but + * it matches Win98's behavior. Other errors come from winerror.h, not from + * winsock.h. Again, this is to match Win98 behavior. * */ -DWORD WINAPI WsControl(DWORD protocoll, +DWORD WINAPI WsControl(DWORD protocol, DWORD action, LPVOID pRequestInfo, LPDWORD pcbRequestInfoLen, @@ -108,288 +108,400 @@ DWORD WINAPI WsControl(DWORD protocoll, rather than void */ TDIObjectID *pcommand = (TDIObjectID *)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 ); - - + 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: + case WSCNTL_TCPIP_QUERY_INFO: + { + if (pcommand->toi_class != INFO_CLASS_GENERIC && + pcommand->toi_class != INFO_CLASS_PROTOCOL) { - switch (pcommand->toi_id) + ERR("Unexpected class %ld for WSCNTL_TCPIP_QUERY_INFO", + 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: { - /* - ENTITY_LIST_ID seems to get number of adapters in the system. - (almost like an index to be used when calling other WsControl options) - */ - case ENTITY_LIST_ID: + TDIEntityID *baseptr = (TDIEntityID *)pResponseInfo; + DWORD numInt, i, ifTable, spaceNeeded; + PMIB_IFTABLE table; + + if (!pcbResponseInfoLen) + return ERROR_BAD_ENVIRONMENT; + if (pcommand->toi_class != INFO_CLASS_GENERIC) { - TDIEntityID *baseptr = pResponseInfo; - DWORD numInt, i, ipAddrTableSize; - PMIB_IPADDRTABLE table; + FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx", + pcommand->toi_class); + return (ERROR_BAD_ENVIRONMENT); + } - if (pcommand->toi_class != INFO_CLASS_GENERIC && - pcommand->toi_type != INFO_TYPE_PROVIDER) - { - FIXME ("Unexpected Option for ENTITY_LIST_ID request -> toi_class=0x%lx, toi_type=0x%lx\n", - pcommand->toi_class, pcommand->toi_type); - return (WSAEOPNOTSUPP); - } + GetNumberOfInterfaces(&numInt); + spaceNeeded = sizeof(TDIEntityID) * (numInt + 4); - GetNumberOfInterfaces(&numInt); + if (*pcbResponseInfoLen < spaceNeeded) + return (ERROR_LOCK_VIOLATION); - if (*pcbResponseInfoLen < sizeof(TDIEntityID)*(numInt*2) ) - { - return (STATUS_BUFFER_TOO_SMALL); - } + ifTable = 0; + GetIfTable(NULL, &ifTable, FALSE); + table = (PMIB_IFTABLE)calloc(1, ifTable); + if (!table) + return ERROR_NOT_ENOUGH_MEMORY; + GetIfTable(table, &ifTable, FALSE); - /* expect a 1:1 correspondence between interfaces and IP - addresses, so use the cheaper (less memory allocated) - GetIpAddrTable rather than GetIfTable */ - ipAddrTableSize = 0; - GetIpAddrTable(NULL, &ipAddrTableSize, FALSE); - table = (PMIB_IPADDRTABLE)calloc(1, ipAddrTableSize); - if (!table) return -1; /* FIXME: better error code */ - GetIpAddrTable(table, &ipAddrTableSize, FALSE); - - /* 0 it out first */ - memset(baseptr, 0, sizeof(TDIEntityID)*(table->dwNumEntries*2)); - - for (i=0; idwNumEntries; i++) - { - /* tei_instance is an network interface identifier. - I'm not quite sure what the difference is between tei_entity values of - CL_NL_ENTITY and IF_ENTITY */ - baseptr->tei_entity = CL_NL_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; - baseptr->tei_entity = IF_ENTITY; baseptr->tei_instance = table->table[i].dwIndex; baseptr++; - } - - /* Calculate size of out buffer */ - *pcbResponseInfoLen = sizeof(TDIEntityID)*(table->dwNumEntries*2); + spaceNeeded = sizeof(TDIEntityID) * (table->dwNumEntries + 4); + if (*pcbResponseInfoLen < spaceNeeded) + { free(table); - - break; + return (ERROR_LOCK_VIOLATION); } + memset(baseptr, 0, spaceNeeded); - /* ENTITY_TYPE_ID is used to obtain simple information about a - network card, such as MAC Address, description, interface type, - number of network addresses, etc. */ - case ENTITY_TYPE_ID: /* ALSO: IP_MIB_STATS_ID */ + for (i = 0; i < table->dwNumEntries; i++) { - if (pcommand->toi_class == INFO_CLASS_GENERIC && pcommand->toi_type == INFO_TYPE_PROVIDER) + /* Return IF_GENERIC on every interface, and AT_ENTITY, + * CL_NL_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) { - if (pcommand->toi_entity.tei_entity == IF_ENTITY) - { - * ((ULONG *)pResponseInfo) = IF_MIB; - - /* Calculate size of out buffer */ - *pcbResponseInfoLen = sizeof (ULONG); - - } - else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY) - { - * ((ULONG *)pResponseInfo) = CL_NL_IP; - - /* Calculate size of out buffer */ - *pcbResponseInfoLen = sizeof (ULONG); - } + 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 = CL_NL_ENTITY; + baseptr->tei_instance = table->table[i].dwIndex; + baseptr++; + baseptr->tei_entity = AT_ENTITY; + baseptr->tei_instance = table->table[i].dwIndex; + baseptr++; } - else if (pcommand->toi_class == INFO_CLASS_PROTOCOL && - pcommand->toi_type == INFO_TYPE_PROVIDER) - { - if (pcommand->toi_entity.tei_entity == IF_ENTITY) - { - MIB_IFROW row; - DWORD index = pcommand->toi_entity.tei_instance, ret; - DWORD size = sizeof(row) - sizeof(row.wszName) - - sizeof(row.bDescr); - - if (*pcbResponseInfoLen < size) - { - return (STATUS_BUFFER_TOO_SMALL); - } - row.dwIndex = index; - ret = GetIfEntry(&row); - if (ret != NO_ERROR) - { - ERR ("Error retrieving data for interface index %lu\n", index); - return -1; /* FIXME: better error code */ - } - size = sizeof(row) - sizeof(row.wszName) - - sizeof(row.bDescr) + row.dwDescrLen; - if (*pcbResponseInfoLen < size) - { - return (STATUS_BUFFER_TOO_SMALL); - } - memcpy(pResponseInfo, &row.dwIndex, size); - *pcbResponseInfoLen = size; - } - else if (pcommand->toi_entity.tei_entity == CL_NL_ENTITY) - { - /* This case is used to obtain general statistics about the - network */ - - if (*pcbResponseInfoLen < sizeof(MIB_IPSTATS)) - { - return (STATUS_BUFFER_TOO_SMALL); - } - GetIpStatistics((PMIB_IPSTATS)pResponseInfo); - - /* Calculate size of out buffer */ - *pcbResponseInfoLen = sizeof(MIB_IPSTATS); - } - } - else - { - FIXME ("Unexpected Option for ENTITY_TYPE_ID request -> toi_class=0x%lx, toi_type=0x%lx\n", - pcommand->toi_class, pcommand->toi_type); - - return (WSAEOPNOTSUPP); - } - - break; + baseptr->tei_entity = IF_GENERIC; + baseptr->tei_instance = table->table[i].dwIndex; + baseptr++; } + *pcbResponseInfoLen = spaceNeeded; + free(table); - /* IP_MIB_ADDRTABLE_ENTRY_ID is used to obtain more detailed information about a - particular network adapter */ - case IP_MIB_ADDRTABLE_ENTRY_ID: - { - DWORD index = pcommand->toi_entity.tei_instance; - PMIB_IPADDRROW baseIPInfo = (PMIB_IPADDRROW) pResponseInfo; - PMIB_IPADDRTABLE table; - DWORD tableSize, i; - - if (*pcbResponseInfoLen < sizeof(MIB_IPADDRROW)) - { - return (STATUS_BUFFER_TOO_SMALL); - } - - /* overkill, get entire table, because there isn't an - exported function that gets just one entry, and don't - necessarily want our own private export. */ - tableSize = 0; - GetIpAddrTable(NULL, &tableSize, FALSE); - table = (PMIB_IPADDRTABLE)calloc(1, tableSize); - if (!table) return -1; /* FIXME: better error code */ - GetIpAddrTable(table, &tableSize, FALSE); - for (i = 0; i < table->dwNumEntries; i++) - { - if (table->table[i].dwIndex == index) - { - memcpy(baseIPInfo, &table->table[i], - sizeof(MIB_IPADDRROW)); - break; - } - } - free(table); - - /************************************************************************/ - - /* Calculate size of out buffer */ - *pcbResponseInfoLen = sizeof(MIB_IPADDRROW); - break; - } - - - /* 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 IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */ - { - DWORD routeTableSize, numRoutes, ndx; - PMIB_IPFORWARDTABLE table; - IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo; - - GetIpForwardTable(NULL, &routeTableSize, FALSE); - numRoutes = min(routeTableSize - sizeof(MIB_IPFORWARDTABLE), 0) - / sizeof(MIB_IPFORWARDROW) + 1; - if (*pcbResponseInfoLen < sizeof(IPRouteEntry) * numRoutes) - { - return (STATUS_BUFFER_TOO_SMALL); - } - table = (PMIB_IPFORWARDTABLE)calloc(1, routeTableSize); - if (!table) return -1; /* FIXME: better return value */ - GetIpForwardTable(table, &routeTableSize, FALSE); - - 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; - - free(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, toi_type=0x%lx\n", - pcommand->toi_id, pcommand->toi_entity.tei_entity, pcommand->toi_entity.tei_instance, - pcommand->toi_class, pcommand->toi_type); - - return (WSAEOPNOTSUPP); - } + 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) + { + ERR ("Error retrieving data for interface index %lu\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. + * FIXME: Win98 seems to assume ARP will always be on interface + * index 1, so arp.exe fails when this isn't the case. + */ + 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 = (PULONG)pResponseInfo; + + if (!pcbResponseInfoLen) + return ERROR_BAD_ENVIRONMENT; + if (*pcbResponseInfoLen < sizeof(ULONG) * 2) + return (ERROR_LOCK_VIOLATION); + GetIpNetTable(NULL, &size, FALSE); + table = (PMIB_IPNETTABLE)calloc(1, 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; + free(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((PMIB_IPSTATS)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((PMIB_UDPSTATS)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((PMIB_TCPSTATS)pResponseInfo); + *pcbResponseInfoLen = sizeof(MIB_TCPSTATS); + } + break; + + default: + ERR("Unknown entity %ld for ENTITY_TYPE_ID query", + 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 = (PMIB_IPADDRROW) 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 = (PMIB_IPADDRTABLE)calloc(1, 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) + { + memcpy(baseIPInfo, &table->table[i], + sizeof(MIB_IPADDRROW)); + break; + } + } + free(table); + + *pcbResponseInfoLen = sizeof(MIB_IPADDRROW); + break; + } + + /* 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 IP_MIB_ROUTETABLE_ENTRY_ID: /* FIXME: not real name. Value is 0x101 */ + { + DWORD routeTableSize, numRoutes, ndx; + PMIB_IPFORWARDTABLE table; + IPRouteEntry *winRouteTable = (IPRouteEntry *) pResponseInfo; + + if (!pcbResponseInfoLen) + return ERROR_BAD_ENVIRONMENT; + GetIpForwardTable(NULL, &routeTableSize, FALSE); + numRoutes = min(routeTableSize - sizeof(MIB_IPFORWARDTABLE), 0) + / sizeof(MIB_IPFORWARDROW) + 1; + if (*pcbResponseInfoLen < sizeof(IPRouteEntry) * numRoutes) + return (ERROR_LOCK_VIOLATION); + table = (PMIB_IPFORWARDTABLE)calloc(1, routeTableSize); + if (!table) + return ERROR_NOT_ENOUGH_MEMORY; + GetIpForwardTable(table, &routeTableSize, FALSE); + + 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; + + free(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); + } } - 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("Protocoll Not Supported -> protocoll=0x%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n", - protocoll, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen); - - return (WSAEOPNOTSUPP); - } + 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%lx, action=0x%lx, Request=%p, RequestLen=%p, Response=%p, ResponseLen=%p\n", + protocol, action, pRequestInfo, pcbRequestInfoLen, pResponseInfo, pcbResponseInfoLen); + + return (WSAEOPNOTSUPP); + + } return (WSCTL_SUCCESS); } diff --git a/dlls/wsock32/wscontrol.h b/dlls/wsock32/wscontrol.h index 1cca5b1c62e..576a43395f6 100644 --- a/dlls/wsock32/wscontrol.h +++ b/dlls/wsock32/wscontrol.h @@ -6,9 +6,12 @@ * * The functionality of WsControl was created by observing its behaviour * in Windows 98, so there are likely to be bugs with the assumptions - * that were made. + * that were made. A significant amount of help came from + * http://tangentsoft.net/wskfaq/articles/wscontrol.html , especially the + * trace by Thomas Divine (www.pcausa.net). * * Copyright 2000 James Hatheway + * Copyright 2003 Juan Lang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,8 +31,6 @@ #ifndef WSCONTROL_H_INCLUDED #define WSCONTROL_H_INCLUDED -typedef unsigned char uchar; /* This doesn't seem to be in any standard headers */ - #define WSCTL_SUCCESS 0 /* @@ -57,44 +58,6 @@ typedef struct TDIObjectID unsigned long toi_id; } TDIObjectID; -typedef struct IPSNMPInfo -{ - unsigned long ipsi_forwarding; - unsigned long ipsi_defaultttl; - unsigned long ipsi_inreceives; - unsigned long ipsi_inhdrerrors; - unsigned long ipsi_inaddrerrors; - unsigned long ipsi_forwdatagrams; - unsigned long ipsi_inunknownprotos; - unsigned long ipsi_indiscards; - unsigned long ipsi_indelivers; - unsigned long ipsi_outrequests; - unsigned long ipsi_routingdiscards; - unsigned long ipsi_outdiscards; - unsigned long ipsi_outnoroutes; - unsigned long ipsi_reasmtimeout; - unsigned long ipsi_reasmreqds; - unsigned long ipsi_reasmoks; - unsigned long ipsi_reasmfails; - unsigned long ipsi_fragoks; - unsigned long ipsi_fragfails; - unsigned long ipsi_fragcreates; - unsigned long ipsi_numif; - unsigned long ipsi_numaddr; - unsigned long ipsi_numroutes; -} IPSNMPInfo; - -typedef struct IPAddrEntry -{ - unsigned long iae_addr; - unsigned long iae_index; - unsigned long iae_mask; - unsigned long iae_bcastaddr; - unsigned long iae_reasmsize; - ushort iae_context; - ushort iae_pad; -} IPAddrEntry; - #ifdef if_type #undef if_type #endif @@ -114,7 +77,7 @@ typedef struct IFEntry unsigned long if_mtu; unsigned long if_speed; unsigned long if_physaddrlen; - uchar if_physaddr[MAX_PHYSADDR_SIZE]; + unsigned char if_physaddr[MAX_PHYSADDR_SIZE]; unsigned long if_adminstatus; unsigned long if_operstatus; unsigned long if_lastchange; @@ -131,7 +94,7 @@ typedef struct IFEntry unsigned long if_outerrors; unsigned long if_outqlen; unsigned long if_descrlen; - uchar if_descr[1]; + unsigned char if_descr[1]; } IFEntry; @@ -153,34 +116,58 @@ typedef struct IPRouteEntry { } IPRouteEntry; -/* Not sure what EXACTLY most of this stuff does. - WsControl was implemented mainly by observing - its behaviour in Win98 ************************/ -#define INFO_CLASS_GENERIC 0x100 -#define INFO_CLASS_PROTOCOL 0x200 -#define INFO_TYPE_PROVIDER 0x100 -#define ENTITY_LIST_ID 0 -#define CL_NL_ENTITY 0x301 -#define IF_ENTITY 0x200 -#define ENTITY_TYPE_ID 1 -#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 -#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101 /* FIXME: not real name */ -/************************************************/ +/* Constants for use in the toi_id field */ +#define ENTITY_LIST_ID 0 /* to get the list of entity IDs */ +#define ENTITY_TYPE_ID 1 /* it's an interface; what type of interface is it? */ +#define IP_MIB_ROUTETABLE_ENTRY_ID 0x101 /* not real name */ +#define IP_MIB_ADDRTABLE_ENTRY_ID 0x102 -/* Valid values to get back from entity type ID query */ -#define CO_TL_NBF 0x400 /* Entity implements NBF prot. */ -#define CO_TL_SPX 0x402 /* Entity implements SPX prot. */ -#define CO_TL_TCP 0x404 /* Entity implements TCP prot. */ -#define CO_TL_SPP 0x406 /* Entity implements SPP prot. */ -#define CL_TL_NBF 0x401 /* CL NBF protocol */ -#define CL_TL_UDP 0x403 /* Entity implements UDP */ -#define ER_ICMP 0x380 /* The ICMP protocol */ -#define CL_NL_IPX 0x301 /* Entity implements IPX */ -#define CL_NL_IP 0x303 /* Entity implements IP */ -#define AT_ARP 0x280 /* Entity implements ARP */ -#define AT_NULL 0x282 /* Entity does no address */ -#define IF_GENERIC 0x200 /* Generic interface */ -#define IF_MIB 0x202 /* Supports MIB-2 interface */ +/* Constants for use in the toi_class field */ +#define INFO_CLASS_GENERIC 0x100 +#define INFO_CLASS_PROTOCOL 0x200 +/* Constants for use in the toi_type field */ +#define INFO_TYPE_PROVIDER 0x100 + +/* Interface types. The first one can be returned in the entity ID list--it's + * an interface, and it can be further queried for what type of interface it is. + */ +#define IF_GENERIC 0x200 /* generic interface */ +#define IF_MIB 0x202 /* supports MIB-2 interface */ + +/* address translation types. The first can be turned in the entity ID list-- + * it supports address translation of some type, and it can be further queried + * for what type of address translation it supports (I think). + */ +#define AT_ENTITY 0x280 +#define AT_ARP 0x280 +#define AT_NULL 0x282 /* doesn't do address translation after all (liar) */ + +/* network layer service providers. The first one can be returned in the + * entity list ID--it supports a network layer (datagram) service, and it can + * be further queried for what type of network layer service it provides. + */ +#define CL_NL_ENTITY 0x301 +#define CL_NL_IPX 0x301 /* implements IPX--probably won't see this, since + * we're querying the TCP protocol */ +#define CL_NL_IP 0x303 /* implements IP */ + +/* echo request/response types. The first can be returned in the entity ID + * list--it can be further queried for what type of echo it supports (I think). + */ +#define ER_ENTITY 0x380 +#define ER_ICMP 0x380 + +/* connection-oriented transport layer protocols--you know the drill by now */ +#define CO_TL_ENTITY 0x400 +#define CO_TL_NBF 0x400 +#define CO_TL_SPX 0x402 +#define CO_TL_TCP 0x404 +#define CO_TL_SPP 0x406 + +/* connectionless transport layer protocols--you know the drill by now */ +#define CL_TL_ENTITY 0x401 +#define CL_TL_NBF 0x401 +#define CL_TL_UDP 0x403 #endif /* WSCONTROL_H_INCLUDED */