snmp_agent.c
Go to the documentation of this file.
1 /**
2  * @file snmp_agent.c
3  * @brief SNMP agent (Simple Network Management Protocol)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * SNMP is a simple protocol by which management information for a network
30  * element may be inspected or altered by logically remote users. Refer
31  * to the following RFCs for complete details:
32  * - RFC 1157: A Simple Network Management Protocol (SNMP)
33  * - RFC 1905: Protocol Operations for Version 2 of the Simple Network
34  * Management Protocol (SNMPv2)
35  * - RFC 3410: Introduction and Applicability Statements for Internet
36  * Standard Management Framework
37  * - RFC 3411: An Architecture for Describing SNMP Management Frameworks
38  * - RFC 3412: Message Processing and Dispatching for the SNMP
39  * - RFC 3413: Simple Network Management Protocol (SNMP) Applications
40  * - RFC 3584: Coexistence between Version 1, Version 2, and Version 3 of
41  * SNMP Framework
42  *
43  * @author Oryx Embedded SARL (www.oryx-embedded.com)
44  * @version 2.6.0
45  **/
46 
47 //Switch to the appropriate trace level
48 #define TRACE_LEVEL SNMP_TRACE_LEVEL
49 
50 //Dependencies
51 #include "core/net.h"
52 #include "snmp/snmp_agent.h"
54 #include "snmp/snmp_agent_pdu.h"
55 #include "snmp/snmp_agent_misc.h"
56 #include "snmp/snmp_agent_trap.h"
57 #include "snmp/snmp_agent_inform.h"
58 #include "mibs/mib2_module.h"
59 #include "core/crypto.h"
60 #include "encoding/asn1.h"
61 #include "encoding/oid.h"
62 #include "debug.h"
63 
64 //Check TCP/IP stack configuration
65 #if (SNMP_AGENT_SUPPORT == ENABLED)
66 
67 
68 /**
69  * @brief Initialize settings with default values
70  * @param[out] settings Structure that contains SNMP agent settings
71  **/
72 
74 {
75  //Default task parameters
76  settings->task = OS_TASK_DEFAULT_PARAMS;
78  settings->task.priority = SNMP_AGENT_PRIORITY;
79 
80  //TCP/IP stack context
81  settings->netContext = NULL;
82  //The SNMP agent is not bound to any interface
83  settings->interface = NULL;
84 
85  //Minimum version accepted by the SNMP agent
86  settings->versionMin = SNMP_VERSION_1;
87  //Maximum version accepted by the SNMP agent
88  settings->versionMax = SNMP_VERSION_3;
89 
90  //SNMP port number
91  settings->port = SNMP_PORT;
92  //SNMP trap port number
93  settings->trapPort = SNMP_TRAP_PORT;
94 
95  //Random data generation callback function
96  settings->randCallback = NULL;
97 }
98 
99 
100 /**
101  * @brief SNMP agent initialization
102  * @param[in] context Pointer to the SNMP agent context
103  * @param[in] settings SNMP agent specific settings
104  * @return Error code
105  **/
106 
108  const SnmpAgentSettings *settings)
109 {
110  error_t error;
111 
112  //Debug message
113  TRACE_INFO("Initializing SNMP agent...\r\n");
114 
115  //Ensure the parameters are valid
116  if(context == NULL || settings == NULL)
118 
119  //Check minimum and maximum SNMP versions
120  if(settings->versionMin > settings->versionMax)
122 
123  //Clear the SNMP agent context
124  osMemset(context, 0, sizeof(SnmpAgentContext));
125 
126  //Initialize task parameters
127  context->taskParams = settings->task;
128  context->taskId = OS_INVALID_TASK_ID;
129 
130  //Attach TCP/IP stack context
131  if(settings->netContext != NULL)
132  {
133  context->netContext = settings->netContext;
134  }
135  else if(settings->interface != NULL)
136  {
137  context->netContext = settings->interface->netContext;
138  }
139  else
140  {
141  context->netContext = netGetDefaultContext();
142  }
143 
144  //Save user settings
145  context->interface = settings->interface;
146  context->versionMin = settings->versionMin;
147  context->versionMax = settings->versionMax;
148  context->port = settings->port;
149  context->trapPort = settings->trapPort;
150  context->randCallback = settings->randCallback;
151 
152  //Initialize request identifier
153  context->requestId = netGetRandRange(context->netContext, 1, INT32_MAX);
154 
155  //Start of exception handling block
156  do
157  {
158  //Create a mutex to prevent simultaneous access to SNMP agent context
159  if(!osCreateMutex(&context->mutex))
160  {
161  //Failed to create mutex
162  error = ERROR_OUT_OF_RESOURCES;
163  break;
164  }
165 
166  //Create an event object to poll the state of the UDP socket
167  if(!osCreateEvent(&context->event))
168  {
169  //Failed to create event
170  error = ERROR_OUT_OF_RESOURCES;
171  break;
172  }
173 
174 #if (SNMP_AGENT_INFORM_SUPPORT == ENABLED)
175  //Create an event object to manage inform request retransmissions
176  if(!osCreateEvent(&context->informEvent))
177  {
178  //Failed to create event
179  error = ERROR_OUT_OF_RESOURCES;
180  break;
181  }
182 #endif
183 
184 #if (SNMP_V3_SUPPORT == ENABLED)
185  //Get current time
186  context->systemTime = osGetSystemTime();
187 
188  //Each SNMP engine maintains 2 values, snmpEngineBoots and snmpEngineTime,
189  //which taken together provide an indication of time at that SNMP engine
190  context->engineBoots = 1;
191  context->engineTime = 0;
192 
193  //Initialize message identifier
194  context->msgId = netGetRandRange(context->netContext, 1, INT32_MAX);
195 
196  //Check whether SNMPv3 is supported
197  if(settings->versionMin <= SNMP_VERSION_3 &&
198  settings->versionMax >= SNMP_VERSION_3)
199  {
200  //Make sure a random number generator has been registered
201  if(settings->randCallback == NULL)
202  {
203  //Report en error
204  error = ERROR_INVALID_PARAMETER;
205  break;
206  }
207 
208  //The salt integer is initialized to an arbitrary value at boot time
209  error = settings->randCallback(context->salt, sizeof(context->salt));
210  //Any error to report?
211  if(error)
212  break;
213  }
214 #endif
215 
216  //Successful initialization
217  error = NO_ERROR;
218 
219  //End of exception handling block
220  } while(0);
221 
222  //Any error to report?
223  if(error)
224  {
225  //Clean up side effects
226  snmpAgentDeinit(context);
227  }
228 
229  //Return status code
230  return error;
231 }
232 
233 
234 /**
235  * @brief Start SNMP agent
236  * @param[in] context Pointer to the SNMP agent context
237  * @return Error code
238  **/
239 
241 {
242  error_t error;
243 
244  //Make sure the SNMP agent context is valid
245  if(context == NULL)
247 
248  //Debug message
249  TRACE_INFO("Starting SNMP agent...\r\n");
250 
251  //Make sure the SNMP agent is not already running
252  if(context->running)
253  return ERROR_ALREADY_RUNNING;
254 
255  //Start of exception handling block
256  do
257  {
258  //Open a UDP socket
259  context->socket = socketOpenEx(context->netContext, SOCKET_TYPE_DGRAM,
261  //Failed to open socket?
262  if(context->socket == NULL)
263  {
264  //Report an error
265  error = ERROR_OPEN_FAILED;
266  break;
267  }
268 
269  //Force the socket to operate in non-blocking mode
270  error = socketSetTimeout(context->socket, 0);
271  //Any error to report?
272  if(error)
273  break;
274 
275  //Associate the socket with the relevant interface
276  error = socketBindToInterface(context->socket, context->interface);
277  //Unable to bind the socket to the desired interface?
278  if(error)
279  break;
280 
281  //The SNMP agent listens for messages on port 161
282  error = socketBind(context->socket, &IP_ADDR_ANY, context->port);
283  //Unable to bind the socket to the desired port?
284  if(error)
285  break;
286 
287  //Start the SNMP agent
288  context->stop = FALSE;
289  context->running = TRUE;
290 
291  //Create a task
292  context->taskId = osCreateTask("SNMP Agent", (OsTaskCode) snmpAgentTask,
293  context, &context->taskParams);
294 
295  //Failed to create task?
296  if(context->taskId == OS_INVALID_TASK_ID)
297  {
298  //Report an error
299  error = ERROR_OUT_OF_RESOURCES;
300  break;
301  }
302 
303  //End of exception handling block
304  } while(0);
305 
306  //Any error to report?
307  if(error)
308  {
309  //Clean up side effects
310  context->running = FALSE;
311 
312  //Close the UDP socket
313  socketClose(context->socket);
314  context->socket = NULL;
315  }
316 
317  //Return status code
318  return error;
319 }
320 
321 
322 /**
323  * @brief Stop SNMP agent
324  * @param[in] context Pointer to the SNMP agent context
325  * @return Error code
326  **/
327 
329 {
330  //Make sure the SNMP agent context is valid
331  if(context == NULL)
333 
334  //Debug message
335  TRACE_INFO("Stopping SNMP agent...\r\n");
336 
337  //Check whether the SNMP agent is running
338  if(context->running)
339  {
340 #if (NET_RTOS_SUPPORT == ENABLED)
341  //Stop the SNMP agent
342  context->stop = TRUE;
343  //Send a signal to the task to abort any blocking operation
344  osSetEvent(&context->event);
345 
346  //Wait for the task to terminate
347  while(context->running)
348  {
349  osDelayTask(1);
350  }
351 #endif
352 
353  //Close the UDP socket
354  socketClose(context->socket);
355  context->socket = NULL;
356  }
357 
358  //Successful processing
359  return NO_ERROR;
360 }
361 
362 
363 /**
364  * @brief Load a MIB module
365  * @param[in] context Pointer to the SNMP agent context
366  * @param[in] module Pointer the MIB module to be loaded
367  * @return Error code
368  **/
369 
371 {
372  error_t error;
373  uint_t i;
374 
375  //Check parameters
376  if(context == NULL || module == NULL)
378  if(module->numObjects < 1)
380 
381  //Acquire exclusive access to the SNMP agent context
382  osAcquireMutex(&context->mutex);
383 
384  //Loop through existing MIBs
385  for(i = 0; i < SNMP_AGENT_MAX_MIBS; i++)
386  {
387  //Check whether the specified MIB module is already loaded
388  if(context->mibTable[i] == module)
389  break;
390  }
391 
392  //MIB module found?
393  if(i < SNMP_AGENT_MAX_MIBS)
394  {
395  //Prevent the SNMP agent from loading the same MIB multiple times
396  error = NO_ERROR;
397  }
398  else
399  {
400  //Loop through existing MIBs
401  for(i = 0; i < SNMP_AGENT_MAX_MIBS; i++)
402  {
403  //Check if the current entry is available
404  if(context->mibTable[i] == NULL)
405  break;
406  }
407 
408  //Make sure there is enough room to add the specified MIB
409  if(i < SNMP_AGENT_MAX_MIBS)
410  {
411  //Invoke user callback, if any
412  if(module->load != NULL)
413  {
414  error = module->load(context);
415  }
416  else
417  {
418  error = NO_ERROR;
419  }
420 
421  //Check status code
422  if(!error)
423  {
424  //Add the MIB to the list
425  context->mibTable[i] = module;
426  }
427  }
428  else
429  {
430  //Failed to load the specified MIB
431  error = ERROR_OUT_OF_RESOURCES;
432  }
433  }
434 
435  //Release exclusive access to the SNMP agent context
436  osReleaseMutex(&context->mutex);
437 
438  //Return status code
439  return error;
440 }
441 
442 
443 /**
444  * @brief Unload a MIB module
445  * @param[in] context Pointer to the SNMP agent context
446  * @param[in] module Pointer the MIB module to be unloaded
447  * @return Error code
448  **/
449 
451 {
452  error_t error;
453  uint_t i;
454 
455  //Check parameters
456  if(context == NULL || module == NULL)
458 
459  //Acquire exclusive access to the SNMP agent context
460  osAcquireMutex(&context->mutex);
461 
462  //Loop through existing MIBs
463  for(i = 0; i < SNMP_AGENT_MAX_MIBS; i++)
464  {
465  //Check whether the specified MIB module is already loaded
466  if(context->mibTable[i] == module)
467  break;
468  }
469 
470  //MIB module found?
471  if(i < SNMP_AGENT_MAX_MIBS)
472  {
473  //Any registered callback?
474  if(context->mibTable[i]->unload != NULL)
475  {
476  //Invoke user callback function
477  context->mibTable[i]->unload(context);
478  }
479 
480  //Remove the MIB from the list
481  context->mibTable[i] = NULL;
482 
483  //Successful processing
484  error = NO_ERROR;
485  }
486  else
487  {
488  //Failed to unload the specified MIB
489  error = ERROR_NOT_FOUND;
490  }
491 
492  //Release exclusive access to the SNMP agent context
493  osReleaseMutex(&context->mutex);
494 
495  //Return status code
496  return error;
497 }
498 
499 
500 /**
501  * @brief Set minimum and maximum versions permitted
502  * @param[in] context Pointer to the SNMP agent context
503  * @param[in] versionMin Minimum version accepted by the SNMP agent
504  * @param[in] versionMax Maximum version accepted by the SNMP agent
505  * @return Error code
506  **/
507 
509  SnmpVersion versionMin, SnmpVersion versionMax)
510 {
511  //Check parameters
512  if(context == NULL)
514  if(versionMin > versionMax)
516 
517  //Acquire exclusive access to the SNMP agent context
518  osAcquireMutex(&context->mutex);
519 
520  //Set minimum and maximum versions permitted
521  context->versionMin = versionMin;
522  context->versionMax = versionMax;
523 
524  //Release exclusive access to the SNMP agent context
525  osReleaseMutex(&context->mutex);
526 
527  //Successful processing
528  return NO_ERROR;
529 }
530 
531 
532 /**
533  * @brief Set the value of the snmpEngineBoots variable
534  * @param[in] context Pointer to the SNMP agent context
535  * @param[in] engineBoots Number of times the SNMP engine has re-booted
536  * @return Error code
537  **/
538 
539 error_t snmpAgentSetEngineBoots(SnmpAgentContext *context, int32_t engineBoots)
540 {
541 #if (SNMP_V3_SUPPORT == ENABLED)
542  //Check parameters
543  if(context == NULL)
545  if(engineBoots < 0)
546  return ERROR_OUT_OF_RANGE;
547 
548  //Acquire exclusive access to the SNMP agent context
549  osAcquireMutex(&context->mutex);
550 
551  //Get current time
552  context->systemTime = osGetSystemTime();
553 
554  //Set the value of the snmpEngineBoots
555  context->engineBoots = engineBoots;
556  //The snmpEngineTime is reset to zero
557  context->engineTime = 0;
558 
559  //Release exclusive access to the SNMP agent context
560  osReleaseMutex(&context->mutex);
561 
562  //Successful processing
563  return NO_ERROR;
564 #else
565  //Not implemented
566  return ERROR_NOT_IMPLEMENTED;
567 #endif
568 }
569 
570 
571 /**
572  * @brief Get the value of the snmpEngineBoots variable
573  * @param[in] context Pointer to the SNMP agent context
574  * @param[out] engineBoots Number of times the SNMP engine has re-booted
575  * @return Error code
576  **/
577 
578 error_t snmpAgentGetEngineBoots(SnmpAgentContext *context, int32_t *engineBoots)
579 {
580 #if (SNMP_V3_SUPPORT == ENABLED)
581  //Check parameters
582  if(context == NULL || engineBoots == NULL)
584 
585  //Acquire exclusive access to the SNMP agent context
586  osAcquireMutex(&context->mutex);
587  //Get the current value of the snmpEngineBoots
588  *engineBoots = context->engineBoots;
589  //Release exclusive access to the SNMP agent context
590  osReleaseMutex(&context->mutex);
591 
592  //Successful processing
593  return NO_ERROR;
594 #else
595  //Not implemented
596  return ERROR_NOT_IMPLEMENTED;
597 #endif
598 }
599 
600 
601 /**
602  * @brief Set enterprise OID
603  * @param[in] context Pointer to the SNMP agent context
604  * @param[in] enterpriseOid Pointer to the enterprise OID
605  * @param[in] enterpriseOidLen Length of the enterprise OID
606  * @return Error code
607  **/
608 
610  const uint8_t *enterpriseOid, size_t enterpriseOidLen)
611 {
612  //Check parameters
613  if(context == NULL || enterpriseOid == NULL)
615  if(enterpriseOidLen > SNMP_MAX_OID_SIZE)
617 
618  //Acquire exclusive access to the SNMP agent context
619  osAcquireMutex(&context->mutex);
620 
621  //Set enterprise OID
622  osMemcpy(context->enterpriseOid, enterpriseOid, enterpriseOidLen);
623  //Save the length of the enterprise OID
624  context->enterpriseOidLen = enterpriseOidLen;
625 
626  //Release exclusive access to the SNMP agent context
627  osReleaseMutex(&context->mutex);
628 
629  //Successful processing
630  return NO_ERROR;
631 }
632 
633 
634 /**
635  * @brief Set context engine identifier
636  * @param[in] context Pointer to the SNMP agent context
637  * @param[in] contextEngine Pointer to the context engine identifier
638  * @param[in] contextEngineLen Length of the context engine identifier
639  * @return Error code
640  **/
641 
643  const void *contextEngine, size_t contextEngineLen)
644 {
645 #if (SNMP_V3_SUPPORT == ENABLED)
646  //Check parameters
647  if(context == NULL || contextEngine == NULL)
649  if(contextEngineLen > SNMP_MAX_CONTEXT_ENGINE_SIZE)
651 
652  //Acquire exclusive access to the SNMP agent context
653  osAcquireMutex(&context->mutex);
654 
655  //Set context engine identifier
656  osMemcpy(context->contextEngine, contextEngine, contextEngineLen);
657  //Save the length of the context engine identifier
658  context->contextEngineLen = contextEngineLen;
659 
660  //Release exclusive access to the SNMP agent context
661  osReleaseMutex(&context->mutex);
662 
663  //Successful processing
664  return NO_ERROR;
665 #else
666  //Not implemented
667  return ERROR_NOT_IMPLEMENTED;
668 #endif
669 }
670 
671 
672 /**
673  * @brief Set context name
674  * @param[in] context Pointer to the SNMP agent context
675  * @param[in] contextName NULL-terminated string that contains the context name
676  * @return Error code
677  **/
678 
680  const char_t *contextName)
681 {
682 #if (SNMP_V3_SUPPORT == ENABLED)
683  size_t n;
684 
685  //Check parameters
686  if(context == NULL || contextName == NULL)
688 
689  //Retrieve the length of the context name
690  n = osStrlen(contextName);
691 
692  //Make sure the context name is valid
694  return ERROR_INVALID_LENGTH;
695 
696  //Acquire exclusive access to the SNMP agent context
697  osAcquireMutex(&context->mutex);
698  //Set context name
699  osStrcpy(context->contextName, contextName);
700  //Release exclusive access to the SNMP agent context
701  osReleaseMutex(&context->mutex);
702 
703  //Successful processing
704  return NO_ERROR;
705 #else
706  //Not implemented
707  return ERROR_NOT_IMPLEMENTED;
708 #endif
709 }
710 
711 
712 /**
713  * @brief Create a new community string
714  * @param[in] context Pointer to the SNMP agent context
715  * @param[in] community NULL-terminated string that contains the community name
716  * @param[in] mode Access rights
717  * @return Error code
718  **/
719 
721  const char_t *community, SnmpAccess mode)
722 {
723 #if (SNMP_V1_SUPPORT == ENABLED || SNMP_V2C_SUPPORT == ENABLED)
724  error_t error;
725  size_t n;
726  SnmpUserEntry *entry;
727 
728  //Check parameters
729  if(context == NULL || community == NULL)
731 
732  //Retrieve the length of the community string
733  n = osStrlen(community);
734 
735  //Make sure the community string is valid
736  if(n == 0 || n > SNMP_MAX_USER_NAME_LEN)
737  return ERROR_INVALID_LENGTH;
738 
739  //Acquire exclusive access to the SNMP agent context
740  osAcquireMutex(&context->mutex);
741 
742  //Check whether the community string already exists
743  entry = snmpFindCommunityEntry(context, community, osStrlen(community));
744 
745  //If the specified community string does not exist, then a new entry
746  //should be created
747  if(entry == NULL)
748  {
749  //Create a new entry
750  entry = snmpCreateCommunityEntry(context);
751  }
752 
753  //Any entry available?
754  if(entry != NULL)
755  {
756  //Clear the contents
757  osMemset(entry, 0, sizeof(SnmpUserEntry));
758 
759  //Save community string
760  osStrcpy(entry->name, community);
761  //Set access rights
762  entry->mode = mode;
763  //The entry is now available for use
764  entry->status = MIB_ROW_STATUS_ACTIVE;
765 
766  //Successful processing
767  error = NO_ERROR;
768  }
769  else
770  {
771  //The table runs out of space
772  error = ERROR_OUT_OF_RESOURCES;
773  }
774 
775  //Release exclusive access to the SNMP agent context
776  osReleaseMutex(&context->mutex);
777 
778  //Return error code
779  return error;
780 #else
781  //Not implemented
782  return ERROR_NOT_IMPLEMENTED;
783 #endif
784 }
785 
786 
787 /**
788  * @brief Remove a community string
789  * @param[in] context Pointer to the SNMP agent context
790  * @param[in] community NULL-terminated string that contains the community name
791  * @return Error code
792  **/
793 
795 {
796 #if (SNMP_V1_SUPPORT == ENABLED || SNMP_V2C_SUPPORT == ENABLED)
797  error_t error;
798  SnmpUserEntry *entry;
799 
800  //Check parameters
801  if(context == NULL || community == NULL)
803 
804  //Acquire exclusive access to the SNMP agent context
805  osAcquireMutex(&context->mutex);
806 
807  //Search the community table for the specified community string
808  entry = snmpFindCommunityEntry(context, community, osStrlen(community));
809 
810  //Any matching entry found?
811  if(entry != NULL)
812  {
813  //Clear the contents
814  osMemset(entry, 0, sizeof(SnmpUserEntry));
815  //Now mark the entry as free
816  entry->status = MIB_ROW_STATUS_UNUSED;
817 
818  //Successful processing
819  error = NO_ERROR;
820  }
821  else
822  {
823  //The specified community string does not exist
824  error = ERROR_NOT_FOUND;
825  }
826 
827  //Release exclusive access to the SNMP agent context
828  osReleaseMutex(&context->mutex);
829 
830  //Return status code
831  return error;
832 #else
833  //Not implemented
834  return ERROR_NOT_IMPLEMENTED;
835 #endif
836 }
837 
838 
839 /**
840  * @brief Create a new user
841  * @param[in] context Pointer to the SNMP agent context
842  * @param[in] userName NULL-terminated string that contains the user name
843  * @param[in] mode Access rights
844  * @param[in] keyFormat Key format (ASCII password or raw key)
845  * @param[in] authProtocol Authentication type
846  * @param[in] authKey Key to be used for data authentication
847  * @param[in] privProtocol Privacy type
848  * @param[in] privKey Key to be used for data encryption
849  * @return Error code
850  **/
851 
853  const char_t *userName, SnmpAccess mode, SnmpKeyFormat keyFormat,
854  SnmpAuthProtocol authProtocol, const void *authKey,
855  SnmpPrivProtocol privProtocol, const void *privKey)
856 {
857 #if (SNMP_V3_SUPPORT == ENABLED)
858  error_t error;
859  size_t n;
860  SnmpUserEntry *entry;
861 
862  //Check parameters
863  if(context == NULL || userName == NULL)
865 
866  //Data authentication?
867  if(authProtocol != SNMP_AUTH_PROTOCOL_NONE)
868  {
869  //Check key format
870  if(keyFormat != SNMP_KEY_FORMAT_TEXT &&
871  keyFormat != SNMP_KEY_FORMAT_RAW &&
872  keyFormat != SNMP_KEY_FORMAT_LOCALIZED)
873  {
875  }
876 
877  //Data authentication requires a key
878  if(authKey == NULL)
880  }
881 
882  //Data confidentiality?
883  if(privProtocol != SNMP_PRIV_PROTOCOL_NONE)
884  {
885  //Check key format
886  if(keyFormat != SNMP_KEY_FORMAT_TEXT && keyFormat != SNMP_KEY_FORMAT_RAW)
888 
889  //Data confidentiality requires a key
890  if(privKey == NULL)
892 
893  //There is no provision for data confidentiality without data authentication
894  if(authProtocol == SNMP_AUTH_PROTOCOL_NONE)
896  }
897 
898  //Retrieve the length of the user name
899  n = osStrlen(userName);
900 
901  //Make sure the user name is valid
902  if(n == 0 || n > SNMP_MAX_USER_NAME_LEN)
903  return ERROR_INVALID_LENGTH;
904 
905  //Acquire exclusive access to the SNMP agent context
906  osAcquireMutex(&context->mutex);
907 
908  //Check whether the user name already exists
909  entry = snmpFindUserEntry(context, userName, osStrlen(userName));
910 
911  //If the specified user name does not exist, then a new entry
912  //should be created
913  if(entry == NULL)
914  {
915  //Create a security profile for the new user
916  entry = snmpCreateUserEntry(context);
917  }
918 
919  //Any entry available?
920  if(entry != NULL)
921  {
922  //Clear the security profile of the user
923  osMemset(entry, 0, sizeof(SnmpUserEntry));
924 
925  //Save user name
926  osStrcpy(entry->name, userName);
927  //Access rights
928  entry->mode = mode;
929  //Authentication protocol
930  entry->authProtocol = authProtocol;
931  //Privacy protocol
932  entry->privProtocol = privProtocol;
933 
934  //Initialize status code
935  error = NO_ERROR;
936 
937  //Data authentication?
938  if(authProtocol != SNMP_AUTH_PROTOCOL_NONE)
939  {
940  //ASCII password or raw key?
941  if(keyFormat == SNMP_KEY_FORMAT_TEXT)
942  {
943  //Generate the authentication key from the provided password
944  error = snmpGenerateKey(authProtocol, authKey, &entry->rawAuthKey);
945 
946  //Check status code
947  if(!error)
948  {
949  //Localize the key with the engine ID
950  error = snmpLocalizeKey(authProtocol,
951  context->contextEngine, context->contextEngineLen,
952  &entry->rawAuthKey, &entry->localizedAuthKey);
953  }
954  }
955  else if(keyFormat == SNMP_KEY_FORMAT_RAW)
956  {
957  //Save the authentication key
958  osMemcpy(&entry->rawAuthKey, authKey, sizeof(SnmpKey));
959 
960  //Now localize the key with the engine ID
961  error = snmpLocalizeKey(authProtocol,
962  context->contextEngine, context->contextEngineLen,
963  &entry->rawAuthKey, &entry->localizedAuthKey);
964  }
965  else
966  {
967  //The authentication key is already localized
968  osMemcpy(&entry->localizedAuthKey, authKey, sizeof(SnmpKey));
969  }
970  }
971 
972  //Check status code
973  if(!error)
974  {
975  //Data confidentiality?
976  if(privProtocol != SNMP_PRIV_PROTOCOL_NONE)
977  {
978  //ASCII password or raw key?
979  if(keyFormat == SNMP_KEY_FORMAT_TEXT)
980  {
981  //Generate the privacy key from the provided password
982  error = snmpGenerateKey(authProtocol, privKey, &entry->rawPrivKey);
983 
984  //Check status code
985  if(!error)
986  {
987  //Localize the key with the engine ID
988  error = snmpLocalizeKey(authProtocol,
989  context->contextEngine, context->contextEngineLen,
990  &entry->rawPrivKey, &entry->localizedPrivKey);
991  }
992  }
993  else if(keyFormat == SNMP_KEY_FORMAT_RAW)
994  {
995  //Save the privacy key
996  osMemcpy(&entry->rawPrivKey, privKey, sizeof(SnmpKey));
997 
998  //Now localize the key with the engine ID
999  error = snmpLocalizeKey(authProtocol,
1000  context->contextEngine, context->contextEngineLen,
1001  &entry->rawPrivKey, &entry->localizedPrivKey);
1002  }
1003  else
1004  {
1005  //The privacy key is already localized
1006  osMemcpy(&entry->localizedPrivKey, privKey, sizeof(SnmpKey));
1007  }
1008  }
1009  }
1010 
1011  //Check status code
1012  if(!error)
1013  {
1014  //The entry is now available for use
1015  entry->status = MIB_ROW_STATUS_ACTIVE;
1016  }
1017  else
1018  {
1019  //Clean up side effects
1020  osMemset(entry, 0, sizeof(SnmpUserEntry));
1021  //Now mark the entry as free
1022  entry->status = MIB_ROW_STATUS_UNUSED;
1023  }
1024  }
1025  else
1026  {
1027  //The user table runs out of space
1028  error = ERROR_OUT_OF_RESOURCES;
1029  }
1030 
1031  //Release exclusive access to the SNMP agent context
1032  osReleaseMutex(&context->mutex);
1033 
1034  //Return error code
1035  return error;
1036 #else
1037  //Not implemented
1038  return ERROR_NOT_IMPLEMENTED;
1039 #endif
1040 }
1041 
1042 
1043 /**
1044  * @brief Remove existing user
1045  * @param[in] context Pointer to the SNMP agent context
1046  * @param[in] userName NULL-terminated string that contains the user name
1047  * @return Error code
1048  **/
1049 
1051 {
1052 #if (SNMP_V3_SUPPORT == ENABLED)
1053  error_t error;
1054  SnmpUserEntry *entry;
1055 
1056  //Check parameters
1057  if(context == NULL || userName == NULL)
1058  return ERROR_INVALID_PARAMETER;
1059 
1060  //Acquire exclusive access to the SNMP agent context
1061  osAcquireMutex(&context->mutex);
1062 
1063  //Search the user table for the specified user name
1064  entry = snmpFindUserEntry(context, userName, osStrlen(userName));
1065 
1066  //Any matching entry found?
1067  if(entry != NULL)
1068  {
1069  //Clear the security profile of the user
1070  osMemset(entry, 0, sizeof(SnmpUserEntry));
1071  //Now mark the entry as free
1072  entry->status = MIB_ROW_STATUS_UNUSED;
1073 
1074  //Successful processing
1075  error = NO_ERROR;
1076  }
1077  else
1078  {
1079  //The specified user name does not exist
1080  error = ERROR_NOT_FOUND;
1081  }
1082 
1083  //Release exclusive access to the SNMP agent context
1084  osReleaseMutex(&context->mutex);
1085 
1086  //Return status code
1087  return error;
1088 #else
1089  //Not implemented
1090  return ERROR_NOT_IMPLEMENTED;
1091 #endif
1092 }
1093 
1094 
1095 /**
1096  * @brief Join a group of users
1097  * @param[in] context Pointer to the SNMP agent context
1098  * @param[in] userName NULL-terminated string that contains the user name
1099  * @param[in] securityModel Security model
1100  * @param[in] groupName NULL-terminated string that contains the group name
1101  * @return Error code
1102  **/
1103 
1105  SnmpSecurityModel securityModel, const char_t *groupName)
1106 {
1107 #if (SNMP_AGENT_VACM_SUPPORT == ENABLED)
1108  error_t error;
1109  size_t n;
1110  SnmpGroupEntry *entry;
1111 
1112  //Check parameters
1113  if(context == NULL || userName == NULL || groupName == NULL)
1114  return ERROR_INVALID_PARAMETER;
1115 
1116  //Check security model
1117  if(securityModel != SNMP_SECURITY_MODEL_V1 &&
1118  securityModel != SNMP_SECURITY_MODEL_V2C &&
1119  securityModel != SNMP_SECURITY_MODEL_USM)
1120  {
1121  return ERROR_INVALID_PARAMETER;
1122  }
1123 
1124  //Retrieve the length of the user name
1125  n = osStrlen(userName);
1126 
1127  //Make sure the user name is valid
1128  if(n == 0 || n > SNMP_MAX_USER_NAME_LEN)
1129  return ERROR_INVALID_LENGTH;
1130 
1131  //Retrieve the length of the group name
1132  n = osStrlen(groupName);
1133 
1134  //Make sure the group name is valid
1135  if(n == 0 || n > SNMP_MAX_GROUP_NAME_LEN)
1136  return ERROR_INVALID_LENGTH;
1137 
1138  //Acquire exclusive access to the SNMP agent context
1139  osAcquireMutex(&context->mutex);
1140 
1141  //Search the group table for a matching entry
1142  entry = snmpFindGroupEntry(context, securityModel, userName,
1143  osStrlen(userName));
1144 
1145  //No matching entry found?
1146  if(entry == NULL)
1147  {
1148  //Create a new entry in the group table
1149  entry = snmpCreateGroupEntry(context);
1150  }
1151 
1152  //Any entry available?
1153  if(entry != NULL)
1154  {
1155  //Clear entry
1156  osMemset(entry, 0, sizeof(SnmpGroupEntry));
1157 
1158  //Save security model
1159  entry->securityModel = securityModel;
1160  //Save user name
1161  osStrcpy(entry->securityName, userName);
1162  //Save group name
1163  osStrcpy(entry->groupName, groupName);
1164 
1165  //The entry is now available for use
1166  entry->status = MIB_ROW_STATUS_ACTIVE;
1167 
1168  //Successful processing
1169  error = NO_ERROR;
1170  }
1171  else
1172  {
1173  //The group table runs out of space
1174  error = ERROR_OUT_OF_RESOURCES;
1175  }
1176 
1177  //Release exclusive access to the SNMP agent context
1178  osReleaseMutex(&context->mutex);
1179 
1180  //Return status code
1181  return error;
1182 #else
1183  //Not implemented
1184  return ERROR_NOT_IMPLEMENTED;
1185 #endif
1186 }
1187 
1188 
1189 /**
1190  * @brief Leave a group of users
1191  * @param[in] context Pointer to the SNMP agent context
1192  * @param[in] userName NULL-terminated string that contains the user name
1193  * @param[in] securityModel Security model
1194  * @return Error code
1195  **/
1196 
1198  const char_t *userName, SnmpSecurityModel securityModel)
1199 {
1200 #if (SNMP_AGENT_VACM_SUPPORT == ENABLED)
1201  error_t error;
1202  SnmpGroupEntry *entry;
1203 
1204  //Check parameters
1205  if(context == NULL || userName == NULL)
1206  return ERROR_INVALID_PARAMETER;
1207 
1208  //Acquire exclusive access to the SNMP agent context
1209  osAcquireMutex(&context->mutex);
1210 
1211  //Search the group table for a matching entry
1212  entry = snmpFindGroupEntry(context, securityModel, userName,
1213  osStrlen(userName));
1214 
1215  //Any matching entry found?
1216  if(entry != NULL)
1217  {
1218  //Clear the entry
1219  osMemset(entry, 0, sizeof(SnmpGroupEntry));
1220  //Now mark the entry as free
1221  entry->status = MIB_ROW_STATUS_UNUSED;
1222 
1223  //Successful processing
1224  error = NO_ERROR;
1225  }
1226  else
1227  {
1228  //The specified entry does not exist
1229  error = ERROR_NOT_FOUND;
1230  }
1231 
1232  //Release exclusive access to the SNMP agent context
1233  osReleaseMutex(&context->mutex);
1234 
1235  //Return status code
1236  return error;
1237 #else
1238  //Not implemented
1239  return ERROR_NOT_IMPLEMENTED;
1240 #endif
1241 }
1242 
1243 
1244 /**
1245  * @brief Create access policy for the specified group name
1246  * @param[in] context Pointer to the SNMP agent context
1247  * @param[in] groupName NULL-terminated string that contains the group name
1248  * @param[in] securityModel Security model
1249  * @param[in] securityLevel Security level
1250  * @param[in] contextPrefix NULL-terminated string that contains the context name prefix
1251  * @param[in] contextMatch Context match
1252  * @param[in] readViewName NULL-terminated string that contains the read view name
1253  * @param[in] writeViewName NULL-terminated string that contains the write view name
1254  * @param[in] notifyViewName NULL-terminated string that contains the notify view name
1255  * @return Error code
1256  **/
1257 
1259  const char_t *groupName, SnmpSecurityModel securityModel,
1260  SnmpSecurityLevel securityLevel, const char_t *contextPrefix,
1261  SnmpContextMatch contextMatch, const char_t *readViewName,
1262  const char_t *writeViewName, const char_t *notifyViewName)
1263 {
1264 #if (SNMP_AGENT_VACM_SUPPORT == ENABLED)
1265  error_t error;
1266  size_t n;
1267  SnmpAccessEntry *entry;
1268 
1269  //Check parameters
1270  if(context == NULL || groupName == NULL || contextPrefix == NULL)
1271  return ERROR_INVALID_PARAMETER;
1272  if(readViewName == NULL || writeViewName == NULL || notifyViewName == NULL)
1273  return ERROR_INVALID_PARAMETER;
1274 
1275  //Check security model
1276  if(securityModel != SNMP_SECURITY_MODEL_ANY &&
1277  securityModel != SNMP_SECURITY_MODEL_V1 &&
1278  securityModel != SNMP_SECURITY_MODEL_V2C &&
1279  securityModel != SNMP_SECURITY_MODEL_USM)
1280  {
1281  return ERROR_INVALID_PARAMETER;
1282  }
1283 
1284  //Check security level
1285  if(securityLevel != SNMP_SECURITY_LEVEL_NO_AUTH_NO_PRIV &&
1286  securityLevel != SNMP_SECURITY_LEVEL_AUTH_NO_PRIV &&
1287  securityLevel != SNMP_SECURITY_LEVEL_AUTH_PRIV)
1288  {
1289  return ERROR_INVALID_PARAMETER;
1290  }
1291 
1292  //Check context match
1293  if(contextMatch != SNMP_CONTEXT_MATCH_EXACT &&
1294  contextMatch != SNMP_CONTEXT_MATCH_PREFIX)
1295  {
1296  return ERROR_INVALID_PARAMETER;
1297  }
1298 
1299  //Retrieve the length of the group name
1300  n = osStrlen(groupName);
1301 
1302  //Make sure the group name is valid
1303  if(n == 0 || n > SNMP_MAX_GROUP_NAME_LEN)
1304  return ERROR_INVALID_LENGTH;
1305 
1306  //Make sure the context name prefix is valid
1308  return ERROR_INVALID_LENGTH;
1309 
1310  //Make sure the read view name is valid
1311  if(osStrlen(readViewName) > SNMP_MAX_VIEW_NAME_LEN)
1312  return ERROR_INVALID_LENGTH;
1313 
1314  //Make sure the write view name is valid
1315  if(osStrlen(writeViewName) > SNMP_MAX_VIEW_NAME_LEN)
1316  return ERROR_INVALID_LENGTH;
1317 
1318  //Make sure the notify view name is valid
1319  if(osStrlen(notifyViewName) > SNMP_MAX_VIEW_NAME_LEN)
1320  return ERROR_INVALID_LENGTH;
1321 
1322  //Acquire exclusive access to the SNMP agent context
1323  osAcquireMutex(&context->mutex);
1324 
1325  //Search the access table for a matching entry
1326  entry = snmpFindAccessEntry(context, groupName, contextPrefix,
1327  securityModel, securityLevel);
1328 
1329  //No matching entry found?
1330  if(entry == NULL)
1331  {
1332  //Create a new entry in the access table
1333  entry = snmpCreateAccessEntry(context);
1334  }
1335 
1336  //Any entry available?
1337  if(entry != NULL)
1338  {
1339  //Clear entry
1340  osMemset(entry, 0, sizeof(SnmpAccessEntry));
1341 
1342  //Save group name
1343  osStrcpy(entry->groupName, groupName);
1344  //Save context name prefix
1346  //Save security model
1347  entry->securityModel = securityModel;
1348  //Save security level
1349  entry->securityLevel = securityLevel;
1350  //Save context match
1351  entry->contextMatch = contextMatch;
1352  //Save read view name
1353  osStrcpy(entry->readViewName, readViewName);
1354  //Save write view name
1355  osStrcpy(entry->writeViewName, writeViewName);
1356  //Save notify view name
1357  osStrcpy(entry->notifyViewName, notifyViewName);
1358 
1359  //The entry is now available for use
1360  entry->status = MIB_ROW_STATUS_ACTIVE;
1361 
1362  //Successful processing
1363  error = NO_ERROR;
1364  }
1365  else
1366  {
1367  //The access table runs out of space
1368  error = ERROR_OUT_OF_RESOURCES;
1369  }
1370 
1371  //Release exclusive access to the SNMP agent context
1372  osReleaseMutex(&context->mutex);
1373 
1374  //Return status code
1375  return error;
1376 #else
1377  //Not implemented
1378  return ERROR_NOT_IMPLEMENTED;
1379 #endif
1380 }
1381 
1382 
1383 /**
1384  * @brief Delete an existing access policy
1385  * @param[in] context Pointer to the SNMP agent context
1386  * @param[in] groupName NULL-terminated string that contains the group name
1387  * @param[in] securityModel Security model
1388  * @param[in] securityLevel Security level
1389  * @param[in] contextPrefix NULL-terminated string that contains the context name prefix
1390  * @return Error code
1391  **/
1392 
1394  const char_t *groupName, SnmpSecurityModel securityModel,
1395  SnmpSecurityLevel securityLevel, const char_t *contextPrefix)
1396 {
1397 #if (SNMP_AGENT_VACM_SUPPORT == ENABLED)
1398  error_t error;
1399  SnmpAccessEntry *entry;
1400 
1401  //Check parameters
1402  if(context == NULL || groupName == NULL || contextPrefix == NULL)
1403  return ERROR_INVALID_PARAMETER;
1404 
1405  //Acquire exclusive access to the SNMP agent context
1406  osAcquireMutex(&context->mutex);
1407 
1408  //Search the access table for a matching entry
1409  entry = snmpFindAccessEntry(context, groupName, contextPrefix,
1410  securityModel, securityLevel);
1411 
1412  //Any matching entry found?
1413  if(entry != NULL)
1414  {
1415  //Clear the entry
1416  osMemset(entry, 0, sizeof(SnmpAccessEntry));
1417  //Now mark the entry as free
1418  entry->status = MIB_ROW_STATUS_UNUSED;
1419 
1420  //Successful processing
1421  error = NO_ERROR;
1422  }
1423  else
1424  {
1425  //The specified entry does not exist
1426  error = ERROR_NOT_FOUND;
1427  }
1428 
1429  //Release exclusive access to the SNMP agent context
1430  osReleaseMutex(&context->mutex);
1431 
1432  //Return status code
1433  return error;
1434 #else
1435  //Not implemented
1436  return ERROR_NOT_IMPLEMENTED;
1437 #endif
1438 }
1439 
1440 
1441 /**
1442  * @brief Create a new MIB view
1443  * @param[in] context Pointer to the SNMP agent context
1444  * @param[in] viewName NULL-terminated string that contains the view name
1445  * @param[in] subtree Pointer to the subtree
1446  * @param[in] subtreeLen Length of the subtree, in bytes
1447  * @param[in] mask Pointer to the bit mask
1448  * @param[in] maskLen Length of the bit mask
1449  * @param[in] type View type
1450  * @return Error code
1451  **/
1452 
1454  const char_t *viewName, const uint8_t *subtree, size_t subtreeLen,
1455  const uint8_t *mask, size_t maskLen, SnmpViewType type)
1456 {
1457 #if (SNMP_AGENT_VACM_SUPPORT == ENABLED)
1458  error_t error;
1459  size_t n;
1460  SnmpViewEntry *entry;
1461 
1462  //Check parameters
1463  if(context == NULL || viewName == NULL || subtree == NULL)
1464  return ERROR_INVALID_PARAMETER;
1465 
1466  //Check view type
1467  if(type != SNMP_VIEW_TYPE_INCLUDED &&
1469  {
1470  return ERROR_INVALID_PARAMETER;
1471  }
1472 
1473  //Retrieve the length of the view name
1474  n = osStrlen(viewName);
1475 
1476  //Make sure the view name is valid
1477  if(n == 0 || n > SNMP_MAX_VIEW_NAME_LEN)
1478  return ERROR_INVALID_LENGTH;
1479 
1480  //Make sure the subtree is valid
1481  if(subtreeLen == 0 || subtreeLen > MIB_MAX_OID_SIZE)
1482  return ERROR_INVALID_PARAMETER;
1483 
1484  //Make sure the bit mask is valid
1485  if(maskLen > 0 && mask == NULL)
1486  return ERROR_INVALID_PARAMETER;
1487  if(maskLen > SNMP_MAX_BIT_MASK_SIZE)
1488  return ERROR_INVALID_PARAMETER;
1489 
1490  //Acquire exclusive access to the SNMP agent context
1491  osAcquireMutex(&context->mutex);
1492 
1493  //Search the view table for a matching entry
1494  entry = snmpFindViewEntry(context, viewName, subtree, subtreeLen);
1495 
1496  //No matching entry found?
1497  if(entry == NULL)
1498  {
1499  //Create a new entry in the view table
1500  entry = snmpCreateViewEntry(context);
1501  }
1502 
1503  //Any entry available?
1504  if(entry != NULL)
1505  {
1506  //Clear entry
1507  osMemset(entry, 0, sizeof(SnmpViewEntry));
1508 
1509  //Save view name
1510  osStrcpy(entry->viewName, viewName);
1511  //Save subtree
1512  osMemcpy(entry->subtree, subtree, subtreeLen);
1513  //Save the length of the subtree
1514  entry->subtreeLen = subtreeLen;
1515  //Save bit mask
1516  osMemcpy(entry->mask, mask, maskLen);
1517  //Save the length of the bit mask
1518  entry->maskLen = maskLen;
1519  //Save type
1520  entry->type = type;
1521 
1522  //The entry is now available for use
1523  entry->status = MIB_ROW_STATUS_ACTIVE;
1524 
1525  //Successful processing
1526  error = NO_ERROR;
1527  }
1528  else
1529  {
1530  //The view table runs out of space
1531  error = ERROR_OUT_OF_RESOURCES;
1532  }
1533 
1534  //Release exclusive access to the SNMP agent context
1535  osReleaseMutex(&context->mutex);
1536 
1537  //Return status code
1538  return error;
1539 #else
1540  //Not implemented
1541  return ERROR_NOT_IMPLEMENTED;
1542 #endif
1543 }
1544 
1545 
1546 /**
1547  * @brief Delete an existing MIB view
1548  * @param[in] context Pointer to the SNMP agent context
1549  * @param[in] viewName NULL-terminated string that contains the view name
1550  * @param[in] subtree Pointer to the subtree
1551  * @param[in] subtreeLen Length of the subtree, in bytes
1552  * @return Error code
1553  **/
1554 
1556  const char_t *viewName, const uint8_t *subtree, size_t subtreeLen)
1557 {
1558 #if (SNMP_AGENT_VACM_SUPPORT == ENABLED)
1559  error_t error;
1560  SnmpViewEntry *entry;
1561 
1562  //Check parameters
1563  if(context == NULL || viewName == NULL || subtree == NULL)
1564  return ERROR_INVALID_PARAMETER;
1565 
1566  //Acquire exclusive access to the SNMP agent context
1567  osAcquireMutex(&context->mutex);
1568 
1569  //Search the view table for a matching entry
1570  entry = snmpFindViewEntry(context, viewName, subtree, subtreeLen);
1571 
1572  //Any matching entry found?
1573  if(entry != NULL)
1574  {
1575  //Clear the entry
1576  osMemset(entry, 0, sizeof(SnmpViewEntry));
1577  //Now mark the entry as free
1578  entry->status = MIB_ROW_STATUS_UNUSED;
1579 
1580  //Successful processing
1581  error = NO_ERROR;
1582  }
1583  else
1584  {
1585  //The specified entry does not exist
1586  error = ERROR_NOT_FOUND;
1587  }
1588 
1589  //Release exclusive access to the SNMP agent context
1590  osReleaseMutex(&context->mutex);
1591 
1592  //Return status code
1593  return error;
1594 #else
1595  //Not implemented
1596  return ERROR_NOT_IMPLEMENTED;
1597 #endif
1598 }
1599 
1600 
1601 /**
1602  * @brief Send SNMP trap notification
1603  * @param[in] context Pointer to the SNMP agent context
1604  * @param[in] destIpAddr Destination IP address
1605  * @param[in] version SNMP version identifier
1606  * @param[in] userName User name or community name
1607  * @param[in] genericTrapType Generic trap type
1608  * @param[in] specificTrapCode Specific code
1609  * @param[in] objectList List of object names
1610  * @param[in] objectListSize Number of entries in the list
1611  * @return Error code
1612  **/
1613 
1615  const IpAddr *destIpAddr, SnmpVersion version, const char_t *userName,
1616  uint_t genericTrapType, uint_t specificTrapCode,
1617  const SnmpTrapObject *objectList, uint_t objectListSize)
1618 {
1619 #if (SNMP_AGENT_TRAP_SUPPORT == ENABLED)
1620  error_t error;
1621 
1622  //Check parameters
1623  if(context == NULL || destIpAddr == NULL || userName == NULL)
1624  return ERROR_INVALID_PARAMETER;
1625 
1626  //Make sure the list of objects is valid
1627  if(objectListSize > 0 && objectList == NULL)
1628  return ERROR_INVALID_PARAMETER;
1629 
1630  //Acquire exclusive access to the SNMP agent context
1631  osAcquireMutex(&context->mutex);
1632 
1633 #if (SNMP_V3_SUPPORT == ENABLED)
1634  //Refresh SNMP engine time
1635  snmpRefreshEngineTime(context);
1636 #endif
1637 
1638  //Format Trap message
1639  error = snmpFormatTrapMessage(context, version, userName,
1640  genericTrapType, specificTrapCode, objectList, objectListSize);
1641 
1642  //Check status code
1643  if(!error)
1644  {
1645  //Total number of messages which were passed from the SNMP protocol
1646  //entity to the transport service
1647  MIB2_SNMP_INC_COUNTER32(snmpOutPkts, 1);
1648 
1649  //Debug message
1650  TRACE_INFO("Sending SNMP message to %s port %" PRIu16 " (%" PRIuSIZE " bytes)...\r\n",
1651  ipAddrToString(destIpAddr, NULL), context->trapPort,
1652  context->response.length);
1653 
1654  //Display the contents of the SNMP message
1655  TRACE_DEBUG_ARRAY(" ", context->response.pos, context->response.length);
1656  //Display ASN.1 structure
1657  asn1DumpObject(context->response.pos, context->response.length, 0);
1658 
1659  //Send SNMP message
1660  error = socketSendTo(context->socket, destIpAddr, context->trapPort,
1661  context->response.pos, context->response.length, NULL, 0);
1662  }
1663 
1664  //Release exclusive access to the SNMP agent context
1665  osReleaseMutex(&context->mutex);
1666 
1667  //Return status code
1668  return error;
1669 #else
1670  //Not implemented
1671  return ERROR_NOT_IMPLEMENTED;
1672 #endif
1673 }
1674 
1675 
1676 /**
1677  * @brief Send SNMP inform request
1678  * @param[in] context Pointer to the SNMP agent context
1679  * @param[in] destIpAddr Destination IP address
1680  * @param[in] version SNMP version identifier
1681  * @param[in] userName User name or community name
1682  * @param[in] genericTrapType Generic trap type
1683  * @param[in] specificTrapCode Specific code
1684  * @param[in] objectList List of object names
1685  * @param[in] objectListSize Number of entries in the list
1686  * @return Error code
1687  **/
1688 
1690  const IpAddr *destIpAddr, SnmpVersion version, const char_t *userName,
1691  uint_t genericTrapType, uint_t specificTrapCode,
1692  const SnmpTrapObject *objectList, uint_t objectListSize)
1693 {
1694 #if (SNMP_AGENT_INFORM_SUPPORT == ENABLED)
1695  error_t error;
1696  bool_t status;
1697 
1698  //Check parameters
1699  if(context == NULL || destIpAddr == NULL || userName == NULL)
1700  return ERROR_INVALID_PARAMETER;
1701 
1702  //Make sure the list of objects is valid
1703  if(objectListSize > 0 && objectList == NULL)
1704  return ERROR_INVALID_PARAMETER;
1705 
1706  //Initialize status code
1707  error = NO_ERROR;
1708 
1709  //Acquire exclusive access to the SNMP agent context
1710  osAcquireMutex(&context->mutex);
1711 
1712  //Send an inform request and wait for the acknowledgment to be received
1713  while(!error)
1714  {
1715  //Check current state
1716  if(context->informState == SNMP_AGENT_STATE_IDLE)
1717  {
1718  //Reset event object
1719  osResetEvent(&context->informEvent);
1720  //Initialize retransmission counter
1721  context->informRetransmitCount = 0;
1722 
1723 #if (SNMP_V3_SUPPORT == ENABLED)
1724  //SNMPv3 version?
1725  if(version == SNMP_VERSION_3)
1726  {
1727  //The User-based Security Model (USM) of SNMPv3 provides a mechanism
1728  //to discover the snmpEngineID of the remote SNMP engine
1729  context->informContextEngineLen = 0;
1730  context->informEngineBoots = 0;
1731  context->informEngineTime = 0;
1732 
1733  //Perform discovery process
1734  context->informState = SNMP_AGENT_STATE_SENDING_GET_REQ;
1735  }
1736  else
1737 #endif
1738  //SNMPv2c version?
1739  {
1740  //Send an inform request message
1741  context->informState = SNMP_AGENT_STATE_SENDING_INFORM_REQ;
1742  }
1743  }
1744 #if (SNMP_V3_SUPPORT == ENABLED)
1745  else if(context->informState == SNMP_AGENT_STATE_SENDING_GET_REQ)
1746  {
1747  //Format GetRequest message
1748  error = snmpFormatGetRequestMessage(context, version);
1749 
1750  //Check status
1751  if(!error)
1752  {
1753  //Total number of messages which were passed from the SNMP protocol
1754  //entity to the transport service
1755  MIB2_SNMP_INC_COUNTER32(snmpOutPkts, 1);
1756 
1757  //Debug message
1758  TRACE_INFO("Sending SNMP message to %s port %" PRIu16 " (%" PRIuSIZE " bytes)...\r\n",
1759  ipAddrToString(destIpAddr, NULL), context->trapPort,
1760  context->response.length);
1761 
1762  //Display the contents of the SNMP message
1763  TRACE_DEBUG_ARRAY(" ", context->response.pos, context->response.length);
1764  //Display ASN.1 structure
1765  asn1DumpObject(context->response.pos, context->response.length, 0);
1766 
1767  //Send SNMP message
1768  error = socketSendTo(context->socket, destIpAddr, context->trapPort,
1769  context->response.pos, context->response.length, NULL, 0);
1770  }
1771 
1772  //Check status code
1773  if(!error)
1774  {
1775  //Save the time at which the GetResponse-PDU was sent
1776  context->informTimestamp = osGetSystemTime();
1777  //Increment retransmission counter
1778  context->informRetransmitCount++;
1779  //Wait for an Report-PDU to be received
1780  context->informState = SNMP_AGENT_STATE_WAITING_REPORT;
1781  }
1782  else
1783  {
1784  //Back to default state
1785  context->informState = SNMP_AGENT_STATE_IDLE;
1786  }
1787  }
1788  else if(context->informState == SNMP_AGENT_STATE_WAITING_REPORT)
1789  {
1790  //Release exclusive access to the SNMP agent context
1791  osReleaseMutex(&context->mutex);
1792 
1793  //Wait for a matching Report-PDU to be received
1794  status = osWaitForEvent(&context->informEvent,
1796 
1797  //Acquire exclusive access to the SNMP agent context
1798  osAcquireMutex(&context->mutex);
1799 
1800  //Any Report-PDU received?
1801  if(status && context->informContextEngineLen > 0)
1802  {
1803  //Reset event object
1804  osResetEvent(&context->informEvent);
1805  //Initialize retransmission counter
1806  context->informRetransmitCount = 0;
1807  //Send an inform request message
1808  context->informState = SNMP_AGENT_STATE_SENDING_INFORM_REQ;
1809  }
1810  else
1811  {
1812 #if (NET_RTOS_SUPPORT == DISABLED)
1813  //Get current time
1815 
1816  //Check current time
1817  if(timeCompare(time, context->informTimestamp + SNMP_AGENT_INFORM_TIMEOUT) < 0)
1818  {
1819  //Exit immediately
1820  error = ERROR_WOULD_BLOCK;
1821  }
1822  else
1823 #endif
1824  {
1825  //The request should be retransmitted if no corresponding response
1826  //is received in an appropriate time interval
1827  if(context->informRetransmitCount < SNMP_AGENT_INFORM_MAX_RETRIES)
1828  {
1829  //Retransmit the request
1830  context->informState = SNMP_AGENT_STATE_SENDING_GET_REQ;
1831  }
1832  else
1833  {
1834  //Back to default state
1835  context->informState = SNMP_AGENT_STATE_IDLE;
1836  //Report a timeout error
1837  error = ERROR_TIMEOUT;
1838  }
1839  }
1840  }
1841  }
1842 #endif
1843  else if(context->informState == SNMP_AGENT_STATE_SENDING_INFORM_REQ)
1844  {
1845  //Format InformRequest message
1846  error = snmpFormatInformRequestMessage(context, version, userName,
1847  genericTrapType, specificTrapCode, objectList, objectListSize);
1848 
1849  //Check status code
1850  if(!error)
1851  {
1852  //Total number of messages which were passed from the SNMP protocol
1853  //entity to the transport service
1854  MIB2_SNMP_INC_COUNTER32(snmpOutPkts, 1);
1855 
1856  //Debug message
1857  TRACE_INFO("Sending SNMP message to %s port %" PRIu16 " (%" PRIuSIZE " bytes)...\r\n",
1858  ipAddrToString(destIpAddr, NULL), context->trapPort,
1859  context->response.length);
1860 
1861  //Display the contents of the SNMP message
1862  TRACE_DEBUG_ARRAY(" ", context->response.pos, context->response.length);
1863  //Display ASN.1 structure
1864  asn1DumpObject(context->response.pos, context->response.length, 0);
1865 
1866  //Send SNMP message
1867  error = socketSendTo(context->socket, destIpAddr, context->trapPort,
1868  context->response.pos, context->response.length, NULL, 0);
1869  }
1870 
1871  //Check status code
1872  if(!error)
1873  {
1874  //Save the time at which the InformRequest-PDU was sent
1875  context->informTimestamp = osGetSystemTime();
1876  //Increment retransmission counter
1877  context->informRetransmitCount++;
1878  //Wait for a GetResponse-PDU to be received
1879  context->informState = SNMP_AGENT_STATE_WAITING_GET_RESP;
1880  }
1881  else
1882  {
1883  //Back to default state
1884  context->informState = SNMP_AGENT_STATE_IDLE;
1885  }
1886  }
1887  else if(context->informState == SNMP_AGENT_STATE_WAITING_GET_RESP)
1888  {
1889  //Release exclusive access to the SNMP agent context
1890  osReleaseMutex(&context->mutex);
1891 
1892  //Wait for a matching GetResponse-PDU to be received
1893  status = osWaitForEvent(&context->informEvent,
1895 
1896  //Acquire exclusive access to the SNMP agent context
1897  osAcquireMutex(&context->mutex);
1898 
1899  //Any GetResponse-PDU received?
1900  if(status)
1901  {
1902  //Back to default state
1903  context->informState = SNMP_AGENT_STATE_IDLE;
1904  //The inform request has been acknowledged
1905  error = NO_ERROR;
1906  //We are done
1907  break;
1908  }
1909  else
1910  {
1911 #if (NET_RTOS_SUPPORT == DISABLED)
1912  //Get current time
1914 
1915  //Check current time
1916  if(timeCompare(time, context->informTimestamp + SNMP_AGENT_INFORM_TIMEOUT) < 0)
1917  {
1918  //Exit immediately
1919  error = ERROR_WOULD_BLOCK;
1920  }
1921  else
1922 #endif
1923  {
1924  //The request should be retransmitted if no corresponding response
1925  //is received in an appropriate time interval
1926  if(context->informRetransmitCount < SNMP_AGENT_INFORM_MAX_RETRIES)
1927  {
1928  //Retransmit the request
1929  context->informState = SNMP_AGENT_STATE_SENDING_INFORM_REQ;
1930  }
1931  else
1932  {
1933  //Back to default state
1934  context->informState = SNMP_AGENT_STATE_IDLE;
1935  //Report a timeout error
1936  error = ERROR_TIMEOUT;
1937  }
1938  }
1939  }
1940  }
1941  else
1942  {
1943  //Back to default state
1944  context->informState = SNMP_AGENT_STATE_IDLE;
1945  //Report an error
1946  error = ERROR_WRONG_STATE;
1947  }
1948  }
1949 
1950  //Release exclusive access to the SNMP agent context
1951  osReleaseMutex(&context->mutex);
1952 
1953  //Return status code
1954  return error;
1955 #else
1956  //Not implemented
1957  return ERROR_NOT_IMPLEMENTED;
1958 #endif
1959 }
1960 
1961 
1962 /**
1963  * @brief SNMP agent task
1964  * @param[in] context Pointer to the SNMP agent context
1965  **/
1966 
1968 {
1969  error_t error;
1970  SocketMsg msg;
1971  SocketEventDesc eventDesc;
1972 
1973 #if (NET_RTOS_SUPPORT == ENABLED)
1974  //Task prologue
1975  osEnterTask();
1976 
1977  //Main loop
1978  while(1)
1979  {
1980 #endif
1981  //Specify the events the application is interested in
1982  eventDesc.socket = context->socket;
1983  eventDesc.eventMask = SOCKET_EVENT_RX_READY;
1984  eventDesc.eventFlags = 0;
1985 
1986  //Wait for an event
1987  socketPoll(&eventDesc, 1, &context->event, INFINITE_DELAY);
1988 
1989  //Stop request?
1990  if(context->stop)
1991  {
1992  //Stop SNMP agent operation
1993  context->running = FALSE;
1994  //Task epilogue
1995  osExitTask();
1996  //Kill ourselves
1998  }
1999 
2000  //Any datagram received?
2001  if(eventDesc.eventFlags != 0)
2002  {
2003  //Point to the receive buffer
2004  msg = SOCKET_DEFAULT_MSG;
2005  msg.data = context->request.buffer;
2006  msg.size = SNMP_MAX_MSG_SIZE;
2007 
2008  //Receive incoming datagram
2009  error = socketReceiveMsg(context->socket, &msg, 0);
2010 
2011  //Check status code
2012  if(!error)
2013  {
2014  //Make sure the destination IP address is a valid unicast address
2015  if(!ipIsMulticastAddr(&msg.destIpAddr))
2016  {
2017  //Acquire exclusive access to the SNMP agent context
2018  osAcquireMutex(&context->mutex);
2019 
2020  //Retrieve the length of the datagram
2021  context->request.bufferLen = msg.length;
2022 
2023  //Get the source and destination IP addresses
2024  context->localInterface = msg.interface;
2025  context->localIpAddr = msg.destIpAddr;
2026  context->remoteIpAddr = msg.srcIpAddr;
2027  context->remotePort = msg.srcPort;
2028 
2029  //Debug message
2030  TRACE_INFO("\r\nSNMP message received from %s port %" PRIu16
2031  " (%" PRIuSIZE " bytes)...\r\n",
2032  ipAddrToString(&context->remoteIpAddr, NULL),
2033  context->remotePort, context->request.bufferLen);
2034 
2035  //Display the contents of the SNMP message
2036  TRACE_DEBUG_ARRAY(" ", context->request.buffer,
2037  context->request.bufferLen);
2038  //Dump ASN.1 structure
2039  asn1DumpObject(context->request.buffer,
2040  context->request.bufferLen, 0);
2041 
2042  //Process incoming SNMP message
2043  error = snmpProcessMessage(context);
2044 
2045  //Check status code
2046  if(!error)
2047  {
2048  //Any response?
2049  if(context->response.length > 0)
2050  {
2051  //Debug message
2052  TRACE_INFO("Sending SNMP message to %s port %" PRIu16
2053  " (%" PRIuSIZE " bytes)...\r\n",
2054  ipAddrToString(&context->remoteIpAddr, NULL),
2055  context->remotePort, context->response.length);
2056 
2057  //Display the contents of the SNMP message
2058  TRACE_DEBUG_ARRAY(" ", context->response.pos,
2059  context->response.length);
2060  //Display ASN.1 structure
2061  asn1DumpObject(context->response.pos,
2062  context->response.length, 0);
2063 
2064  //Point to the send buffer
2065  msg = SOCKET_DEFAULT_MSG;
2066  msg.data = context->response.pos;
2067  msg.length = context->response.length;
2068 
2069  //Set the source and destination IP addresses
2070  msg.interface = context->localInterface;
2071  msg.srcIpAddr = context->localIpAddr;
2072  msg.destIpAddr = context->remoteIpAddr;
2073  msg.destPort = context->remotePort;
2074 
2075  //Send SNMP response message
2076  socketSendMsg(context->socket, &msg, 0);
2077  }
2078  }
2079 
2080  //Release exclusive access to the SNMP agent context
2081  osReleaseMutex(&context->mutex);
2082  }
2083  }
2084  }
2085 #if (NET_RTOS_SUPPORT == ENABLED)
2086  }
2087 #endif
2088 }
2089 
2090 
2091 /**
2092  * @brief Release SNMP agent context
2093  * @param[in] context Pointer to the SNMP agent context
2094  **/
2095 
2097 {
2098  //Make sure the SNMP agent context is valid
2099  if(context != NULL)
2100  {
2101  //Free previously allocated resources
2102  osDeleteMutex(&context->mutex);
2103  osDeleteEvent(&context->event);
2104 
2105 #if (SNMP_AGENT_INFORM_SUPPORT == ENABLED)
2106  osDeleteEvent(&context->informEvent);
2107 #endif
2108 
2109  //Clear SNMP agent context
2110  osMemset(context, 0, sizeof(SnmpAgentContext));
2111  }
2112 }
2113 
2114 #endif
uint8_t subtree[SNMP_MAX_OID_SIZE]
char_t writeViewName[SNMP_MAX_VIEW_NAME_LEN+1]
@ SNMP_SECURITY_MODEL_ANY
Any.
MIB-II module.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
@ SOCKET_IP_PROTO_UDP
Definition: socket.h:108
@ SNMP_SECURITY_MODEL_V1
SNMPv1.
SnmpVersion versionMax
Maximum version accepted by the SNMP agent.
Definition: snmp_agent.h:137
SnmpSecurityModel securityModel
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:1344
@ SNMP_KEY_FORMAT_LOCALIZED
Localized key.
MibLoad load
Definition: mib_common.h:299
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
@ ERROR_OUT_OF_RANGE
Definition: error.h:138
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
error_t snmpAgentDeleteView(SnmpAgentContext *context, const char_t *viewName, const uint8_t *subtree, size_t subtreeLen)
Delete an existing MIB view.
Definition: snmp_agent.c:1555
SnmpViewEntry * snmpCreateViewEntry(SnmpAgentContext *context)
Create a new view entry.
#define osExitTask()
#define SNMP_MAX_VIEW_NAME_LEN
Definition: snmp_common.h:102
@ ERROR_WOULD_BLOCK
Definition: error.h:96
SnmpUserEntry * snmpFindCommunityEntry(SnmpAgentContext *context, const char_t *community, size_t length)
Search the community table for a given community string.
SnmpKey localizedPrivKey
Localized privacy key.
IP network address.
Definition: ip.h:90
SnmpSecurityModel
Security models.
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
error_t snmpAgentInit(SnmpAgentContext *context, const SnmpAgentSettings *settings)
SNMP agent initialization.
Definition: snmp_agent.c:107
error_t snmpAgentSetVersion(SnmpAgentContext *context, SnmpVersion versionMin, SnmpVersion versionMax)
Set minimum and maximum versions permitted.
Definition: snmp_agent.c:508
SnmpAccess mode
Access mode.
error_t snmpAgentSetContextName(SnmpAgentContext *context, const char_t *contextName)
Set context name.
Definition: snmp_agent.c:679
OID (Object Identifier)
uint32_t netGetRandRange(NetContext *context, uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net.c:473
char_t contextPrefix[SNMP_MAX_CONTEXT_NAME_LEN+1]
@ SNMP_CONTEXT_MATCH_PREFIX
OsTaskParameters task
Task parameters.
Definition: snmp_agent.h:133
SnmpContextMatch
Context match.
#define TRUE
Definition: os_port.h:50
char_t groupName[SNMP_MAX_GROUP_NAME_LEN+1]
Message and ancillary data.
Definition: socket.h:241
#define OS_INVALID_TASK_ID
error_t snmpAgentCreateCommunity(SnmpAgentContext *context, const char_t *community, SnmpAccess mode)
Create a new community string.
Definition: snmp_agent.c:720
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2094
size_t subtreeLen
SnmpKeyFormat
SNMP key format.
#define SNMP_AGENT_PRIORITY
Definition: snmp_agent.h:64
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
char_t * ipAddrToString(const IpAddr *ipAddr, char_t *str)
Convert a binary IP address to a string representation.
Definition: ip.c:810
@ SNMP_CONTEXT_MATCH_EXACT
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
Object descriptor for trap notifications.
@ SNMP_AGENT_STATE_WAITING_REPORT
void * data
Pointer to the payload.
Definition: socket.h:242
uint8_t type
Definition: coap_common.h:176
error_t asn1DumpObject(const uint8_t *data, size_t length, uint_t level)
Display an ASN.1 data object.
Definition: asn1.c:999
SnmpGroupEntry * snmpFindGroupEntry(SnmpAgentContext *context, uint_t securityModel, const char_t *securityName, size_t securityNameLen)
Search the group table.
#define SNMP_AGENT_INFORM_MAX_RETRIES
SnmpGroupEntry * snmpCreateGroupEntry(SnmpAgentContext *context)
Create a new group entry.
@ SNMP_SECURITY_MODEL_USM
User-based security model.
char_t securityName[SNMP_MAX_GROUP_NAME_LEN+1]
#define SNMP_AGENT_MAX_MIBS
Definition: snmp_agent.h:69
#define SNMP_MAX_GROUP_NAME_LEN
Definition: snmp_common.h:95
#define osStrlen(s)
Definition: os_port.h:168
SNMP trap notifications.
uint8_t version
Definition: coap_common.h:177
SnmpAccessEntry * snmpCreateAccessEntry(SnmpAgentContext *context)
Create a new access entry.
User table entry.
char_t groupName[SNMP_MAX_GROUP_NAME_LEN+1]
#define OS_SELF_TASK_ID
#define timeCompare(t1, t2)
Definition: os_port.h:40
SnmpViewType
View type.
Structure describing socket events.
Definition: socket.h:433
size_t maskLen
#define SNMP_AGENT_INFORM_TIMEOUT
SnmpUserEntry * snmpCreateCommunityEntry(SnmpAgentContext *context)
Create a new community entry.
SNMP agent (Simple Network Management Protocol)
@ ERROR_WRONG_STATE
Definition: error.h:210
SnmpVersion
SNMP version identifiers.
Definition: snmp_common.h:137
error_t snmpAgentSetContextEngine(SnmpAgentContext *context, const void *contextEngine, size_t contextEngineLen)
Set context engine identifier.
Definition: snmp_agent.c:642
uint16_t trapPort
SNMP trap port number.
Definition: snmp_agent.h:139
@ ERROR_OPEN_FAILED
Definition: error.h:75
@ SNMP_AGENT_STATE_SENDING_INFORM_REQ
char_t readViewName[SNMP_MAX_VIEW_NAME_LEN+1]
uint16_t destPort
Destination port.
Definition: socket.h:252
SnmpUserEntry * snmpCreateUserEntry(SnmpAgentContext *context)
Create a new user entry.
error_t snmpAgentDeleteAccess(SnmpAgentContext *context, const char_t *groupName, SnmpSecurityModel securityModel, SnmpSecurityLevel securityLevel, const char_t *contextPrefix)
Delete an existing access policy.
Definition: snmp_agent.c:1393
const IpAddr IP_ADDR_ANY
Definition: ip.c:53
error_t snmpAgentStart(SnmpAgentContext *context)
Start SNMP agent.
Definition: snmp_agent.c:240
error_t socketSendMsg(Socket *socket, const SocketMsg *message, uint_t flags)
Send a message to a connectionless socket.
Definition: socket.c:1666
void osDeleteTask(OsTaskId taskId)
Delete a task.
NetInterface * interface
Underlying network interface.
Definition: socket.h:248
SnmpKey localizedAuthKey
Localized authentication key.
#define SNMP_MAX_CONTEXT_NAME_LEN
Definition: snmp_common.h:74
#define FALSE
Definition: os_port.h:46
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:52
uint_t numObjects
Definition: mib_common.h:297
size_t length
Actual length of the payload, in bytes.
Definition: socket.h:244
error_t snmpAgentLeaveGroup(SnmpAgentContext *context, const char_t *userName, SnmpSecurityModel securityModel)
Leave a group of users.
Definition: snmp_agent.c:1197
error_t snmpAgentLoadMib(SnmpAgentContext *context, const MibModule *module)
Load a MIB module.
Definition: snmp_agent.c:370
char_t notifyViewName[SNMP_MAX_VIEW_NAME_LEN+1]
error_t snmpAgentDeleteUser(SnmpAgentContext *context, const char_t *userName)
Remove existing user.
Definition: snmp_agent.c:1050
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
SNMP inform notifications.
@ SNMP_PRIV_PROTOCOL_NONE
No privacy.
error_t
Error codes.
Definition: error.h:43
bool_t ipIsMulticastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a multicast address.
Definition: ip.c:251
#define MIB_MAX_OID_SIZE
Definition: mib_common.h:39
#define SNMP_MAX_USER_NAME_LEN
Definition: snmp_common.h:81
#define MIB2_SNMP_INC_COUNTER32(name, value)
Definition: mib2_module.h:169
void(* OsTaskCode)(void *arg)
Task routine.
SnmpContextMatch contextMatch
error_t snmpFormatInformRequestMessage(SnmpAgentContext *context, SnmpVersion version, const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Format SNMP InformRequest message.
@ SNMP_AGENT_STATE_WAITING_GET_RESP
SnmpViewType type
SnmpUserEntry * snmpFindUserEntry(SnmpAgentContext *context, const char_t *name, size_t length)
Search the user table for a given user name.
SnmpPrivProtocol
@ SNMP_KEY_FORMAT_TEXT
ASCII password.
#define SNMP_TRAP_PORT
Definition: snmp_common.h:124
error_t snmpProcessMessage(SnmpAgentContext *context)
Process incoming SNMP message.
@ SNMP_VIEW_TYPE_INCLUDED
void osDeleteEvent(OsEvent *event)
Delete an event object.
@ SNMP_SECURITY_LEVEL_NO_AUTH_NO_PRIV
#define SNMP_MAX_BIT_MASK_SIZE
Definition: snmp_common.h:109
MibRowStatus status
IpAddr srcIpAddr
Source IP address.
Definition: socket.h:249
#define SNMP_MAX_OID_SIZE
Definition: snmp_common.h:116
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ MIB_ROW_STATUS_UNUSED
Definition: mib_common.h:102
General definitions for cryptographic algorithms.
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1926
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
SnmpViewEntry * snmpFindViewEntry(SnmpAgentContext *context, const char_t *viewName, const uint8_t *subtree, size_t subtreeLen)
Search the view table for a given entry.
uint8_t mask
Definition: web_socket.h:319
Helper functions for SNMP agent.
error_t snmpAgentJoinGroup(SnmpAgentContext *context, const char_t *userName, SnmpSecurityModel securityModel, const char_t *groupName)
Join a group of users.
Definition: snmp_agent.c:1104
@ SNMP_AGENT_STATE_IDLE
error_t snmpAgentSendTrap(SnmpAgentContext *context, const IpAddr *destIpAddr, SnmpVersion version, const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Send SNMP trap notification.
Definition: snmp_agent.c:1614
@ SNMP_SECURITY_LEVEL_AUTH_PRIV
#define TRACE_INFO(...)
Definition: debug.h:105
error_t snmpAgentGetEngineBoots(SnmpAgentContext *context, int32_t *engineBoots)
Get the value of the snmpEngineBoots variable.
Definition: snmp_agent.c:578
error_t snmpAgentSendInform(SnmpAgentContext *context, const IpAddr *destIpAddr, SnmpVersion version, const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Send SNMP inform request.
Definition: snmp_agent.c:1689
error_t snmpAgentSetEngineBoots(SnmpAgentContext *context, int32_t engineBoots)
Set the value of the snmpEngineBoots variable.
Definition: snmp_agent.c:539
MIB module.
Definition: mib_common.h:292
#define osEnterTask()
uint_t eventFlags
Returned events.
Definition: socket.h:436
MibRowStatus status
Status of the user.
error_t socketPoll(SocketEventDesc *eventDesc, uint_t size, OsEvent *extEvent, systime_t timeout)
Wait for one of a set of sockets to become ready to perform I/O.
Definition: socket.c:2182
#define socketBindToInterface
Definition: net_legacy.h:193
#define SNMP_AGENT_STACK_SIZE
Definition: snmp_agent.h:57
@ SNMP_VERSION_3
Definition: snmp_common.h:140
char_t viewName[SNMP_MAX_VIEW_NAME_LEN+1]
uint32_t systime_t
System time.
error_t snmpAgentCreateUser(SnmpAgentContext *context, const char_t *userName, SnmpAccess mode, SnmpKeyFormat keyFormat, SnmpAuthProtocol authProtocol, const void *authKey, SnmpPrivProtocol privProtocol, const void *privKey)
Create a new user.
Definition: snmp_agent.c:852
IpAddr destIpAddr
Destination IP address.
Definition: socket.h:251
SNMP secret key.
void snmpAgentGetDefaultSettings(SnmpAgentSettings *settings)
Initialize settings with default values.
Definition: snmp_agent.c:73
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:55
Ipv6Addr contextPrefix
Definition: ndp.h:519
@ MIB_ROW_STATUS_ACTIVE
Definition: mib_common.h:103
void snmpAgentTask(SnmpAgentContext *context)
SNMP agent task.
Definition: snmp_agent.c:1967
SnmpSecurityLevel securityLevel
uint16_t port
SNMP port number.
Definition: snmp_agent.h:138
uint32_t time
MibRowStatus status
error_t snmpAgentCreateView(SnmpAgentContext *context, const char_t *viewName, const uint8_t *subtree, size_t subtreeLen, const uint8_t *mask, size_t maskLen, SnmpViewType type)
Create a new MIB view.
Definition: snmp_agent.c:1453
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
SnmpAuthProtocol authProtocol
Authentication protocol.
char_t name[SNMP_MAX_USER_NAME_LEN+1]
User name.
SnmpAgentRandCallback randCallback
Random data generation callback function.
Definition: snmp_agent.h:140
@ SOCKET_EVENT_RX_READY
Definition: socket.h:179
#define SNMP_MAX_MSG_SIZE
Definition: snmp_common.h:60
uint8_t n
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
uint8_t mask[SNMP_MAX_BIT_MASK_SIZE]
NetInterface * interface
Underlying network interface.
Definition: snmp_agent.h:135
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
NetContext * netContext
TCP/IP stack context.
Definition: snmp_agent.h:134
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Socket * socketOpenEx(NetContext *context, uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:146
View table entry.
Access table entry.
@ SNMP_AGENT_STATE_SENDING_GET_REQ
bool_t osCreateEvent(OsEvent *event)
Create an event object.
SnmpVersion versionMin
Minimum version accepted by the SNMP agent.
Definition: snmp_agent.h:136
SnmpKey rawAuthKey
Raw authentication key.
error_t snmpLocalizeKey(SnmpAuthProtocol authProtocol, const uint8_t *engineId, size_t engineIdLen, SnmpKey *key, SnmpKey *localizedKey)
Key localization algorithm.
error_t snmpFormatTrapMessage(SnmpAgentContext *context, SnmpVersion version, const char_t *userName, uint_t genericTrapType, uint_t specificTrapCode, const SnmpTrapObject *objectList, uint_t objectListSize)
Format SNMP Trap message.
size_t size
Size of the payload, in bytes.
Definition: socket.h:243
SnmpAuthProtocol
error_t snmpAgentCreateAccess(SnmpAgentContext *context, const char_t *groupName, SnmpSecurityModel securityModel, SnmpSecurityLevel securityLevel, const char_t *contextPrefix, SnmpContextMatch contextMatch, const char_t *readViewName, const char_t *writeViewName, const char_t *notifyViewName)
Create access policy for the specified group name.
Definition: snmp_agent.c:1258
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:1535
@ SNMP_VERSION_1
Definition: snmp_common.h:138
#define SNMP_PORT
Definition: snmp_common.h:122
SnmpPrivProtocol privProtocol
Privacy protocol.
SnmpSecurityModel securityModel
#define SNMP_MAX_CONTEXT_ENGINE_SIZE
Definition: snmp_common.h:67
#define SnmpAgentContext
Definition: snmp_agent.h:36
error_t snmpGenerateKey(SnmpAuthProtocol authProtocol, const char_t *password, SnmpKey *key)
Password to key algorithm.
error_t snmpAgentUnloadMib(SnmpAgentContext *context, const MibModule *module)
Unload a MIB module.
Definition: snmp_agent.c:450
void osDelayTask(systime_t delay)
Delay routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
SnmpSecurityLevel
Security levels.
SNMP agent (PDU processing)
@ SNMP_SECURITY_MODEL_V2C
SNMPv2c.
Group table entry.
Socket * socket
Handle to a socket to monitor.
Definition: socket.h:434
void snmpRefreshEngineTime(SnmpAgentContext *context)
Refresh SNMP engine time.
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
@ SNMP_AUTH_PROTOCOL_NONE
No authentication.
void snmpAgentDeinit(SnmpAgentContext *context)
Release SNMP agent context.
Definition: snmp_agent.c:2096
@ SNMP_KEY_FORMAT_RAW
Raw key.
@ SNMP_VIEW_TYPE_EXCLUDED
error_t snmpAgentDeleteCommunity(SnmpAgentContext *context, const char_t *community)
Remove a community string.
Definition: snmp_agent.c:794
SNMP agent settings.
Definition: snmp_agent.h:132
#define osStrcpy(s1, s2)
Definition: os_port.h:210
uint16_t srcPort
Source port.
Definition: socket.h:250
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:169
SnmpKey rawPrivKey
Raw privacy key.
SnmpAccess
Access modes.
uint_t eventMask
Requested events.
Definition: socket.h:435
@ ERROR_ALREADY_RUNNING
Definition: error.h:294
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ SNMP_SECURITY_LEVEL_AUTH_NO_PRIV
ASN.1 (Abstract Syntax Notation One)
error_t snmpAgentStop(SnmpAgentContext *context)
Stop SNMP agent.
Definition: snmp_agent.c:328
SnmpAccessEntry * snmpFindAccessEntry(SnmpAgentContext *context, const char_t *groupName, const char_t *contextPrefix, uint_t securityModel, uint_t securityLevel)
Search the access table for a given entry.
#define INFINITE_DELAY
Definition: os_port.h:75
error_t snmpFormatGetRequestMessage(SnmpAgentContext *context, SnmpVersion version)
Format SNMP GetRequest message.
MibRowStatus status
error_t snmpAgentSetEnterpriseOid(SnmpAgentContext *context, const uint8_t *enterpriseOid, size_t enterpriseOidLen)
Set enterprise OID.
Definition: snmp_agent.c:609
systime_t osGetSystemTime(void)
Retrieve system time.
SNMP message dispatching.
Ipv4Addr destIpAddr
Definition: ipcp.h:80