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.0
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"))
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"))
203  {
204  //Write access is not required
205  }
206  //snmpCommunityContextEngineID object?
207  else if(!osStrcmp(object->name, "snmpCommunityContextEngineID"))
208  {
209  //Write access is not required
210  }
211  //snmpCommunityContextName object?
212  else if(!osStrcmp(object->name, "snmpCommunityContextName"))
213  {
214  //Write access is not required
215  }
216  //snmpCommunityTransportTag object?
217  else if(!osStrcmp(object->name, "snmpCommunityTransportTag"))
218  {
219  //Write access is not required
220  }
221  //snmpCommunityStorageType object?
222  else if(!osStrcmp(object->name, "snmpCommunityStorageType"))
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"))
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"))
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"))
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"))
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"))
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"))
490  {
491  //The default value is the empty string
492  *valueLen = 0;
493  }
494  //snmpCommunityStorageType object?
495  else if(!osStrcmp(object->name, "snmpCommunityStorageType"))
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"))
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
ASN.1 (Abstract Syntax Notation One)
unsigned int uint_t
Definition: compiler_port.h:50
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_INFO(...)
Definition: debug.h:95
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_WRONG_LENGTH
Definition: error.h:120
@ ERROR_WRITE_FAILED
Definition: error.h:221
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:255
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:256
@ ERROR_WRONG_VALUE
Definition: error.h:123
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
@ ERROR_INCONSISTENT_VALUE
Definition: error.h:124
uint8_t oid[]
Definition: lldp_tlv.h:300
uint8_t oidLen
Definition: lldp_tlv.h:299
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
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
Common definitions for MIB modules.
#define MibObject
Definition: mib_common.h:46
MibRowStatus
Row status.
Definition: mib_common.h:101
@ MIB_ROW_STATUS_CREATE_AND_WAIT
Definition: mib_common.h:107
@ MIB_ROW_STATUS_UNUSED
Definition: mib_common.h:102
@ MIB_ROW_STATUS_ACTIVE
Definition: mib_common.h:103
@ MIB_ROW_STATUS_NOT_IN_SERVICE
Definition: mib_common.h:104
@ MIB_ROW_STATUS_DESTROY
Definition: mib_common.h:108
@ MIB_ROW_STATUS_CREATE_AND_GO
Definition: mib_common.h:106
@ MIB_STORAGE_TYPE_NON_VOLATILE
Definition: mib_common.h:120
@ MIB_STORAGE_TYPE_OTHER
Definition: mib_common.h:118
@ MIB_STORAGE_TYPE_READ_ONLY
Definition: mib_common.h:122
@ MIB_STORAGE_TYPE_PERMANENT
Definition: mib_common.h:121
@ MIB_STORAGE_TYPE_VOLATILE
Definition: mib_common.h:119
MibVariant
Definition: mib_common.h:196
TCP/IP stack core.
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
OID (Object Identifier)
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osStrcmp(s1, s2)
Definition: os_port.h:171
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define osStrlen(s)
Definition: os_port.h:165
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define osStrcpy(s1, s2)
Definition: os_port.h:207
SNMP agent (Simple Network Management Protocol)
#define SnmpAgentContext
Definition: snmp_agent.h:36
#define SNMP_AGENT_MAX_COMMUNITIES
Definition: snmp_agent.h:76
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_ACCESS_READ_WRITE
#define SNMP_MAX_USER_NAME_LEN
Definition: snmp_common.h:81
error_t snmpCommunityMibInit(void)
SNMP COMMUNITY MIB module initialization.
void snmpCommunityMibUnload(void *context)
Unload SNMP COMMUNITY MIB module.
error_t snmpCommunityMibGetNextCommunityEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next snmpCommunityEntry object.
void snmpCommunityMibUnlock(void)
Unlock SNMP COMMUNITY MIB base.
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.
error_t snmpCommunityMibLoad(void *context)
Load SNMP COMMUNITY MIB module.
error_t snmpCommunityMibGetCommunityEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get snmpCommunityEntry object value.
void snmpCommunityMibLock(void)
Lock SNMP COMMUNITY MIB base.
SNMP COMMUNITY MIB module implementation.
SnmpCommunityMibBase snmpCommunityMibBase
SNMP COMMUNITY MIB base.
SNMP COMMUNITY MIB module.
User table entry.
MibRowStatus status
Status of the user.
SnmpAccess mode
Access mode.
char_t name[SNMP_MAX_USER_NAME_LEN+1]
User name.
uint8_t value[]
Definition: tcp.h:369