?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * Simple Network Management Protocol (SNMP) Version 1 Agent
4 * Simple Network Management Protocol (SNMP) Version 2 community based Agent
5 * Module for Microchip TCP/IP Stack
6 * -Provides SNMP API for doing stuff
7 *
8 * -Reference: RFC 1157 (for SNMP V1)
9 * RFC 3416 (for SNMPv2C)
10 *********************************************************************
11 * FileName: SNMP.c
12 * Dependencies: UDP, ARP
13 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
14 * Compiler: Microchip C32 v1.05 or higher
15 * Microchip C30 v3.12 or higher
16 * Microchip C18 v3.30 or higher
17 * HI-TECH PICC-18 PRO 9.63PL2 or higher
18 * Company: Microchip Technology, Inc.
19 *
20 * Software License Agreement
21 *
22 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
23 * reserved.
24 *
25 * Microchip licenses to you the right to use, modify, copy, and
26 * distribute:
27 * (i) the Software when embedded on a Microchip microcontroller or
28 * digital signal controller product ("Device") which is
29 * integrated into Licensee's product; or
30 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
31 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
32 * used in conjunction with a Microchip ethernet controller for
33 * the sole purpose of interfacing with the ethernet controller.
34 *
35 * You should refer to the license agreement accompanying this
36 * Software for additional information regarding your rights and
37 * obligations.
38 *
39 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
40 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
41 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
42 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
43 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
44 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
45 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
46 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
47 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
48 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
49 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
50 *
51 * Author Date Comment
52 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 * Nilesh Rajbharti 1/9/03 Original (Rev 1.0)
54 * Dan Cohen 12/11/03 Removed trap support by #define if not
55 * required to lower code space requirements
56 * Amit Shirbhate 09/24/08 SNMPv2c Support, comments and function
57 * headers added.
58 * Hrisikesh Sahu 04/15/10 SNMPv2 Trap Format Support.
59 ********************************************************************/
60  
61 #define __SNMP_C
62  
63 #include "TCPIPConfig.h"
64  
65 #if defined(STACK_USE_SNMP_SERVER)
66  
67 #include "TCPIP Stack/TCPIP.h"
68  
69 #if defined(STACK_USE_MPFS2)
70 /****************************************************************************
71 *
72 * Begin SNMP for MPFS2.
73 *
74 ****************************************************************************/
75  
76 /****************************************************************************
77 Section:
78 Macros and Definitions
79 ***************************************************************************/
80  
81 // Section: SNMP agent version types
82 #define SNMP_V1 (0)
83 #define SNMP_V2C (1)
84  
85 // Section: SNMP specific variables
86 #define STRUCTURE (0x30u)
87 #define ASN_INT (0x02u)
88 #define OCTET_STRING (0x04u)
89 #define ASN_NULL (0x05u)
90 #define ASN_OID (0x06u)
91  
92 #define SNMP_IP_ADDR (0x40)
93 #define SNMP_COUNTER32 (0x41)
94 #define SNMP_GAUGE32 (0x42)
95 #define SNMP_TIME_TICKS (0x43)
96 #define SNMP_OPAQUE (0x44)
97 #define SNMP_NSAP_ADDR (0x45)
98  
99 // Section: SNMP v1 and v2c pdu types
100 #define GET_REQUEST (0xa0)
101 #define GET_NEXT_REQUEST (0xa1)
102 #define GET_RESPONSE (0xa2)
103 #define SET_REQUEST (0xa3)
104 #define TRAP (0xa4)
105 #define GET_BULK_REQUEST (0xa5)
106  
107 // Section: SNMP specific data validation
108 #define IS_STRUCTURE(a) (a==STRUCTURE)
109 #define IS_ASN_INT(a) (a==ASN_INT)
110 #define IS_OCTET_STRING(a) (a==OCTET_STRING)
111 #define IS_OID(a) (a==ASN_OID)
112 #define IS_ASN_NULL(a) (a==ASN_NULL)
113 #define IS_GET_REQUEST(a) (a==GET_REQUEST)
114 #define IS_GET_NEXT_REQUEST(a) (a==GET_NEXT_REQUEST)
115 #define IS_GET_RESPONSE(a) (a==GET_RESPONSE)
116 #define IS_SET_REQUEST(a) (a==SET_REQUEST)
117 #define IS_TRAP(a) (a==TRAP)
118 #define IS_AGENT_PDU(a) (a==GET_REQUEST || \
119 a==GET_NEXT_REQUEST || \
120 a==SET_REQUEST || \
121 a==SNMP_V2C_GET_BULK)
122 // Section: SNMP Udp ports
123 #define SNMP_AGENT_PORT (161)
124 #define SNMP_NMS_PORT (162)
125 #define AGENT_NOTIFY_PORT (0xfffe)
126  
127 // Section: SNMP Tx pdu offset settings
128 #define _SNMPSetTxOffset(o) (SNMPTxOffset = o)
129 #define _SNMPGetTxOffset() SNMPTxOffset
130  
131  
132 /****************************************************************************
133 Section:
134 Data Structures and Enumerations
135 ***************************************************************************/
136  
137 // Section: SNMP specific errors
138 typedef enum
139 {
140 SNMP_NO_ERR = 0, //Snmp no error
141 SNMP_TOO_BIG, //Value too big error
142 SNMP_NO_SUCH_NAME, //No such name in MIB error
143 SNMP_BAD_VALUE, //Not assignable value for the var error
144 SNMP_READ_ONLY, //Read only variable, write not allowed err
145 SNMP_GEN_ERR, //Snmp gen error
146 SNMP_NO_ACCESS, //Access to modify or read not granted err
147 SNMP_WRONG_TYPE, //Variable data type wrong error
148 SNMP_WRONG_LENGTH, //Wrong data length error
149 SNMP_WRONG_ENCODING, //Wrong encoding error
150 SNMP_WRONG_VALUE, //Wrong value for the var type
151 SNMP_NO_CREATION, //No creationg error
152 SNMP_INCONSISTENT_VAL, //Inconsistent value error
153 SNMP_RESOURCE_UNAVAILABE, //Resource unavailbe error
154 SNMP_COMMIT_FAILED, //Modification update failed error
155 SNMP_UNDO_FAILED, //Modification undo failed
156 SNMP_AUTH_ERROR, //Authorization failed error
157 SNMP_NOT_WRITABLE, //Variable read only
158 SNMP_INCONSISTENT_NAME, //Inconsistent name
159 SNMP_NO_SUCH_OBJ=128, //No such object error
160 SNMP_NO_SUCH_INSTANCE=129, //No such instance error
161 SNMP_END_OF_MIB_VIEW=130 //Reached to end of mib error
162 } SNMP_ERR_STATUS;
163  
164  
165 // Section: SNMP specific data tyes
166 typedef enum
167 {
168 INT8_VAL = 0x00, //8 bit integer value
169 INT16_VAL = 0x01, //16 bit integer value
170 INT32_VAL = 0x02, //32 bit integer value
171 BYTE_ARRAY = 0x03, //Aray of bytes
172 ASCII_STRING = 0x04, //Ascii string type
173 IP_ADDRESS = 0x05, //IP address variable
174 COUNTER32 = 0x06, //32 bit counter variable
175 TIME_TICKS_VAL = 0x07, //Timer vakue counter variable
176 GAUGE32 = 0x08, //32 bit guage variable
177 OID_VAL = 0x09, //Object id value var
178 DATA_TYPE_UNKNOWN //Unknown data type
179 } DATA_TYPE;
180  
181  
182 // Section: SNMP specific mib file access information
183 typedef union
184 {
185 struct
186 {
187 unsigned int bIsFileOpen : 1; //MIB file access int flag
188 } Flags;
189 BYTE Val; //MIB file access byte flag
190 } SNMP_STATUS;
191  
192  
193 // Section: SNMP OID index information
194 typedef union
195 {
196 struct
197 {
198 unsigned int bIsOID:1; //value is OID/index int flag
199 } Flags;
200 BYTE Val; //value is OID/index byte flag
201 } INDEX_INFO;
202  
203  
204 // Section: SNMP object information
205 typedef union
206 {
207 struct
208 {
209 unsigned int bIsDistantSibling : 1; //Object have distant sibling node
210 unsigned int bIsConstant : 1; //Object is constant
211 unsigned int bIsSequence : 1; //Object is sequence
212 unsigned int bIsSibling : 1; //Sibling node flag
213  
214 unsigned int bIsParent : 1; //Node is parent flag
215 unsigned int bIsEditable : 1; //Node is editable flag
216 unsigned int bIsAgentID : 1; //Node have agent id flag
217 unsigned int bIsIDPresent : 1; //Id present flag
218 } Flags;
219 BYTE Val; //MIB Obj info as byte value
220 } MIB_INFO;
221  
222  
223 // Section: SNMP reuested variable list error status information.
224 //Max variable in a request supported 15
225 typedef struct
226 {
227 WORD noSuchObjectErr; //Var list no such obj errors flags
228 WORD noSuchNameErr; //Var list no such name error
229 WORD noSuchInstanceErr; //Var list no such instance error
230 WORD endOfMibViewErr; //Var list end of mib view error
231 }reqVarErrStatus;
232  
233  
234 // Section: ASN data type info
235 typedef struct
236 {
237 BYTE asnType; //ASN data type
238 BYTE asnLen; //ASN data length
239 } DATA_TYPE_INFO;
240  
241  
242 // Section: SNMP trap notification information for agent
243 typedef struct
244 {
245 char community[NOTIFY_COMMUNITY_LEN]; //Community name array
246 BYTE communityLen; //Community name length
247 SNMP_ID agentIDVar; //Agent id for trap identification
248 BYTE notificationCode; //Trap notification code
249 UDP_SOCKET socket; //Udp socket number
250 DWORD_VAL timestamp; //Time stamp for trap
251 } SNMP_NOTIFY_INFO;
252  
253  
254 // Section: SNMP MIB variable object information
255 typedef struct
256 {
257 DWORD hNode; //Node location in the mib
258 BYTE oid; //Object Id
259 MIB_INFO nodeInfo; //Node info
260 DATA_TYPE dataType; //Data type
261 SNMP_ID id; //Snmp Id
262 WORD_VAL dataLen; //Data length
263 DWORD hData; //Data
264 DWORD hSibling; //Sibling info
265 DWORD hChild; //Child info
266 BYTE index; //Index of object
267 BYTE indexLen; //Index length
268 } OID_INFO;
269  
270  
271 // Section: SNMP pdu information database
272 typedef struct
273 {
274 DWORD_VAL requestID; //Snmp request id
275 BYTE nonRepeators; //# non repeaters in the request
276 BYTE maxRepetitions; //# max repeaters in the request
277 BYTE pduType; //Snmp pdu type
278 BYTE errorStatus; //Pdu error status
279 BYTE erroIndex; //Pdu error Index
280 BYTE snmpVersion; //Snmp version
281 WORD pduLength; //Pdu length
282 } PDU_INFO;
283  
284  
285 /****************************************************************************
286 Section:
287 Function Prototypes
288 ***************************************************************************/
289  
290 // Section: Process SNMP request pdus,form response pdus routines
291 static BYTE _SNMPGet(void);
292 static void _SNMPPut(BYTE v);
293 static BYTE FindOIDsInRequest(WORD pdulen);
294 static SNMP_ACTION ProcessHeader(PDU_INFO* pduDbPtr, char* community, BYTE* len);
295 static BOOL ProcessGetSetHeader(PDU_INFO* pduDbPtr);
296 static BOOL ProcessVariables(PDU_INFO* pduDbPtr,char* community, BYTE len);
297 static BYTE ProcessGetVar(OID_INFO* rec, BOOL bAsOID);
298 static BYTE ProcessGetNextVar(OID_INFO* rec);
299 static BYTE ProcessSetVar(PDU_INFO* pduDbPtr,OID_INFO* rec, SNMP_ERR_STATUS* errorStatus);
300 static BYTE ProcessGetBulkVar(OID_INFO* rec, BYTE* oidValuePtr, BYTE* oidLenPtr,BYTE* successor);
301  
302 // Section: Routines to validate snmp request pdu elements for SNMP format
303 static BOOL IsValidOID(BYTE* oid, BYTE* len);
304 static BOOL IsValidCommunity(char* community, BYTE* len);
305 static BOOL IsValidInt(DWORD* val);
306 static BOOL IsValidPDU(SNMP_ACTION* pdu);
307 static BYTE IsValidLength(WORD* len);
308 static BYTE IsValidStructure(WORD* dataLen);
309 static BOOL IsASNNull(void);
310  
311 // Section: Routines to read/search OIDs,objects from the SNMP MIB database
312 static BYTE OIDLookup(PDU_INFO* pduDbPtr,BYTE* oid, BYTE oidLen, OID_INFO* rec);
313 static BOOL GetNextLeaf(OID_INFO* rec);
314 static BOOL GetOIDStringByAddr(OID_INFO* rec, BYTE* oidString, BYTE* len);
315 static BOOL GetDataTypeInfo(DATA_TYPE dataType, DATA_TYPE_INFO* info);
316 static void ReadMIBRecord(DWORD h, OID_INFO* rec);
317  
318 // Section: Global variables configuration for pdu processings
319 static void _SNMPDuplexInit(UDP_SOCKET socket);
320 static void SetErrorStatus(WORD errorStatusOffset,WORD errorIndexOffset,SNMP_ERR_STATUS errorStatus,BYTE errorIndex);
321  
322 // Section: Routine to check if private mib object is requested by NMS.
323 static BOOL SNMPCheckIfPvtMibObjRequested(BYTE* OIDValuePtr);
324  
325 // This function is used only when TRAP is enabled.
326 #if !defined(SNMP_TRAP_DISABLED)
327 static BOOL GetOIDStringByID(SNMP_ID id, OID_INFO* info, BYTE* oidString, BYTE* len);
328 #endif
329  
330  
331  
332 /****************************************************************************
333 Section:
334 Global Variables
335 ***************************************************************************/
336 static WORD SNMPTxOffset; //Snmp udp buffer tx offset
337 static WORD SNMPRxOffset; //Snmp udp buffer rx offset
338 static SNMP_STATUS SNMPStatus; //MIB file access status
339 static UDP_SOCKET SNMPAgentSocket = INVALID_UDP_SOCKET; //Snmp udp socket
340 static MPFS_HANDLE hMPFS; //MPFS file handler
341 extern TRAP_INFO trapInfo; //trap information
342  
343 static BYTE appendZeroToOID;//global flag to modify OID by appending zero
344 reqVarErrStatus snmpReqVarErrStatus; //vars from req list processing err status
345  
346 // SNMPNotifyInfo is not required if TRAP is disabled
347 #if !defined(SNMP_TRAP_DISABLED)
348 static SNMP_NOTIFY_INFO SNMPNotifyInfo; //notify info for trap
349 #endif
350  
351 //ASN format datatype for snmp v1 and v2c
352 static ROM DATA_TYPE_INFO dataTypeTable[] =
353 {
354 { ASN_INT, 1 }, //INT8_VAL
355 { ASN_INT, 2 }, //INT16_VAL
356 { ASN_INT, 4 }, //INT32_VAL
357 { OCTET_STRING, 0xff }, //BYTE_ARRAY
358 { OCTET_STRING, 0xff }, //ASCII_ARRAY
359 { SNMP_IP_ADDR, 4 }, //IP_ADDRESS
360 { SNMP_COUNTER32, 4 }, //COUNTER32
361 { SNMP_TIME_TICKS, 4 }, //TIME_TICKS_VAL
362 { SNMP_GAUGE32, 4 }, //GAUTE32
363 { ASN_OID, 0xff } //OID_VAL
364 };
365  
366  
367 /****************************************************************************
368 ===========================================================================
369 Section:
370 SNMP v1 and v2c Agent Routines
371 ===========================================================================
372 ***************************************************************************/
373  
374 /****************************************************************************
375 Function:
376 void SNMPInit(void)
377  
378 Summary:
379 Initialize SNMP module internals.
380  
381 Description:
382 This function initializes the Snmp agent. One udp socket is intialized
383 and opened at port 161. Agent will receive and transmit all the snmp
384 pdus on this udp socket.
385  
386 Precondition:
387 At least one UDP socket must be available. UDPInit() is already called.
388  
389 Parameters:
390 None
391  
392 Returns:
393 None
394  
395 Remarks:
396 This function is called only once during lifetime of the application.
397 One UDP socket will be used.
398 ***************************************************************************/
399 void SNMPInit(void)
400 {
401 // Start with no error or flag set.
402 SNMPStatus.Val = 0;
403  
404 SNMPAgentSocket = UDPOpen(SNMP_AGENT_PORT, 0, INVALID_UDP_SOCKET);
405 // SNMPAgentSocket must not be INVALID_UDP_SOCKET.
406 // If it is, compile time value of UDP Socket numbers must be increased.
407  
408 return;
409 }
410  
411  
412 /****************************************************************************
413 Function:
414 BOOL SNMPTask(void)
415  
416 Summary:
417 Polls for every snmp pdu received.
418  
419 Description:
420 Handle incoming SNMP requests as well as any outgoing SNMP
421 responses and timeout conditions.
422  
423 Precondition:
424 SNMPInit() is already called.
425  
426 Parameters:
427 None
428  
429 Return Values:
430 TRUE - If SNMP module has finished with a state
431 FALSE - If a state has not been finished.
432  
433 Remarks:
434 None
435 ***************************************************************************/
436 BOOL SNMPTask(void)
437 {
438 char community[SNMP_COMMUNITY_MAX_LEN];
439 BYTE communityLen;
440 PDU_INFO pduInfoDB; //received pdu information database
441 BOOL lbReturn;
442  
443 if(SNMPAgentSocket == INVALID_UDP_SOCKET)
444 return TRUE;
445  
446 // Check to see if there is any packet on SNMP Agent socket.
447 if ( !UDPIsGetReady(SNMPAgentSocket) )
448 return TRUE;
449  
450 // As we process SNMP variables, we will prepare response on-the-fly
451 // creating full duplex transfer.
452 // Current MAC layer does not support full duplex transfer, so
453 // SNMP needs to manage its own full duplex connection.
454 // Prepare for full duplex transfer.
455 _SNMPDuplexInit(SNMPAgentSocket);
456  
457 communityLen = 0; // Suppress C30 warning: 'communityLen' may be used uninitialized in this function
458 pduInfoDB.pduType = ProcessHeader(&pduInfoDB,community, &communityLen);
459  
460 if ( pduInfoDB.pduType == SNMP_ACTION_UNKNOWN )
461 goto _SNMPDiscard;
462  
463 if ( !ProcessGetSetHeader(&pduInfoDB))
464 goto _SNMPDiscard;
465  
466 // Open MIB file.
467 SNMPStatus.Flags.bIsFileOpen = FALSE;
468  
469  
470  
471 hMPFS = MPFSOpenROM((ROM BYTE*)SNMP_BIB_FILE_NAME);
472  
473  
474 if(hMPFS != MPFS_INVALID_HANDLE)
475 {
476 SNMPStatus.Flags.bIsFileOpen = TRUE;
477 }
478  
479 lbReturn = ProcessVariables(&pduInfoDB,community, communityLen);
480 if ( SNMPStatus.Flags.bIsFileOpen )
481 {
482 MPFSClose(hMPFS);
483 }
484  
485 if ( lbReturn == FALSE )
486 goto _SNMPDiscard;
487  
488 if(gSendTrapFlag==(BYTE)FALSE)
489 UDPFlush();
490  
491 return TRUE;
492  
493 _SNMPDiscard:
494 UDPDiscard();
495  
496 return TRUE;
497 }
498  
499  
500 #if !defined(SNMP_TRAP_DISABLED)
501 /****************************************************************************
502 Function:
503 void SNMPNotifyPrepare(IP_ADDR* remoteHost,
504 char* community,
505 BYTE communityLen,
506 SNMP_ID agentIDVar,
507 BYTE notificationCode,
508 DWORD timestamp)
509  
510 Summary:
511 Collects trap notification info and send ARP to remote host.
512  
513 Description:
514 This function prepares SNMP module to send SNMP trap notification
515 to remote host. It sends ARP request to remote host to learn remote
516 host MAC address.
517  
518 Precondition:
519 SNMPInit() is already called.
520  
521 Parameters:
522 remoteHost - pointer to remote Host IP address
523 community - Community string to use to notify
524 communityLen- Community string length
525 agentIDVar - System ID to use identify this agent
526 notificaitonCode - Notification Code to use
527 timestamp - Notification timestamp in 100th of second.
528  
529 Returns:
530 None
531  
532 Remarks:
533 This is first of series of functions to complete SNMP notification.
534 ***************************************************************************/
535 void SNMPNotifyPrepare(IP_ADDR* remoteHost,
536 char* community,
537 BYTE communityLen,
538 SNMP_ID agentIDVar,
539 BYTE notificationCode,
540 DWORD timestamp )
541 {
542 IP_ADDR* remHostIpAddrPtr;
543 remHostIpAddrPtr = remoteHost;
544  
545 strcpy(SNMPNotifyInfo.community, community);
546 SNMPNotifyInfo.communityLen = communityLen;
547  
548 SNMPNotifyInfo.agentIDVar = agentIDVar;
549 SNMPNotifyInfo.notificationCode = notificationCode;
550  
551 SNMPNotifyInfo.timestamp.Val = timestamp;
552  
553 ARPResolve(remHostIpAddrPtr);
554 }
555  
556  
557 /****************************************************************************
558 Function:
559 BOOL SNMPIsNotifyReady(IP_ADDR* remoteHost)
560  
561 Summary:
562 Resolves given remoteHost IP address into MAC address.
563  
564 Description:
565 This function resolves given remoteHost IP address into MAC address using
566 ARP module. If remoteHost is not aviailable, this function would never
567 return TRUE. Application must implement timeout logic to handle
568 "remoteHost not avialable" situation.
569  
570 Precondition:
571 SNMPNotifyPrepare() is already called.
572  
573 Parameters:
574 remoteHost - Pointer to remote Host IP address
575  
576 Return Values:
577 TRUE - If remoteHost IP address is resolved and
578 SNMPNotify may be called.
579 FALSE - If remoteHost IP address is not resolved.
580  
581 Remarks:
582 This would fail if there were not UDP socket to open.
583 ***************************************************************************/
584 BOOL SNMPIsNotifyReady(IP_ADDR* remoteHost)
585 {
586 NODE_INFO remoteNode;
587  
588 IP_ADDR * remHostIpAddrPtr;
589 remHostIpAddrPtr = remoteHost;
590  
591 if ( ARPIsResolved(remHostIpAddrPtr, &remoteNode.MACAddr) )
592 {
593 remoteNode.IPAddr.Val = remHostIpAddrPtr->Val;
594  
595 SNMPNotifyInfo.socket = UDPOpen(AGENT_NOTIFY_PORT, &remoteNode, SNMP_NMS_PORT);
596  
597 return (SNMPNotifyInfo.socket != INVALID_UDP_SOCKET);
598 }
599 return FALSE;
600 }
601  
602 /****************************************************************************
603 Function:
604 BYTE *getSnmpV2GenTrapOid(BYTE generic_trap_code,BYTE *len)
605 Summary:
606 Resolves generic trap code to generic trap OID.
607  
608 Description:
609 This function resolves given generic trap code to generic trap OID.
610  
611 Precondition:
612 SNMPNotifyPrepare() is already called.
613  
614 Parameters:
615 generic_trap_code - GENERIC_TRAP_NOTIFICATION_TYPE
616 len - generic trap OID length
617  
618 Return Values:
619 BYTE *- TRAP OID
620  
621 Remarks:
622 This would fail if generic_trap_code is not coming under
623 GENERIC_TRAP_NOTIFICATION_TYPE
624 ***************************************************************************/
625  
626 BYTE *getSnmpV2GenTrapOid(BYTE generic_trap_code,BYTE *len)
627 {
628 static BYTE gen_trap_oid[] = {0x2b,6,1,6,3,1,1,5,1};
629 /*
630 static BYTE cold_trap_oid[] = {0x2b,6,1,6,3,1,1,5,1};
631 static BYTE warm_start_oid = {0x2b,6,1,6,3,1,1,5,2};
632 static BYTE auth_fail_oid = {0x2b,6,1,6,3,1,1,5,5};
633 static BYTE linkdown_oid = {0x2b,6,1,6,3,1,1,5,3};
634 static BYTE linkup_oid = {0x2b,6,1,6,3,1,1,5,4};
635 */
636 static BYTE snmptrap_oids[] = {0x2b,6,1,6,3,1,1,4,1 };
637  
638 *len = sizeof(gen_trap_oid);
639 switch (generic_trap_code)
640 {
641 case COLD_START:
642 gen_trap_oid[*len-1] = 1;
643 break;
644  
645 case WARM_START:
646 gen_trap_oid[*len-1] = 2;
647 break;
648 case LINK_UP:
649 gen_trap_oid[*len-1] = 4;
650 break;
651 case LINK_DOWN:
652 gen_trap_oid[*len-1] = 3;
653 break;
654 case AUTH_FAILURE:
655 gen_trap_oid[*len-1] = 5;
656 break;
657 case ENTERPRISE_SPECIFIC:
658 *len = sizeof(snmptrap_oids);
659 return snmptrap_oids;
660 default:
661 return NULL;
662  
663 } /* switch (generic_trap_code) */
664  
665 return gen_trap_oid;
666  
667 } /* end getSnmpV2TrapOid() */
668  
669  
670  
671 /****************************************************************************
672 Function:
673 BOOL SNMPNotify(SNMP_ID var,SNMP_VAL val,SNMP_INDEX index)
674  
675 Summary:
676 Creates and Sends TRAP pdu.
677  
678 Description:
679 This function creates SNMP V2 Trap PDU and sends it to previously specified
680 remoteHost.
681  
682 snmpv1 trap pdu:
683 | PDU-type | enterprise | agent-addr | generic-trap | specific-trap |
684 | time-stamp | varbind-list |
685  
686 The v1 enterprise is mapped directly to SNMPv2TrapOID.0
687 SNMP v2 trap pdu:
688 version (0 or 1) | community | SNMP-PDU |pdu-type | request-id | error-status
689 |err-index |varbinds
690  
691 The first two variables (in varbind-list) of snmpv2 are: sysUpTime.0 and
692 SNMPv2TrapOID.0
693  
694 Generic Trap OID is used as the varbind for authentication failure.
695  
696 Precondition:
697 SNMPIsNotifyReady() is already called and returned TRUE.
698  
699 Parameters:
700 var - SNMP var ID that is to be used in notification
701 val - Value of var. Only value of BYTE, WORD or DWORD can be sent.
702 index - Index of var. If this var is a single,index would be 0, or else
703 if this var Is a sequence, index could be any value
704 from 0 to 127
705  
706 Return Values:
707 TRUE - if SNMP notification was successful sent.
708 This does not guarantee that remoteHost recieved it.
709 FALSE - Notification sent failed.
710 This would fail under following contions:
711 1) Given SNMP_BIB_FILE does not exist in MPFS
712 2) Given var does not exist.
713 3) Previously given agentID does not exist
714 4) Data type of given var is unknown - only
715 possible if MPFS itself was corrupted.
716  
717 Remarks:
718 This would fail if there were not UDP socket to open.
719 ***************************************************************************/
720 #if defined(SNMP_STACK_USE_V2_TRAP)
721  
722 BOOL SNMPNotify(SNMP_ID var, SNMP_VAL val, SNMP_INDEX index)
723 {
724 char* pCommunity;
725 BYTE len;
726 BYTE OIDValue[OID_MAX_LEN];
727 BYTE OIDLen;
728 static DWORD varbindlen = 0;
729 BYTE agentIDLen;
730 BYTE* pOIDValue;
731 static WORD packetStructLenOffset = 0;
732 static WORD pduStructLenOffset = 0;
733 static WORD varBindStructLenOffset = 0;
734 static WORD varPairStructLenOffset = 0;
735 static WORD prevOffset = 0;
736 WORD tempOffset = 0;
737 OID_INFO rec;
738 DATA_TYPE_INFO dataTypeInfo;
739 BYTE snmptrap_oids[] = {0x2b,6,1,6,3,1,1,4,1 }; /* len=10 */
740 BYTE sysUpTime_oids[] = {0x2b,6,1,2,1,1,3}; /* len = 8 */
741  
742 hMPFS = MPFSOpenROM((ROM BYTE*)SNMP_BIB_FILE_NAME);
743 if ( hMPFS == MPFS_INVALID_HANDLE )
744 {
745 UDPClose(SNMPNotifyInfo.socket);
746 return FALSE;
747 }
748  
749 if((packetStructLenOffset == 0)&&(pduStructLenOffset==0))
750 {
751 _SNMPDuplexInit(SNMPNotifyInfo.socket);
752 prevOffset = _SNMPGetTxOffset();
753  
754 len = SNMPNotifyInfo.communityLen;
755 pCommunity = SNMPNotifyInfo.community;
756  
757 _SNMPPut(STRUCTURE); // First item is packet structure
758 packetStructLenOffset = SNMPTxOffset;
759 _SNMPPut(0);
760  
761 // Put SNMP version info.
762 _SNMPPut(ASN_INT); // Int type.
763 _SNMPPut(1); // One byte long value.
764 _SNMPPut(SNMP_V2C); // v2
765  
766 //len = strlen(community); // Save community length for later use.
767 _SNMPPut(OCTET_STRING); // Octet string type.
768 _SNMPPut(len); // community string length
769 while( len-- ) // Copy entire string.
770 _SNMPPut(*(pCommunity++));
771  
772 //TRAP Version type.
773 _SNMPPut(SNMP_V2_TRAP);
774 pduStructLenOffset = SNMPTxOffset;
775 _SNMPPut(0);
776  
777 //put Request ID for the trapv2 as 1
778 _SNMPPut(ASN_INT); // Int type.
779 _SNMPPut(4); // To simplify logic, always use 4 byte long requestID
780 _SNMPPut(0); _SNMPPut(0); _SNMPPut(0); _SNMPPut(1);
781  
782 // Put error status.
783 _SNMPPut(ASN_INT); // Int type
784 _SNMPPut(1); // One byte long.
785 _SNMPPut(0); // Placeholder.
786  
787 // Similarly put error index.
788 _SNMPPut(ASN_INT); // Int type
789 _SNMPPut(1); // One byte long
790 _SNMPPut(0); // Placeholder.
791  
792 // Variable binding structure header
793 _SNMPPut(0x30);
794 varBindStructLenOffset = SNMPTxOffset;
795 _SNMPPut(0);
796  
797 // Create variable name-pair structure
798 _SNMPPut(0x30);
799 varPairStructLenOffset = SNMPTxOffset;
800 _SNMPPut(0);
801  
802 // Set 1st varbind object i,e sysUpTime.0 time stamp for the snmpv2 trap
803 // Get complete notification variable OID string.
804  
805 _SNMPPut(ASN_OID);
806 OIDLen = (BYTE)sizeof(sysUpTime_oids);
807 _SNMPPut((BYTE)(OIDLen)+1);
808 pOIDValue = sysUpTime_oids;
809 while( OIDLen-- )
810 _SNMPPut(*pOIDValue++);
811  
812 //1st varbind and this is a scalar object so index = 0
813 _SNMPPut(0);
814  
815 // Time stamp
816 _SNMPPut(SNMP_TIME_TICKS);
817 _SNMPPut(4);
818 _SNMPPut(SNMPNotifyInfo.timestamp.v[3]);
819 _SNMPPut(SNMPNotifyInfo.timestamp.v[2]);
820 _SNMPPut(SNMPNotifyInfo.timestamp.v[1]);
821 _SNMPPut(SNMPNotifyInfo.timestamp.v[0]);
822  
823 tempOffset = _SNMPGetTxOffset();
824 //set the snmp time varbind trap offset
825 _SNMPSetTxOffset(varPairStructLenOffset);
826  
827 // SNMP time stamp varbind length
828 OIDLen = 2 // 1st varbind header
829 + (BYTE)sizeof(sysUpTime_oids)
830 + 1 // index byte
831 + 6 ; // time stamp
832  
833 _SNMPPut(OIDLen);
834 //set the previous TX offset
835 _SNMPSetTxOffset(tempOffset);
836 varbindlen += OIDLen // varbind length
837 + 2; // varbind type(30) and length of individual varbind pdu
838  
839 // Set 2nd varbind object i,e snmpTrapOID.0 for the snmpv2 trap
840 // Get complete notification variable OID string.
841  
842 // Create variable name-pair structure
843 _SNMPPut(0x30);
844 varPairStructLenOffset = SNMPTxOffset;
845 _SNMPPut(0);
846  
847 // Copy OID string into PDU.
848 _SNMPPut(ASN_OID);
849 OIDLen = (BYTE)sizeof(snmptrap_oids);
850 _SNMPPut((BYTE)(OIDLen)+1);
851  
852 pOIDValue = snmptrap_oids;
853 while( OIDLen-- )
854 _SNMPPut(*pOIDValue++);
855  
856 //2nd varbind and this is a scalar object so index = 0
857 _SNMPPut(0);
858  
859 // for microchip , SNMPNotifyInfo.agentIDVar == MICROCHIP
860 if ( !GetOIDStringByID(SNMPNotifyInfo.agentIDVar, &rec, OIDValue, &OIDLen) )
861 {
862 MPFSClose(hMPFS);
863 UDPClose(SNMPNotifyInfo.socket);
864 return FALSE;
865 }
866 if ( !rec.nodeInfo.Flags.bIsAgentID )
867 {
868 MPFSClose(hMPFS);
869 UDPClose(SNMPNotifyInfo.socket);
870 return FALSE;
871 }
872  
873 MPFSSeek(hMPFS, rec.hData, MPFS_SEEK_START);
874  
875 _SNMPPut(ASN_OID);
876 MPFSGet(hMPFS, &len);
877 agentIDLen = len;
878 _SNMPPut(agentIDLen);
879 while( len-- )
880 {
881 BYTE c;
882 MPFSGet(hMPFS, &c);
883 _SNMPPut(c);
884 }
885 tempOffset = _SNMPGetTxOffset();
886 //set the snmp varbind trap offset
887 _SNMPSetTxOffset(varPairStructLenOffset);
888 // Snmp trap varbind length
889 OIDLen = 2 // Agent ID header bytes
890 + (BYTE)sizeof(snmptrap_oids)
891 + 1 // index byte
892 + 2 // header
893 + agentIDLen; // Agent ID bytes
894 _SNMPPut(OIDLen);
895  
896 //set the previous TX offset
897 _SNMPSetTxOffset(tempOffset);
898 varbindlen += OIDLen // varbind length
899 + 2; // varbind type(30) and length of individual varbind pdu
900  
901 }
902 else
903 { // collect the last varbind offset value.
904 _SNMPSetTxOffset(varPairStructLenOffset);
905 }
906  
907 // Create variable name-pair structure
908 _SNMPPut(0x30);
909 varPairStructLenOffset = SNMPTxOffset;
910 _SNMPPut(0);
911 /* to send generic trap trap */
912 if(gGenericTrapNotification != ENTERPRISE_SPECIFIC)
913 {
914 pOIDValue = getSnmpV2GenTrapOid(gGenericTrapNotification,&OIDLen);
915 if(pOIDValue == NULL)
916 {
917 MPFSClose(hMPFS);
918 UDPClose(SNMPNotifyInfo.socket);
919 return FALSE;
920 }
921 // Copy OID string into PDU.
922 _SNMPPut(ASN_OID);
923 _SNMPPut((BYTE)(OIDLen)+1);
924 while( OIDLen-- )
925 _SNMPPut(*pOIDValue++);
926  
927 //2nd varbind and this is a scalar object so index = 0
928 _SNMPPut(0);
929 // for microchip , SNMPNotifyInfo.agentIDVar == MICROCHIP
930 if ( !GetOIDStringByID(SNMPNotifyInfo.agentIDVar, &rec, OIDValue, &OIDLen) )
931 {
932 MPFSClose(hMPFS);
933 UDPClose(SNMPNotifyInfo.socket);
934 return FALSE;
935 }
936 if ( !rec.nodeInfo.Flags.bIsAgentID )
937 {
938 MPFSClose(hMPFS);
939 UDPClose(SNMPNotifyInfo.socket);
940 return FALSE;
941 }
942  
943 MPFSSeek(hMPFS, rec.hData, MPFS_SEEK_START);
944  
945 _SNMPPut(ASN_OID);
946 MPFSGet(hMPFS, &len);
947 agentIDLen = len;
948 _SNMPPut(agentIDLen);
949 while( len-- )
950 {
951 BYTE c;
952 MPFSGet(hMPFS, &c);
953 _SNMPPut(c);
954 }
955 tempOffset = _SNMPGetTxOffset();
956 //set the snmp varbind trap offset
957 _SNMPSetTxOffset(varPairStructLenOffset);
958 // Snmp trap varbind length
959 OIDLen = 2 // Agent ID header bytes
960 + (BYTE)sizeof(snmptrap_oids)
961 + 1 // index byte
962 + 2 // header
963 + agentIDLen; // Agent ID bytes
964 _SNMPPut(OIDLen);
965 len = OIDLen;
966 }
967 else
968 {
969 // Get complete notification variable OID string.
970 if ( !GetOIDStringByID(var, &rec, OIDValue, &OIDLen) )
971 {
972 MPFSClose(hMPFS);
973 UDPClose(SNMPNotifyInfo.socket);
974 return FALSE;
975 }
976 pOIDValue = OIDValue;
977  
978 // Copy OID string into packet.
979 _SNMPPut(ASN_OID);
980 _SNMPPut((BYTE)(OIDLen+1));
981 len = OIDLen;
982 while( len-- )
983 _SNMPPut(*pOIDValue++);
984 _SNMPPut(index);
985  
986 // Encode and Copy actual data bytes
987 if ( !GetDataTypeInfo(rec.dataType, &dataTypeInfo) )
988 {
989 MPFSClose(hMPFS);
990 UDPClose(SNMPNotifyInfo.socket);
991 return FALSE;
992 }
993 _SNMPPut(dataTypeInfo.asnType);
994 //Modified to Send trap even for dataTypeInfo.asnType= ASCII_STRING,
995 //where dataTypeInfo.asnLen=0xff
996 if ( dataTypeInfo.asnLen == 0xff )
997 {
998 dataTypeInfo.asnLen=0x4;
999 val.dword=0;
1000 }
1001 len = dataTypeInfo.asnLen;
1002  
1003 _SNMPPut(len);
1004 while( len-- )
1005 _SNMPPut(val.v[len]);
1006  
1007 len = dataTypeInfo.asnLen // data bytes count
1008 + 1 // Length byte
1009 + 1 // Data type byte
1010 + OIDLen // OID bytes
1011 + 2 // OID header bytes
1012 + 1; // index byte
1013 tempOffset = _SNMPGetTxOffset();
1014 _SNMPSetTxOffset(varPairStructLenOffset);
1015 _SNMPPut(len);
1016 }
1017 //set the previous TX offset
1018 _SNMPSetTxOffset(tempOffset);
1019 varPairStructLenOffset = tempOffset;
1020  
1021 varbindlen += len // length of varbind
1022 +2; // varbind type(30) and length of individual varbind pdu
1023 if(gSetTrapSendFlag == TRUE)
1024 {
1025 MPFSClose(hMPFS);
1026 return TRUE;
1027 }
1028  
1029 _SNMPSetTxOffset(varBindStructLenOffset);
1030 _SNMPPut(varbindlen);
1031  
1032 len = varbindlen
1033 + 2 // Variable Binding structure header
1034 + 12; // req , error and error status for SNMPv2
1035  
1036 _SNMPSetTxOffset(pduStructLenOffset);
1037 _SNMPPut(len);
1038  
1039 len = len // PDU struct length
1040 + 2 // PDU trap header
1041 + SNMPNotifyInfo.communityLen // Community string bytes
1042 + 2 // Community header bytes
1043 + 3; // SNMP version bytes
1044  
1045  
1046 _SNMPSetTxOffset(packetStructLenOffset);
1047 _SNMPPut(len);
1048  
1049 _SNMPSetTxOffset(prevOffset);
1050  
1051 // after setting all the offset values, initialize all static variables to 0.
1052 packetStructLenOffset = 0;
1053 pduStructLenOffset = 0;
1054 varBindStructLenOffset = 0;
1055 varPairStructLenOffset = 0;
1056 prevOffset = 0;
1057 varbindlen = 0;
1058  
1059 MPFSClose(hMPFS);
1060 UDPFlush();
1061 UDPClose(SNMPNotifyInfo.socket);
1062  
1063 return TRUE;
1064 }
1065  
1066 #else /* SNMP_STACK_USE_V2_TRAP */
1067  
1068 /****************************************************************************
1069 Function:
1070 BOOL SNMPNotify(SNMP_ID var,SNMP_VAL val,SNMP_INDEX index)
1071  
1072 Summary:
1073 Creates and Sends TRAP pdu.
1074  
1075 Description:
1076 This function creates SNMP trap PDU and sends it to previously specified
1077 remoteHost.
1078 snmpv1 trap pdu:
1079 | PDU-type | enterprise | agent-addr | generic-trap | specific-trap |
1080 | time-stamp | varbind-list |
1081  
1082 The v1 enterprise is mapped directly to SNMPv2TrapOID.0
1083  
1084 Precondition:
1085 SNMPIsNotifyReady() is already called and returned TRUE.
1086  
1087 Parameters:
1088 var - SNMP var ID that is to be used in notification
1089 val - Value of var. Only value of BYTE, WORD or DWORD can be sent.
1090 index - Index of var. If this var is a single,index would be 0, or else
1091 if this var Is a sequence, index could be any value
1092 from 0 to 127
1093  
1094 Return Values:
1095 TRUE - if SNMP notification was successful sent.
1096 This does not guarantee that remoteHost recieved it.
1097 FALSE - Notification sent failed.
1098 This would fail under following contions:
1099 1) Given SNMP_BIB_FILE does not exist in MPFS
1100 2) Given var does not exist.
1101 3) Previously given agentID does not exist
1102 4) Data type of given var is unknown - only
1103 possible if MPFS itself was corrupted.
1104  
1105 Remarks:
1106 This would fail if there were not UDP socket to open.
1107 ***************************************************************************/
1108 BOOL SNMPNotify(SNMP_ID var, SNMP_VAL val, SNMP_INDEX index)
1109 {
1110 char* pCommunity;
1111 BYTE len;
1112 BYTE OIDValue[OID_MAX_LEN];
1113 BYTE OIDLen;
1114 BYTE agentIDLen;
1115 BYTE* pOIDValue;
1116 WORD packetStructLenOffset;
1117 WORD pduStructLenOffset;
1118 WORD varBindStructLenOffset;
1119 WORD varPairStructLenOffset;
1120 WORD prevOffset;
1121 OID_INFO rec;
1122 DATA_TYPE_INFO dataTypeInfo;
1123  
1124 hMPFS = MPFSOpenROM((ROM BYTE*)SNMP_BIB_FILE_NAME);
1125 if ( hMPFS == MPFS_INVALID_HANDLE )
1126 {
1127 UDPClose(SNMPNotifyInfo.socket);
1128 return FALSE;
1129 }
1130  
1131 _SNMPDuplexInit(SNMPNotifyInfo.socket);
1132  
1133 len = SNMPNotifyInfo.communityLen;
1134 pCommunity = SNMPNotifyInfo.community;
1135  
1136 _SNMPPut(STRUCTURE); // First item is packet structure
1137 packetStructLenOffset = SNMPTxOffset;
1138 _SNMPPut(0);
1139  
1140 // Put SNMP version info.
1141 _SNMPPut(ASN_INT); // Int type.
1142 _SNMPPut(1); // One byte long value.
1143  
1144 //Application has to decide which snmp version has to be
1145 //updated to the notification pdu.
1146 _SNMPPut(SNMP_V1); // v1.
1147  
1148  
1149 //len = strlen(community); // Save community length for later use.
1150 _SNMPPut(OCTET_STRING); // Octet string type.
1151 _SNMPPut(len); // community string length
1152 while( len-- ) // Copy entire string.
1153 _SNMPPut(*(pCommunity++));
1154  
1155 // Put PDU type. SNMP agent's response is always GET RESPONSE
1156 _SNMPPut(TRAP);
1157 pduStructLenOffset = SNMPTxOffset;
1158 _SNMPPut(0);
1159  
1160 // Get complete OID string from MPFS.
1161 if ( !GetOIDStringByID(SNMPNotifyInfo.agentIDVar,
1162 &rec, OIDValue, &agentIDLen) )
1163 {
1164 MPFSClose(hMPFS);
1165 UDPClose(SNMPNotifyInfo.socket);
1166 return FALSE;
1167 }
1168  
1169 if ( !rec.nodeInfo.Flags.bIsAgentID )
1170 {
1171 MPFSClose(hMPFS);
1172 UDPClose(SNMPNotifyInfo.socket);
1173 return FALSE;
1174 }
1175  
1176 MPFSSeek(hMPFS, rec.hData, MPFS_SEEK_START);
1177  
1178 _SNMPPut(ASN_OID);
1179 MPFSGet(hMPFS, &len);
1180 agentIDLen = len;
1181 _SNMPPut(len);
1182 while( len-- )
1183 {
1184 BYTE c;
1185 MPFSGet(hMPFS, &c);
1186 _SNMPPut(c);
1187 }
1188  
1189 // This agent's IP address.
1190 _SNMPPut(SNMP_IP_ADDR);
1191 _SNMPPut(4);
1192 _SNMPPut(AppConfig.MyIPAddr.v[0]);
1193 _SNMPPut(AppConfig.MyIPAddr.v[1]);
1194 _SNMPPut(AppConfig.MyIPAddr.v[2]);
1195 _SNMPPut(AppConfig.MyIPAddr.v[3]);
1196  
1197 // Geberic/Enterprise Trap code
1198 _SNMPPut(ASN_INT);
1199 _SNMPPut(1);
1200 _SNMPPut(gGenericTrapNotification);
1201  
1202 // Specific Trap code
1203 _SNMPPut(ASN_INT);
1204 _SNMPPut(1);
1205 _SNMPPut(SNMPNotifyInfo.notificationCode);
1206  
1207 // Time stamp
1208 _SNMPPut(SNMP_TIME_TICKS);
1209 _SNMPPut(4);
1210 _SNMPPut(SNMPNotifyInfo.timestamp.v[3]);
1211 _SNMPPut(SNMPNotifyInfo.timestamp.v[2]);
1212 _SNMPPut(SNMPNotifyInfo.timestamp.v[1]);
1213 _SNMPPut(SNMPNotifyInfo.timestamp.v[0]);
1214  
1215 // Variable binding structure header
1216 _SNMPPut(0x30);
1217 varBindStructLenOffset = SNMPTxOffset;
1218 _SNMPPut(0);
1219  
1220 // Create variable name-pair structure
1221 _SNMPPut(0x30);
1222 varPairStructLenOffset = SNMPTxOffset;
1223 _SNMPPut(0);
1224  
1225 // Get complete notification variable OID string.
1226 if ( !GetOIDStringByID(var, &rec, OIDValue, &OIDLen) )
1227 {
1228 MPFSClose(hMPFS);
1229 UDPClose(SNMPNotifyInfo.socket);
1230 return FALSE;
1231 }
1232  
1233 // Copy OID string into packet.
1234 _SNMPPut(ASN_OID);
1235 _SNMPPut((BYTE)(OIDLen+1));
1236 len = OIDLen;
1237 pOIDValue = OIDValue;
1238 while( len-- )
1239 _SNMPPut(*pOIDValue++);
1240 _SNMPPut(index);
1241  
1242 // Encode and Copy actual data bytes
1243 if ( !GetDataTypeInfo(rec.dataType, &dataTypeInfo) )
1244 {
1245 MPFSClose(hMPFS);
1246 UDPClose(SNMPNotifyInfo.socket);
1247 return FALSE;
1248 }
1249  
1250 _SNMPPut(dataTypeInfo.asnType);
1251  
1252  
1253 //Modified to Send trap even for dataTypeInfo.asnType= ASCII_STRING,
1254 //where dataTypeInfo.asnLen=0xff
1255 if ( dataTypeInfo.asnLen == 0xff )
1256 {
1257 dataTypeInfo.asnLen=0x4;
1258 val.dword=0;
1259 }
1260  
1261 len = dataTypeInfo.asnLen;
1262 _SNMPPut(len);
1263 while( len-- )
1264 _SNMPPut(val.v[len]);
1265  
1266 len = dataTypeInfo.asnLen // data bytes count
1267 + 1 // Length byte
1268 + 1 // Data type byte
1269 + OIDLen // OID bytes
1270 + 2 // OID header bytes
1271 + 1; // index byte
1272  
1273 prevOffset = _SNMPGetTxOffset();
1274 _SNMPSetTxOffset(varPairStructLenOffset);
1275 _SNMPPut(len);
1276  
1277 len += 2; // Variable Binding structure header
1278 _SNMPSetTxOffset(varBindStructLenOffset);
1279 _SNMPPut(len);
1280  
1281 len = len
1282 + 2 // Var bind struct header
1283 + 6 // 6 bytes of timestamp
1284 + 3 // 3 bytes of trap code
1285 + 3 // 3 bytes of notification code
1286 + 6 // 6 bytes of agnent IP address
1287 + agentIDLen // Agent ID bytes
1288 + 2; // Agent ID header bytes
1289 _SNMPSetTxOffset(pduStructLenOffset);
1290 _SNMPPut(len);
1291  
1292 len = len // PDU struct length
1293 + 2 // PDU header
1294 + SNMPNotifyInfo.communityLen // Community string bytes
1295 + 2 // Community header bytes
1296 + 3; // SNMP version bytes
1297 _SNMPSetTxOffset(packetStructLenOffset);
1298 _SNMPPut(len);
1299  
1300 _SNMPSetTxOffset(prevOffset);
1301  
1302 MPFSClose(hMPFS);
1303 UDPFlush();
1304 UDPClose(SNMPNotifyInfo.socket);
1305  
1306 return TRUE;
1307 }
1308  
1309 #endif
1310  
1311 #endif // Code removed when SNMP_TRAP_DISABLED
1312  
1313  
1314 /****************************************************************************
1315 Function:
1316 SNMP_ACTION ProcessHeader(PDU_INFO* pduDbPtr,
1317 char* community, BYTE* len)
1318  
1319 Summary:
1320 Validates the received udp packet Snmp header.
1321  
1322 Description:
1323 Collects PDU_INFO (SNMP pdu information database),community name,
1324 community length and length of data payload.
1325 This function validates the received udp packet for these different
1326 variables of snmp pdu. The sequence in which these elements
1327 are received is important. The validation is done for the agent
1328 processing capabilities and the max UDP packet length as UDP packets
1329 can not be fragmented.
1330  
1331 Precondition:
1332 UDPIsGetReady(SNMPAgentSocket) is called in SNMPTask(),
1333 it check if there is any packet on SNMP Agent socket,
1334 should return TRUE.
1335  
1336 Parameters:
1337 pduDbPtr - Pointer to received pdu information database
1338 community - Pointer to var storing, community string in rxed pdu
1339 len - Pointer to var storing, community string length rxed in pdu
1340  
1341 Return Values:
1342 SNMP_ACTION - Snmp request pdu type.
1343  
1344 Remarks:
1345 The received pdu will be processed only if this routine returns the
1346 pdu type else the pdu is discarded as not Snmp pdu.
1347 ***************************************************************************/
1348 static SNMP_ACTION ProcessHeader(PDU_INFO* pduDbPtr, char* community, BYTE* len)
1349 {
1350 DWORD_VAL tempLen;
1351 SNMP_ACTION pdu;
1352  
1353 // Very first item must be a structure
1354 if ( !IsValidStructure((WORD*)&tempLen) )
1355 return SNMP_ACTION_UNKNOWN;
1356  
1357 if ( !IsValidInt(&tempLen.Val) )
1358 return SNMP_ACTION_UNKNOWN;
1359  
1360 pduDbPtr->snmpVersion= tempLen.v[0];
1361 if ( (tempLen.v[0] != (BYTE)SNMP_V1) && ( tempLen.v[0] != (BYTE)SNMP_V2C ))
1362 return SNMP_ACTION_UNKNOWN;
1363  
1364 // This function populates response as it processes community string.
1365 if ( !IsValidCommunity(community, len) )
1366 return SNMP_ACTION_UNKNOWN;
1367  
1368 // Fetch and validate pdu type.
1369 if ( !IsValidPDU(&pdu) )
1370 return SNMP_ACTION_UNKNOWN;
1371  
1372 pduDbPtr->pduType = pdu;
1373  
1374 //Get_Bulk_Request is not defined in SNMP V1, hence discard udp request packet
1375 if(pduDbPtr->snmpVersion==(BYTE)SNMP_V1 && pduDbPtr->pduType == GET_BULK_REQUEST)
1376 return SNMP_ACTION_UNKNOWN;
1377  
1378  
1379 // Ask main application to verify community name against requested pdu type.
1380 if(SNMPValidateCommunity((BYTE *)community)==(BYTE)INVALID_COMMUNITY)
1381 return SNMP_ACTION_UNKNOWN;
1382  
1383 return pdu;
1384 }
1385  
1386 /****************************************************************************
1387 Function:
1388 BOOL ProcessGetSetHeader(PDU_INFO* pduDbPtr)
1389  
1390 Summary:
1391 Validates the received udp packet Get/Set request header.
1392  
1393 Description:
1394 All the variables of snmp pdu request header are validated for their
1395 data types. Collects request_id for the snmp request pdu. Fetch,validates
1396 error status,error index and discard as they are need not to be processed
1397 as received in request pdu. Collects non repeaters and max repeaters
1398 values in case of Get_Bulk request.
1399  
1400 Precondition:
1401 ProcessHeader() is called and returns pdu type and do not returns
1402 SNMP_ACTION_UNKNOWN
1403  
1404 Parameters:
1405 pduDbPtr - Pointer to received pdu information database.
1406  
1407 Return Values:
1408 TRUE - If the received request header is validated and passed.
1409 FALSE - If rxed request header is not valid.
1410  
1411 Remarks:
1412 The request pdu will be processed only if this routine returns TRUE
1413 ***************************************************************************/
1414 static BOOL ProcessGetSetHeader(PDU_INFO* pduDbPtr)
1415 {
1416 DWORD_VAL tempData;
1417  
1418 // Fetch and save request ID.
1419 if ( IsValidInt(&tempData.Val) )
1420 pduDbPtr->requestID.Val = tempData.Val;
1421 else
1422 return FALSE;
1423  
1424 if((pduDbPtr->snmpVersion == (BYTE)SNMP_V1 || pduDbPtr->snmpVersion == (BYTE)SNMP_V2C) &&(pduDbPtr->pduType != GET_BULK_REQUEST))
1425 {
1426 // Fetch and discard error status
1427 if ( !IsValidInt(&tempData.Val) )
1428 return FALSE;
1429  
1430 // Fetch and disacard error index
1431 return IsValidInt(&tempData.Val);
1432 }
1433 else if( pduDbPtr->snmpVersion == (BYTE)SNMP_V2C && pduDbPtr->pduType == GET_BULK_REQUEST )
1434 {
1435 // Fetch non-repeaters value
1436 if ( IsValidInt(&tempData.Val) )
1437 pduDbPtr->nonRepeators=tempData.v[0];
1438 else
1439 return FALSE;
1440  
1441 // Fetch Max-repetitions value
1442 if(IsValidInt(&tempData.Val))
1443 pduDbPtr->maxRepetitions=(BYTE)tempData.v[0];
1444 else
1445 return FALSE;
1446 }
1447 else
1448 return FALSE;
1449  
1450 return TRUE;
1451 }
1452  
1453  
1454 /****************************************************************************
1455 Function:
1456 BOOL ProcessVariables(PDU_INFO* pduDbPtr,BYTE* community, BYTE len)
1457  
1458 Summary:
1459 This routine processes the snmp request and parallely creates the
1460 response pdu.
1461  
1462 Description:
1463 Once the received pdu is validated as Snmp pdu, it is forwarded for
1464 processing to this routine. This rotuine handles Get, Get_Next, Get_Bulk,
1465 Set request and creates appropriate response as Get_Response.
1466 This routine will decide on whether the request pdu should be processed
1467 or be discarded.
1468  
1469 Precondition:
1470 The received udp packet is varified as SNMP request.
1471 ProcessHeader() and ProcessGetSetHeader() returns but FALSE.
1472  
1473 Parameters:
1474 pduDbPtr - Pointer to received pdu information database
1475 community - Pointer to var, storing community string in rxed pdu
1476 len - Pointer to var, storing community string length rxed in pdu
1477  
1478 Return Values:
1479 TRUE - If the snmp request processing is successful.
1480 FALSE - If the processing failed else the processing is not completed.
1481  
1482 Remarks:
1483 None
1484 ***************************************************************************/
1485 static BOOL ProcessVariables(PDU_INFO* pduDbPtr,char* community, BYTE len)
1486 {
1487 BYTE temp =0;
1488 BYTE OIDValue[OID_MAX_LEN];
1489 BYTE OIDLen;
1490 BYTE varIndex =0;
1491 BYTE errorIndex;
1492 BYTE communityLen=0,commRetVal=0;
1493 BYTE noOfOIDsInReq=0,tempNonRepeators=0,noOfVarToBeInResponse=0;
1494 BYTE repeatCntr,varBindCntr;
1495 BYTE Getbulk_N=0,Getbulk_M=0,Getbulk_R=0;/*Refer RFC 3416 Section "4.2.3" GetBulkRequest-PDU*/
1496 BYTE oidLookUpRet;
1497 BYTE templen;
1498 BYTE successor=0;// 'I'th lexicographic successor
1499  
1500 BYTE *ptemp;
1501 BYTE *ptroid;
1502 BYTE *rxedCommunityName;
1503  
1504 WORD oidOffset;
1505 WORD prevOffset;
1506 WORD packetStructLenOffset=0;
1507 WORD pduLenOffset=0;
1508 WORD errorStatusOffset=0;
1509 WORD errorIndexOffset=0;
1510 WORD varBindStructOffset=0;
1511 WORD varStructLenOffset=0;
1512 WORD prevSnmpRxOffset=0;
1513  
1514 WORD_VAL varBindingLen;
1515 WORD_VAL tempLen;
1516 WORD_VAL varPairLen;
1517 WORD_VAL varBindLen;
1518  
1519 OID_INFO OIDInfo;
1520 SNMP_ERR_STATUS errorStatus;
1521  
1522 static enum
1523 {
1524 SM_PKT_STRUCT_LEN_OFFSET=0u,
1525 SM_RESPONSE_PDU_LEN_OFFSET,
1526 SM_ERROR_STATUS_OFFSET,
1527 SM_ERROR_INDEX_OFFSET,
1528 SM_FIND_NO_OF_REQUESTED_VARBINDS,
1529 SM_FIND_NO_OF_RESPONSE_VARBINDS,
1530 SM_VARBIND_STRUCT_OFFSET,
1531 SM_VARSTRUCT_LEN_OFFSET,
1532 SM_POPULATE_REQ_OID,
1533 SM_FIND_OID_IN_MIB,
1534 SM_NON_REPETITIONS,
1535 SM_MAX_REPETITIONS
1536 }smSnmp=SM_PKT_STRUCT_LEN_OFFSET;
1537  
1538 snmpReqVarErrStatus.noSuchInstanceErr=0x0000;
1539 snmpReqVarErrStatus.noSuchNameErr=0x0000;
1540 snmpReqVarErrStatus.noSuchObjectErr=0x0000;
1541 snmpReqVarErrStatus.endOfMibViewErr=0x0000;
1542  
1543 rxedCommunityName=(BYTE *)community;
1544  
1545 while(1)
1546 {
1547 switch(smSnmp)
1548 {
1549  
1550 // Before each variables are processed, prepare necessary header.
1551  
1552 case SM_PKT_STRUCT_LEN_OFFSET:
1553  
1554 varPairLen.Val=0x0000;
1555  
1556 _SNMPPut(STRUCTURE); // First item is packet structure
1557  
1558 // Since we do not know length of structure at this point, use
1559 // placeholder bytes that will be replaced with actual value.
1560 _SNMPPut(0x82);
1561 packetStructLenOffset = SNMPTxOffset;
1562 _SNMPPut(0);
1563 _SNMPPut(0);
1564  
1565 // Put SNMP version info - only v1.0 is supported.
1566 _SNMPPut(ASN_INT); // Int type.
1567 _SNMPPut(1); // One byte long value.
1568 _SNMPPut(pduDbPtr->snmpVersion); // v1.0.
1569  
1570 // Put community string
1571 communityLen = len; // Save community length for later use.
1572 _SNMPPut(OCTET_STRING); // Octet string type.
1573 _SNMPPut(len); // community string length
1574 while( len-- ) // Copy entire string.
1575 _SNMPPut(*community++);
1576  
1577 smSnmp++;
1578  
1579 //return FALSE;
1580 case SM_RESPONSE_PDU_LEN_OFFSET:
1581  
1582 // Put PDU type. SNMP agent's response is always GET RESPONSE
1583 _SNMPPut(GET_RESPONSE);
1584  
1585 // Since we don't know length of this response, use placeholders until
1586 // we know for sure...
1587 _SNMPPut(0x82);
1588 pduLenOffset = SNMPTxOffset;
1589 _SNMPPut(0); // Be prepared for 2 byte-long length
1590 _SNMPPut(0);
1591  
1592 // Put original request back.
1593 _SNMPPut(ASN_INT); // Int type.
1594 _SNMPPut(4); // To simplify logic, always use 4 byte long requestID
1595 _SNMPPut(pduDbPtr->requestID.v[3]); // Start MSB
1596 _SNMPPut(pduDbPtr->requestID.v[2]);
1597 _SNMPPut(pduDbPtr->requestID.v[1]);
1598 _SNMPPut(pduDbPtr->requestID.v[0]);
1599  
1600 smSnmp++;
1601  
1602 //return FALSE;
1603  
1604 case SM_ERROR_STATUS_OFFSET :
1605  
1606 // Put error status.
1607 // Since we do not know error status, put place holder until we know it...
1608 _SNMPPut(ASN_INT); // Int type
1609 _SNMPPut(1); // One byte long.
1610 errorStatusOffset = SNMPTxOffset;
1611 _SNMPPut(0); // Placeholder.
1612 smSnmp++;
1613  
1614 case SM_ERROR_INDEX_OFFSET :
1615  
1616 // Similarly put error index.
1617 _SNMPPut(ASN_INT); // Int type
1618 _SNMPPut(1); // One byte long
1619 errorIndexOffset = SNMPTxOffset;
1620 _SNMPPut(0); // Placeholder.
1621  
1622 varIndex = 0;
1623 errorIndex = 0;
1624 errorStatus = SNMP_NO_ERR;
1625  
1626 smSnmp++;
1627  
1628 case SM_FIND_NO_OF_REQUESTED_VARBINDS:
1629  
1630 // Decode variable binding structure
1631 if ( !IsValidStructure(&varBindingLen.Val) )
1632 return FALSE;
1633  
1634 //Find number of OIDs/varbinds's data requested in received PDU.
1635 noOfOIDsInReq=FindOIDsInRequest(varBindingLen.Val);
1636  
1637 smSnmp++;
1638  
1639 //return FALSE;
1640  
1641 case SM_FIND_NO_OF_RESPONSE_VARBINDS:
1642  
1643 //Calulate number of variables to be responded for the received request
1644 Getbulk_N = noOfOIDsInReq; Getbulk_M=0; Getbulk_R=0;
1645 if((pduDbPtr->snmpVersion == (BYTE)SNMP_V2C) && (pduDbPtr->pduType == GET_BULK_REQUEST))
1646 {
1647 if((pduDbPtr->nonRepeators) <= noOfOIDsInReq)
1648 {
1649 Getbulk_N = pduDbPtr->nonRepeators;
1650 }
1651  
1652 Getbulk_M = pduDbPtr->maxRepetitions;
1653  
1654 if((noOfOIDsInReq - Getbulk_N)>=0u)
1655 Getbulk_R = noOfOIDsInReq-Getbulk_N;
1656 }
1657  
1658 tempNonRepeators = Getbulk_N;
1659  
1660 noOfVarToBeInResponse = Getbulk_N + (Getbulk_M * Getbulk_R);//Refer RFC 3416
1661  
1662 smSnmp++;
1663  
1664 //return FALSE;
1665  
1666 case SM_VARBIND_STRUCT_OFFSET:
1667  
1668 // Put variable binding response structure
1669 _SNMPPut(STRUCTURE);
1670 _SNMPPut(0x82);
1671  
1672 // Since we do not know data payload length, put place holder until we know it...
1673 varBindStructOffset = SNMPTxOffset;
1674 _SNMPPut(0);
1675 _SNMPPut(0);
1676  
1677 varBindLen.Val = 0;
1678  
1679 smSnmp++;
1680  
1681 //return FALSE;
1682  
1683 case SM_VARSTRUCT_LEN_OFFSET:
1684  
1685 /* If the getbulk request is received with zero non-repeaters, process
1686 variable State Machine jumps to SM_MAX_REPETITIONS. Modify the Rx
1687 and Tx offset accordigly. */
1688 if(Getbulk_N==0u)
1689 {
1690 prevSnmpRxOffset=SNMPRxOffset;
1691 smSnmp=SM_MAX_REPETITIONS;
1692 varStructLenOffset = SNMPTxOffset;
1693 SNMPTxOffset=SNMPTxOffset+4;
1694 break;
1695 }
1696  
1697 /*
1698 Need to know what variable we are processing, so that in case
1699 if there is problem for that varaible, we can put it in
1700 errorIndex location of SNMP packet.
1701 */
1702 varIndex++;
1703  
1704 // Decode variable length structure
1705 temp = IsValidStructure(&tempLen.Val);
1706 if ( !temp )
1707 return FALSE;
1708  
1709 varBindingLen.Val -= tempLen.Val;
1710 varBindingLen.Val -= temp;
1711  
1712 varStructLenOffset = SNMPTxOffset;
1713  
1714 if(pduDbPtr->pduType == GET_BULK_REQUEST )
1715 {
1716 SNMPTxOffset=SNMPTxOffset+4;
1717 }
1718 smSnmp++;
1719  
1720 //return FALSE;
1721  
1722 case SM_POPULATE_REQ_OID:
1723  
1724 /* Populate received pdu for the requested OIDs and also create the
1725 response pdu on the go.*/
1726  
1727 // Decode next object
1728 if ( !IsValidOID(OIDValue, &OIDLen) )
1729 return FALSE;
1730  
1731 // For Get & Get-Next, value must be NULL.
1732 if ( pduDbPtr->pduType != (BYTE)SET_REQUEST )
1733 {
1734 if ( !IsASNNull() )
1735 return FALSE;
1736 }
1737  
1738 if(pduDbPtr->pduType != GET_BULK_REQUEST )
1739 {
1740 // Prepare response - original variable
1741 _SNMPPut(ASN_OID);
1742 oidOffset = SNMPTxOffset;
1743 _SNMPPut(OIDLen);
1744 ptemp = OIDValue;
1745 temp = OIDLen;
1746 while( temp-- )
1747 _SNMPPut(*ptemp++);
1748 }
1749  
1750  
1751 /*
1752 Match "rxedCommunityName" to "readCommunity" to authorize access
1753 to private MIB objects.
1754 As we start supporting the secured encrypted community transaction,
1755 rxed community string can be an encrypted string which the agent
1756 need to decrypt and validate to autohrize access.
1757 The agent should respond with encrypted community name.
1758 */
1759  
1760 commRetVal=SNMPValidateCommunity(rxedCommunityName);
1761  
1762 smSnmp=SM_PKT_STRUCT_LEN_OFFSET; // Start out assuming commRetVal == INVALID_COMMUNITY
1763 if(pduDbPtr->pduType == (BYTE)SET_REQUEST)
1764 {
1765 if(commRetVal==(BYTE)WRITE_COMMUNITY)//If SET request, then "community==WRITE_COMMUNITY" is must.
1766 smSnmp=SM_FIND_OID_IN_MIB;
1767 }
1768 else
1769 {
1770 if(commRetVal!=(BYTE)INVALID_COMMUNITY)//If any GET request, then "community!=INVALID_COMMUNITY" is must (community is WRITE_COMMUNITY or READ_COMMUNITY).
1771 smSnmp=SM_FIND_OID_IN_MIB;
1772 }
1773  
1774 //Verify if trying to access the private object
1775 //Application has to decide on what community name should allowed to
1776 //read write the private mib objects.
1777  
1778 if(SNMPCheckIfPvtMibObjRequested(OIDValue) && (smSnmp==SM_PKT_STRUCT_LEN_OFFSET) )
1779 {
1780 //If private mib object is requested and community do not match,
1781 //generate authentication failure TRAP
1782  
1783 Getbulk_N=0;
1784 noOfVarToBeInResponse=0;
1785 smSnmp=SM_PKT_STRUCT_LEN_OFFSET;
1786  
1787 //Searching the requested OID in the MIB database
1788 oidLookUpRet = OIDLookup(pduDbPtr,OIDValue, OIDLen, &OIDInfo);
1789 gOIDCorrespondingSnmpMibID=OIDInfo.id;
1790  
1791 _SNMPSetTxOffset(packetStructLenOffset-2);
1792 gSpecificTrapNotification=VENDOR_TRAP_DEFAULT;
1793 gGenericTrapNotification=AUTH_FAILURE;
1794 gSendTrapFlag=TRUE;
1795  
1796 }
1797 /*else
1798 smSnmp++;*/
1799  
1800 if(smSnmp==SM_PKT_STRUCT_LEN_OFFSET || smSnmp==SM_VARSTRUCT_LEN_OFFSET)
1801 break;
1802  
1803 //return FALSE;
1804  
1805 case SM_FIND_OID_IN_MIB:
1806  
1807 /* Search for the requested OID in the MIB database with the agent.*/
1808  
1809 if(Getbulk_N!= 0u)
1810 Getbulk_N--;
1811  
1812 if(Getbulk_N==0u)
1813 prevSnmpRxOffset=SNMPRxOffset;
1814  
1815 noOfVarToBeInResponse--;
1816  
1817 //Searching the requested OID in the MIB database
1818 oidLookUpRet = OIDLookup(pduDbPtr,OIDValue, OIDLen, &OIDInfo);
1819  
1820 if(oidLookUpRet != (BYTE)TRUE && pduDbPtr->pduType != GET_NEXT_REQUEST)
1821 {
1822 _SNMPSetTxOffset(varStructLenOffset);
1823  
1824 // Put corresponding variable response structure
1825 _SNMPPut(STRUCTURE);
1826 _SNMPPut(0x82);
1827  
1828 varStructLenOffset=_SNMPGetTxOffset();
1829 _SNMPPut(0x00);//Place holder
1830 _SNMPPut(0x00);
1831  
1832 // ASN OID data type
1833 templen=OIDLen;
1834 ptroid=OIDValue;
1835 _SNMPPut(ASN_OID);
1836  
1837 if(appendZeroToOID)
1838 _SNMPPut(OIDLen+1);//for appending "0"
1839 else
1840 _SNMPPut(OIDLen);//do not append "0"
1841  
1842 //Put OID
1843 while( templen-- )
1844 _SNMPPut(*ptroid++);
1845  
1846 if(appendZeroToOID)
1847 {
1848 _SNMPPut(0x00);//Appending '0' to OID in response
1849 varPairLen.Val += OIDLen+1+2; //Modify the response length
1850 }
1851 else
1852 varPairLen.Val += OIDLen+2;
1853  
1854 //update and send the error status and the error index.
1855 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
1856 {
1857 errorStatus = SNMP_NO_SUCH_NAME;
1858 SetErrorStatus(errorStatusOffset,errorIndexOffset,SNMP_NO_SUCH_NAME,varIndex);
1859  
1860 _SNMPPut(ASN_NULL);
1861 _SNMPPut(0);
1862 }
1863 else if( pduDbPtr->snmpVersion == (BYTE)SNMP_V2C && pduDbPtr->pduType != SET_REQUEST)
1864 {
1865 if(pduDbPtr->pduType == SNMP_GET)
1866 {
1867 _SNMPPut(oidLookUpRet);
1868 _SNMPPut(0x00);
1869 if(oidLookUpRet == SNMP_NO_SUCH_OBJ)
1870 {
1871 snmpReqVarErrStatus.noSuchObjectErr|=(0x0001 << varIndex);
1872 }
1873 else if(oidLookUpRet == SNMP_NO_SUCH_INSTANCE)
1874 {
1875 snmpReqVarErrStatus.noSuchInstanceErr|=(0x0001 << varIndex);
1876 }
1877 }
1878 else if(pduDbPtr->pduType == GET_BULK_REQUEST )
1879 {
1880 _SNMPPut(SNMP_END_OF_MIB_VIEW);
1881 _SNMPPut(0x00);
1882 snmpReqVarErrStatus.endOfMibViewErr|=(0x0001 << varIndex);
1883 }
1884 }
1885  
1886 varPairLen.Val +=2 ;
1887  
1888 varBindLen.Val += 4 // Variable Pair STRUCTURE byte + 1 length byte.
1889 + varPairLen.Val;
1890  
1891 //Now update the place holder for var pair length
1892 prevOffset = _SNMPGetTxOffset();
1893 _SNMPSetTxOffset(varStructLenOffset);
1894  
1895 _SNMPPut(varPairLen.v[1]);
1896 _SNMPPut(varPairLen.v[0]);
1897  
1898 _SNMPSetTxOffset(prevOffset);
1899  
1900 varPairLen.Val=0x00;
1901  
1902 //Reset to state machine to access the next oid in request
1903 smSnmp=SM_VARSTRUCT_LEN_OFFSET;
1904 break;
1905 }
1906 smSnmp++;
1907  
1908 //return FALSE;
1909  
1910 case SM_NON_REPETITIONS:
1911  
1912 /* Variables in get,get_next,set and get_bulk ( non repetition variables)
1913 of snmp request are processed in this part of the state machine.*/
1914  
1915 //Save SnmpTxOffsetfor future uses.
1916 prevOffset = _SNMPGetTxOffset();
1917 _SNMPSetTxOffset(varStructLenOffset);
1918  
1919 //Start response variable binding with ASN STRUCTURE type.
1920 _SNMPPut(STRUCTURE);
1921 _SNMPPut(0x82);
1922  
1923 varStructLenOffset=_SNMPGetTxOffset();
1924 _SNMPPut(0x00); //place holder
1925 _SNMPPut(0x00);
1926  
1927 _SNMPPut(ASN_OID);
1928  
1929 if(pduDbPtr->pduType == SNMP_SET)
1930 {
1931 templen=OIDLen;
1932 ptroid=OIDValue;
1933  
1934 if(appendZeroToOID)
1935 _SNMPPut(OIDLen+1);//for appending "0"
1936 else
1937 _SNMPPut(OIDLen);//do not append "0"
1938  
1939 //Put OID
1940 while( templen-- )
1941 _SNMPPut(*ptroid++);
1942  
1943 if(appendZeroToOID)
1944 _SNMPPut(0x00);//Appending '0' to OID in response
1945  
1946 //Now process the SET command
1947 temp = ProcessSetVar(pduDbPtr,&OIDInfo, &errorStatus);
1948  
1949 if ( errorStatus != SNMP_NO_ERR )
1950 {
1951 //SET var command failed. Update the error status.
1952 SetErrorStatus(errorStatusOffset,
1953 errorIndexOffset,
1954 errorStatus,
1955 varIndex);
1956  
1957 }
1958  
1959 if(appendZeroToOID)
1960 varPairLen.Val = OIDLen+1 +2 // OID name + header bytes
1961 + temp; // value bytes as put by SetVar
1962 else
1963 varPairLen.Val = OIDLen+2+temp;
1964  
1965 }
1966 else if(pduDbPtr->pduType == SNMP_GET || pduDbPtr->pduType == SNMP_V2C_GET_BULK)
1967 {
1968 templen=OIDLen;
1969 ptroid=OIDValue;
1970  
1971 if(appendZeroToOID)
1972 _SNMPPut(OIDLen+1);//for appending "0"
1973 else
1974 _SNMPPut(OIDLen);//do not append "0"
1975  
1976 //Put OID
1977 while( templen-- )
1978 _SNMPPut(*ptroid++);
1979  
1980 if(appendZeroToOID)
1981 {
1982 _SNMPPut(0x00);//Appending '0' to OID in response
1983 varPairLen.Val = OIDLen + 2+1;
1984 }
1985 else
1986 varPairLen.Val = OIDLen +2;
1987  
1988 //Now process the GET command
1989 temp=ProcessGetVar(&OIDInfo,FALSE);
1990  
1991 }
1992 else if(pduDbPtr->pduType == SNMP_GET_NEXT)
1993 {
1994 temp=ProcessGetNextVar(&OIDInfo);
1995  
1996 //If Get Next command failed
1997 if(temp==0u)
1998 {
1999 templen=OIDLen;
2000 ptroid=OIDValue;
2001  
2002 if(appendZeroToOID)
2003 _SNMPPut(OIDLen+1);//for appending "0"
2004 else
2005 _SNMPPut(OIDLen);//do not append "0"
2006  
2007 //Put OID
2008 while( templen-- )
2009 _SNMPPut(*ptroid++);
2010  
2011 if(appendZeroToOID)
2012 _SNMPPut(0x00);//Appending '0' to OID in response
2013 }
2014 }
2015  
2016  
2017 /* If the request command processing is failed, update
2018 the error status, index accordingly and response pdu.*/
2019 if(temp == 0u &&(pduDbPtr->pduType != SNMP_SET))
2020 {
2021 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
2022 {
2023 errorStatus = SNMP_NO_SUCH_NAME;
2024 SetErrorStatus(errorStatusOffset,errorIndexOffset,SNMP_NO_SUCH_NAME,
2025 varIndex);
2026 }
2027  
2028 _SNMPPut(ASN_NULL);
2029 _SNMPPut(0);
2030  
2031 if((pduDbPtr->pduType == SNMP_GET_NEXT|| pduDbPtr->pduType == SNMP_V2C_GET_BULK)&&pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
2032 {
2033 SNMPTxOffset=SNMPTxOffset-2;
2034 _SNMPPut(SNMP_END_OF_MIB_VIEW);
2035 _SNMPPut(0);
2036  
2037 }
2038  
2039 if(pduDbPtr->pduType == SNMP_GET || pduDbPtr->pduType == SNMP_V2C_GET_BULK)
2040 {
2041 temp = 2;
2042 }
2043 else if(pduDbPtr->pduType == SNMP_GET_NEXT) {
2044 varPairLen.Val = OIDLen+1 // as put by GetNextVar()
2045 + 2 // OID header
2046 + 2; // END_OF_MIB_VIEW bytes
2047 }
2048  
2049  
2050 /* Applications can make use of the below information
2051 to find the error status for the given variable and to
2052 build the logic arround. */
2053 snmpReqVarErrStatus.noSuchNameErr |=(0x0001 << varIndex);
2054 snmpReqVarErrStatus.noSuchObjectErr |=(0x0001 << varIndex);
2055 snmpReqVarErrStatus.noSuchInstanceErr|=(0x0001 << varIndex);
2056 snmpReqVarErrStatus.endOfMibViewErr |=(0x0001 << varIndex);
2057  
2058 }
2059 else if(pduDbPtr->pduType == SNMP_GET_NEXT)
2060 {
2061 //varPairLen.Val = (temp + 2+OIDLen+1+1);
2062 varPairLen.Val = (temp + 2);
2063 }
2064  
2065 if(pduDbPtr->pduType == SNMP_GET || pduDbPtr->pduType == SNMP_V2C_GET_BULK)
2066 varPairLen.Val += temp;
2067  
2068 varBindLen.Val += 4 // Variable Pair STRUCTURE byte + 1 length byte.
2069 + varPairLen.Val;
2070  
2071 //Update place holder
2072 prevOffset = _SNMPGetTxOffset();
2073 _SNMPSetTxOffset(varStructLenOffset);
2074 _SNMPPut(varPairLen.v[1]);
2075 _SNMPPut(varPairLen.v[0]);
2076  
2077 _SNMPSetTxOffset(prevOffset);
2078 varStructLenOffset = _SNMPGetTxOffset();
2079  
2080 varPairLen.Val=0x00;
2081  
2082 /* Decide on the number of Non repetition variables remained to
2083 be processed, decide the course of state machine.*/
2084  
2085 if((pduDbPtr->pduType==GET_BULK_REQUEST) &&
2086 (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C) &&( Getbulk_N == 0u))
2087 smSnmp=SM_MAX_REPETITIONS;
2088 else
2089 smSnmp=SM_VARSTRUCT_LEN_OFFSET;
2090 break;
2091  
2092 //return FALSE;
2093  
2094 case SM_MAX_REPETITIONS:
2095  
2096 /*Process each variable in request as Get_Next for
2097 Getbulk_M (Max_repetition) times */
2098 for(repeatCntr=0;repeatCntr<Getbulk_M;repeatCntr++)
2099 {
2100 SNMPRxOffset=prevSnmpRxOffset;
2101  
2102 //Process every veriable in the request.
2103 for(varBindCntr=0;varBindCntr<Getbulk_R;varBindCntr++)
2104 {
2105  
2106 if(varBindCntr==0u)
2107 varIndex=(noOfOIDsInReq-Getbulk_R);
2108  
2109 varIndex++;
2110  
2111 if((snmpReqVarErrStatus.endOfMibViewErr >> (tempNonRepeators+varBindCntr+1))&0x0001)
2112 {
2113 noOfVarToBeInResponse--;
2114 temp = IsValidStructure(&tempLen.Val);
2115  
2116 if(varBindCntr!=Getbulk_R)
2117 {
2118 SNMPRxOffset=SNMPRxOffset+tempLen.Val;//2+OIDLen+2;
2119 }
2120 continue;
2121 }
2122  
2123 noOfVarToBeInResponse--;
2124 prevOffset = _SNMPGetTxOffset();
2125 _SNMPSetTxOffset(varStructLenOffset);
2126  
2127 _SNMPPut(STRUCTURE);
2128 _SNMPPut(0x82);
2129 varStructLenOffset=_SNMPGetTxOffset();
2130 _SNMPPut(0x00);
2131 _SNMPPut(0x00);
2132  
2133 successor=repeatCntr;
2134  
2135 // Decode variable length structure
2136 temp = IsValidStructure(&tempLen.Val);
2137 if ( !temp )
2138 break;
2139  
2140 // Decode next object
2141 if ( !IsValidOID(OIDValue, &OIDLen) )
2142 return FALSE;
2143  
2144 templen=OIDLen;
2145 ptroid=OIDValue;
2146  
2147 // For Get & Get-Next, value must be NULL.
2148 if ( pduDbPtr->pduType != (BYTE)SET_REQUEST )
2149 if ( !IsASNNull() )
2150 break;
2151  
2152 if(!OIDLookup(pduDbPtr,OIDValue, OIDLen, &OIDInfo))
2153 {
2154 templen=OIDLen;
2155 ptroid=OIDValue;
2156 _SNMPPut(ASN_OID);
2157  
2158 if(appendZeroToOID)
2159 _SNMPPut(OIDLen+1);//for appending "0"
2160 else
2161 _SNMPPut(OIDLen);//for appending "0"
2162  
2163 //Put OID
2164 while( templen-- )
2165 _SNMPPut(*ptroid++);
2166  
2167 if(appendZeroToOID)
2168 _SNMPPut(0x00);//Appending '0' to OID in response
2169  
2170 _SNMPPut(SNMP_END_OF_MIB_VIEW);
2171 _SNMPPut(0x00);
2172  
2173 //Start counting total number of bytes in this structure.
2174 varPairLen.Val = OIDLen+1 // as put by GetNextVar()
2175 +2 // OID header
2176 +2; // endOfMibView bytes
2177  
2178 snmpReqVarErrStatus.endOfMibViewErr |=(0x0001 << varIndex);
2179 }
2180 else
2181 {
2182 temp = ProcessGetBulkVar(&OIDInfo, &OIDValue[0],&OIDLen,&successor);
2183 if ( temp == 0u )
2184 {
2185 templen=OIDLen;
2186 ptroid=OIDValue;
2187 _SNMPPut(ASN_OID);
2188 _SNMPPut(OIDLen);
2189  
2190 //Put OID
2191 while( templen-- )
2192 _SNMPPut(*ptroid++);
2193  
2194 /*Do send back the Same OID if get_next is EndOfMibView. Do not
2195 append zero to this OID*/
2196  
2197 _SNMPPut(SNMP_END_OF_MIB_VIEW);
2198 _SNMPPut(0x00);
2199  
2200 snmpReqVarErrStatus.endOfMibViewErr |=(0x0001 << varIndex);
2201  
2202 //Start counting total number of bytes in this structure.
2203 varPairLen.Val = OIDLen // as put by GetNextVar()
2204 + 2 // OID header
2205 + 2; // endOfMibView byte.
2206 }
2207 else
2208 varPairLen.Val = (temp + 2); // + OID headerbytes
2209 }
2210  
2211 varBindLen.Val += 4 // Variable Pair STRUCTURE byte + 1 length byte.
2212 + varPairLen.Val;
2213  
2214 prevOffset = _SNMPGetTxOffset();
2215 _SNMPSetTxOffset(varStructLenOffset);
2216  
2217 _SNMPPut(varPairLen.v[1]);
2218 _SNMPPut(varPairLen.v[0]);
2219  
2220 _SNMPSetTxOffset(prevOffset);
2221 varStructLenOffset = _SNMPGetTxOffset();
2222  
2223 }//for(varBindCntr=0;varBindCntr<Getbulk_R;varBindCntr++)
2224  
2225 }//for(repeatCntr=0;repeatCntr<Getbulk_M;repeatCntr++)
2226  
2227 break;
2228 }//end of switch(smSnmp)
2229  
2230 /*If all the variables are processed and the repsonse pdu is updated with
2231 the number of variable responses ought to be in the response; you are done
2232 with the request pdu processing. Else continue to processing.*/
2233 if(Getbulk_N==0u && noOfVarToBeInResponse==0u)
2234 {
2235 smSnmp=SM_PKT_STRUCT_LEN_OFFSET;
2236 break;
2237 }
2238  
2239 }//end of while(1)
2240  
2241  
2242 // Update the place holders with respective values.
2243  
2244 prevOffset = _SNMPGetTxOffset();
2245  
2246 _SNMPSetTxOffset(varBindStructOffset);
2247 _SNMPPut(varBindLen.v[1]);
2248 _SNMPPut(varBindLen.v[0]);
2249  
2250 // varBindLen is reused as "pduLen"
2251 varBindLen.Val = varBindLen.Val+4 // Variable Binding Strucure length
2252 + 6 // Request ID bytes (4+2)
2253 + 3 // Error status (2+1)
2254 + 3; // Error index (2+1)
2255  
2256 _SNMPSetTxOffset(pduLenOffset);
2257 _SNMPPut(varBindLen.v[1]);
2258 _SNMPPut(varBindLen.v[0]);
2259  
2260 // varBindLen is reused as "packetLen".
2261 varBindLen.Val = 3 // SNMP Version bytes
2262 + 2 + communityLen // community string bytes
2263 + 4 // PDU structure header bytes.
2264 + varBindLen.Val;
2265  
2266 _SNMPSetTxOffset(packetStructLenOffset);
2267 _SNMPPut(varBindLen.v[1]);
2268 _SNMPPut(varBindLen.v[0]);
2269  
2270 _SNMPSetTxOffset(prevOffset);
2271  
2272 return TRUE;
2273  
2274 }
2275  
2276  
2277 /****************************************************************************
2278 Function:
2279 BYTE ProcessGetNextVar(OID_INFO* rec)
2280  
2281 Summary:
2282 Retrieves next node from the MIB database.
2283  
2284 Description:
2285 This routine reads into the MIB stored with the agent in MPFS2 format.
2286 It will search for the first lexicographic successor of the variable
2287 binding's name in the incoming GetNextRequest-PDU. If found, the
2288 corresponding variable binding's name and value fields in the Response
2289 pdu are set to the name and value of the located variable. If the
2290 lexicographic succesor is not found, the vlaue filed is set to
2291 "endofMibView" and name field is retained as in request.
2292  
2293 Precondition:
2294 ProcessVariables() is called.
2295  
2296 Parameters:
2297 rec - Pointer to SNMP MIB object information for which next node
2298 to be found
2299  
2300 Return Values:
2301 temp.V[0]- Total number of bytes copied to response packet if succesful.
2302 FALSE - If End of MIB is reached or processing is failure.
2303  
2304 Remarks:
2305 None.
2306 ***************************************************************************/
2307 static BYTE ProcessGetNextVar(OID_INFO* rec)
2308 {
2309 WORD_VAL temp;
2310 BYTE putBytes;
2311 OID_INFO indexRec;
2312 BYTE *pOIDValue;
2313 BYTE OIDValue[OID_MAX_LEN];
2314 BYTE OIDLen;
2315 INDEX_INFO indexInfo;
2316 MIB_INFO varNodeInfo;
2317 SNMP_ID varID;
2318 WORD OIDValOffset;
2319 WORD prevOffset;
2320 BOOL lbNextLeaf;
2321 BYTE ref;
2322 static SNMP_VAL v;
2323 static BYTE varDataType;
2324 static BYTE indexBytes;
2325  
2326 lbNextLeaf = FALSE;
2327 temp.v[0] = 0;
2328  
2329 // Get next leaf only if this OID is a parent or a simple leaf node.
2330 if ( rec->nodeInfo.Flags.bIsParent ||
2331 (!rec->nodeInfo.Flags.bIsParent && !rec->nodeInfo.Flags.bIsSequence) )
2332 {
2333 _GetNextLeaf:
2334 lbNextLeaf = TRUE;
2335 if ( !GetNextLeaf(rec))
2336 return FALSE;
2337 }
2338  
2339 // Get complete OID string from oid record.
2340 if ( !GetOIDStringByAddr(rec, OIDValue, &OIDLen))
2341 {
2342 return FALSE;
2343 }
2344  
2345 // Copy complete OID string to create response packet.
2346 pOIDValue = OIDValue;
2347 OIDValOffset = _SNMPGetTxOffset();
2348 temp.v[0] = OIDLen;
2349 _SNMPSetTxOffset(OIDValOffset+1);
2350  
2351 //Put OID
2352 while( temp.v[0]-- )
2353 _SNMPPut(*pOIDValue++);
2354  
2355 // Start counting number of bytes put - OIDLen is already counted.
2356 temp.v[0] = OIDLen;
2357  
2358 varDataType = rec->dataType;
2359 varID = rec->id;
2360  
2361 // If this is a simple OID, handle it as a GetVar command.
2362 if(!rec->nodeInfo.Flags.bIsSequence)
2363 {
2364 // This is an addition to previously copied OID string.
2365 // This is index value of '0'.
2366 _SNMPPut(0);
2367 temp.v[0]++;
2368  
2369 // Since we added one more byte to previously copied OID
2370 // string, we need to update OIDLen value.
2371 prevOffset = _SNMPGetTxOffset();
2372 _SNMPSetTxOffset(OIDValOffset);
2373 _SNMPPut(++OIDLen);
2374 _SNMPSetTxOffset(prevOffset);
2375  
2376 // Now do Get on this simple variable.
2377 prevOffset = _SNMPGetTxOffset();
2378 putBytes = ProcessGetVar(rec, FALSE);
2379 if ( putBytes == 0u )
2380 {
2381 _SNMPSetTxOffset(prevOffset);
2382 _SNMPPut(ASN_NULL);
2383 _SNMPPut(0);
2384 putBytes = 2;
2385 }
2386  
2387 temp.v[0] += putBytes; // ProcessGetVar(rec, FALSE);
2388  
2389 // Return with total number of bytes copied to response packet.
2390 return temp.v[0];
2391 }
2392  
2393 // This is a sequence variable.
2394 // First of all make sure that there is a next index after this
2395 // index. We also need to make sure that we do not do this foerever.
2396 // So make sure that this is not a repeat test.
2397 ref = 0;
2398 if ( lbNextLeaf == TRUE )
2399 {
2400 // Let application tell us whether this is a valid index or not.
2401 if ( !SNMPGetVar(rec->id, rec->index, &ref, &v) )
2402 {
2403 // If not, then we need to get next leaf in line.
2404 // Remember that we have already did this once, so that we do not
2405 // do this forever.
2406 //lbNextSequence = TRUE;
2407  
2408 // Reset the response packet pointer to begining of OID.
2409 _SNMPSetTxOffset(OIDValOffset);
2410  
2411 // Jump to this label within this function - Not a good SW engineering
2412 // practice, but this will reuse code at much lower expense.
2413 goto _GetNextLeaf;
2414 }
2415 }
2416  
2417 // Need to fetch index information from MIB and prepare complete OID+
2418 // index response.
2419 varNodeInfo.Val = rec->nodeInfo.Val;
2420  
2421 // In this version, only 7-bit index is supported.
2422 MPFSGet(hMPFS, NULL);
2423  
2424 indexBytes = 0;
2425  
2426 MPFSGet(hMPFS, &indexInfo.Val);
2427  
2428 // Fetch index ID.
2429 MPFSGet(hMPFS, &indexRec.id);
2430  
2431 // Fetch index data type.
2432 indexRec.dataType = 0;
2433 MPFSGet(hMPFS, (BYTE*)&indexRec.dataType);
2434  
2435 indexRec.index = rec->index;
2436  
2437 // Check with application to see if there exists next index
2438 // for this index id.
2439 if ( !lbNextLeaf && !SNMPGetNextIndex(indexRec.id, &indexRec.index) )
2440 {
2441 //lbNextSeqeuence = TRUE;
2442 // Reset the response packet pointer to begining of OID.
2443 _SNMPSetTxOffset(OIDValOffset);
2444  
2445 // Jump to this label. Not a good practice, but once-in-a-while
2446 // it should be acceptable !
2447 goto _GetNextLeaf;
2448 }
2449  
2450 // Index is assumed to be dynamic, and leaf node.
2451 // mib2bib has already ensured that this was the case.
2452 indexRec.nodeInfo.Flags.bIsConstant = 0;
2453 indexRec.nodeInfo.Flags.bIsParent = 0;
2454 indexRec.nodeInfo.Flags.bIsSequence = 1;
2455  
2456 // Now handle this as simple GetVar.
2457 // Keep track of number of bytes added to OID.
2458 indexBytes += ProcessGetVar(&indexRec, TRUE);
2459  
2460 rec->index = indexRec.index;
2461  
2462 // These are the total number of bytes put so far as a result of this function.
2463 temp.v[0] += indexBytes;
2464  
2465 // These are the total number of bytes in OID string including index bytes.
2466 OIDLen += indexBytes;
2467  
2468 // Since we added index bytes to previously copied OID
2469 // string, we need to update OIDLen value.
2470 prevOffset = _SNMPGetTxOffset();
2471 _SNMPSetTxOffset(OIDValOffset);
2472 _SNMPPut(OIDLen);
2473 _SNMPSetTxOffset(prevOffset);
2474  
2475  
2476 // Fetch actual value itself.
2477 // Need to restore original OID value.
2478 rec->nodeInfo.Val = varNodeInfo.Val;
2479 rec->id = varID;
2480 rec->dataType = varDataType;
2481  
2482 temp.v[0] += ProcessGetVar(rec, FALSE);
2483 return temp.v[0];
2484 }
2485  
2486  
2487 /****************************************************************************
2488 Function:
2489 BYTE ProcessGetBulkVar(OID_INFO* rec, BYTE* oidValuePtr,
2490 BYTE* oidLenPtr,BYTE* successor)
2491  
2492 Summary:
2493 This routine process the SNMPv2c Get Bulk Request.
2494  
2495 Description:
2496 ProcessVariables() processes the received snmp request pdu for each of
2497 the variable binding in the variable binding list to produce a response
2498 pdu. Depending on the number of the Max_repetitions for every variable
2499 in the list for which Bulk information is expected, ProcessGetBulkVar()
2500 is executed. It searches for the next lexicographically ordered
2501 successor for of the OID received in the request. For each of the
2502 iterations upto max-repetitions, the next leaf node is searched in the
2503 MIB to that of the leaf node found in the last iteration, for the
2504 corresponding variable binding.
2505  
2506 Precondition:
2507 ProcessVariables() is called.
2508  
2509 Parameters:
2510 rec - Pointer to SNMP MIB variable object information OID
2511 oidValuePtr - Pointer to new node OID found in MIB
2512 oidLenPtr - Oid length
2513 successor - 'I'th lexicographic successor to be found value
2514  
2515 Return Values:
2516 FALSE - If no lexicographic successor found
2517 temp.v[0] - Total number of bytes copied to response packet
2518  
2519 Remarks:
2520 None.
2521 ***************************************************************************/
2522 static BYTE ProcessGetBulkVar(OID_INFO* rec, BYTE* oidValuePtr, BYTE* oidLenPtr,BYTE* successor)
2523 {
2524  
2525 BYTE ref,putBytes,cntr;
2526 BYTE OIDLen;
2527 static BYTE varDataType;
2528 static BYTE indexBytes;
2529 SNMP_ID varID;
2530 BOOL lbNextLeaf;
2531 INDEX_INFO indexInfo;
2532 MIB_INFO varNodeInfo;
2533 WORD OIDValOffset;
2534 WORD prevOffset;
2535 WORD_VAL temp;
2536 OID_INFO indexRec;
2537 static SNMP_VAL v;
2538  
2539 lbNextLeaf = FALSE;
2540 temp.v[0] = 0;
2541  
2542 //Reach to the node for the expected iteration
2543 for(cntr=1;cntr<=*successor;cntr++)
2544 {
2545 // Get next leaf only if this OID is a parent or a simple leaf node.
2546 if((rec->nodeInfo.Flags.bIsParent)||(rec->nodeInfo.Flags.bIsSequence)||
2547 (!rec->nodeInfo.Flags.bIsParent && !rec->nodeInfo.Flags.bIsSequence))
2548 {
2549 _GetNextLeaf:
2550 lbNextLeaf = TRUE;
2551 if(!GetNextLeaf(rec))
2552 return FALSE;
2553 }
2554 }
2555  
2556 // Get complete OID string from oid record.
2557 if(!GetOIDStringByAddr(rec, oidValuePtr, &OIDLen))
2558 return FALSE;
2559  
2560 _SNMPPut(ASN_OID);
2561  
2562 OIDValOffset = _SNMPGetTxOffset();
2563 temp.v[0] =*oidLenPtr= OIDLen;
2564 _SNMPSetTxOffset(OIDValOffset+1);
2565  
2566 //Put OID
2567 while( temp.v[0]-- )
2568 {
2569 _SNMPPut(*oidValuePtr);
2570 oidValuePtr++;
2571 }
2572  
2573 // Start counting number of bytes put - OIDLen is already counted.
2574 temp.v[0] =*oidLenPtr= OIDLen;
2575  
2576 varDataType = rec->dataType;
2577 varID = rec->id;
2578  
2579 // If this is a simple OID, handle it as a GetVar command.
2580 if ( !rec->nodeInfo.Flags.bIsSequence )
2581 {
2582  
2583 // This is an addition to previously copied OID string.
2584 // This is index value of '0'.
2585 _SNMPPut(0);
2586 temp.v[0]++;
2587  
2588 // Since we added one more byte to previously copied OID
2589 // string, we need to update OIDLen value.
2590 prevOffset = _SNMPGetTxOffset();
2591 _SNMPSetTxOffset(OIDValOffset);
2592 _SNMPPut(++OIDLen);
2593 _SNMPSetTxOffset(prevOffset);
2594  
2595 // Now do Get on this simple variable.
2596 prevOffset = _SNMPGetTxOffset();
2597 putBytes = ProcessGetVar(rec, FALSE);
2598  
2599 temp.v[0] += putBytes; // ProcessGetVar(rec, FALSE);
2600  
2601 // Return with total number of bytes copied to response packet.
2602 return temp.v[0];
2603 }
2604  
2605 ref = 0;
2606 if ( lbNextLeaf == TRUE )
2607 {
2608 // Let application tell us whether this is a valid index or not.
2609 if ( !SNMPGetVar(rec->id, rec->index, &ref, &v) )
2610 {
2611 // Reset the response packet pointer to begining of OID.
2612 _SNMPSetTxOffset(OIDValOffset);
2613  
2614 // Jump to this label within this function - Not a good SW engineering
2615 // practice, but this will reuse code at much lower expense.
2616 goto _GetNextLeaf;
2617 }
2618 }
2619  
2620 // Need to fetch index information from MIB and prepare complete OID+
2621 // index response.
2622 varNodeInfo.Val = rec->nodeInfo.Val;
2623  
2624 // In this version, only 7-bit index is supported.
2625 MPFSGet(hMPFS, NULL);
2626  
2627 indexBytes = 0;
2628  
2629 MPFSGet(hMPFS, &indexInfo.Val);
2630  
2631 // Fetch index ID.
2632 MPFSGet(hMPFS, &indexRec.id);
2633 // Fetch index data type.
2634 indexRec.dataType = 0;
2635 MPFSGet(hMPFS, (BYTE*)&indexRec.dataType);
2636  
2637 indexRec.index = rec->index;
2638  
2639 // Check with application to see if there exists next index
2640 // for this index id.
2641 if ( !lbNextLeaf && !SNMPGetNextIndex(indexRec.id, &indexRec.index) )
2642 {
2643 //lbNextSeqeuence = TRUE;
2644  
2645 // Reset the response packet pointer to begining of OID.
2646 _SNMPSetTxOffset(OIDValOffset);
2647  
2648 // Jump to this label. Not a good practice, but once-in-a-while
2649 // it should be acceptable !
2650  
2651 goto _GetNextLeaf;
2652 }
2653  
2654 // Index is assumed to be dynamic, and leaf node.
2655 // mib2bib has already ensured that this was the case.
2656 indexRec.nodeInfo.Flags.bIsConstant = 0;
2657 indexRec.nodeInfo.Flags.bIsParent = 0;
2658 indexRec.nodeInfo.Flags.bIsSequence = 1;
2659  
2660 // Now handle this as simple GetVar.
2661 // Keep track of number of bytes added to OID.
2662 indexBytes += ProcessGetVar(&indexRec, TRUE);
2663  
2664 rec->index = indexRec.index;
2665  
2666 // These are the total number of bytes put so far as a result of this function.
2667 temp.v[0] += indexBytes;
2668  
2669 // These are the total number of bytes in OID string including index bytes.
2670 OIDLen += indexBytes;
2671  
2672 // Since we added index bytes to previously copied OID
2673 // string, we need to update OIDLen value.
2674 prevOffset = _SNMPGetTxOffset();
2675 _SNMPSetTxOffset(OIDValOffset);
2676 _SNMPPut(OIDLen);
2677 _SNMPSetTxOffset(prevOffset);
2678  
2679  
2680 // Fetch actual value itself.
2681 // Need to restore original OID value.
2682 rec->nodeInfo.Val = varNodeInfo.Val;
2683 rec->id = varID;
2684 rec->dataType = varDataType;
2685  
2686 temp.v[0] += ProcessGetVar(rec, FALSE);
2687  
2688 return temp.v[0];
2689 }
2690  
2691  
2692 /****************************************************************************
2693 Function:
2694 BYTE OIDLookup(PDU_INFO* pduDbPtr,BYTE* oid, BYTE oidLen, OID_INFO* rec)
2695  
2696 Summary:
2697 To search and validate whether the requested OID is in the MIB database.
2698  
2699 Description:
2700 The MIB database is stored with the agent in binary mib format.
2701 This is the binary mib format:
2702 <oid, nodeInfo, [id], [SiblingOffset], [DistantSibling], [dataType],
2703 [dataLen], [data], [{IndexCount, <IndexType>, <Index>, ...>]}, ChildNode
2704 variable bind name is a dotted string of oid. Every oid is a node in the
2705 MIB tree and have varied information. This routine on reception of the
2706 snmp request, will search for every oid in the var name. This routine
2707 will return information whether the requested var name is part of the
2708 MIB tree data structre of this agent or not.
2709  
2710 Precondition:
2711 Valid snmp request with valid OID format is received.
2712  
2713 Parameters:
2714 pduDbPtr - Pointer to received snmp pdu elements information
2715 oid - Pointer to the string of OID to be searched
2716 oidLen - Oid length
2717 rec - Pointer to SNMP MIB variable object information
2718  
2719 Return Values:
2720 TRUE - If the complete OID string is found in the mib
2721 FALSE - If complete OID do not match.
2722 Also different erros returned are
2723 SNMP_END_OF_MIB_VIEW
2724 SNMP_NO_SUCH_NAME
2725 SNMP_NO_SUCH_OBJ
2726 SNMP_NO_SUCH_INSTANCE
2727 Remarks:
2728 This routine works for the MPFS2 mib storage format. It uses the MPFS2
2729 APIs to read,search and collect information from the mib database.
2730 ***************************************************************************/
2731 static BYTE OIDLookup(PDU_INFO* pduDbPtr,BYTE* oid, BYTE oidLen, OID_INFO* rec)
2732 {
2733  
2734 BYTE savedOID,tempSavedOID;
2735 BYTE matchedCount;
2736 BYTE snmpVer;
2737 BYTE snmpReqType;
2738 BYTE tempLen;
2739 BYTE* reqOidPtr;
2740 BYTE comapreOidWithSibling=FALSE;
2741  
2742 WORD_VAL tempData;
2743 DWORD hNode,tempHNode;// MPFS hNode;
2744  
2745 appendZeroToOID=TRUE;
2746  
2747 snmpVer=pduDbPtr->snmpVersion;
2748 snmpReqType=pduDbPtr->pduType;
2749  
2750 if(!SNMPStatus.Flags.bIsFileOpen )
2751 return FALSE;
2752  
2753 hNode = 0;
2754 matchedCount = oidLen;
2755  
2756 tempLen=oidLen;
2757 reqOidPtr=oid;
2758  
2759 while( 1 )
2760 {
2761  
2762 MPFSSeek(hMPFS, hNode, MPFS_SEEK_START);
2763  
2764 // Remember offset of this node so that we can find its sibling
2765 // and child data.
2766 rec->hNode = MPFSTell(hMPFS); // hNode;
2767  
2768 // Read OID byte.
2769 MPFSGet(hMPFS, &savedOID);
2770  
2771 if(comapreOidWithSibling==(BYTE)FALSE)
2772 {
2773 tempSavedOID=savedOID;
2774 tempHNode=hNode;
2775 }
2776  
2777 // Read Node Info
2778 MPFSGet(hMPFS, &rec->nodeInfo.Val);
2779  
2780 // Next byte will be node id, if this is a leaf node with variable data.
2781 if(rec->nodeInfo.Flags.bIsIDPresent)
2782 MPFSGet(hMPFS, &rec->id);
2783  
2784 // Read sibling offset, if there is any.
2785 if(rec->nodeInfo.Flags.bIsSibling)
2786 {
2787 MPFSGet(hMPFS, &tempData.v[0]);
2788 MPFSGet(hMPFS, &tempData.v[1]);
2789 rec->hSibling = tempData.Val;
2790 }
2791  
2792 if ( savedOID != *reqOidPtr )
2793 {
2794 /*if very first OID byte does not match, it may be because it is
2795 0, 1 or 2. In that case declare that there is a match.
2796 The command processor would detect OID type and continue or reject
2797 this OID as a valid argument.*/
2798 if(matchedCount == oidLen)
2799 goto FoundIt;
2800  
2801 if(comapreOidWithSibling==(BYTE)TRUE && !rec->nodeInfo.Flags.bIsSibling)
2802 goto DidNotFindIt;
2803  
2804 if ( rec->nodeInfo.Flags.bIsSibling )
2805 {
2806 hNode = MPFSSeek(hMPFS, tempData.Val, MPFS_SEEK_START);
2807 hNode = MPFSTell(hMPFS);
2808 comapreOidWithSibling=TRUE;
2809 }
2810 else
2811 goto DidNotFindIt;
2812 }
2813 else
2814 {
2815 // One more oid byte matched.
2816 matchedCount--;
2817 reqOidPtr++;
2818  
2819 // A node is said to be matched if last matched node is a leaf node
2820 // or all but last OID string is matched and last byte of OID is '0'.
2821 // i.e. single index.
2822 if ( !rec->nodeInfo.Flags.bIsParent )
2823 {
2824 // Read and discard Distant Sibling info if there is any.
2825 if ( rec->nodeInfo.Flags.bIsDistantSibling )
2826 {
2827 MPFSGet(hMPFS, &tempData.v[0]);
2828 MPFSGet(hMPFS, &tempData.v[1]);
2829 rec->hSibling = tempData.Val;
2830 }
2831  
2832 rec->dataType = 0;
2833 MPFSGet(hMPFS, (BYTE*)&rec->dataType);
2834 rec->hData = MPFSTell(hMPFS);
2835  
2836 if(snmpReqType==SNMP_GET && matchedCount == 0u)
2837 {
2838 appendZeroToOID=FALSE;
2839 goto DidNotFindIt;
2840 }
2841 else if(snmpReqType==(BYTE)SNMP_GET && matchedCount == 1u && *reqOidPtr == 0x00u)
2842 {
2843 appendZeroToOID=FALSE;
2844 }
2845 else if(snmpReqType==SNMP_GET_NEXT && matchedCount == 0u)
2846 {
2847 appendZeroToOID=TRUE;
2848 snmpReqType=pduDbPtr->pduType=SNMP_GET;
2849 }
2850  
2851 goto FoundIt;
2852 }
2853 else if(matchedCount == 1u && *reqOidPtr == 0x00u)
2854 {
2855 appendZeroToOID=FALSE;
2856  
2857 if(rec->nodeInfo.Flags.bIsParent)
2858 {
2859 goto DidNotFindIt;
2860 }
2861  
2862 }
2863 else if(matchedCount == 0u)
2864 {
2865 if(rec->nodeInfo.Flags.bIsParent || snmpReqType==SNMP_GET)
2866 {
2867 appendZeroToOID=FALSE;
2868  
2869 goto DidNotFindIt;
2870 }
2871 else
2872 goto FoundIt;
2873 }
2874 else
2875 {
2876 hNode = MPFSTell(hMPFS);
2877 // Try to match following child node.
2878 continue;
2879 }
2880 }
2881 }
2882  
2883 FoundIt:
2884  
2885 // Convert index info from OID to regular value format.
2886 rec->index = savedOID;
2887  
2888 /*To Reach To The Next leaf Node */
2889 savedOID = *reqOidPtr;
2890  
2891 rec->indexLen = 1;
2892  
2893 if(matchedCount ==1u)
2894 {
2895 rec->index = *reqOidPtr;
2896 }
2897 else if(matchedCount == 0u)
2898 {
2899 rec->index = 0;
2900 }
2901 else if ( matchedCount > 1u || savedOID & 0x80 /*In this version, we only support 7-bit index*/)
2902 {
2903 // Current instnace spans across more than 7-bit.
2904 rec->indexLen = 0xff;
2905  
2906 if(snmpReqType==SNMP_GET && snmpVer==(BYTE)SNMP_V1)
2907 {
2908 return SNMP_NO_SUCH_NAME;
2909 }
2910 else if(snmpReqType==SNMP_GET && snmpVer==(BYTE)SNMP_V2C)
2911 {
2912 if(matchedCount== oidLen) //No OBJECT IDNETIFIER Prefix match
2913 return SNMP_NO_SUCH_INSTANCE;
2914 else
2915 return SNMP_NO_SUCH_OBJ;
2916 }
2917  
2918 return FALSE;
2919 }
2920  
2921 return TRUE;
2922  
2923 DidNotFindIt:
2924  
2925 if(snmpReqType==SNMP_GET)
2926 {
2927 if(snmpVer==(BYTE)SNMP_V1)
2928 return SNMP_NO_SUCH_NAME;
2929  
2930 else if(snmpVer==(BYTE)SNMP_V2C)
2931 {
2932 if(matchedCount== oidLen) //No OBJECT IDNETIFIER Prefix match
2933 return SNMP_NO_SUCH_INSTANCE;
2934 else
2935 return SNMP_NO_SUCH_OBJ;
2936 }
2937 }
2938 else if((snmpReqType==SNMP_GET_NEXT||snmpReqType==SNMP_V2C_GET_BULK) && snmpVer==(BYTE)SNMP_V2C)
2939 {
2940 return SNMP_END_OF_MIB_VIEW;
2941 }
2942  
2943 return FALSE;
2944 }
2945  
2946  
2947 /****************************************************************************
2948 Function:
2949 BOOL GetNextLeaf(OID_INFO* rec)
2950  
2951 Summary:
2952 Searches for the next leaf node in the MIP tree.
2953  
2954 Description:
2955 This routine searches for the next leaf node from the current node.
2956 The input to this function is the node from where next leaf node
2957 is to be located. The next leaf node will be a silbing else distant
2958 sibling or leaf node of next branch, if any present. The input parameter
2959 var pointer will be updated with the newly found leaf node OID info.
2960  
2961 Precondition:
2962 ProcessGetBulkVar() else ProcessGetNextVar() is called.
2963  
2964 Parameters:
2965 rec - Pointer to SNMP MIB variable object information
2966  
2967 Return Values:
2968 TRUE - If next leaf node is found.
2969 FALSE - There is no next leaf node.
2970  
2971 Remarks:
2972 None.
2973 ***************************************************************************/
2974 static BOOL GetNextLeaf(OID_INFO* rec)
2975 {
2976 WORD_VAL temp;
2977  
2978 // If current node is leaf, its next sibling (near or distant) is the next leaf.
2979 if ( !rec->nodeInfo.Flags.bIsParent )
2980 {
2981 // Since this is a leaf node, it must have at least one distant or near
2982 // sibling to get next sibling.
2983 if(rec->nodeInfo.Flags.bIsSibling ||
2984 rec->nodeInfo.Flags.bIsDistantSibling )
2985 {
2986 // Reposition at sibling.
2987 MPFSSeek(hMPFS, rec->hSibling, MPFS_SEEK_START);
2988  
2989 // Fetch node related information
2990 }
2991 // There is no sibling to this leaf. This must be the very last node on the tree.
2992 else
2993 {
2994 //--MPFSClose();
2995 return FALSE;
2996 }
2997 }
2998  
2999 while( 1 )
3000 {
3001 // Remember current MPFS position for this node.
3002 rec->hNode = MPFSTell(hMPFS);
3003  
3004 // Read OID byte.
3005 MPFSGet(hMPFS, &rec->oid);
3006  
3007 // Read Node Info
3008 MPFSGet(hMPFS, &rec->nodeInfo.Val);
3009  
3010 // Next byte will be node id, if this is a leaf node with variable data.
3011 if ( rec->nodeInfo.Flags.bIsIDPresent )
3012 MPFSGet(hMPFS, &rec->id);
3013  
3014 // Fetch sibling offset, if there is any.
3015 if ( rec->nodeInfo.Flags.bIsSibling ||
3016 rec->nodeInfo.Flags.bIsDistantSibling )
3017 {
3018 MPFSGet(hMPFS, &temp.v[0]);
3019 MPFSGet(hMPFS, &temp.v[1]);
3020 rec->hSibling = temp.Val;
3021 }
3022  
3023 // If we have not reached a leaf yet, continue fetching next child in line.
3024 if ( rec->nodeInfo.Flags.bIsParent )
3025 {
3026 continue;
3027 }
3028  
3029 // Fetch data type.
3030 rec->dataType = 0;
3031 MPFSGet(hMPFS, (BYTE*)&rec->dataType);
3032  
3033 rec->hData = MPFSTell(hMPFS);
3034  
3035 // Since we just found next leaf in line, it will always have zero index
3036 // to it.
3037 rec->indexLen = 1;
3038 rec->index = 0;
3039  
3040 return TRUE;
3041 }
3042 return FALSE;
3043 }
3044  
3045  
3046 /****************************************************************************
3047 Function:
3048 BOOL IsValidCommunity(char* community, BYTE* len)
3049  
3050 Summary:
3051 Verifies for the community string datatype and the max
3052 community name and length, this agent can process.
3053  
3054 Description:
3055 This routine populates and validates the community datatype, community
3056 name and length from the received snmp request pdu. Community name is
3057 used for accessing public and private memebrs of the mib.
3058  
3059 Precondition:
3060 ProcessHeader() is called.
3061  
3062 Parameters:
3063 community - Pointer to memory where community string will be stored.
3064 len - Pointer to memory where comunity length gets stored.
3065  
3066 Return Values:
3067 TRUE - If valid community received.
3068 FALSE - If community is not valid.
3069  
3070 Remarks:
3071 None.
3072 ***************************************************************************/
3073 static BOOL IsValidCommunity(char* community, BYTE* len)
3074 {
3075 BYTE tempData;
3076 BYTE tempLen;
3077  
3078 tempData = _SNMPGet();
3079 if ( !IS_OCTET_STRING(tempData) )
3080 return FALSE;
3081  
3082 tempLen = _SNMPGet();
3083 *len = tempLen;
3084 if ( tempLen > SNMP_COMMUNITY_MAX_LEN )
3085 return FALSE;
3086  
3087 while( tempLen-- )
3088 {
3089 tempData = _SNMPGet();
3090 *community++ = tempData;
3091 }
3092 *community = '\0';
3093 return TRUE;
3094 }
3095  
3096  
3097 /****************************************************************************
3098 Function:
3099 BOOL IsValidInt(DWORD* val)
3100  
3101 Summary:
3102 Verifies variable datatype as INT and retrieves its value.
3103  
3104 Description:
3105 This routine populates and validates the received variable for the
3106 data type as "ASN_INT" and the data length for max 4 bytes.
3107  
3108 Precondition:
3109 ProcessHeader() or ProcessGetSetHeader() is called.
3110  
3111 Parameters:
3112 val - Pointer to memory where int var value will be stored.
3113  
3114 ReturnValues:
3115 TRUE - If valid integer type and value is received.
3116 FALSE - Other than integer data type and value received .
3117  
3118 Remarks:
3119 None.
3120 ***************************************************************************/
3121 static BOOL IsValidInt(DWORD* val)
3122 {
3123 DWORD_VAL tempData;
3124 DWORD_VAL tempLen;
3125  
3126 tempLen.Val = 0;
3127  
3128 // Get variable type
3129 if ( !IS_ASN_INT(_SNMPGet()) )
3130 return FALSE;
3131  
3132 if ( !IsValidLength(&tempLen.w[0]) )
3133 return FALSE;
3134  
3135 // Integer length of more than 32-bit is not supported.
3136 if ( tempLen.Val > 4u )
3137 return FALSE;
3138  
3139 tempData.Val = 0;
3140 while( tempLen.v[0]-- )
3141 tempData.v[tempLen.v[0]] = _SNMPGet();
3142  
3143 *val = tempData.Val;
3144  
3145 return TRUE;
3146 }
3147  
3148  
3149 /****************************************************************************
3150 Function:
3151 BOOL IsValidPDU(SNMP_ACTION* pdu)
3152  
3153 Summary:
3154 Verifies for the snmp request type.
3155  
3156 Description:
3157 This routine populates and verifies for the received snmp request
3158 pdu type.
3159  
3160 Precondition:
3161 ProcessHeader() is called.
3162  
3163 Parameters:
3164 val - Pointer to memory where received snmp request type is stored.
3165  
3166 Return Values:
3167 TRUE - If this snmp request can be processed by the agent.
3168 FALSE - If the request can not be processed.
3169  
3170 Remarks:
3171 None.
3172 ***************************************************************************/
3173 static BOOL IsValidPDU(SNMP_ACTION* pdu)
3174 {
3175 BYTE tempData;
3176 WORD tempLen;
3177  
3178  
3179 // Fetch pdu data type
3180 tempData = _SNMPGet();
3181 if ( !IS_AGENT_PDU(tempData) )
3182 return FALSE;
3183  
3184 *pdu = tempData;
3185  
3186  
3187 /* Now fetch pdu length. We don't need to remember pdu length.
3188 Do this to proceed to next pdu element of interest*/
3189 return IsValidLength(&tempLen);
3190 }
3191  
3192  
3193  
3194  
3195 /****************************************************************************
3196 Function:
3197 BYTE IsValidLength(WORD* len)
3198  
3199 Summary:
3200 Retrieves the packet length and actual pdu length.
3201  
3202 Description:
3203 Checks current packet and returns total length value as well as
3204 actual length bytes.We do not support any length byte count of more
3205 than 2 i.e. total length value must not be more than 16-bit.
3206  
3207 Precondition:
3208 None
3209  
3210 Parameters:
3211 len - Pointer to memory where actual length is stored.
3212  
3213 Return Values:
3214 lengthBytes - Total length bytes are 0x80 itself plus tempData.
3215  
3216 Remarks:
3217 None.
3218 ***************************************************************************/
3219 static BYTE IsValidLength(WORD *len)
3220 {
3221 BYTE tempData;
3222 WORD_VAL tempLen;
3223 BYTE lengthBytes;
3224  
3225 // Initialize length value.
3226 tempLen.Val = 0;
3227 lengthBytes = 0;
3228  
3229 tempData = _SNMPGet();
3230 tempLen.v[0] = tempData;
3231 if ( tempData & 0x80 )
3232 {
3233 tempData &= 0x7F;
3234  
3235 // We do not support any length byte count of more than 2
3236 // i.e. total length value must not be more than 16-bit.
3237 if ( tempData > 2u )
3238 return FALSE;
3239  
3240 // Total length bytes are 0x80 itself plus tempData.
3241 lengthBytes = tempData + 1;
3242  
3243 // Get upto 2 bytes of length value.
3244 while( tempData-- )
3245 tempLen.v[tempData] = _SNMPGet();
3246 }
3247 else
3248 lengthBytes = 1;
3249  
3250 *len = tempLen.Val;
3251  
3252 return lengthBytes;
3253 }
3254  
3255  
3256 /****************************************************************************
3257 Function:
3258 BOOL IsASNNull(void)
3259  
3260  
3261 Summary:
3262 Verifies the value type as ASN_NULL.
3263  
3264 Description:
3265 For Get,Get_Next,Get_Bulk snmp reuest, the var bind the value data type
3266 should be ASN_NULL and value field must be NULL and . This routine
3267 verifies the data type and value fields in the received requests.
3268 The SET request, the value data type can not be ASN_NULL,
3269 otherwise the snmp request is not processed.
3270  
3271 Precondition:
3272 None
3273  
3274 Parameters:
3275 None
3276  
3277 Returns Values
3278 TRUE - If value type is ASN_NULL and value is NULL.
3279 FALSE - If data type and value is other than ASN_NULL and NULL resp.
3280  
3281 Remarks:
3282 None.
3283 ***************************************************************************/
3284 static BOOL IsASNNull(void)
3285 {
3286 BYTE a;
3287  
3288  
3289 // Fetch and verify that this is NULL data type.
3290 /*if ( !IS_ASN_NULL(_SNMPGet()) )
3291 return FALSE;*/
3292  
3293 a=_SNMPGet();
3294  
3295 if (!IS_ASN_NULL(a))
3296 return FALSE;
3297  
3298 // Fetch and verify that length value is zero.
3299 return (_SNMPGet() == 0u );
3300 }
3301  
3302  
3303 /****************************************************************************
3304 Function:
3305 BOOL IsValidOID(BYTE* oid, BYTE* len)
3306  
3307 Summary:
3308 Populates OID type, length and oid string from the received pdu.
3309  
3310 Description:
3311 In this routine, OID data type "ASN_OID" is verified in the received pdu.
3312 If the data type is matched, then only var bind is processed. OID length
3313 and OID is populated. The max OID length can be 15.
3314  
3315 Precondition:
3316 ProcessVariabels() is called.
3317  
3318 Parameters:
3319 oid - Pointer to memory to store the received OID string
3320 len - Pointer to memory to store OID length
3321  
3322 Return Values:
3323 TRUE - If value type is ASN_OID and oid length not more than 15.
3324 FALSE - Otherwise.
3325  
3326 Remarks:
3327 None.
3328 ***************************************************************************/
3329 static BOOL IsValidOID(BYTE* oid, BYTE* len)
3330 {
3331 DWORD_VAL tempLen;
3332  
3333 // Fetch and verify that this is OID.
3334 if ( !IS_OID(_SNMPGet()) )
3335 return FALSE;
3336  
3337 // Retrieve OID length
3338 if ( !IsValidLength(&tempLen.w[0]) )
3339 return FALSE;
3340  
3341 // Make sure that OID length is within our capability.
3342 if ( tempLen.w[0] > (BYTE)OID_MAX_LEN )
3343 return FALSE;
3344  
3345 *len = tempLen.v[0];
3346  
3347 while( tempLen.v[0]-- )
3348 {
3349 *oid++ = _SNMPGet();
3350 }
3351 *oid=0xff;
3352 return TRUE;
3353 }
3354  
3355 /****************************************************************************
3356 Function:
3357 BYTE IsValidStructure(WORD* dataLen)
3358  
3359 Summary:
3360 Decode variable length structure.
3361  
3362 Description:
3363 This routine is used to verify whether the received varbind is of type
3364 STRUCTURE and to find out the variable binding structure length.
3365  
3366 Precondition:
3367 ProcessHeader() is called.
3368  
3369 Parameters:
3370 datalen - Pointer to memory to store OID structure length.
3371  
3372 Return Values:
3373 headrbytes - Variable binding length.
3374 FALSE - If variable data structure is not type STRUCTURE.
3375  
3376 Remarks:
3377 None.
3378 ***************************************************************************/
3379 static BYTE IsValidStructure(WORD* dataLen)
3380 {
3381 DWORD_VAL tempLen;
3382 BYTE headerBytes;
3383  
3384 if ( !IS_STRUCTURE(_SNMPGet()) )
3385 return FALSE;
3386  
3387 // Retrieve structure length
3388 headerBytes = IsValidLength(&tempLen.w[0]);
3389 if ( !headerBytes )
3390 return FALSE;
3391  
3392 headerBytes++;
3393  
3394 // Since we are using UDP as our transport and UDP are not fragmented,
3395 // this structure length cannot be more than 1500 bytes.
3396 // As a result, we will only use lower WORD of length value.
3397 *dataLen = tempLen.w[0];
3398  
3399 return headerBytes;
3400 }
3401  
3402 /****************************************************************************
3403 Function:
3404 void _SNMPDuplexInit(UDP_SOCKET socket)
3405  
3406 Summary:
3407 Prepare for full duplex transfer.
3408  
3409 Description:
3410 As we process SNMP variables, we will prepare response on-the-fly
3411 creating full duplex transfer. Current MAC layer does not support
3412 full duplex transfer, so SNMP needs to manage its own full duplex
3413 connection. Prepare for full duplex transfer. Set the Tx and Rx
3414 offset to start of the buffer.
3415  
3416 Precondition:
3417 SNMPTask() is called.
3418  
3419 Parameters:
3420 socket - An active udp socket for which tx and rx offset to be set.
3421  
3422 Returns:
3423 None.
3424  
3425 Remarks:
3426 This routine should be called for every new snmp packet received.
3427 ***************************************************************************/
3428 static void _SNMPDuplexInit(UDP_SOCKET socket)
3429 {
3430 // In full duplex transfer, transport protocol must be ready to
3431 // accept new transmit packet.
3432 while( !UDPIsPutReady(socket) ) ;
3433  
3434 // Initialize buffer offsets.
3435 SNMPRxOffset = 0;
3436 SNMPTxOffset = 0;
3437 }
3438  
3439  
3440 /****************************************************************************
3441 Function:
3442 void _SNMPPut(BYTE v)
3443  
3444 Summary:
3445 Copy byte to tx buffer.
3446  
3447 Description:
3448 This function writes a single byte to the currently active UDP socket,
3449 transmit buffer, while incrementing the buffer offset for the next write
3450 operation.
3451  
3452 Precondition:
3453 SNMPTask() is called.
3454 A active udp socket is availabe to tx from.
3455  
3456 Parameters:
3457 None.
3458  
3459 Returns:
3460 None.
3461  
3462 Remarks:
3463 None.
3464 ***************************************************************************/
3465 static void _SNMPPut(BYTE v)
3466 {
3467 UDPSetTxBuffer(SNMPTxOffset);
3468  
3469 UDPPut(v);
3470  
3471 SNMPTxOffset++;
3472 }
3473  
3474 /****************************************************************************
3475 Function:
3476 BYTE _SNMPGet(void)
3477  
3478 Summary:
3479 Read byte from snmp udp socket rx buffer.
3480  
3481 Description:
3482 This function reads a single byte from the currently active UDP socket,
3483 receive buffer, while incrementing the buffer offset from where the next
3484 byte will be read.
3485  
3486 Precondition:
3487 SNMPTask() is called.
3488 A active udp socket is available to read from.
3489  
3490 Parameters:
3491 None
3492  
3493 Returns:
3494 None.
3495  
3496 Remarks:
3497 None.
3498 ***************************************************************************/
3499 static BYTE _SNMPGet(void)
3500 {
3501 BYTE v;
3502  
3503 UDPSetRxBuffer(SNMPRxOffset++);
3504 UDPGet(&v);
3505 return v;
3506 }
3507  
3508 #if !defined(SNMP_TRAP_DISABLED)
3509 /****************************************************************************
3510 Function:
3511 BOOL GetOIDStringByID(SNMP_ID id, OID_INFO* info,
3512 BYTE* oidString, BYTE* len)
3513  
3514 Summary:
3515 Get complete notification variable OID string from MPFS using var id.
3516  
3517 Description:
3518 This routine is called when a OID string is required to be searched
3519 from MPFS using agent id. The string is saved with agent.
3520 TRAP pdu is send with this OID corresponding to the SNMP_ID used
3521 by the agent application to send the pdu.
3522  
3523 Precondition:
3524 SNMPNotify() is called.
3525  
3526 Parameters:
3527 id - System ID to use identify this agent.
3528 info - Pointer to SNMP MIB variable object information
3529 oidString - Pointer to store the string of OID serached
3530 len - Oid length
3531  
3532 Return Values:
3533 TRUE - If oid string is found for the variable id in MPFS.
3534 FLASE - Otherwise.
3535  
3536 Remarks:
3537 This function is used only when TRAP is enabled.
3538 ***************************************************************************/
3539 static BOOL GetOIDStringByID(SNMP_ID id, OID_INFO* info, BYTE* oidString, BYTE* len)
3540 {
3541 DWORD hCurrent;
3542  
3543 hCurrent = 0;
3544  
3545 while (1)
3546 {
3547 //Read in the Mib record for the oid info
3548 ReadMIBRecord(hCurrent, info);
3549  
3550 if ( !info->nodeInfo.Flags.bIsParent )
3551 {
3552 if ( info->nodeInfo.Flags.bIsIDPresent )
3553 {
3554 if ( info->id == id )
3555 return GetOIDStringByAddr(info, oidString, len);
3556 }
3557  
3558 if ( info->nodeInfo.Flags.bIsSibling ||
3559 info->nodeInfo.Flags.bIsDistantSibling )
3560 MPFSSeek(hMPFS, info->hSibling, MPFS_SEEK_START);
3561  
3562 else
3563 break;
3564  
3565 }
3566 hCurrent = MPFSTell(hMPFS);
3567 }
3568 return FALSE;
3569 }
3570 #endif
3571  
3572  
3573 /****************************************************************************
3574 Function:
3575 BOOL GetOIDStringByAddr(OID_INFO* rec, BYTE* oidString, BYTE* len)
3576  
3577 Summary:
3578 Get OID string from MPFS using the node address.
3579  
3580 Description:
3581 This routine is called when a OID string is required to be searched
3582 from MPFS using node address.
3583  
3584 Precondition:
3585 None.
3586  
3587 Parameters:
3588 rec - Pointer to SNMP MIB variable object information
3589 oidString - Pointer to store the string of OID serached
3590 len - Oid length
3591  
3592 Return Values:
3593 TRUE - If oid string is found.
3594 FLASE - Otherwise.
3595  
3596 Remarks:
3597 None.
3598 ***************************************************************************/
3599 static BOOL GetOIDStringByAddr(OID_INFO* rec, BYTE* oidString, BYTE* len)
3600 {
3601 DWORD hTarget;
3602 DWORD hCurrent;
3603 DWORD hNext;
3604 OID_INFO currentMIB;
3605 BYTE index;
3606 enum { SM_PROBE_SIBLING, SM_PROBE_CHILD } state;
3607  
3608 hCurrent = 0;
3609  
3610  
3611 hTarget = rec->hNode;//node address
3612 state = SM_PROBE_SIBLING;
3613 index = 0;
3614  
3615 while( 1 )
3616 {
3617 ReadMIBRecord(hCurrent, &currentMIB);
3618  
3619 oidString[index] = currentMIB.oid;
3620  
3621 if ( hTarget == hCurrent )
3622 {
3623 *len = ++index;
3624 return TRUE;
3625 }
3626  
3627 switch(state)
3628 {
3629 case SM_PROBE_SIBLING:
3630 if ( !currentMIB.nodeInfo.Flags.bIsSibling )
3631 state = SM_PROBE_CHILD;
3632  
3633 else
3634 {
3635 hNext = currentMIB.hSibling;
3636 MPFSSeek(hMPFS, hNext, MPFS_SEEK_START);
3637 hNext = MPFSTell(hMPFS);
3638 if ( hTarget >= hNext )
3639 {
3640 hCurrent = hNext;
3641 break;
3642 }
3643 else
3644 state = SM_PROBE_CHILD;
3645 }
3646  
3647 case SM_PROBE_CHILD:
3648 if ( !currentMIB.nodeInfo.Flags.bIsParent )
3649 return FALSE;
3650  
3651 index++;
3652  
3653 hCurrent = currentMIB.hChild;
3654 state = SM_PROBE_SIBLING;
3655 break;
3656 }
3657 }
3658 return FALSE;
3659 }
3660  
3661  
3662 /****************************************************************************
3663 Function:
3664 void ReadMIBRecord(DWORD h, OID_INFO* rec)
3665  
3666 Summary:
3667 Get OID string from MPFS using the node address.
3668  
3669 Description:
3670 This routine is called when a OID string is required to be searched
3671 from MPFS using node address.
3672  
3673 Precondition:
3674 GetOIDStringByID() or GetOIDStringByAddr() is called.
3675  
3676 Parameters:
3677 h - Node adderess whose oid is to be read.
3678 rec - Pointer to store SNMP MIB variable object information
3679  
3680 Returns:
3681 None.
3682  
3683 Remarks:
3684 None.
3685 ***************************************************************************/
3686 static void ReadMIBRecord(DWORD h, OID_INFO* rec)
3687 {
3688 MIB_INFO nodeInfo;
3689 WORD_VAL tempVal;
3690  
3691 MPFSSeek(hMPFS, h, MPFS_SEEK_START);
3692  
3693 // Remember location of this record.
3694 rec->hNode = h;
3695  
3696 // Read OID
3697 MPFSGet(hMPFS, &rec->oid);
3698  
3699 // Read nodeInfo
3700 MPFSGet(hMPFS, &rec->nodeInfo.Val);
3701 nodeInfo = rec->nodeInfo;
3702  
3703 // Read id, if there is any: Only leaf node with dynamic data will have id.
3704 if ( nodeInfo.Flags.bIsIDPresent )
3705 MPFSGet(hMPFS, &rec->id);
3706  
3707 // Read Sibling offset if there is any - any node may have sibling
3708 if ( nodeInfo.Flags.bIsSibling )
3709 {
3710 MPFSGet(hMPFS, &tempVal.v[0]);
3711 MPFSGet(hMPFS, &tempVal.v[1]);
3712 rec->hSibling = tempVal.Val;
3713 }
3714  
3715 // All rest of the parameters are applicable to leaf node only.
3716 if ( nodeInfo.Flags.bIsParent )
3717 rec->hChild = MPFSTell(hMPFS);
3718 else
3719 {
3720 if ( nodeInfo.Flags.bIsDistantSibling )
3721 {
3722 // Read Distant Sibling if there is any - only leaf node will have distant sibling
3723 MPFSGet(hMPFS, &tempVal.v[0]);
3724 MPFSGet(hMPFS, &tempVal.v[1]);
3725 rec->hSibling = tempVal.Val;
3726 }
3727  
3728 // Save data type for this node.
3729 rec->dataType = 0;
3730 MPFSGet(hMPFS, (BYTE*)&rec->dataType);
3731  
3732 rec->hData = MPFSTell(hMPFS);
3733  
3734 }
3735  
3736 }
3737  
3738 static BOOL GetDataTypeInfo(DATA_TYPE dataType, DATA_TYPE_INFO *info )
3739 {
3740 if ( dataType >= DATA_TYPE_UNKNOWN )
3741 {
3742 info->asnType = 0x00;
3743 info->asnLen = 0x00;
3744 return FALSE;
3745 }
3746  
3747 info->asnType = dataTypeTable[dataType].asnType;
3748 info->asnLen = dataTypeTable[dataType].asnLen;
3749  
3750 return TRUE;
3751 }
3752  
3753  
3754 /****************************************************************************
3755 Function:
3756 BYTE ProcessSetVar(PDU_INFO* pduDbPtr,OID_INFO* rec,
3757 SNMP_ERR_STATUS* errorStatus)
3758  
3759 Summary:
3760 Processes snmp Set request pdu.
3761  
3762 Description:
3763 This routine processes the received snmp set request pdu for the
3764 variable binding in the request and also creates the response pdu.
3765  
3766 Precondition:
3767 ProcessVariables() is called.
3768  
3769 Parameters:
3770 pduDbPtr - Received pdu information database pointer
3771 rec - Pointer to SNMP MIB variable object information
3772 errorStatus - Pointer to update error status info
3773  
3774 Return Values:
3775 copiedBytes - Number of bytes copied by this routine to the
3776 snmp pdu tx buffer.
3777  
3778 Remarks:
3779 None.
3780 ***************************************************************************/
3781 static BYTE ProcessSetVar(PDU_INFO* pduDbPtr,OID_INFO* rec, SNMP_ERR_STATUS* errorStatus)
3782 {
3783 BYTE ref;
3784 BYTE temp;
3785 BYTE dataType;
3786 BYTE dataLen;
3787 BYTE copiedBytes;
3788 SNMP_ERR_STATUS errorCode;
3789 DATA_TYPE_INFO actualDataTypeInfo;
3790 SNMP_VAL dataValue;
3791  
3792 // Start with no error.
3793 errorCode = SNMP_NO_ERR;
3794 copiedBytes = 0;
3795  
3796 // Non-leaf, Constant and ReadOnly node cannot be modified
3797 if(rec->nodeInfo.Flags.bIsParent ||
3798 rec->nodeInfo.Flags.bIsConstant ||
3799 !rec->nodeInfo.Flags.bIsEditable )
3800 {
3801 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3802 errorCode = SNMP_NO_SUCH_NAME;
3803 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3804 errorCode = SNMP_NOT_WRITABLE;
3805 }
3806  
3807 dataType = _SNMPGet();
3808 _SNMPPut(dataType);
3809 copiedBytes++;
3810  
3811 // Get data type for this node.
3812 //actualDataType = MPFSGet();
3813 if ( !GetDataTypeInfo(rec->dataType, &actualDataTypeInfo) )
3814 {
3815 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3816 errorCode = SNMP_BAD_VALUE;
3817 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3818 errorCode = SNMP_WRONG_TYPE;
3819 }
3820  
3821 // Make sure that received data type is same as what is declared
3822 // for this node.
3823 if ( dataType != actualDataTypeInfo.asnType )
3824 {
3825 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3826 errorCode = SNMP_BAD_VALUE;
3827 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3828 errorCode = SNMP_WRONG_TYPE;
3829 }
3830  
3831 // Make sure that received data length is within our capability.
3832 dataLen = _SNMPGet();
3833 _SNMPPut(dataLen);
3834 copiedBytes++;
3835  
3836 // Only max data length of 127 is supported.
3837 if ( dataLen > 0x7fu )
3838 {
3839 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3840 errorCode = SNMP_BAD_VALUE;
3841 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3842 errorCode = SNMP_WRONG_LENGTH;
3843 }
3844  
3845  
3846 // If this is a Simple variable and given index is other than '0',
3847 // it is considered bad value
3848 if ( !rec->nodeInfo.Flags.bIsSequence && rec->index != 0x00u ){
3849 errorCode = SNMP_NO_SUCH_NAME;}
3850  
3851 dataValue.dword = 0;
3852 ref = 0;
3853  
3854 // If data length is within 4 bytes, fetch all at once and pass it
3855 // to application.
3856 if ( actualDataTypeInfo.asnLen != 0xff )
3857 {
3858 // According to mib def., this data length for this data type/
3859 // must be less or equal to 4, if not, we don't know what this
3860 // is.
3861 if ( dataLen <= 4u )
3862 {
3863 // Now that we have verified data length, fetch them all
3864 // at once and save it in correct place.
3865 //dataLen--;
3866  
3867 while( dataLen-- )
3868 {
3869 temp = _SNMPGet();
3870 dataValue.v[dataLen] = temp;
3871  
3872 // Copy same byte back to create response...
3873 _SNMPPut(temp);
3874 copiedBytes++;
3875 }
3876  
3877  
3878 // Pass it to application.
3879 if ( errorCode == SNMP_NO_ERR )
3880 {
3881 if(!SNMPSetVar(rec->id, rec->index, ref, dataValue))
3882 {
3883 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3884 errorCode = SNMP_BAD_VALUE;
3885 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3886 errorCode = SNMP_WRONG_VALUE;
3887 }
3888 }
3889 }
3890 else
3891 {
3892 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3893 errorCode = SNMP_BAD_VALUE;
3894 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3895 { if( rec->nodeInfo.Flags.bIsConstant)
3896 errorCode = SNMP_NOT_WRITABLE;
3897 else
3898 errorCode = SNMP_WRONG_LENGTH;
3899 }
3900 }
3901 }
3902 else
3903 {
3904 // This is a multi-byte Set operation.
3905 // Check with application to see if this many bytes can be
3906 // written to current variable.
3907 if ( !SNMPIsValidSetLen(rec->id, dataLen) )
3908 {
3909 if(pduDbPtr->snmpVersion == (BYTE)SNMP_V1)
3910 errorCode = SNMP_BAD_VALUE;
3911 else if (pduDbPtr->snmpVersion == (BYTE)SNMP_V2C)
3912 {
3913 if( rec->nodeInfo.Flags.bIsConstant)
3914 errorCode = SNMP_NOT_WRITABLE;
3915 else
3916 errorCode = SNMP_WRONG_LENGTH;
3917 }
3918 }
3919 // Even though there may have been error processing this
3920 // variable, we still need to reply with original data
3921 // so at least copy those bytes.
3922 while( dataLen-- )
3923 {
3924 dataValue.byte = _SNMPGet();
3925  
3926 _SNMPPut(dataValue.byte);
3927 copiedBytes++;
3928  
3929 // Ask applicaton to set this variable only if there was
3930 // no previous error.
3931 if ( errorCode == SNMP_NO_ERR )
3932 {
3933 if ( !SNMPSetVar(rec->id, rec->index, ref++, dataValue) )
3934 {
3935 errorCode = SNMP_BAD_VALUE;
3936 }
3937 }
3938 }
3939 // Let application know about end of data transfer
3940 if ( errorCode == SNMP_NO_ERR )
3941 {
3942 SNMPSetVar(rec->id, rec->index, (WORD)SNMP_END_OF_VAR, dataValue);
3943 }
3944 }
3945 *errorStatus = errorCode;
3946  
3947 return copiedBytes;
3948 }
3949  
3950  
3951 /****************************************************************************
3952 Function:
3953 BYTE ProcessGetVar(OID_INFO* rec, BOOL bAsOID)
3954  
3955 Summary:
3956 Processes snmp Get request pdu.
3957  
3958 Description:
3959 This routine processes the received snmp Get request pdu for the
3960 variable binding in the request and also creates the response pdu.
3961  
3962 Precondition:
3963 ProcessVariables() is called.
3964  
3965 Parameters:
3966 rec - Pointer to SNMP MIB variable object information
3967 bAsOID - Oid flag.
3968  
3969 Return Values:
3970 varLen - Number of bytes put in response tx pdu
3971 FALSE - If any of the elements of the request pdu validation fails.
3972  
3973 Remarks:
3974 None.
3975 ***************************************************************************/
3976 static BYTE ProcessGetVar(OID_INFO* rec, BOOL bAsOID)
3977 {
3978 BYTE ref;
3979 BYTE temp;
3980 BYTE varLen;
3981 BYTE dataType;
3982 WORD offset;
3983 WORD prevOffset;
3984 SNMP_VAL v;
3985 DATA_TYPE_INFO dataTypeInfo;
3986  
3987 offset = 0; // Suppress C30 warning: 'offset' may be used uninitialized in this function
3988 v.dword = 0;
3989  
3990 // Non-leaf node does not contain any data.
3991 if ( rec->nodeInfo.Flags.bIsParent )
3992 return FALSE;
3993  
3994 // If current OID is Simple variable and index is other than .0
3995 // we don't Get this variable.
3996 if ( !rec->nodeInfo.Flags.bIsSequence )
3997 {
3998 // index of other than '0' is not invalid.
3999 if ( rec->index > 0u )
4000 return FALSE;
4001 }
4002  
4003 dataType = rec->dataType;
4004 if ( !GetDataTypeInfo(dataType, &dataTypeInfo) )
4005 return FALSE;
4006  
4007 if ( !bAsOID )
4008 {
4009 _SNMPPut(dataTypeInfo.asnType);
4010  
4011 offset = SNMPTxOffset;
4012 _SNMPPut(dataTypeInfo.asnLen);
4013 }
4014  
4015 if ( rec->nodeInfo.Flags.bIsConstant )
4016 {
4017 BYTE c;
4018 MPFSSeek(hMPFS, rec->hData, MPFS_SEEK_START);
4019  
4020 MPFSGet(hMPFS, &varLen);
4021 temp = varLen;
4022 while( temp-- )
4023 {
4024 MPFSGet(hMPFS, &c);
4025 _SNMPPut(c);
4026 }
4027 }
4028 else
4029 {
4030 ref = SNMP_START_OF_VAR;
4031 v.dword = 0;
4032 varLen = 0;
4033  
4034 do
4035 {
4036 if ( SNMPGetVar(rec->id, rec->index, &ref, &v) )
4037 {
4038 if ( dataTypeInfo.asnLen != 0xff )
4039 {
4040 varLen = dataTypeInfo.asnLen;
4041  
4042 while( dataTypeInfo.asnLen )
4043 _SNMPPut(v.v[--dataTypeInfo.asnLen]);
4044  
4045 break;
4046 }
4047 else
4048 {
4049 varLen++;
4050 _SNMPPut(v.v[0]);
4051 }
4052 }
4053 else
4054 return FALSE;
4055  
4056 } while( ref != SNMP_END_OF_VAR );
4057 }
4058  
4059 if ( !bAsOID )
4060 {
4061 prevOffset = _SNMPGetTxOffset();
4062  
4063 _SNMPSetTxOffset(offset);
4064 _SNMPPut(varLen);
4065  
4066 _SNMPSetTxOffset(prevOffset);
4067  
4068 varLen++;
4069 varLen++;
4070 }
4071  
4072 return varLen;
4073 }
4074  
4075  
4076 /****************************************************************************
4077 Function:
4078 void SetErrorStatus(WORD errorStatusOffset,
4079 WORD errorIndexOffset,
4080 SNMP_ERR_STATUS errorStatus,
4081 BYTE errorIndex)
4082 Summary:
4083 Set snmp error status in the response pdu.
4084  
4085 Description:
4086 This routine processes the received snmp Get request pdu for the
4087 variable binding in the request and also creates the response pdu.
4088  
4089 Precondition:
4090 ProcessVariables() is called.
4091  
4092 Parameters:
4093 errorStatusOffset - Offset to update error status in Response Tx pdu
4094 errorIndexOffset - Offset to update error index
4095 errorStatus - Snmp process error to be updated in response.
4096 errorIndex - Index of the request varbind in the var bind list
4097 for which error status is to be updated.
4098  
4099 Returns:
4100 None.
4101  
4102 Remarks:
4103 None.
4104 ***************************************************************************/
4105 static void SetErrorStatus(WORD errorStatusOffset,
4106 WORD errorIndexOffset,
4107 SNMP_ERR_STATUS errorStatus,
4108 BYTE errorIndex)
4109 {
4110 WORD prevOffset;
4111  
4112 prevOffset = _SNMPGetTxOffset();
4113  
4114 _SNMPSetTxOffset(errorStatusOffset);
4115 _SNMPPut((BYTE)errorStatus);
4116  
4117 _SNMPSetTxOffset(errorIndexOffset);
4118 _SNMPPut(errorIndex);
4119  
4120 _SNMPSetTxOffset(prevOffset);
4121 }
4122  
4123  
4124 /****************************************************************************
4125 Function:
4126 BYTE FindOIDsInRequest(WORD pdulen)
4127  
4128 Summary:
4129 Finds number of varbinds in the varbind list received in a pdu.
4130  
4131 Description:
4132 This routine is used to find the number of OIDs requested in the received
4133 snmp pdu.
4134  
4135 Precondition :
4136 ProcessVariables() is called.
4137  
4138 Parameters:
4139 pdulen - Length of snmp pdu request received.
4140  
4141 Return Values:
4142 varCount - Number of OIDs found in a pdu request.
4143  
4144 Remarks:
4145 None.
4146 ***************************************************************************/
4147 static BYTE FindOIDsInRequest(WORD pdulen)
4148 {
4149 BYTE varCount=0;
4150 WORD prevUDPRxOffset;
4151 WORD varBindLen;
4152 WORD snmpPduLen;
4153  
4154 snmpPduLen=pdulen;
4155  
4156 prevUDPRxOffset=SNMPRxOffset;
4157  
4158 while(snmpPduLen)
4159 {
4160  
4161 if(!IsValidStructure(&varBindLen))
4162 return FALSE;
4163  
4164 SNMPRxOffset=SNMPRxOffset+varBindLen;
4165 varCount++;
4166 snmpPduLen=snmpPduLen
4167 -1 //1 byte for STRUCTURE identifier
4168 -1//1 byte for varbind length
4169 -varBindLen;
4170 }
4171  
4172 SNMPRxOffset=prevUDPRxOffset;
4173  
4174 return varCount;
4175 }
4176  
4177 /****************************************************************************
4178 Function:
4179 BOOL SNMPCheckIfPvtMibObjRequested(BYTE* OIDValuePtr)
4180  
4181 Summary:
4182 To find whether requested OID is only for private access.
4183  
4184 Description:
4185 This routine is used to find whether requested object belongs
4186 to the private object group of the mib of agent. If yes, then
4187 that mib object can be accessed only with private community
4188 (supported in SNMPv2c).
4189  
4190 Precondition :
4191 ProcessVariables() is called.
4192  
4193 Parameters:
4194 OIDValuePtr - Pointer to memory stored with received OID.
4195  
4196 Return Values:
4197 TRUE - If the requested object is of private branch of the mib.
4198 FLASE - If the requested object is publically accessible.
4199  
4200 Remarks:
4201 None.
4202 ***************************************************************************/
4203 static BOOL SNMPCheckIfPvtMibObjRequested(BYTE* OIDValuePtr)
4204 {
4205 BYTE cnt=0;
4206 BYTE pvtObjIdentifier[4]={0x2b,0x06/*dod*/,0x01/*internet*/,0x04/*private*/};
4207  
4208 while(cnt<4u)
4209 {
4210 //check whether requested oid is for pvt obj
4211 if(pvtObjIdentifier[cnt]== OIDValuePtr[cnt])
4212 {
4213 cnt++;
4214 }
4215 else
4216 {
4217 cnt=0;
4218 return FALSE;
4219 }
4220 if(cnt == 0x04u)
4221 return TRUE;
4222 }
4223 return FALSE;
4224  
4225 }
4226  
4227  
4228 #endif
4229  
4230 #endif //#if defined(STACK_USE_SNMP_SERVER)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3