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