snmp_community_mib_impl.c
Go to the documentation of this file.
1 /**
2  * @file snmp_community_mib_impl.c
3  * @brief SNMP COMMUNITY MIB module implementation
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  * The SNMP-MIB describes managed objects which describe the behavior
30  * of an SNMP entity. Refer to RFC 3418 for more details
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.4.4
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL SNMP_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/net.h"
41 #include "mibs/mib_common.h"
44 #include "snmp/snmp_agent.h"
45 #include "snmp/snmp_agent_misc.h"
46 #include "core/crypto.h"
47 #include "encoding/asn1.h"
48 #include "encoding/oid.h"
49 #include "debug.h"
50 
51 //Check TCP/IP stack configuration
52 #if (SNMP_COMMUNITY_MIB_SUPPORT == ENABLED)
53 
54 
55 /**
56  * @brief SNMP COMMUNITY MIB module initialization
57  * @return Error code
58  **/
59 
61 {
62  //Debug message
63  TRACE_INFO("Initializing SNMP COMMUNITY MIB base...\r\n");
64 
65  //Clear SNMP COMMUNITY MIB base
67 
68  //Successful processing
69  return NO_ERROR;
70 }
71 
72 
73 /**
74  * @brief Load SNMP COMMUNITY MIB module
75  * @param[in] context Pointer to the SNMP agent context
76  * @return Error code
77  **/
78 
80 {
81  //Register SNMP agent context
82  snmpCommunityMibBase.context = context;
83 
84  //Successful processing
85  return NO_ERROR;
86 }
87 
88 
89 /**
90  * @brief Unload SNMP COMMUNITY MIB module
91  * @param[in] context Pointer to the SNMP agent context
92  **/
93 
94 void snmpCommunityMibUnload(void *context)
95 {
96  //Unregister SNMP agent context
98 }
99 
100 
101 /**
102  * @brief Lock SNMP COMMUNITY MIB base
103  **/
104 
106 {
107  //Clear temporary community
109 }
110 
111 
112 /**
113  * @brief Unlock SNMP COMMUNITY MIB base
114  **/
115 
117 {
118  //Clear temporary user
120 }
121 
122 
123 /**
124  * @brief Set snmpCommunityEntry object value
125  * @param[in] object Pointer to the MIB object descriptor
126  * @param[in] oid Object identifier (object name and instance identifier)
127  * @param[in] oidLen Length of the OID, in bytes
128  * @param[in] value Object value
129  * @param[in] valueLen Length of the object value, in bytes
130  * @param[in] commit This flag tells whether the changes shall be committed
131  * to the MIB base
132  * @return Error code
133  **/
134 
136  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
137 {
138 #if (SNMP_COMMUNITY_MIB_SET_SUPPORT == ENABLED)
139  error_t error;
140  size_t n;
141  char_t index[SNMP_MAX_USER_NAME_LEN + 1];
142  SnmpAgentContext *context;
143  SnmpUserEntry *community;
144 
145  //Point to the instance identifier
146  n = object->oidLen;
147 
148  //snmpCommunityIndex is used as instance identifier
149  error = mibDecodeString(oid, oidLen, &n, index,
151  //Invalid instance identifier?
152  if(error)
153  return error;
154 
155  //Sanity check
156  if(n != oidLen)
158 
159  //Point to the SNMP agent context
161  //Sanity check
162  if(context == NULL)
164 
165  //Search the community table for the specified community string
166  community = snmpFindCommunityEntry(context, index, osStrlen(index));
167 
168  //snmpCommunityName object?
169  if(osStrcmp(object->name, "snmpCommunityName") == 0)
170  {
171  //Ensure the length of the community string is valid
172  if(valueLen > SNMP_MAX_USER_NAME_LEN)
173  return ERROR_WRONG_LENGTH;
174 
175  //Test if the conceptual row exists in the agent
176  if(community != NULL)
177  {
178  //Commit phase?
179  if(commit)
180  {
181  //Set community string
182  osMemcpy(community->name, value->octetString, valueLen);
183  //Properly terminate the string with a NULL character
184  community->name[valueLen] = '\0';
185  }
186  }
187  else
188  {
189  //Prepare phase?
190  if(!commit)
191  {
192  //Save the community string for later use
194  value->octetString, valueLen);
195 
196  //Properly terminate the string with a NULL character
197  snmpCommunityMibBase.tempCommunity.name[valueLen] = '\0';
198  }
199  }
200  }
201  //snmpCommunitySecurityName object?
202  else if(osStrcmp(object->name, "snmpCommunitySecurityName") == 0)
203  {
204  //Write access is not required
205  }
206  //snmpCommunityContextEngineID object?
207  else if(osStrcmp(object->name, "snmpCommunityContextEngineID") == 0)
208  {
209  //Write access is not required
210  }
211  //snmpCommunityContextName object?
212  else if(osStrcmp(object->name, "snmpCommunityContextName") == 0)
213  {
214  //Write access is not required
215  }
216  //snmpCommunityTransportTag object?
217  else if(osStrcmp(object->name, "snmpCommunityTransportTag") == 0)
218  {
219  //Write access is not required
220  }
221  //snmpCommunityStorageType object?
222  else if(osStrcmp(object->name, "snmpCommunityStorageType") == 0)
223  {
224  //The snmpCommunityStorageType object specifies the storage type
225  //for this conceptual row
226  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
227  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
228  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
229  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
230  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
231  {
232  return ERROR_WRONG_VALUE;
233  }
234  }
235  //snmpCommunityStatus object?
236  else if(osStrcmp(object->name, "snmpCommunityStatus") == 0)
237  {
238  MibRowStatus status;
239 
240  //Get row status
241  status = (MibRowStatus) value->integer;
242 
243  //Check the value specified by the set operation
244  if(status == MIB_ROW_STATUS_ACTIVE ||
246  {
247  //No matching row found?
248  if(community == NULL)
250 
251  //Commit phase?
252  if(commit)
253  {
254  //Valid community string specified?
257 
258  //A newly created row cannot be made active until a value has been
259  //set for snmpCommunityName
260  if(community->name[0] == '\0')
262 
263  //Update the status of the conceptual row
264  community->status = status;
265  }
266  }
267  else if(status == MIB_ROW_STATUS_CREATE_AND_GO)
268  {
269  //Row already instantiated?
270  if(community != NULL)
272 
273  //Create a new row
274  community = snmpCreateCommunityEntry(context);
275  //Row creation failed?
276  if(community == NULL)
277  return ERROR_WRITE_FAILED;
278 
279  //Commit phase?
280  if(commit)
281  {
282  //Valid community string specified?
284  {
285  //Save community string
287  //Set default access rights
288  community->mode = SNMP_ACCESS_READ_WRITE;
289 
290  //The conceptual row is now available for use by the managed device
291  community->status = MIB_ROW_STATUS_ACTIVE;
292  }
293  else
294  {
295  //The newly created row cannot be made active
297  }
298  }
299  }
300  else if(status == MIB_ROW_STATUS_CREATE_AND_WAIT)
301  {
302  //Row already instantiated?
303  if(community != NULL)
305 
306  //Create a new row
307  community = snmpCreateCommunityEntry(context);
308  //Row creation failed?
309  if(community == NULL)
310  return ERROR_WRITE_FAILED;
311 
312  //Commit phase?
313  if(commit)
314  {
315  //Ensure the community string is valid
318 
319  //Copy the community string
321  //Set default access rights
322  community->mode = SNMP_ACCESS_READ_WRITE;
323 
324  //Instances of all corresponding columns are now configured
326  }
327  }
328  else if(status == MIB_ROW_STATUS_DESTROY)
329  {
330  //Test if the conceptual row exists in the agent
331  if(community != NULL)
332  {
333  //Commit phase?
334  if(commit)
335  {
336  //Delete the conceptual row from the table
337  community->status = MIB_ROW_STATUS_UNUSED;
338  }
339  }
340  }
341  else
342  {
343  //Unsupported action
345  }
346  }
347  //Unknown object?
348  else
349  {
350  //The specified object does not exist
351  error = ERROR_OBJECT_NOT_FOUND;
352  }
353 
354  //Return status code
355  return error;
356 #else
357  //SET operation is not supported
358  return ERROR_WRITE_FAILED;
359 #endif
360 }
361 
362 
363 /**
364  * @brief Get snmpCommunityEntry object value
365  * @param[in] object Pointer to the MIB object descriptor
366  * @param[in] oid Object identifier (object name and instance identifier)
367  * @param[in] oidLen Length of the OID, in bytes
368  * @param[out] value Object value
369  * @param[in,out] valueLen Length of the object value, in bytes
370  * @return Error code
371  **/
372 
374  size_t oidLen, MibVariant *value, size_t *valueLen)
375 {
376  error_t error;
377  size_t n;
378  char_t index[SNMP_MAX_USER_NAME_LEN + 1];
379  SnmpAgentContext *context;
380  SnmpUserEntry *community;
381 
382  //Point to the instance identifier
383  n = object->oidLen;
384 
385  //snmpCommunityIndex is used as instance identifier
386  error = mibDecodeString(oid, oidLen, &n, index,
388  //Invalid instance identifier?
389  if(error)
390  return error;
391 
392  //Sanity check
393  if(n != oidLen)
395 
396  //Point to the SNMP agent context
398  //Sanity check
399  if(context == NULL)
401 
402  //Search the community table for the specified community string
403  community = snmpFindCommunityEntry(context, index, osStrlen(index));
404  //Unknown community string?
405  if(community == NULL)
407 
408  //snmpCommunityName object?
409  if(osStrcmp(object->name, "snmpCommunityName") == 0)
410  {
411  //Retrieve the length of the community string
412  n = osStrlen(community->name);
413 
414  //Make sure the buffer is large enough to hold the entire object
415  if(*valueLen >= n)
416  {
417  //Copy object value
418  osMemcpy(value->octetString, community->name, n);
419  //Return object length
420  *valueLen = n;
421  }
422  else
423  {
424  //Report an error
425  error = ERROR_BUFFER_OVERFLOW;
426  }
427  }
428  //snmpCommunitySecurityName object?
429  else if(osStrcmp(object->name, "snmpCommunitySecurityName") == 0)
430  {
431  //Retrieve the length of the community string
432  n = osStrlen(community->name);
433 
434  //Make sure the buffer is large enough to hold the entire object
435  if(*valueLen >= n)
436  {
437  //Copy object value
438  osMemcpy(value->octetString, community->name, n);
439  //Return object length
440  *valueLen = n;
441  }
442  else
443  {
444  //Report an error
445  error = ERROR_BUFFER_OVERFLOW;
446  }
447  }
448  //snmpCommunityContextEngineID object?
449  else if(osStrcmp(object->name, "snmpCommunityContextEngineID") == 0)
450  {
451  //Retrieve the length of the context engine identifier
452  n = context->contextEngineLen;
453 
454  //Make sure the buffer is large enough to hold the entire object
455  if(*valueLen >= n)
456  {
457  //Copy object value
458  osMemcpy(value->octetString, context->contextEngine, n);
459  //Return object length
460  *valueLen = n;
461  }
462  else
463  {
464  //Report an error
465  error = ERROR_BUFFER_OVERFLOW;
466  }
467  }
468  //snmpCommunityContextName object?
469  else if(osStrcmp(object->name, "snmpCommunityContextName") == 0)
470  {
471  //Retrieve the length of the context name
472  n = osStrlen(context->contextName);
473 
474  //Make sure the buffer is large enough to hold the entire object
475  if(*valueLen >= n)
476  {
477  //Copy object value
478  osMemcpy(value->octetString, context->contextName, n);
479  //Return object length
480  *valueLen = n;
481  }
482  else
483  {
484  //Report an error
485  error = ERROR_BUFFER_OVERFLOW;
486  }
487  }
488  //snmpCommunityTransportTag object?
489  else if(osStrcmp(object->name, "snmpCommunityTransportTag") == 0)
490  {
491  //The default value is the empty string
492  *valueLen = 0;
493  }
494  //snmpCommunityStorageType object?
495  else if(osStrcmp(object->name, "snmpCommunityStorageType") == 0)
496  {
497  //Get the storage type for this conceptual row
498  value->integer = MIB_STORAGE_TYPE_VOLATILE;
499  }
500  //snmpCommunityStatus object?
501  else if(osStrcmp(object->name, "snmpCommunityStatus") == 0)
502  {
503  //Get the status of this conceptual row
504  value->integer = community->status;
505  }
506  //Unknown object?
507  else
508  {
509  //The specified object does not exist
510  error = ERROR_OBJECT_NOT_FOUND;
511  }
512 
513  //Return status code
514  return error;
515 }
516 
517 
518 /**
519  * @brief Get next snmpCommunityEntry object
520  * @param[in] object Pointer to the MIB object descriptor
521  * @param[in] oid Object identifier
522  * @param[in] oidLen Length of the OID, in bytes
523  * @param[out] nextOid OID of the next object in the MIB
524  * @param[out] nextOidLen Length of the next object identifier, in bytes
525  * @return Error code
526  **/
527 
529  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
530 {
531  error_t error;
532  uint_t i;
533  size_t n;
534  bool_t acceptable;
535  SnmpAgentContext *context;
536  SnmpUserEntry *entry;
537  SnmpUserEntry *nextEntry;
538 
539  //Initialize variables
540  nextEntry = NULL;
541 
542  //Point to the SNMP agent context
544  //Sanity check
545  if(context == NULL)
546  return ERROR_OBJECT_NOT_FOUND;
547 
548  //Make sure the buffer is large enough to hold the OID prefix
549  if(*nextOidLen < object->oidLen)
550  return ERROR_BUFFER_OVERFLOW;
551 
552  //Copy OID prefix
553  osMemcpy(nextOid, object->oid, object->oidLen);
554 
555  //Loop through the list of community strings
556  for(i = 0; i < SNMP_AGENT_MAX_COMMUNITIES; i++)
557  {
558  //Point to the current entry
559  entry = &context->communityTable[i];
560 
561  //Check the status of the row
562  if(entry->status != MIB_ROW_STATUS_UNUSED)
563  {
564  //Append the instance identifier to the OID prefix
565  n = object->oidLen;
566 
567  //snmpCommunityIndex is used as instance identifier
568  error = mibEncodeString(nextOid, *nextOidLen, &n, entry->name, TRUE);
569  //Any error to report?
570  if(error)
571  return error;
572 
573  //Check whether the resulting object identifier lexicographically
574  //follows the specified OID
575  if(oidComp(nextOid, n, oid, oidLen) > 0)
576  {
577  //Perform lexicographic comparison
578  if(nextEntry == NULL)
579  {
580  acceptable = TRUE;
581  }
582  else if(osStrcmp(entry->name, nextEntry->name) < 0)
583  {
584  acceptable = TRUE;
585  }
586  else
587  {
588  acceptable = FALSE;
589  }
590 
591  //Save the closest object identifier that follows the specified
592  //OID in lexicographic order
593  if(acceptable)
594  nextEntry = entry;
595  }
596  }
597  }
598 
599  //The specified OID does not lexicographically precede the name
600  //of some object?
601  if(nextEntry == NULL)
602  return ERROR_OBJECT_NOT_FOUND;
603 
604  //Append the instance identifier to the OID prefix
605  n = object->oidLen;
606 
607  //snmpCommunityIndex is used as instance identifier
608  error = mibEncodeString(nextOid, *nextOidLen, &n, nextEntry->name, TRUE);
609  //Any error to report?
610  if(error)
611  return error;
612 
613  //Save the length of the resulting object identifier
614  *nextOidLen = n;
615  //Next object found
616  return NO_ERROR;
617 }
618 
619 #endif
@ MIB_ROW_STATUS_NOT_IN_SERVICE
Definition: mib_common.h:104
error_t mibEncodeString(uint8_t *oid, size_t maxOidLen, size_t *pos, const char_t *string, bool_t implied)
Encode instance identifier (string)
Definition: mib_common.c:129
SNMP COMMUNITY MIB module implementation.
SnmpCommunityMibBase snmpCommunityMibBase
SNMP COMMUNITY MIB base.
int bool_t
Definition: compiler_port.h:53
void snmpCommunityMibUnload(void *context)
Unload SNMP COMMUNITY MIB module.
@ SNMP_ACCESS_READ_WRITE
SnmpUserEntry * snmpFindCommunityEntry(SnmpAgentContext *context, const char_t *community, size_t length)
Search the community table for a given community string.
@ MIB_ROW_STATUS_CREATE_AND_GO
Definition: mib_common.h:106
@ MIB_STORAGE_TYPE_NON_VOLATILE
Definition: mib_common.h:120
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
SnmpAccess mode
Access mode.
OID (Object Identifier)
@ MIB_STORAGE_TYPE_OTHER
Definition: mib_common.h:118
#define TRUE
Definition: os_port.h:50
#define osStrcmp(s1, s2)
Definition: os_port.h:171
#define osStrlen(s)
Definition: os_port.h:165
User table entry.
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
@ MIB_ROW_STATUS_DESTROY
Definition: mib_common.h:108
uint8_t oid[]
Definition: lldp_tlv.h:300
@ MIB_STORAGE_TYPE_READ_ONLY
Definition: mib_common.h:122
error_t snmpCommunityMibLoad(void *context)
Load SNMP COMMUNITY MIB module.
SnmpUserEntry * snmpCreateCommunityEntry(SnmpAgentContext *context)
Create a new community entry.
SNMP agent (Simple Network Management Protocol)
error_t snmpCommunityMibSetCommunityEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set snmpCommunityEntry object value.
#define FALSE
Definition: os_port.h:46
error_t snmpCommunityMibGetCommunityEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get snmpCommunityEntry object value.
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:257
#define SNMP_MAX_USER_NAME_LEN
Definition: snmp_common.h:81
SNMP COMMUNITY MIB module.
error_t snmpCommunityMibInit(void)
SNMP COMMUNITY MIB module initialization.
@ MIB_ROW_STATUS_UNUSED
Definition: mib_common.h:102
General definitions for cryptographic algorithms.
Helper functions for SNMP agent.
@ ERROR_WRONG_LENGTH
Definition: error.h:120
#define SNMP_AGENT_MAX_COMMUNITIES
Definition: snmp_agent.h:76
#define TRACE_INFO(...)
Definition: debug.h:95
MibRowStatus status
Status of the user.
char char_t
Definition: compiler_port.h:48
@ MIB_ROW_STATUS_ACTIVE
Definition: mib_common.h:103
char_t name[SNMP_MAX_USER_NAME_LEN+1]
User name.
MibRowStatus
Row status.
Definition: mib_common.h:101
Common definitions for MIB modules.
uint8_t n
@ ERROR_WRONG_VALUE
Definition: error.h:123
@ ERROR_WRITE_FAILED
Definition: error.h:222
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:256
void snmpCommunityMibUnlock(void)
Unlock SNMP COMMUNITY MIB base.
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:369
uint8_t oidLen
Definition: lldp_tlv.h:299
@ MIB_ROW_STATUS_CREATE_AND_WAIT
Definition: mib_common.h:107
@ MIB_STORAGE_TYPE_VOLATILE
Definition: mib_common.h:119
#define SnmpAgentContext
Definition: snmp_agent.h:36
void snmpCommunityMibLock(void)
Lock SNMP COMMUNITY MIB base.
error_t mibDecodeString(const uint8_t *oid, size_t oidLen, size_t *pos, char_t *string, size_t maxStringLen, bool_t implied)
Decode instance identifier (string)
Definition: mib_common.c:149
MibVariant
Definition: mib_common.h:196
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
TCP/IP stack core.
#define osStrcpy(s1, s2)
Definition: os_port.h:207
@ ERROR_INCONSISTENT_VALUE
Definition: error.h:124
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
ASN.1 (Abstract Syntax Notation One)
@ MIB_STORAGE_TYPE_PERMANENT
Definition: mib_common.h:121
error_t snmpCommunityMibGetNextCommunityEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next snmpCommunityEntry object.