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