Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmain.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2008 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 #include <assert.h> 00021 #include <stdarg.h> 00022 #include <stdlib.h> 00023 #include <limits.h> 00024 00025 #define NONAMELESSUNION 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "snmp.h" 00030 #include "iphlpapi.h" 00031 #include "wine/debug.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(inetmib1); 00034 00038 static DWORD copyInt(AsnAny *value, void *src) 00039 { 00040 value->asnType = ASN_INTEGER; 00041 value->asnValue.number = *(DWORD *)src; 00042 return SNMP_ERRORSTATUS_NOERROR; 00043 } 00044 00045 static void setStringValue(AsnAny *value, BYTE type, DWORD len, BYTE *str) 00046 { 00047 AsnAny strValue; 00048 00049 strValue.asnType = type; 00050 strValue.asnValue.string.stream = str; 00051 strValue.asnValue.string.length = len; 00052 strValue.asnValue.string.dynamic = FALSE; 00053 SnmpUtilAsnAnyCpy(value, &strValue); 00054 } 00055 00056 typedef DWORD (*copyValueFunc)(AsnAny *value, void *src); 00057 00058 struct structToAsnValue 00059 { 00060 size_t offset; 00061 copyValueFunc copy; 00062 }; 00063 00064 static AsnInteger32 mapStructEntryToValue(struct structToAsnValue *map, 00065 UINT mapLen, void *record, UINT id, SnmpVarBind *pVarBind) 00066 { 00067 /* OIDs are 1-based */ 00068 if (!id) 00069 return SNMP_ERRORSTATUS_NOSUCHNAME; 00070 --id; 00071 if (id >= mapLen) 00072 return SNMP_ERRORSTATUS_NOSUCHNAME; 00073 if (!map[id].copy) 00074 return SNMP_ERRORSTATUS_NOSUCHNAME; 00075 return map[id].copy(&pVarBind->value, (BYTE *)record + map[id].offset); 00076 } 00077 00078 static DWORD copyIpAddr(AsnAny *value, void *src) 00079 { 00080 setStringValue(value, ASN_IPADDRESS, sizeof(DWORD), src); 00081 return SNMP_ERRORSTATUS_NOERROR; 00082 } 00083 00084 static UINT mib2[] = { 1,3,6,1,2,1 }; 00085 static UINT mib2System[] = { 1,3,6,1,2,1,1 }; 00086 00087 typedef BOOL (*varqueryfunc)(BYTE bPduType, SnmpVarBind *pVarBind, 00088 AsnInteger32 *pErrorStatus); 00089 00090 struct mibImplementation 00091 { 00092 AsnObjectIdentifier name; 00093 void (*init)(void); 00094 varqueryfunc query; 00095 void (*cleanup)(void); 00096 }; 00097 00098 static UINT mib2IfNumber[] = { 1,3,6,1,2,1,2,1 }; 00099 static PMIB_IFTABLE ifTable; 00100 00101 static void mib2IfNumberInit(void) 00102 { 00103 DWORD size = 0, ret = GetIfTable(NULL, &size, FALSE); 00104 00105 if (ret == ERROR_INSUFFICIENT_BUFFER) 00106 { 00107 MIB_IFTABLE *table = HeapAlloc(GetProcessHeap(), 0, size); 00108 if (table) 00109 { 00110 if (!GetIfTable(table, &size, FALSE)) ifTable = table; 00111 else HeapFree(GetProcessHeap(), 0, table ); 00112 } 00113 } 00114 } 00115 00116 static void mib2IfNumberCleanup(void) 00117 { 00118 HeapFree(GetProcessHeap(), 0, ifTable); 00119 } 00120 00121 static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind, 00122 AsnInteger32 *pErrorStatus) 00123 { 00124 AsnObjectIdentifier numberOid = DEFINE_OID(mib2IfNumber); 00125 BOOL ret = TRUE; 00126 00127 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 00128 pErrorStatus); 00129 00130 switch (bPduType) 00131 { 00132 case SNMP_PDU_GET: 00133 case SNMP_PDU_GETNEXT: 00134 if ((bPduType == SNMP_PDU_GET && 00135 !SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength)) 00136 || SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength) 00137 < 0) 00138 { 00139 DWORD numIfs = ifTable ? ifTable->dwNumEntries : 0; 00140 00141 copyInt(&pVarBind->value, &numIfs); 00142 if (bPduType == SNMP_PDU_GETNEXT) 00143 { 00144 SnmpUtilOidFree(&pVarBind->name); 00145 SnmpUtilOidCpy(&pVarBind->name, &numberOid); 00146 } 00147 *pErrorStatus = SNMP_ERRORSTATUS_NOERROR; 00148 } 00149 else 00150 { 00151 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00152 /* Caller deals with OID if bPduType == SNMP_PDU_GETNEXT, so don't 00153 * need to set it here. 00154 */ 00155 } 00156 break; 00157 case SNMP_PDU_SET: 00158 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 00159 ret = FALSE; 00160 break; 00161 default: 00162 FIXME("0x%02x: unsupported PDU type\n", bPduType); 00163 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00164 } 00165 return ret; 00166 } 00167 00168 static DWORD copyOperStatus(AsnAny *value, void *src) 00169 { 00170 value->asnType = ASN_INTEGER; 00171 /* The IPHlpApi definition of operational status differs from the MIB2 one, 00172 * so map it to the MIB2 value. 00173 */ 00174 switch (*(DWORD *)src) 00175 { 00176 case MIB_IF_OPER_STATUS_OPERATIONAL: 00177 value->asnValue.number = MIB_IF_ADMIN_STATUS_UP; 00178 break; 00179 case MIB_IF_OPER_STATUS_CONNECTING: 00180 case MIB_IF_OPER_STATUS_CONNECTED: 00181 value->asnValue.number = MIB_IF_ADMIN_STATUS_TESTING; 00182 break; 00183 default: 00184 value->asnValue.number = MIB_IF_ADMIN_STATUS_DOWN; 00185 }; 00186 return SNMP_ERRORSTATUS_NOERROR; 00187 } 00188 00189 /* Given an OID and a base OID that it must begin with, finds the item and 00190 * integer instance from the OID. E.g., given an OID foo.1.2 and a base OID 00191 * foo, returns item 1 and instance 2. 00192 * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is 00193 * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME. 00194 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and 00195 * instance, or item 1, instance 1 if either is missing. 00196 */ 00197 static AsnInteger32 getItemAndIntegerInstanceFromOid(AsnObjectIdentifier *oid, 00198 AsnObjectIdentifier *base, BYTE bPduType, UINT *item, UINT *instance) 00199 { 00200 AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; 00201 00202 switch (bPduType) 00203 { 00204 case SNMP_PDU_GETNEXT: 00205 if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0) 00206 { 00207 *item = 1; 00208 *instance = 1; 00209 } 00210 else if (!SnmpUtilOidNCmp(oid, base, base->idLength)) 00211 { 00212 if (oid->idLength == base->idLength || 00213 oid->idLength == base->idLength + 1) 00214 { 00215 /* Either the table or an item within the table is specified, 00216 * but the instance is not. Get the first instance. 00217 */ 00218 *instance = 1; 00219 if (oid->idLength == base->idLength + 1) 00220 *item = oid->ids[base->idLength]; 00221 else 00222 *item = 1; 00223 } 00224 else 00225 { 00226 *item = oid->ids[base->idLength]; 00227 *instance = oid->ids[base->idLength + 1] + 1; 00228 } 00229 } 00230 else 00231 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00232 break; 00233 default: 00234 if (!SnmpUtilOidNCmp(oid, base, base->idLength)) 00235 { 00236 if (oid->idLength == base->idLength || 00237 oid->idLength == base->idLength + 1) 00238 { 00239 /* Either the table or an item within the table is specified, 00240 * but the instance is not. 00241 */ 00242 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00243 } 00244 else 00245 { 00246 *item = oid->ids[base->idLength]; 00247 *instance = oid->ids[base->idLength + 1]; 00248 } 00249 } 00250 else 00251 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00252 } 00253 return ret; 00254 } 00255 00256 /* Given an OID and a base OID that it must begin with, finds the item from the 00257 * OID. E.g., given an OID foo.1 and a base OID foo, returns item 1. 00258 * If bPduType is not SNMP_PDU_GETNEXT and the item is missing, returns 00259 * SNMP_ERRORSTATUS_NOSUCHNAME. 00260 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item, or item 00261 * 1 if the item is missing. 00262 */ 00263 static AsnInteger32 getItemFromOid(AsnObjectIdentifier *oid, 00264 AsnObjectIdentifier *base, BYTE bPduType, UINT *item) 00265 { 00266 AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; 00267 00268 switch (bPduType) 00269 { 00270 case SNMP_PDU_GETNEXT: 00271 if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0) 00272 *item = 1; 00273 else if (!SnmpUtilOidNCmp(oid, base, base->idLength)) 00274 { 00275 if (oid->idLength == base->idLength) 00276 { 00277 /* The item is missing, assume the first item */ 00278 *item = 1; 00279 } 00280 else 00281 *item = oid->ids[base->idLength] + 1; 00282 } 00283 else 00284 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00285 break; 00286 default: 00287 if (!SnmpUtilOidNCmp(oid, base, base->idLength)) 00288 { 00289 if (oid->idLength == base->idLength) 00290 { 00291 /* The item is missing */ 00292 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00293 } 00294 else 00295 { 00296 *item = oid->ids[base->idLength]; 00297 if (!*item) 00298 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00299 } 00300 } 00301 else 00302 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00303 } 00304 return ret; 00305 } 00306 00307 struct GenericTable 00308 { 00309 DWORD numEntries; 00310 BYTE entries[1]; 00311 }; 00312 00313 static DWORD oidToIpAddr(AsnObjectIdentifier *oid) 00314 { 00315 assert(oid && oid->idLength >= 4); 00316 /* Map the IDs to an IP address in little-endian order */ 00317 return (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 | 00318 (BYTE)oid->ids[1] << 8 | (BYTE)oid->ids[0]; 00319 } 00320 00321 typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst); 00322 typedef int (*compareFunc)(const void *key, const void *value); 00323 00324 /* Finds the first value in the table that matches key. Returns its 1-based 00325 * index if found, or 0 if not found. 00326 */ 00327 static UINT findValueInTable(const void *key, 00328 struct GenericTable *table, size_t tableEntrySize, compareFunc compare) 00329 { 00330 UINT index = 0; 00331 void *value; 00332 00333 value = bsearch(key, table->entries, table->numEntries, tableEntrySize, 00334 compare); 00335 if (value) 00336 index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize + 1; 00337 return index; 00338 } 00339 00340 /* Finds the first value in the table that matches oid, using makeKey to 00341 * convert the oid to a key for comparison. Returns the value's 1-based 00342 * index if found, or 0 if not found. 00343 */ 00344 static UINT findOidInTable(AsnObjectIdentifier *oid, 00345 struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, 00346 compareFunc compare) 00347 { 00348 UINT index = 0; 00349 void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize); 00350 00351 if (key) 00352 { 00353 makeKey(oid, key); 00354 index = findValueInTable(key, table, tableEntrySize, compare); 00355 HeapFree(GetProcessHeap(), 0, key); 00356 } 00357 return index; 00358 } 00359 00360 /* Finds the first successor to the value in the table that does matches oid, 00361 * using makeKey to convert the oid to a key for comparison. A successor is 00362 * a value that does not match oid, so if multiple entries match an oid, only 00363 * the first will ever be returned using this method. 00364 * Returns the successor's 1-based index if found, or 0 if not found. 00365 */ 00366 static UINT findNextOidInTable(AsnObjectIdentifier *oid, 00367 struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, 00368 compareFunc compare) 00369 { 00370 UINT index = 0; 00371 void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize); 00372 00373 if (key) 00374 { 00375 makeKey(oid, key); 00376 index = findValueInTable(key, table, tableEntrySize, compare); 00377 if (index == 0) 00378 { 00379 /* Not found in table. If it's less than the first entry, return 00380 * the first index. Otherwise just return 0 and let the caller 00381 * handle finding the successor. 00382 */ 00383 if (compare(key, table->entries) < 0) 00384 index = 1; 00385 } 00386 else 00387 { 00388 /* Skip any entries that match the same key. This enumeration will 00389 * be incomplete, but it's what Windows appears to do if there are 00390 * multiple entries with the same index in a table, and it avoids 00391 * an infinite loop. 00392 */ 00393 for (++index; index <= table->numEntries && compare(key, 00394 &table->entries[tableEntrySize * (index - 1)]) == 0; ++index) 00395 ; 00396 } 00397 HeapFree(GetProcessHeap(), 0, key); 00398 } 00399 return index; 00400 } 00401 00402 /* Given an OID and a base OID that it must begin with, finds the item and 00403 * element of the table whose value matches the instance from the OID. 00404 * The OID is converted to a key with the function makeKey, and compared 00405 * against entries in the table with the function compare. 00406 * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is 00407 * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME. 00408 * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and 00409 * instance, or item 1, instance 1 if either is missing. 00410 */ 00411 static AsnInteger32 getItemAndInstanceFromTable(AsnObjectIdentifier *oid, 00412 AsnObjectIdentifier *base, UINT instanceLen, BYTE bPduType, 00413 struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, 00414 compareFunc compare, UINT *item, UINT *instance) 00415 { 00416 AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; 00417 00418 if (!table) 00419 return SNMP_ERRORSTATUS_NOSUCHNAME; 00420 00421 switch (bPduType) 00422 { 00423 case SNMP_PDU_GETNEXT: 00424 if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0) 00425 { 00426 /* Return the first item and instance from the table */ 00427 *item = 1; 00428 *instance = 1; 00429 } 00430 else if (!SnmpUtilOidNCmp(oid, base, base->idLength) && 00431 oid->idLength < base->idLength + instanceLen + 1) 00432 { 00433 /* Either the table or an item is specified, but the instance is 00434 * not. 00435 */ 00436 *instance = 1; 00437 if (oid->idLength >= base->idLength + 1) 00438 { 00439 *item = oid->ids[base->idLength]; 00440 if (!*item) 00441 *item = 1; 00442 } 00443 else 00444 *item = 1; 00445 } 00446 else if (!SnmpUtilOidNCmp(oid, base, base->idLength) && 00447 oid->idLength == base->idLength + instanceLen + 1) 00448 { 00449 *item = oid->ids[base->idLength]; 00450 if (!*item) 00451 { 00452 *instance = 1; 00453 *item = 1; 00454 } 00455 else 00456 { 00457 AsnObjectIdentifier instanceOid = { instanceLen, 00458 oid->ids + base->idLength + 1 }; 00459 00460 *instance = findNextOidInTable(&instanceOid, table, 00461 tableEntrySize, makeKey, compare); 00462 if (!*instance || *instance > table->numEntries) 00463 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00464 } 00465 } 00466 else 00467 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00468 break; 00469 default: 00470 if (!SnmpUtilOidNCmp(oid, base, base->idLength) && 00471 oid->idLength == base->idLength + instanceLen + 1) 00472 { 00473 *item = oid->ids[base->idLength]; 00474 if (!*item) 00475 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00476 else 00477 { 00478 AsnObjectIdentifier instanceOid = { instanceLen, 00479 oid->ids + base->idLength + 1 }; 00480 00481 *instance = findOidInTable(&instanceOid, table, tableEntrySize, 00482 makeKey, compare); 00483 if (!*instance) 00484 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00485 } 00486 } 00487 else 00488 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00489 } 00490 return ret; 00491 } 00492 00493 static INT setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, 00494 UINT item) 00495 { 00496 UINT id; 00497 AsnObjectIdentifier oid; 00498 INT ret; 00499 00500 SnmpUtilOidFree(dst); 00501 ret = SnmpUtilOidCpy(dst, base); 00502 if (ret) 00503 { 00504 oid.idLength = 1; 00505 oid.ids = &id; 00506 id = item; 00507 ret = SnmpUtilOidAppend(dst, &oid); 00508 } 00509 return ret; 00510 } 00511 00512 static INT setOidWithItemAndIpAddr(AsnObjectIdentifier *dst, 00513 AsnObjectIdentifier *base, UINT item, DWORD addr) 00514 { 00515 UINT id; 00516 BYTE *ptr; 00517 AsnObjectIdentifier oid; 00518 INT ret; 00519 00520 ret = setOidWithItem(dst, base, item); 00521 if (ret) 00522 { 00523 oid.idLength = 1; 00524 oid.ids = &id; 00525 for (ptr = (BYTE *)&addr; ret && ptr < (BYTE *)&addr + sizeof(DWORD); 00526 ptr++) 00527 { 00528 id = *ptr; 00529 ret = SnmpUtilOidAppend(dst, &oid); 00530 } 00531 } 00532 return ret; 00533 } 00534 00535 static INT setOidWithItemAndInteger(AsnObjectIdentifier *dst, 00536 AsnObjectIdentifier *base, UINT item, UINT instance) 00537 { 00538 AsnObjectIdentifier oid; 00539 INT ret; 00540 00541 ret = setOidWithItem(dst, base, item); 00542 if (ret) 00543 { 00544 oid.idLength = 1; 00545 oid.ids = &instance; 00546 ret = SnmpUtilOidAppend(dst, &oid); 00547 } 00548 return ret; 00549 } 00550 00551 static DWORD copyIfRowDescr(AsnAny *value, void *src) 00552 { 00553 PMIB_IFROW row = (PMIB_IFROW)((BYTE *)src - 00554 FIELD_OFFSET(MIB_IFROW, dwDescrLen)); 00555 DWORD ret; 00556 00557 if (row->dwDescrLen) 00558 { 00559 setStringValue(value, ASN_OCTETSTRING, row->dwDescrLen, row->bDescr); 00560 ret = SNMP_ERRORSTATUS_NOERROR; 00561 } 00562 else 00563 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00564 return ret; 00565 } 00566 00567 static DWORD copyIfRowPhysAddr(AsnAny *value, void *src) 00568 { 00569 PMIB_IFROW row = (PMIB_IFROW)((BYTE *)src - 00570 FIELD_OFFSET(MIB_IFROW, dwPhysAddrLen)); 00571 DWORD ret; 00572 00573 if (row->dwPhysAddrLen) 00574 { 00575 setStringValue(value, ASN_OCTETSTRING, row->dwPhysAddrLen, 00576 row->bPhysAddr); 00577 ret = SNMP_ERRORSTATUS_NOERROR; 00578 } 00579 else 00580 ret = SNMP_ERRORSTATUS_NOSUCHNAME; 00581 return ret; 00582 } 00583 00584 static struct structToAsnValue mib2IfEntryMap[] = { 00585 { FIELD_OFFSET(MIB_IFROW, dwIndex), copyInt }, 00586 { FIELD_OFFSET(MIB_IFROW, dwDescrLen), copyIfRowDescr }, 00587 { FIELD_OFFSET(MIB_IFROW, dwType), copyInt }, 00588 { FIELD_OFFSET(MIB_IFROW, dwMtu), copyInt }, 00589 { FIELD_OFFSET(MIB_IFROW, dwSpeed), copyInt }, 00590 { FIELD_OFFSET(MIB_IFROW, dwPhysAddrLen), copyIfRowPhysAddr }, 00591 { FIELD_OFFSET(MIB_IFROW, dwAdminStatus), copyInt }, 00592 { FIELD_OFFSET(MIB_IFROW, dwOperStatus), copyOperStatus }, 00593 { FIELD_OFFSET(MIB_IFROW, dwLastChange), copyInt }, 00594 { FIELD_OFFSET(MIB_IFROW, dwInOctets), copyInt }, 00595 { FIELD_OFFSET(MIB_IFROW, dwInUcastPkts), copyInt }, 00596 { FIELD_OFFSET(MIB_IFROW, dwInNUcastPkts), copyInt }, 00597 { FIELD_OFFSET(MIB_IFROW, dwInDiscards), copyInt }, 00598 { FIELD_OFFSET(MIB_IFROW, dwInErrors), copyInt }, 00599 { FIELD_OFFSET(MIB_IFROW, dwInUnknownProtos), copyInt }, 00600 { FIELD_OFFSET(MIB_IFROW, dwOutOctets), copyInt }, 00601 { FIELD_OFFSET(MIB_IFROW, dwOutUcastPkts), copyInt }, 00602 { FIELD_OFFSET(MIB_IFROW, dwOutNUcastPkts), copyInt }, 00603 { FIELD_OFFSET(MIB_IFROW, dwOutDiscards), copyInt }, 00604 { FIELD_OFFSET(MIB_IFROW, dwOutErrors), copyInt }, 00605 { FIELD_OFFSET(MIB_IFROW, dwOutQLen), copyInt }, 00606 }; 00607 00608 static UINT mib2IfEntry[] = { 1,3,6,1,2,1,2,2,1 }; 00609 00610 static BOOL mib2IfEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, 00611 AsnInteger32 *pErrorStatus) 00612 { 00613 AsnObjectIdentifier entryOid = DEFINE_OID(mib2IfEntry); 00614 BOOL ret = TRUE; 00615 00616 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 00617 pErrorStatus); 00618 00619 switch (bPduType) 00620 { 00621 case SNMP_PDU_GET: 00622 case SNMP_PDU_GETNEXT: 00623 if (!ifTable) 00624 { 00625 /* There is no interface present, so let the caller deal 00626 * with finding the successor. 00627 */ 00628 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00629 } 00630 else 00631 { 00632 UINT tableIndex = 0, item = 0; 00633 00634 *pErrorStatus = getItemAndIntegerInstanceFromOid(&pVarBind->name, 00635 &entryOid, bPduType, &item, &tableIndex); 00636 if (!*pErrorStatus) 00637 { 00638 assert(tableIndex); 00639 assert(item); 00640 if (tableIndex > ifTable->dwNumEntries) 00641 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00642 else 00643 { 00644 *pErrorStatus = mapStructEntryToValue(mib2IfEntryMap, 00645 DEFINE_SIZEOF(mib2IfEntryMap), 00646 &ifTable->table[tableIndex - 1], item, 00647 pVarBind); 00648 if (bPduType == SNMP_PDU_GETNEXT) 00649 ret = setOidWithItemAndInteger(&pVarBind->name, 00650 &entryOid, item, tableIndex); 00651 } 00652 } 00653 } 00654 break; 00655 case SNMP_PDU_SET: 00656 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 00657 ret = FALSE; 00658 break; 00659 default: 00660 FIXME("0x%02x: unsupported PDU type\n", bPduType); 00661 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00662 } 00663 return ret; 00664 } 00665 00666 static UINT mib2Ip[] = { 1,3,6,1,2,1,4 }; 00667 static MIB_IPSTATS ipStats; 00668 00669 static void mib2IpStatsInit(void) 00670 { 00671 GetIpStatistics(&ipStats); 00672 } 00673 00674 static struct structToAsnValue mib2IpMap[] = { 00675 { FIELD_OFFSET(MIB_IPSTATS, dwForwarding), copyInt }, /* 1 */ 00676 { FIELD_OFFSET(MIB_IPSTATS, dwDefaultTTL), copyInt }, /* 2 */ 00677 { FIELD_OFFSET(MIB_IPSTATS, dwInReceives), copyInt }, /* 3 */ 00678 { FIELD_OFFSET(MIB_IPSTATS, dwInHdrErrors), copyInt }, /* 4 */ 00679 { FIELD_OFFSET(MIB_IPSTATS, dwInAddrErrors), copyInt }, /* 5 */ 00680 { FIELD_OFFSET(MIB_IPSTATS, dwForwDatagrams), copyInt }, /* 6 */ 00681 { FIELD_OFFSET(MIB_IPSTATS, dwInUnknownProtos), copyInt }, /* 7 */ 00682 { FIELD_OFFSET(MIB_IPSTATS, dwInDiscards), copyInt }, /* 8 */ 00683 { FIELD_OFFSET(MIB_IPSTATS, dwInDelivers), copyInt }, /* 9 */ 00684 { FIELD_OFFSET(MIB_IPSTATS, dwOutRequests), copyInt }, /* 10 */ 00685 { FIELD_OFFSET(MIB_IPSTATS, dwOutDiscards), copyInt }, /* 11 */ 00686 { FIELD_OFFSET(MIB_IPSTATS, dwOutNoRoutes), copyInt }, /* 12 */ 00687 { FIELD_OFFSET(MIB_IPSTATS, dwReasmTimeout), copyInt }, /* 13 */ 00688 { FIELD_OFFSET(MIB_IPSTATS, dwReasmReqds), copyInt }, /* 14 */ 00689 { FIELD_OFFSET(MIB_IPSTATS, dwReasmOks), copyInt }, /* 15 */ 00690 { FIELD_OFFSET(MIB_IPSTATS, dwReasmFails), copyInt }, /* 16 */ 00691 { FIELD_OFFSET(MIB_IPSTATS, dwFragOks), copyInt }, /* 17 */ 00692 { FIELD_OFFSET(MIB_IPSTATS, dwFragFails), copyInt }, /* 18 */ 00693 { FIELD_OFFSET(MIB_IPSTATS, dwFragCreates), copyInt }, /* 19 */ 00694 { 0, NULL }, /* 20: not used, IP addr table */ 00695 { 0, NULL }, /* 21: not used, route table */ 00696 { 0, NULL }, /* 22: not used, net to media (ARP) table */ 00697 { FIELD_OFFSET(MIB_IPSTATS, dwRoutingDiscards), copyInt }, /* 23 */ 00698 }; 00699 00700 static BOOL mib2IpStatsQuery(BYTE bPduType, SnmpVarBind *pVarBind, 00701 AsnInteger32 *pErrorStatus) 00702 { 00703 AsnObjectIdentifier myOid = DEFINE_OID(mib2Ip); 00704 UINT item = 0; 00705 BOOL ret = TRUE; 00706 00707 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 00708 pErrorStatus); 00709 00710 switch (bPduType) 00711 { 00712 case SNMP_PDU_GET: 00713 case SNMP_PDU_GETNEXT: 00714 *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, 00715 &item); 00716 if (!*pErrorStatus) 00717 { 00718 *pErrorStatus = mapStructEntryToValue(mib2IpMap, 00719 DEFINE_SIZEOF(mib2IpMap), &ipStats, item, pVarBind); 00720 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 00721 ret = setOidWithItem(&pVarBind->name, &myOid, item); 00722 } 00723 break; 00724 case SNMP_PDU_SET: 00725 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 00726 ret = FALSE; 00727 break; 00728 default: 00729 FIXME("0x%02x: unsupported PDU type\n", bPduType); 00730 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00731 } 00732 return ret; 00733 } 00734 00735 static UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1 }; 00736 static PMIB_IPADDRTABLE ipAddrTable; 00737 00738 static struct structToAsnValue mib2IpAddrMap[] = { 00739 { FIELD_OFFSET(MIB_IPADDRROW, dwAddr), copyIpAddr }, 00740 { FIELD_OFFSET(MIB_IPADDRROW, dwIndex), copyInt }, 00741 { FIELD_OFFSET(MIB_IPADDRROW, dwMask), copyIpAddr }, 00742 { FIELD_OFFSET(MIB_IPADDRROW, dwBCastAddr), copyInt }, 00743 { FIELD_OFFSET(MIB_IPADDRROW, dwReasmSize), copyInt }, 00744 }; 00745 00746 static void mib2IpAddrInit(void) 00747 { 00748 DWORD size = 0, ret = GetIpAddrTable(NULL, &size, TRUE); 00749 00750 if (ret == ERROR_INSUFFICIENT_BUFFER) 00751 { 00752 MIB_IPADDRTABLE *table = HeapAlloc(GetProcessHeap(), 0, size); 00753 if (table) 00754 { 00755 if (!GetIpAddrTable(table, &size, TRUE)) ipAddrTable = table; 00756 else HeapFree(GetProcessHeap(), 0, table ); 00757 } 00758 } 00759 } 00760 00761 static void mib2IpAddrCleanup(void) 00762 { 00763 HeapFree(GetProcessHeap(), 0, ipAddrTable); 00764 } 00765 00766 static void oidToIpAddrRow(AsnObjectIdentifier *oid, void *dst) 00767 { 00768 MIB_IPADDRROW *row = dst; 00769 00770 row->dwAddr = oidToIpAddr(oid); 00771 } 00772 00773 static int compareIpAddrRow(const void *a, const void *b) 00774 { 00775 const MIB_IPADDRROW *key = a, *value = b; 00776 00777 return key->dwAddr - value->dwAddr; 00778 } 00779 00780 static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind, 00781 AsnInteger32 *pErrorStatus) 00782 { 00783 AsnObjectIdentifier myOid = DEFINE_OID(mib2IpAddr); 00784 UINT tableIndex = 0, item = 0; 00785 BOOL ret = TRUE; 00786 00787 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 00788 pErrorStatus); 00789 00790 switch (bPduType) 00791 { 00792 case SNMP_PDU_GET: 00793 case SNMP_PDU_GETNEXT: 00794 *pErrorStatus = getItemAndInstanceFromTable(&pVarBind->name, 00795 &myOid, 4, bPduType, (struct GenericTable *)ipAddrTable, 00796 sizeof(MIB_IPADDRROW), oidToIpAddrRow, compareIpAddrRow, &item, 00797 &tableIndex); 00798 if (!*pErrorStatus) 00799 { 00800 assert(tableIndex); 00801 assert(item); 00802 *pErrorStatus = mapStructEntryToValue(mib2IpAddrMap, 00803 DEFINE_SIZEOF(mib2IpAddrMap), 00804 &ipAddrTable->table[tableIndex - 1], item, pVarBind); 00805 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 00806 ret = setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, 00807 ipAddrTable->table[tableIndex - 1].dwAddr); 00808 } 00809 break; 00810 case SNMP_PDU_SET: 00811 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 00812 ret = FALSE; 00813 break; 00814 default: 00815 FIXME("0x%02x: unsupported PDU type\n", bPduType); 00816 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00817 } 00818 return ret; 00819 } 00820 00821 static UINT mib2IpRoute[] = { 1,3,6,1,2,1,4,21,1 }; 00822 static PMIB_IPFORWARDTABLE ipRouteTable; 00823 00824 static struct structToAsnValue mib2IpRouteMap[] = { 00825 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardDest), copyIpAddr }, 00826 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardIfIndex), copyInt }, 00827 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric1), copyInt }, 00828 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric2), copyInt }, 00829 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric3), copyInt }, 00830 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric4), copyInt }, 00831 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardNextHop), copyIpAddr }, 00832 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardType), copyInt }, 00833 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardProto), copyInt }, 00834 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardAge), copyInt }, 00835 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMask), copyIpAddr }, 00836 { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric5), copyInt }, 00837 }; 00838 00839 static void mib2IpRouteInit(void) 00840 { 00841 DWORD size = 0, ret = GetIpForwardTable(NULL, &size, TRUE); 00842 00843 if (ret == ERROR_INSUFFICIENT_BUFFER) 00844 { 00845 MIB_IPFORWARDTABLE *table = HeapAlloc(GetProcessHeap(), 0, size); 00846 if (table) 00847 { 00848 if (!GetIpForwardTable(table, &size, TRUE)) ipRouteTable = table; 00849 else HeapFree(GetProcessHeap(), 0, table ); 00850 } 00851 } 00852 } 00853 00854 static void mib2IpRouteCleanup(void) 00855 { 00856 HeapFree(GetProcessHeap(), 0, ipRouteTable); 00857 } 00858 00859 static void oidToIpForwardRow(AsnObjectIdentifier *oid, void *dst) 00860 { 00861 MIB_IPFORWARDROW *row = dst; 00862 00863 row->dwForwardDest = oidToIpAddr(oid); 00864 } 00865 00866 static int compareIpForwardRow(const void *a, const void *b) 00867 { 00868 const MIB_IPFORWARDROW *key = a, *value = b; 00869 00870 return key->dwForwardDest - value->dwForwardDest; 00871 } 00872 00873 static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind, 00874 AsnInteger32 *pErrorStatus) 00875 { 00876 AsnObjectIdentifier myOid = DEFINE_OID(mib2IpRoute); 00877 UINT tableIndex = 0, item = 0; 00878 BOOL ret = TRUE; 00879 00880 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 00881 pErrorStatus); 00882 00883 switch (bPduType) 00884 { 00885 case SNMP_PDU_GET: 00886 case SNMP_PDU_GETNEXT: 00887 *pErrorStatus = getItemAndInstanceFromTable(&pVarBind->name, 00888 &myOid, 4, bPduType, (struct GenericTable *)ipRouteTable, 00889 sizeof(MIB_IPFORWARDROW), oidToIpForwardRow, compareIpForwardRow, 00890 &item, &tableIndex); 00891 if (!*pErrorStatus) 00892 { 00893 assert(tableIndex); 00894 assert(item); 00895 *pErrorStatus = mapStructEntryToValue(mib2IpRouteMap, 00896 DEFINE_SIZEOF(mib2IpRouteMap), 00897 &ipRouteTable->table[tableIndex - 1], item, pVarBind); 00898 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 00899 ret = setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, 00900 ipRouteTable->table[tableIndex - 1].dwForwardDest); 00901 } 00902 break; 00903 case SNMP_PDU_SET: 00904 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 00905 ret = FALSE; 00906 break; 00907 default: 00908 FIXME("0x%02x: unsupported PDU type\n", bPduType); 00909 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00910 } 00911 return ret; 00912 } 00913 00914 static UINT mib2IpNet[] = { 1,3,6,1,2,1,4,22,1 }; 00915 static PMIB_IPNETTABLE ipNetTable; 00916 00917 static DWORD copyIpNetPhysAddr(AsnAny *value, void *src) 00918 { 00919 PMIB_IPNETROW row = (PMIB_IPNETROW)((BYTE *)src - FIELD_OFFSET(MIB_IPNETROW, 00920 dwPhysAddrLen)); 00921 00922 setStringValue(value, ASN_OCTETSTRING, row->dwPhysAddrLen, row->bPhysAddr); 00923 return SNMP_ERRORSTATUS_NOERROR; 00924 } 00925 00926 static struct structToAsnValue mib2IpNetMap[] = { 00927 { FIELD_OFFSET(MIB_IPNETROW, dwIndex), copyInt }, 00928 { FIELD_OFFSET(MIB_IPNETROW, dwPhysAddrLen), copyIpNetPhysAddr }, 00929 { FIELD_OFFSET(MIB_IPNETROW, dwAddr), copyIpAddr }, 00930 { FIELD_OFFSET(MIB_IPNETROW, dwType), copyInt }, 00931 }; 00932 00933 static void mib2IpNetInit(void) 00934 { 00935 DWORD size = 0, ret = GetIpNetTable(NULL, &size, FALSE); 00936 00937 if (ret == ERROR_INSUFFICIENT_BUFFER) 00938 { 00939 MIB_IPNETTABLE *table = HeapAlloc(GetProcessHeap(), 0, size); 00940 if (table) 00941 { 00942 if (!GetIpNetTable(table, &size, FALSE)) ipNetTable = table; 00943 else HeapFree(GetProcessHeap(), 0, table ); 00944 } 00945 } 00946 } 00947 00948 static void mib2IpNetCleanup(void) 00949 { 00950 HeapFree(GetProcessHeap(), 0, ipNetTable); 00951 } 00952 00953 static BOOL mib2IpNetQuery(BYTE bPduType, SnmpVarBind *pVarBind, 00954 AsnInteger32 *pErrorStatus) 00955 { 00956 AsnObjectIdentifier myOid = DEFINE_OID(mib2IpNet); 00957 BOOL ret = TRUE; 00958 00959 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 00960 pErrorStatus); 00961 00962 switch (bPduType) 00963 { 00964 case SNMP_PDU_GET: 00965 case SNMP_PDU_GETNEXT: 00966 if (!ipNetTable) 00967 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00968 else 00969 { 00970 UINT tableIndex = 0, item = 0; 00971 00972 *pErrorStatus = getItemAndIntegerInstanceFromOid(&pVarBind->name, 00973 &myOid, bPduType, &item, &tableIndex); 00974 if (!*pErrorStatus) 00975 { 00976 assert(tableIndex); 00977 assert(item); 00978 if (tableIndex > ipNetTable->dwNumEntries) 00979 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00980 else 00981 { 00982 *pErrorStatus = mapStructEntryToValue(mib2IpNetMap, 00983 DEFINE_SIZEOF(mib2IpNetMap), 00984 &ipNetTable[tableIndex - 1], item, pVarBind); 00985 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 00986 ret = setOidWithItemAndInteger(&pVarBind->name, &myOid, 00987 item, tableIndex); 00988 } 00989 } 00990 } 00991 break; 00992 case SNMP_PDU_SET: 00993 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 00994 ret = FALSE; 00995 break; 00996 default: 00997 FIXME("0x%02x: unsupported PDU type\n", bPduType); 00998 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 00999 } 01000 return ret; 01001 } 01002 01003 static UINT mib2Icmp[] = { 1,3,6,1,2,1,5 }; 01004 static MIB_ICMP icmpStats; 01005 01006 static void mib2IcmpInit(void) 01007 { 01008 GetIcmpStatistics(&icmpStats); 01009 } 01010 01011 static struct structToAsnValue mib2IcmpMap[] = { 01012 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwMsgs), copyInt }, 01013 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwErrors), copyInt }, 01014 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwDestUnreachs), copyInt }, 01015 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimeExcds), copyInt }, 01016 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwParmProbs), copyInt }, 01017 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwSrcQuenchs), copyInt }, 01018 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwRedirects), copyInt }, 01019 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwEchos), copyInt }, 01020 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwEchoReps), copyInt }, 01021 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimestamps), copyInt }, 01022 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimestampReps), copyInt }, 01023 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwAddrMasks), copyInt }, 01024 { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwAddrMaskReps), copyInt }, 01025 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwMsgs), copyInt }, 01026 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwErrors), copyInt }, 01027 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwDestUnreachs), copyInt }, 01028 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimeExcds), copyInt }, 01029 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwParmProbs), copyInt }, 01030 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwSrcQuenchs), copyInt }, 01031 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwRedirects), copyInt }, 01032 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwEchos), copyInt }, 01033 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwEchoReps), copyInt }, 01034 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimestamps), copyInt }, 01035 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimestampReps), copyInt }, 01036 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwAddrMasks), copyInt }, 01037 { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwAddrMaskReps), copyInt }, 01038 }; 01039 01040 static BOOL mib2IcmpQuery(BYTE bPduType, SnmpVarBind *pVarBind, 01041 AsnInteger32 *pErrorStatus) 01042 { 01043 AsnObjectIdentifier myOid = DEFINE_OID(mib2Icmp); 01044 UINT item = 0; 01045 BOOL ret = TRUE; 01046 01047 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 01048 pErrorStatus); 01049 01050 switch (bPduType) 01051 { 01052 case SNMP_PDU_GET: 01053 case SNMP_PDU_GETNEXT: 01054 *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, 01055 &item); 01056 if (!*pErrorStatus) 01057 { 01058 *pErrorStatus = mapStructEntryToValue(mib2IcmpMap, 01059 DEFINE_SIZEOF(mib2IcmpMap), &icmpStats, item, 01060 pVarBind); 01061 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 01062 ret = setOidWithItem(&pVarBind->name, &myOid, item); 01063 } 01064 break; 01065 case SNMP_PDU_SET: 01066 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 01067 ret = FALSE; 01068 break; 01069 default: 01070 FIXME("0x%02x: unsupported PDU type\n", bPduType); 01071 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 01072 } 01073 return ret; 01074 } 01075 01076 static UINT mib2Tcp[] = { 1,3,6,1,2,1,6 }; 01077 static MIB_TCPSTATS tcpStats; 01078 01079 static void mib2TcpInit(void) 01080 { 01081 GetTcpStatistics(&tcpStats); 01082 } 01083 01084 static struct structToAsnValue mib2TcpMap[] = { 01085 { FIELD_OFFSET(MIB_TCPSTATS, dwRtoAlgorithm), copyInt }, 01086 { FIELD_OFFSET(MIB_TCPSTATS, dwRtoMin), copyInt }, 01087 { FIELD_OFFSET(MIB_TCPSTATS, dwRtoMax), copyInt }, 01088 { FIELD_OFFSET(MIB_TCPSTATS, dwMaxConn), copyInt }, 01089 { FIELD_OFFSET(MIB_TCPSTATS, dwActiveOpens), copyInt }, 01090 { FIELD_OFFSET(MIB_TCPSTATS, dwPassiveOpens), copyInt }, 01091 { FIELD_OFFSET(MIB_TCPSTATS, dwAttemptFails), copyInt }, 01092 { FIELD_OFFSET(MIB_TCPSTATS, dwEstabResets), copyInt }, 01093 { FIELD_OFFSET(MIB_TCPSTATS, dwCurrEstab), copyInt }, 01094 { FIELD_OFFSET(MIB_TCPSTATS, dwInSegs), copyInt }, 01095 { FIELD_OFFSET(MIB_TCPSTATS, dwOutSegs), copyInt }, 01096 { FIELD_OFFSET(MIB_TCPSTATS, dwRetransSegs), copyInt }, 01097 { FIELD_OFFSET(MIB_TCPSTATS, dwInErrs), copyInt }, 01098 { FIELD_OFFSET(MIB_TCPSTATS, dwOutRsts), copyInt }, 01099 { FIELD_OFFSET(MIB_TCPSTATS, dwNumConns), copyInt }, 01100 }; 01101 01102 static BOOL mib2TcpQuery(BYTE bPduType, SnmpVarBind *pVarBind, 01103 AsnInteger32 *pErrorStatus) 01104 { 01105 AsnObjectIdentifier myOid = DEFINE_OID(mib2Tcp); 01106 UINT item = 0; 01107 BOOL ret = TRUE; 01108 01109 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 01110 pErrorStatus); 01111 01112 switch (bPduType) 01113 { 01114 case SNMP_PDU_GET: 01115 case SNMP_PDU_GETNEXT: 01116 *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, 01117 &item); 01118 if (!*pErrorStatus) 01119 { 01120 *pErrorStatus = mapStructEntryToValue(mib2TcpMap, 01121 DEFINE_SIZEOF(mib2TcpMap), &tcpStats, item, pVarBind); 01122 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 01123 ret = setOidWithItem(&pVarBind->name, &myOid, item); 01124 } 01125 break; 01126 case SNMP_PDU_SET: 01127 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 01128 ret = FALSE; 01129 break; 01130 default: 01131 FIXME("0x%02x: unsupported PDU type\n", bPduType); 01132 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 01133 } 01134 return ret; 01135 } 01136 01137 static UINT mib2Udp[] = { 1,3,6,1,2,1,7 }; 01138 static MIB_UDPSTATS udpStats; 01139 01140 static void mib2UdpInit(void) 01141 { 01142 GetUdpStatistics(&udpStats); 01143 } 01144 01145 static struct structToAsnValue mib2UdpMap[] = { 01146 { FIELD_OFFSET(MIB_UDPSTATS, dwInDatagrams), copyInt }, 01147 { FIELD_OFFSET(MIB_UDPSTATS, dwNoPorts), copyInt }, 01148 { FIELD_OFFSET(MIB_UDPSTATS, dwInErrors), copyInt }, 01149 { FIELD_OFFSET(MIB_UDPSTATS, dwOutDatagrams), copyInt }, 01150 }; 01151 01152 static BOOL mib2UdpQuery(BYTE bPduType, SnmpVarBind *pVarBind, 01153 AsnInteger32 *pErrorStatus) 01154 { 01155 AsnObjectIdentifier myOid = DEFINE_OID(mib2Udp); 01156 UINT item; 01157 BOOL ret = TRUE; 01158 01159 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 01160 pErrorStatus); 01161 01162 switch (bPduType) 01163 { 01164 case SNMP_PDU_GET: 01165 case SNMP_PDU_GETNEXT: 01166 *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, 01167 &item); 01168 if (!*pErrorStatus) 01169 { 01170 *pErrorStatus = mapStructEntryToValue(mib2UdpMap, 01171 DEFINE_SIZEOF(mib2UdpMap), &udpStats, item, pVarBind); 01172 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 01173 ret = setOidWithItem(&pVarBind->name, &myOid, item); 01174 } 01175 break; 01176 case SNMP_PDU_SET: 01177 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 01178 ret = FALSE; 01179 break; 01180 default: 01181 FIXME("0x%02x: unsupported PDU type\n", bPduType); 01182 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 01183 } 01184 return ret; 01185 } 01186 01187 static UINT mib2UdpEntry[] = { 1,3,6,1,2,1,7,5,1 }; 01188 static PMIB_UDPTABLE udpTable; 01189 01190 static void mib2UdpEntryInit(void) 01191 { 01192 DWORD size = 0, ret = GetUdpTable(NULL, &size, TRUE); 01193 01194 if (ret == ERROR_INSUFFICIENT_BUFFER) 01195 { 01196 MIB_UDPTABLE *table = HeapAlloc(GetProcessHeap(), 0, size); 01197 if (table) 01198 { 01199 if (!GetUdpTable(table, &size, TRUE)) udpTable = table; 01200 else HeapFree(GetProcessHeap(), 0, table); 01201 } 01202 } 01203 } 01204 01205 static void mib2UdpEntryCleanup(void) 01206 { 01207 HeapFree(GetProcessHeap(), 0, udpTable); 01208 } 01209 01210 static struct structToAsnValue mib2UdpEntryMap[] = { 01211 { FIELD_OFFSET(MIB_UDPROW, dwLocalAddr), copyIpAddr }, 01212 { FIELD_OFFSET(MIB_UDPROW, dwLocalPort), copyInt }, 01213 }; 01214 01215 static void oidToUdpRow(AsnObjectIdentifier *oid, void *dst) 01216 { 01217 MIB_UDPROW *row = dst; 01218 01219 assert(oid && oid->idLength >= 5); 01220 row->dwLocalAddr = oidToIpAddr(oid); 01221 row->dwLocalPort = oid->ids[4]; 01222 } 01223 01224 static int compareUdpRow(const void *a, const void *b) 01225 { 01226 const MIB_UDPROW *key = a, *value = b; 01227 int ret; 01228 01229 ret = key->dwLocalAddr - value->dwLocalAddr; 01230 if (ret == 0) 01231 ret = key->dwLocalPort - value->dwLocalPort; 01232 return ret; 01233 } 01234 01235 static BOOL mib2UdpEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, 01236 AsnInteger32 *pErrorStatus) 01237 { 01238 AsnObjectIdentifier myOid = DEFINE_OID(mib2UdpEntry); 01239 BOOL ret = TRUE; 01240 01241 TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), 01242 pErrorStatus); 01243 01244 switch (bPduType) 01245 { 01246 case SNMP_PDU_GET: 01247 case SNMP_PDU_GETNEXT: 01248 if (!udpTable) 01249 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 01250 else 01251 { 01252 UINT tableIndex = 0, item = 0; 01253 01254 *pErrorStatus = getItemAndInstanceFromTable(&pVarBind->name, &myOid, 01255 5, bPduType, (struct GenericTable *)udpTable, 01256 sizeof(MIB_UDPROW), oidToUdpRow, compareUdpRow, &item, 01257 &tableIndex); 01258 if (!*pErrorStatus) 01259 { 01260 assert(tableIndex); 01261 assert(item); 01262 *pErrorStatus = mapStructEntryToValue(mib2UdpEntryMap, 01263 DEFINE_SIZEOF(mib2UdpEntryMap), 01264 &udpTable->table[tableIndex - 1], item, pVarBind); 01265 if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) 01266 { 01267 AsnObjectIdentifier oid; 01268 01269 ret = setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, 01270 udpTable->table[tableIndex - 1].dwLocalAddr); 01271 if (ret) 01272 { 01273 oid.idLength = 1; 01274 oid.ids = &udpTable->table[tableIndex - 1].dwLocalPort; 01275 ret = SnmpUtilOidAppend(&pVarBind->name, &oid); 01276 } 01277 } 01278 } 01279 } 01280 break; 01281 case SNMP_PDU_SET: 01282 *pErrorStatus = SNMP_ERRORSTATUS_READONLY; 01283 ret = FALSE; 01284 break; 01285 default: 01286 FIXME("0x%02x: unsupported PDU type\n", bPduType); 01287 *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 01288 } 01289 return ret; 01290 } 01291 01292 /* This list MUST BE lexicographically sorted */ 01293 static struct mibImplementation supportedIDs[] = { 01294 { DEFINE_OID(mib2IfNumber), mib2IfNumberInit, mib2IfNumberQuery, 01295 mib2IfNumberCleanup }, 01296 { DEFINE_OID(mib2IfEntry), NULL, mib2IfEntryQuery, NULL }, 01297 { DEFINE_OID(mib2Ip), mib2IpStatsInit, mib2IpStatsQuery, NULL }, 01298 { DEFINE_OID(mib2IpAddr), mib2IpAddrInit, mib2IpAddrQuery, 01299 mib2IpAddrCleanup }, 01300 { DEFINE_OID(mib2IpRoute), mib2IpRouteInit, mib2IpRouteQuery, 01301 mib2IpRouteCleanup }, 01302 { DEFINE_OID(mib2IpNet), mib2IpNetInit, mib2IpNetQuery, mib2IpNetCleanup }, 01303 { DEFINE_OID(mib2Icmp), mib2IcmpInit, mib2IcmpQuery, NULL }, 01304 { DEFINE_OID(mib2Tcp), mib2TcpInit, mib2TcpQuery, NULL }, 01305 { DEFINE_OID(mib2Udp), mib2UdpInit, mib2UdpQuery, NULL }, 01306 { DEFINE_OID(mib2UdpEntry), mib2UdpEntryInit, mib2UdpEntryQuery, 01307 mib2UdpEntryCleanup }, 01308 }; 01309 static UINT minSupportedIDLength; 01310 01311 /***************************************************************************** 01312 * SnmpExtensionInit [INETMIB1.@] 01313 */ 01314 BOOL WINAPI SnmpExtensionInit(DWORD dwUptimeReference, 01315 HANDLE *phSubagentTrapEvent, AsnObjectIdentifier *pFirstSupportedRegion) 01316 { 01317 AsnObjectIdentifier myOid = DEFINE_OID(mib2System); 01318 UINT i; 01319 01320 TRACE("(%d, %p, %p)\n", dwUptimeReference, phSubagentTrapEvent, 01321 pFirstSupportedRegion); 01322 01323 minSupportedIDLength = UINT_MAX; 01324 for (i = 0; i < sizeof(supportedIDs) / sizeof(supportedIDs[0]); i++) 01325 { 01326 if (supportedIDs[i].init) 01327 supportedIDs[i].init(); 01328 if (supportedIDs[i].name.idLength < minSupportedIDLength) 01329 minSupportedIDLength = supportedIDs[i].name.idLength; 01330 } 01331 *phSubagentTrapEvent = NULL; 01332 SnmpUtilOidCpy(pFirstSupportedRegion, &myOid); 01333 return TRUE; 01334 } 01335 01336 static void cleanup(void) 01337 { 01338 UINT i; 01339 01340 for (i = 0; i < sizeof(supportedIDs) / sizeof(supportedIDs[0]); i++) 01341 if (supportedIDs[i].cleanup) 01342 supportedIDs[i].cleanup(); 01343 } 01344 01345 static struct mibImplementation *findSupportedQuery(UINT *ids, UINT idLength, 01346 UINT *matchingIndex) 01347 { 01348 int indexHigh = DEFINE_SIZEOF(supportedIDs) - 1, indexLow = 0; 01349 AsnObjectIdentifier oid1 = { idLength, ids}; 01350 01351 if (!idLength) 01352 return NULL; 01353 01354 while (indexLow <= indexHigh) 01355 { 01356 INT cmp, i = (indexLow + indexHigh) / 2; 01357 if (!(cmp = SnmpUtilOidNCmp(&oid1, &supportedIDs[i].name, idLength))) 01358 { 01359 *matchingIndex = i; 01360 return &supportedIDs[i]; 01361 } 01362 if (cmp > 0) 01363 indexLow = i + 1; 01364 else 01365 indexHigh = i - 1; 01366 } 01367 return NULL; 01368 } 01369 01370 /***************************************************************************** 01371 * SnmpExtensionQuery [INETMIB1.@] 01372 */ 01373 BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, 01374 AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex) 01375 { 01376 AsnObjectIdentifier mib2oid = DEFINE_OID(mib2); 01377 AsnInteger32 error = SNMP_ERRORSTATUS_NOERROR, errorIndex = 0; 01378 UINT i; 01379 BOOL ret = TRUE; 01380 01381 TRACE("(0x%02x, %p, %p, %p)\n", bPduType, pVarBindList, 01382 pErrorStatus, pErrorIndex); 01383 01384 for (i = 0; !error && i < pVarBindList->len; i++) 01385 { 01386 /* Ignore any OIDs not in MIB2 */ 01387 if (!SnmpUtilOidNCmp(&pVarBindList->list[i].name, &mib2oid, 01388 mib2oid.idLength)) 01389 { 01390 struct mibImplementation *impl = NULL; 01391 UINT len, matchingIndex = 0; 01392 01393 TRACE("%s\n", SnmpUtilOidToA(&pVarBindList->list[i].name)); 01394 /* Search for an implementation matching as many octets as possible 01395 */ 01396 for (len = pVarBindList->list[i].name.idLength; 01397 len >= minSupportedIDLength && !impl; len--) 01398 impl = findSupportedQuery(pVarBindList->list[i].name.ids, len, 01399 &matchingIndex); 01400 if (impl && impl->query) 01401 ret = impl->query(bPduType, &pVarBindList->list[i], &error); 01402 else 01403 error = SNMP_ERRORSTATUS_NOSUCHNAME; 01404 if (error == SNMP_ERRORSTATUS_NOSUCHNAME && 01405 bPduType == SNMP_PDU_GETNEXT) 01406 { 01407 /* GetNext is special: it finds the successor to the given OID, 01408 * so we have to continue until an implementation handles the 01409 * query or we exhaust the table of supported OIDs. 01410 */ 01411 for (matchingIndex++; error == SNMP_ERRORSTATUS_NOSUCHNAME && 01412 matchingIndex < DEFINE_SIZEOF(supportedIDs); 01413 matchingIndex++) 01414 { 01415 error = SNMP_ERRORSTATUS_NOERROR; 01416 impl = &supportedIDs[matchingIndex]; 01417 if (impl->query) 01418 ret = impl->query(bPduType, &pVarBindList->list[i], 01419 &error); 01420 else 01421 error = SNMP_ERRORSTATUS_NOSUCHNAME; 01422 } 01423 /* If the query still isn't resolved, set the OID to the 01424 * successor to the last entry in the table. 01425 */ 01426 if (error == SNMP_ERRORSTATUS_NOSUCHNAME) 01427 { 01428 SnmpUtilOidFree(&pVarBindList->list[i].name); 01429 ret = SnmpUtilOidCpy(&pVarBindList->list[i].name, 01430 &supportedIDs[matchingIndex - 1].name); 01431 pVarBindList->list[i].name.ids[ 01432 pVarBindList->list[i].name.idLength - 1] += 1; 01433 } 01434 } 01435 if (error) 01436 errorIndex = i + 1; 01437 } 01438 } 01439 *pErrorStatus = error; 01440 *pErrorIndex = errorIndex; 01441 return ret; 01442 } 01443 01444 /***************************************************************************** 01445 * DllMain [INETMIB1.@] 01446 */ 01447 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) 01448 { 01449 TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); 01450 01451 switch (fdwReason) 01452 { 01453 case DLL_PROCESS_ATTACH: 01454 DisableThreadLibraryCalls(hinstDLL); 01455 break; 01456 case DLL_PROCESS_DETACH: 01457 cleanup(); 01458 break; 01459 default: 01460 break; 01461 } 01462 01463 return TRUE; 01464 } Generated on Sat May 26 2012 04:15:43 for ReactOS by
1.7.6.1
|