www.pudn.com > snmp.rar > procreq.c


/*++ 
 
Copyright (c) 1992-1996  Microsoft Corporation 
 
Module Name: 
 
    procreq.c 
 
Abstract: 
 
    Provides SNMP message dispatch/processing functionality for Proxy Agent. 
 
Environment: 
 
    User Mode - Win32 
 
Revision History: 
 
    10-May-1996 DonRyan 
        Removed banner from Technology Dynamics, Inc. 
 
--*/ 
  
//--------------------------- WINDOWS DEPENDENCIES -------------------------- 
 
//--------------------------- STANDARD DEPENDENCIES -- #include ---- 
 
#include  
 
#include  
#include  
 
#include  
#include  
#include  
#include  
 
 
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------ 
 
#include  
#include  
#include "..\common\wellknow.h" 
 
#include "..\authapi.\berapi.h" 
#include "..\authapi.\pduapi.h" 
#include "..\authapi.\auth1157.h" 
#include "..\authapi.\authxxxx.h" 
#include "..\authapi.\authapi.h" 
 
#include "regconf.h" 
 
 
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" ----- 
 
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)-- 
 
extern DWORD platformId; 
 
 
//--------------------------- PRIVATE CONSTANTS ----------------------------- 
 
#define SGTTimeout ((DWORD)3600000) 
 
 
//--------------------------- PRIVATE STRUCTS ------------------------------- 
 
typedef struct _RFC1157VarBindXlat { 
 
    UINT view;  // view associated with varbind 
    UINT index; // varbind placement in incoming pdu 
 
} RFC1157VarBindXlat; 
 
typedef struct _SnmpMgmtQuery { 
 
    RFC1157VarBindList  vbl;  // list of varbinds for extension agent 
    RFC1157VarBindXlat *xlat; // information to reorder varbinds 
    FARPROC             addr; // address of extension agent 
 
} SnmpMgmtQuery;  
 
typedef struct _SnmpMgmtQueryList { 
 
    SnmpMgmtQuery *query; // list of subagent queries 
    UINT           len;   // number of queries in list 
    UINT           type;  // type of query (get, set, or getnext) 
 
} SnmpMgmtQueryList; 
 
//--------------------------- PRIVATE VARIABLES ----------------------------- 
 
static UINT *vl    = NULL; // list of extension agent views 
static UINT  vlLen = 0;    // length of the above view list 
 
//--------------------------- PRIVATE PROTOTYPES ---------------------------- 
 
BOOL SnmpSvcAddrToSocket( 
    LPSTR addrText, 
    struct sockaddr *addrEncoding); 
 
int gethostname(OUT char *,IN int ); 
void dp_ipx(int, char *, SOCKADDR_IPX *, char *); 
 
void initvl(); 
 
void vbltoql(RFC1157VarBindList *, SnmpMgmtQueryList *, UINT *, UINT *); 
void qltovbl(SnmpMgmtQueryList *, RFC1157VarBindList *, UINT *, UINT *); 
 
void addql(SnmpMgmtQueryList *, RFC1157VarBindList *, UINT, UINT); 
void delql(SnmpMgmtQueryList *); 
 
void addq(SnmpMgmtQuery *, RFC1157VarBind *, UINT, UINT); 
 
void fixupql(SnmpMgmtQueryList *, UINT *, UINT *); 
void nextvb(SnmpMgmtQuery *, UINT, UINT, UINT *, UINT *); 
 
void fixuperr(SnmpMgmtQuery *, UINT *); 
 
//--------------------------- PRIVATE PROCEDURES ---------------------------- 
 
#define bzero(lp, size)         (void)memset(lp, 0, size) 
 
void initvl() 
    { 
    UINT i; 
    UINT j; 
    UINT temp; 
 
    // allocate an index for each registered subagent  
    vl = (INT *)SnmpUtilMemAlloc(extAgentsLen * sizeof(INT)); 
 
    // flag only if properly initialized  
    for(i=0, vlLen=0; i < (UINT)extAgentsLen; i++) 
        { 
        if (extAgents[i].fInitedOk) 
            { 
            vl[vlLen++] = i; 
            } 
        } 
 
    // sort these indexes... 
    for(i=0; i < vlLen; i++) 
        { 
        for(j=i + 1; j < vlLen; j++) 
            { 
            // if item[i] > item[j] 
            if (0 < SnmpUtilOidCmp( 
                    &(extAgents[vl[i]].supportedView), 
                    &(extAgents[vl[j]].supportedView))) 
                { 
                temp  = vl[i]; 
                vl[i] = vl[j]; 
                vl[j] = temp; 
                } 
            } 
        } 
 
    } // end initvl() 
 
 
void vbltoql(RFC1157VarBindList *vbl, SnmpMgmtQueryList *ql, UINT *errorStatus, UINT *errorIndex) 
    { 
    UINT v;  // index into view list 
    UINT vb; // index into varbind list 
 
    INT  nDiff; 
     
    BOOL fAnyOk; 
    BOOL fFoundOk = FALSE; 
 
    SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: processing %s request containing %d variable(s).\n", 
        (ql->type == ASN_RFC1157_GETREQUEST) 
            ? "get" 
            : (ql->type == ASN_RFC1157_SETREQUEST) 
                ? "set" 
                : (ql->type == ASN_RFC1157_GETNEXTREQUEST) 
                    ? "getnext" 
                    : "unknown", vbl->len)); 
 
    // check to see if getnext is being requested 
    fAnyOk = (ql->type == ASN_RFC1157_GETNEXTREQUEST); 
 
    // initialize status return values 
    *errorStatus = SNMP_ERRORSTATUS_NOERROR; 
    *errorIndex  = 0; 
 
    // process variable bindings 
    for (vb=0; vb < vbl->len; vb++) 
        { 
        // process supported views 
        for (v=0; v < vlLen; v++) 
            { 
            // compare request 
            nDiff = SnmpUtilOidNCmp( 
                        &vbl->list[vb].name, 
                        &extAgents[vl[v]].supportedView, 
                        extAgents[vl[v]].supportedView.idLength 
                        ); 
 
            // analyze results based on request type 
            fFoundOk = (!nDiff || (fAnyOk && (nDiff < 0))); 
 
            // save 
            if (fFoundOk) 
                { 
                // insert into query 
                addql(ql, vbl, vb, v); 
                break; 
                } 
            } 
 
        // not found 
        if (!fFoundOk) 
            { 
            SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: %s not in supported view(s).\n", SnmpUtilOidToA(&vbl->list[vb].name))); 
            *errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; 
            *errorIndex  = vb+1; 
            break; 
            } 
        } 
 
    } // end vbltoql() 
 
 
void addql(SnmpMgmtQueryList *ql, RFC1157VarBindList *vbl, UINT vb, UINT v) 
    { 
    UINT q; // index into query list 
 
    // make sure that the type is correct 
    if ((ql->type != ASN_RFC1157_SETREQUEST) &&  
        (vbl->list[vb].value.asnType != ASN_NULL)) { 
         
        SNMPDBG(( 
            SNMP_LOG_TRACE, 
            "SNMP: PDU: forcing asnType to NULL (asnType=%d).\n", 
            (DWORD)(BYTE)vbl->list[vb].value.asnType 
            )); 
 
        // force the asn type to be null 
        vbl->list[vb].value.asnType = ASN_NULL;         
    }      
 
    // process existing queries 
    for (q=0; q < ql->len; q++) 
        { 
        // compare existing extension agent addresses  
        if (ql->query[q].addr == extAgents[vl[v]].queryAddr) 
            { 
            // add to existing query 
            addq(&ql->query[q], &vbl->list[vb], vb, v); 
            return; 
            } 
        } 
 
    SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: creating query for %s (0x%08lx).\n", extAgents[vl[v]].pathName, extAgents[vl[v]].queryAddr)); 
 
    ql->len++; // add new query to end of list 
    ql->query = (SnmpMgmtQuery *)SnmpUtilMemReAlloc(ql->query, (ql->len * sizeof(SnmpMgmtQuery))); 
 
    ql->query[q].xlat = NULL; 
    ql->query[q].addr = extAgents[vl[v]].queryAddr; 
 
    ql->query[q].vbl.len = 0; 
    ql->query[q].vbl.list = NULL; 
 
    // add to newly created query 
    addq(&ql->query[q], &vbl->list[vb], vb, v); 
 
    } // end addql() 
 
 
void addq(SnmpMgmtQuery *q, RFC1157VarBind *vb, UINT i, UINT v) 
    { 
 
    SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: adding variable %d to query 0x%08lx (%s).\n", i+1, q->addr, SnmpUtilOidToA(&vb->name))); 
 
    q->vbl.len++; // add varbind to end of list 
    q->vbl.list = (RFC1157VarBind *)SnmpUtilMemReAlloc(q->vbl.list, (q->vbl.len * sizeof(RFC1157VarBind))); 
    q->xlat = (RFC1157VarBindXlat *)SnmpUtilMemReAlloc(q->xlat, (q->vbl.len * sizeof(RFC1157VarBindXlat))); 
 
    q->xlat[q->vbl.len-1].view  = v; 
    q->xlat[q->vbl.len-1].index = i; 
 
    SnmpUtilVarBindCpy(&q->vbl.list[q->vbl.len-1], vb); 
 
    } // end addq() 
 
 
void delql(SnmpMgmtQueryList *ql) 
    { 
    UINT q; // index into query list 
 
    // process queries 
    for (q=0; q < ql->len; q++) 
        { 
        SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: deleting query 0x%08lx.\n", ql->query[q].addr)); 
 
        // free translation info 
        SnmpUtilMemFree(ql->query[q].xlat); 
        // free query varbind list (and variables) 
        SnmpUtilVarBindListFree(&ql->query[q].vbl); 
        } 
 
    // free query list 
    SnmpUtilMemFree(ql->query); 
 
    } // end delql() 
 
 
void qltovbl(SnmpMgmtQueryList *ql, RFC1157VarBindList *vbl, UINT *errorStatus, UINT *errorIndex) 
    { 
    UINT q;   // index into queue list 
    UINT vb;  // index into queue varbind list  
    UINT i;   // index into original varbind list  
 
    // only convert back if error not reported 
    if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) 
        { 
        SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: request failed, errorStatus=%s, errorIndex=%d.\n", 
            (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) 
                ? "NOSUCHNAME" 
                : (*errorStatus == SNMP_ERRORSTATUS_BADVALUE) 
                    ? "BADVALUE" 
                    : (*errorStatus == SNMP_ERRORSTATUS_READONLY) 
                        ? "READONLY" 
                        : (*errorStatus == SNMP_ERRORSTATUS_TOOBIG) 
                            ? "TOOBIG" 
                            : "GENERR", *errorIndex 
                            )); 
        // free 
        delql(ql); 
        return; 
        } 
 
    // process queries 
    for (q=0; q < ql->len; q++) 
        { 
        // process variable bindings gathered 
        for (vb=0; vb < ql->query[q].vbl.len; vb++) 
            { 
            // calculate original index 
            i = ql->query[q].xlat[vb].index; 
            // free original variable 
            SnmpUtilVarBindFree(&vbl->list[i]); 
            // replace with new variable 
            vbl->list[i] = ql->query[q].vbl.list[vb]; 
 
            SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: updating variable %d from query 0x%08lx (%s).\n", i+1, ql->query[q].addr, SnmpUtilOidToA(&vbl->list[i].name))); 
            } 
 
        // free translation info 
        SnmpUtilMemFree(ql->query[q].xlat); 
        // free query varbind list  
        SnmpUtilMemFree(ql->query[q].vbl.list); 
        } 
 
    // free query list 
    SnmpUtilMemFree(ql->query); 
 
    } // end qltovbl() 
 
 
void fixupql(SnmpMgmtQueryList *ql, UINT *errorStatus, UINT *errorIndex) 
    { 
    UINT v;   // index into view list  
    UINT q;   // index into queue list 
    UINT vb;  // index into varbind list  
 
    // process queries 
    for (q=0; (q < ql->len) && !(*errorStatus); q++) 
        { 
        SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: validating query 0x%08lx.\n", ql->query[q].addr)); 
 
        // process variable bindings gathered 
        for (vb=0; (vb < ql->query[q].vbl.len) && !(*errorStatus); vb++) 
            { 
            // calculate view index 
            v = ql->query[q].xlat[vb].view; 
            // check oid returned from subagent 
            if (0 < SnmpUtilOidNCmp( 
                        &ql->query[q].vbl.list[vb].name, 
                        &extAgents[vl[v]].supportedView, 
                        extAgents[vl[v]].supportedView.idLength 
                        )) 
                { 
                // retry getnext using next view  
                nextvb(&ql->query[q], vb, v, errorStatus, errorIndex);  
                } 
            } 
        } 
 
    } // end fixupql() 
 
 
void nextvb(SnmpMgmtQuery *q, UINT vb, UINT v, UINT *errorStatus, UINT *errorIndex) 
    { 
    RFC1157VarBindList vbl; 
 
    // process single varbind 
    vbl.list = &q->vbl.list[vb]; 
    vbl.len  = 1; 
 
    SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: %s no longer in view.\n", SnmpUtilOidToA(&vbl.list[0].name))); 
 
    // process remaining views 
    while ((++v < vlLen) && !(*errorStatus)) 
        { 
        // trim oid if necessary 
        vbl.list[0].name.idLength = min( 
            vbl.list[0].name.idLength, 
            extAgents[vl[v]].supportedView.idLength 
            ); 
 
        // validate order 
        if (0 >= SnmpUtilOidNCmp( 
                    &vbl.list[0].name, 
                    &extAgents[vl[v]].supportedView, 
                    extAgents[vl[v]].supportedView.idLength 
                    )) 
            { 
            SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: re-routing request to %s.\n", extAgents[vl[v]].pathName)); 
 
            // send getnext query to subagent 
            if ((*(extAgents[vl[v]].queryAddr))( 
                    ASN_RFC1157_GETNEXTREQUEST, 
                    &vbl, 
                    errorStatus, 
                    errorIndex 
                    )) 
                { 
                // check the subagent status code returned 
                if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) 
                    { 
                    // check oid returned from subagent 
                    if (0 >= SnmpUtilOidNCmp( 
                                &vbl.list[0].name, 
                                &extAgents[vl[v]].supportedView, 
                                extAgents[vl[v]].supportedView.idLength 
                                )) 
                        { 
                        return; // success... 
                        } 
                    } 
                } 
            else 
                { 
                // subagent unable to process query 
                *errorStatus = SNMP_ERRORSTATUS_GENERR; 
                } 
            } 
        } 
 
    *errorStatus = *errorStatus ? *errorStatus : SNMP_ERRORSTATUS_NOSUCHNAME; 
    *errorIndex  = q->xlat[vb].index+1; 
 
    SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: %s not in supported view(s).\n", SnmpUtilOidToA(&vbl.list[0].name))); 
 
    } // end nextvb() 
 
 
void fixuperr(SnmpMgmtQuery *q, UINT *errorIndex) 
    { 
    UINT errorIndexOld = *errorIndex; 
 
    // ignore zero 
    if (errorIndexOld) 
        {     
        // make sure within bounds 
        if (errorIndexOld <= q->vbl.len) 
            { 
            *errorIndex = q->xlat[errorIndexOld-1].index+1; 
            } 
        else  
            { 
            // default to first variable 
            *errorIndex = q->xlat[0].index+1; 
            } 
        } 
 
    } // end fixuperr() 
 
//--------------------------- PUBLIC PROCEDURES ----------------------------- 
 
SNMPAPI SnmpServiceProcessMessage( 
    IN OUT BYTE **pBuf, 
    IN OUT UINT *length) 
    { 
    static BOOL fInitedOk = FALSE; 
 
    RFC1157VarBindList vbl; 
    SnmpMgmtQueryList  ql; 
    SnmpMgmtCom        request; 
 
    AsnInteger errorStatus; 
    AsnInteger errorIndex; 
 
    BOOL fEncodedOk; 
 
    UINT packetType; 
    UINT q; 
 
    // init views 
    if (!fInitedOk) 
        { 
        initvl(); 
        fInitedOk = TRUE; 
        } 
 
    // decode received request into a management comm 
    if (!SnmpSvcDecodeMessage(&packetType, &request, *pBuf, *length, TRUE)) 
        return FALSE; 
 
    // initialize variables 
    vbl = request.pdu.pduValue.pdu.varBinds; 
 
    ql.query = NULL; 
    ql.len   = 0; 
    ql.type  = request.pdu.pduType; 
 
    // disassemble varbinds into queries 
    vbltoql(&vbl, &ql, &errorStatus, &errorIndex); 
 
    // process list of individual queries     
    for (q=0; (q < ql.len) && !errorStatus; q++ ) 
        { 
        SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: processing query 0x%08lx.\n", ql.query[q].addr)); 
 
        // send query to subagent 
        if ((*(ql.query[q].addr))( 
                  ql.type,  
                  &ql.query[q].vbl,  
                  &errorStatus,  
                  &errorIndex 
                  )) 
            { 
            // check the subagent status code returned 
            if (errorStatus != SNMP_ERRORSTATUS_NOERROR) 
                { 
                // adjust index to match request pdu 
                fixuperr(&ql.query[q], &errorIndex); 
                } 
            } 
        else  
            { 
            // subagent unable to process query 
            errorStatus = SNMP_ERRORSTATUS_GENERR; 
            errorIndex  = 1; 
            // adjust index to match request pdu 
            fixuperr(&ql.query[q], &errorIndex); 
            } 
        } 
 
    // make sure queries ready for conversion 
    if (errorStatus == SNMP_ERRORSTATUS_NOERROR) 
        { 
        // special processing needed for getnext  
        if (ql.type == ASN_RFC1157_GETNEXTREQUEST) 
            { 
            // returned oids must match agent view 
            fixupql(&ql, &errorStatus, &errorIndex); 
            } 
        } 
 
    // reassemble queries into response varbinds 
    qltovbl(&ql, &vbl, &errorStatus, &errorIndex);   
 
    // construct reponse pdu with varbinds 
    request.pdu.pduType = ASN_RFC1157_GETRESPONSE; 
 
    request.pdu.pduValue.pdu.errorStatus = errorStatus; 
    request.pdu.pduValue.pdu.errorIndex  = errorIndex; 
 
    request.pdu.pduValue.pdu.varBinds = vbl; 
 
    *pBuf   = NULL; 
    *length = 0; 
 
    // encode response pdu with gathered varbinds 
    fEncodedOk = SnmpSvcEncodeMessage(packetType, &request, pBuf, length); 
 
    // release response message 
    SnmpSvcReleaseMessage(&request); 
 
    return fEncodedOk; 
 
    } // end SnmpServiceProcessMessage() 
 
// filter managers with permitted managers in registry 
BOOL filtmgrs(struct sockaddr *source, INT sourceLen) 
{ 
    BOOL fFound = FALSE; 
    INT  i; 
 
    if (permitMgrsLen > 0) 
    { 
        for(i=0; i < permitMgrsLen && !fFound; i++) 
        { 
            DWORD   test; 
            SOCKADDR_IPX *  pIpx; 
// --------- BEGIN: PROTOCOL SPECIFIC SOCKET CODE BEGIN... --------- 
            switch (source->sa_family) 
            { 
                case AF_INET: 
                if ((*((struct sockaddr_in *)source)).sin_addr.s_addr == 
                    (*((struct sockaddr_in *)&permitMgrs[i].addrEncoding)).sin_addr.s_addr) 
                { 
                    fFound = TRUE; 
                } 
                break; 
 
                case AF_IPX: 
 
#ifdef debug 
                dp_ipx(SNMP_LOG_TRACE, "SNMP: PDU: validating IPX manager @ ", 
                       (SOCKADDR_IPX *) source, " against "); 
                SNMPDBG((SNMP_LOG_TRACE, "(%04X)", permitMgrs[i].addrEncoding.sa_family)); 
                dp_ipx(SNMP_LOG_TRACE, "", (SOCKADDR_IPX*) &permitMgrs[i].addrEncoding, "\n"); 
#endif 
                pIpx = (SOCKADDR_IPX *) &permitMgrs[i].addrEncoding; 
                test = *(DWORD *)((SOCKADDR_IPX *)(&permitMgrs[i].addrEncoding))->sa_netnum; 
                //Below checks for nodenumber regardless of netnumber if the user specified 
                // a netnumber of zero for the permitted IPX mgr 
                if (*(DWORD *)((SOCKADDR_IPX *)(&permitMgrs[i].addrEncoding))->sa_netnum == 0) 
                { 
                    if (memcmp(((SOCKADDR_IPX *)source)->sa_nodenum,  
                           ((SOCKADDR_IPX *)(&permitMgrs[i].addrEncoding))->sa_nodenum,  
                           sizeof(((SOCKADDR_IPX *)source)->sa_nodenum)) == 0) 
                    { 
                        fFound = TRUE; 
                    } 
                } 
                else 
                { 
                    //Compare the entire address 
                    if (memcmp(source,  
                           &permitMgrs[i].addrEncoding,  
                           sizeof(((SOCKADDR_IPX *)source)->sa_netnum) + 
                           sizeof(((SOCKADDR_IPX *)source)->sa_nodenum)) == 0) 
                    { 
                        fFound = TRUE; 
                    } 
                } 
// --------- END: PROTOCOL SPECIFIC SOCKET CODE END. --------------- 
            } // end switch    
        } // end for() 
    } 
    else 
    { 
        fFound = TRUE; // no entries means all managers allowed 
    } // end if 
 
    if (!fFound) 
    { 
        SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: invalid manager filtered.\n")); 
    } 
 
    return fFound; 
 
} // end filtmgrs() 
 
 
//-------------------------------- END -------------------------------------- 
 
// display IPX address in 00000001.123456789ABC form 
 
void dp_ipx(int level, char *msg1, SOCKADDR_IPX* addr, char *msg2) 
    { 
    SNMPDBG((level, "%s%02X%02X%02X%02X.%02X%02X%02X%02X%02X%02X%s", 
              msg1, 
              (unsigned char)addr->sa_netnum[0], 
              (unsigned char)addr->sa_netnum[1], 
              (unsigned char)addr->sa_netnum[2], 
              (unsigned char)addr->sa_netnum[3], 
              (unsigned char)addr->sa_nodenum[0], 
              (unsigned char)addr->sa_nodenum[1], 
              (unsigned char)addr->sa_nodenum[2], 
              (unsigned char)addr->sa_nodenum[3], 
              (unsigned char)addr->sa_nodenum[4], 
              (unsigned char)addr->sa_nodenum[5], 
              msg2)); 
    }