/***************************************************************************/ /* Module: $Id: snmpcli.c,v 1.2 1999/05/07 04:15:26 maf Exp $ /* Description: SNMP client. /* Author: Shamim Ahmed /* Notes: /***************************************************************************/ /* $Log: snmpcli.c,v $ Revision 1.2 1999/05/07 04:15:26 maf pr -e2 Revision 1.1 1997/02/23 18:05:10 maf Initial revision * Revision 2.3 1994/02/04 21:35:17 maf * *** empty log message *** * * Revision 2.2 1994/01/02 20:03:50 maf * Generalized include files to kbcconf.h * * Revision 2.1 1993/10/19 19:37:29 maf * kbconfig 1.7+ * * Revision 1.1 1993/08/29 02:01:28 maf * Initial revision * * Revision 1.1 1993/08/29 01:51:14 maf * Initial revision * * Revision 1.1 1993/08/29 01:42:28 maf * Initial revision * */ #include "osusnmp.h" #include "snmpcli.h" #include CliRequestType *snmpDecodeNew(numObj, maxBuffer) short numObj; short maxBuffer; { CliRequestType *tmp; if(!(tmp = (CliRequestType*) malloc((sizeof(CliRequestType)) + (numObj*sizeof(CliReqObjType)) + (maxBuffer)))) return NULL; tmp->maxObj = numObj; tmp->wkBuffer = (u_char*)((u_char*)tmp + (sizeof(CliRequestType))+ (numObj*sizeof(CliReqObjType))); tmp->wkBufferSize = maxBuffer; tmp->list = (CliReqObjType*)((u_char*)tmp + (sizeof(CliRequestType))); return((CliRequestType *)tmp); } CliRequestType *snmpEncodeNew(numObj) short numObj; { CliRequestType *tmp; if (!(tmp = (CliRequestType*) malloc(sizeof(CliRequestType) + (numObj*sizeof(CliReqObjType))))) return NULL; tmp->maxObj = numObj; tmp->wkBuffer = NULL; tmp->wkBufferSize = 0; tmp->list = (CliReqObjType*)((u_char*)tmp + (sizeof(CliRequestType))); return((CliRequestType *)tmp); } /*------------------------------------------------------------------------*/ /* Encode SNMP PACKET. /* /* req: pointer to the request structure. /* bpp: pointer to pointer to buffer to be fill in ( on return the pointer /* is modified to the start of the packet ). /* blenp: pointer to buffer length. Input buffer size and returns the /* length of snmp packet. /*------------------------------------------------------------------------*/ int snmpEncodePkt(req,bpp,blenp) CliRequestType *req; u_char **bpp; short *blenp; { u_char *bp; /* send pkt buffer ptr */ short sendLen,tlen; /* length of send buffer */ short count; u_char buffOid[MAX_OID_ASN_LEN]; /* temporary buffer to save OID */ u_char buffObj[MAX_OBJ_ASN_LEN]; /* temp buffer for object */ u_char buffCon[8]; /* temporary 8 byte long buffer */ short oidLen,objLen, bUsed; /* temporary integers */ short slen,bLeft; /* bytes left in send packet */ u_char *headerEnd; int snmpError; int x; /* TESTING DELETEME */ #ifdef SNMP_XDEBUG fprintf(stderr, "snmpEncodePkt\n"); #endif /***** assume send header is MAX_SEND_HEADER bytes long */ bp = *bpp + MAX_SNMP_HEADER_LEN; tlen = *blenp; *blenp = 0; headerEnd = bp; bLeft = tlen - MAX_SNMP_HEADER_LEN; sendLen = 0; snmpError = snmpErrorNone; count = 0; if (req->reqCount > MAX_BIND_SIZE) return(1); /* encode all the object id's and object values. */ while ((!snmpError) & (count < req->reqCount)) { /* encode object-ID and put into the packet. Also update pointers in smpReq */ bUsed = MAX_OID_ASN_LEN; #ifdef SNMP_XDEBUG fprintf(stderr, "req->list[count.objlen = %d\n", (int)req->list[count].objLen); fprintf(stderr, "req-.list[count].objlen= %d\n", (int)req->list[count].oidLen); fprintf(stderr, "req->reqCount = %d\n", (int)req->reqCount); for (x = 0; x < req->reqCount; ++x) fprintf(stderr, "req->list[count].objType = %d\n", (int)req->list[x].objType); #endif if ((snmpError = asnEncodeOid( buffOid, req->list[count].oid, req->list[count].oidLen, &bUsed))!=0) return(1); oidLen = bUsed; #ifdef SNMP_XDEBUG fprintf(stderr, "asnEncodeOid done\n"); #endif /* SNMP_XDEBUG */ /* encode object value */ bUsed = MAX_OBJ_ASN_LEN; if ((snmpError = asnEncodeAny((u_char*)buffObj, (u_char*)req->list[count].obj, (PCTypes)req->list[count].objType, (short)req->list[count].objLen, (short*)&bUsed))!=0) return(1); objLen = bUsed; #ifdef SNMP_XDEBUG fprintf(stderr, "asnEncodeAny done\n"); #endif /* SNMP_XDEBUG */ /* put oid and value togather as a constructor type */ bUsed = 8; if ((snmpError = asnEncodeSeq(buffCon, (oidLen + objLen), &bUsed))!=0) return(1); #ifdef SNMP_XDEBUG fprintf(stderr, "asnEncodeSeq done\n"); #endif /* SNMP_XDEBUG */ /* now copy construct header, oid and value to buffer */ bLeft = bLeft -bUsed -objLen -oidLen; if (bLeft <= 0) return(1); snmpbcopy(buffCon, bp, bUsed); bp += bUsed; snmpbcopy(buffOid, bp, oidLen); bp += oidLen; snmpbcopy(buffObj, bp, objLen); bp += objLen; sendLen = sendLen + bUsed + oidLen + objLen; count++; } #ifdef SNMP_XDEBUG fprintf(stderr, "Variables encoded\n"); #endif /* SNMP_XDEBUG */ /* make sure if buffer in limits */ if (sendLen > (tlen - MAX_SNMP_HEADER_LEN)) return (1); /* put the header information header is assemble backword ( high byte then low byte ) */ bLeft = sendLen; bUsed = 8; if ((snmpError = asnEncodeSeq(buffCon, sendLen, &bUsed))!=0) return(1); bp = headerEnd - bUsed; snmpbcopy(buffCon,bp,bUsed); sendLen += bUsed; /* error index always less than 128 */ *--bp = (u_char) req->errorIndex; *--bp = 0x01; *--bp = 0x02; /* error status */ *--bp = (u_char) req->errorStatus; *--bp = 0x01; *--bp = 0x02; sendLen += 6; /* 6 bytes so far */ /* encode snmp packet ID */ bUsed = 6; if ((snmpError = asnEncodeAny(buffObj,(u_char *)&req->id, PC_Integer4, (short) 4, &bUsed))!=0) return(1); sendLen += bUsed; bp = bp - bUsed; snmpbcopy(buffObj,bp,bUsed); /* encode command */ bUsed = 8; if ((snmpError = asnEncodeCommand(buffCon, req->command, sendLen, &bUsed))!=0) return(1); sendLen += bUsed; bp = bp - bUsed ; snmpbcopy(buffCon,bp,bUsed); #ifdef SNMP_XDEBUG fprintf(stderr, "Command encoded\n"); #endif /* SNMP_XDEBUG */ bUsed = MAX_OBJ_LEN; if ((slen = req->communityLen) > (short) 20) return(1); if ((snmpError = asnEncodeAny(buffObj,req->communityName, (u_char) PC_OctectString, slen, &bUsed))!=0) return(1); bp -= bUsed; snmpbcopy(buffObj,bp, bUsed); sendLen += bUsed; #ifdef SNMP_XDEBUG fprintf(stderr, "community encoded\n"); #endif /* SNMP_XDEBUG */ /****** version number *******/ *--bp = (u_char) SNMP_VERSION; *--bp = 0x01; *--bp = 0x02; sendLen = sendLen + 3; /***** and finally encode the total length ******/ bUsed = 8; if ((snmpError = asnEncodeSeq(buffCon,sendLen, &bUsed))!=0) return(1); bp = bp - bUsed ; snmpbcopy(buffCon,bp,bUsed); #ifdef SNMP_XDEBUG fprintf(stderr, "length encoded\n"); #endif /* SNMP_XDEBUG */ *bpp = bp; sendLen += bUsed; /* check if header length in limits */ if ( (sendLen - bLeft) > MAX_SNMP_HEADER_LEN) return (1); *blenp = sendLen; #ifdef SNMP_XDEBUG printf("encode ok "); #endif /* PRINTBYTES(bp,sendLen); */ return ( snmpErrorNone ); } /*======================= DECODE SNMP ========================*/ int snmpDecodePkt(req, buffp, blen) CliRequestType *req; u_char *buffp; short blen; { short bUsed; short bLeft; short count,slen; short wkBuffLeft; u_char *bpr,*wkBuff; short length; long tempi; int error; CliRequestType *reqs; short cmd; #ifdef SNMP_DEBUG printf("snmpDecodePkt "); PRINTBYTES(buffp,blen); #endif reqs = req; wkBuff = req->wkBuffer; wkBuffLeft = req->wkBufferSize; bLeft = blen; /* bytes in the packet */ bpr = buffp; /* pointer to packet */ bUsed = bLeft; /**************************************************************/ /* starts as sequence */ if (asnDecodeSeq(bpr,&length,&bUsed)) return(1); /* bytes left should match sequence length */ if ( (bLeft -= bUsed) != length ) return(2); /* skip bUsed (octets used decoding sequence) forward */ bpr += bUsed; /**************************************************************/ /* decode version number */ bUsed = 4; if (asnDecodeInt(bpr,&tempi,&bUsed)) return(3); /* skip bUsed (octets used decoding int) forward */ bpr += bUsed; bLeft -= bUsed; /* bytes left */ /* compare version number */ if (tempi != SNMP_VERSION) return(4); /**************************************************************/ /* decode community name */ bUsed = wkBuffLeft; /* most can decode */ req->communityName = wkBuff; /* decode into work buffer */ if (asnDecodeOctString(bpr, req->communityName, &length, &bUsed)) return(5); wkBuff += length; wkBuffLeft -= length; *(req->communityName + length) = (u_char) 0; /* null terminate it */ /* skip bUsed (octets used decoding string) forward */ bpr += bUsed; bLeft -= bUsed; /**************************************************************/ /* Decode command */ bUsed = bLeft; if (asnDecodeCommand(bpr,&(req->command),&length,&bUsed)) return(6); /* command length match bytes left in packet one command per packet */ if ( (bLeft -= bUsed) != length ) return(7); /* skip bUsed (octets used decoding command) forward */ bpr = bpr + bUsed; /**************************************************************/ /* deocde request ID */ bUsed = 4; if (asnDecodeInt(bpr,&(req->id),&bUsed)) return(8); /* skip bUsed (octets used decoding int) forward */ bpr = bpr + bUsed; bLeft = bLeft - bUsed; /**************************************************************/ /* decode error and error index */ bUsed = 4; if (asnDecodeInt(bpr,&tempi,&bUsed)) return(9); req->errorStatus = (short) tempi; /* skip bUsed (octets used decoding int) forward */ bpr += bUsed; bLeft -= bUsed; /**************************************************************/ bUsed = 4; if (asnDecodeInt(bpr,&tempi,&bUsed)) return(10); req->errorIndex = (short) tempi; bpr += bUsed; bLeft -= bUsed; /* don't bother decoding the rest of the packet if there was an error since it's not valid anyways */ if (req->errorStatus != snmpErrorNone) return 0; /**************************************************************/ /* now the sequence of variables */ bUsed = bLeft; if (asnDecodeSeq(bpr,&length,&bUsed)) return(11); if ( (bLeft -= bUsed) != length ) return(12); bpr += bUsed; count = 0; error = snmpErrorNone; while ((!error) & (bLeft > 0)) { slen = bLeft; if (asnDecodeSeq(bpr,&length,&slen)) return(100+count); /* check if sufficient bytes are in the packet */ if ( bLeft < (length - slen) ) return(200+count); bpr += slen; bLeft -= slen; bUsed = wkBuffLeft; if (( error = asnDecodeOid(bpr, (req->list[count].oid), &(req->list[count].oidLen), &bUsed))!=0) return(300+count); req = reqs; bpr += bUsed; bLeft -= bUsed; if ( bLeft > 0 ) { /* decode value present */ req->list[count].obj = (u_char *) wkBuff; req->list[count].objLen = wkBuffLeft; if ((error=asnDecodeAny(bpr,wkBuff, &(req->list[count].objType),&(req->list[count].objLen), &bUsed))!=0) return(400 + count); } bpr += bUsed; bLeft -= bUsed; wkBuff += req->list[count].objLen; wkBuffLeft -= req->list[count].objLen; count++; } req->reqCount = count; #ifdef SNMP_DEBUG printf(" snmpdecode ok "); #endif return 0; }