snmp_vacm_mib_impl.c
Go to the documentation of this file.
1 /**
2  * @file snmp_vacm_mib_impl.c
3  * @brief SNMP VACM 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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL SNMP_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "mibs/mib_common.h"
37 #include "snmp/snmp_agent.h"
38 #include "snmp/snmp_agent_misc.h"
39 #include "core/crypto.h"
40 #include "encoding/asn1.h"
41 #include "encoding/oid.h"
42 #include "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (SNMP_VACM_MIB_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief SNMP VACM MIB module initialization
50  * @return Error code
51  **/
52 
54 {
55  //Debug message
56  TRACE_INFO("Initializing SNMP VACM MIB base...\r\n");
57 
58  //Clear SNMP VACM MIB base
59  memset(&snmpVacmMibBase, 0, sizeof(snmpVacmMibBase));
60 
61  //usmUserSpinLock object
63 
64  //Successful processing
65  return NO_ERROR;
66 }
67 
68 
69 /**
70  * @brief Load SNMP VACM MIB module
71  * @param[in] context Pointer to the SNMP agent context
72  * @return Error code
73  **/
74 
75 error_t snmpVacmMibLoad(void *context)
76 {
77  //Register SNMP agent context
78  snmpVacmMibBase.context = context;
79 
80  //Successful processing
81  return NO_ERROR;
82 }
83 
84 
85 /**
86  * @brief Unload SNMP VACM MIB module
87  * @param[in] context Pointer to the SNMP agent context
88  **/
89 
90 void snmpVacmMibUnload(void *context)
91 {
92  //Unregister SNMP agent context
93  snmpVacmMibBase.context = NULL;
94 }
95 
96 
97 /**
98  * @brief Lock SNMP VACM MIB base
99  **/
100 
101 void snmpVacmMibLock(void)
102 {
103  //Clear temporary objects
104  memset(&snmpVacmMibBase.tempGroupEntry, 0, sizeof(SnmpGroupEntry));
105  memset(&snmpVacmMibBase.tempAccessEntry, 0, sizeof(SnmpAccessEntry));
106  memset(&snmpVacmMibBase.tempViewEntry, 0, sizeof(SnmpViewEntry));
107 }
108 
109 
110 /**
111  * @brief Unlock SNMP VACM MIB base
112  **/
113 
115 {
116  //Clear temporary objects
117  memset(&snmpVacmMibBase.tempGroupEntry, 0, sizeof(SnmpGroupEntry));
118  memset(&snmpVacmMibBase.tempAccessEntry, 0, sizeof(SnmpAccessEntry));
119  memset(&snmpVacmMibBase.tempViewEntry, 0, sizeof(SnmpViewEntry));
120 }
121 
122 
123 /**
124  * @brief Get vacmContextEntry 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[out] value Object value
129  * @param[in,out] valueLen Length of the object value, in bytes
130  * @return Error code
131  **/
132 
134  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
135 {
136  error_t error;
137  size_t n;
138  char_t contextName[SNMP_MAX_CONTEXT_NAME_LEN + 1];
139  SnmpAgentContext *context;
140 
141  //Point to the instance identifier
142  n = object->oidLen;
143 
144  //vacmContextName is used as instance identifier
145  error = mibDecodeString(oid, oidLen, &n, contextName,
147  //Invalid instance identifier?
148  if(error)
149  return error;
150 
151  //Sanity check
152  if(n != oidLen)
154 
155  //Point to the SNMP agent context
157  //Sanity check
158  if(context == NULL)
160 
161  //Check context name
162  if(strcmp(contextName, context->contextName))
164 
165  //vacmContextName object?
166  if(!strcmp(object->name, "vacmContextName"))
167  {
168 #if (SNMP_V3_SUPPORT == ENABLED)
169  //Retrieve the length of the context name
170  n = strlen(context->contextName);
171 
172  //Make sure the buffer is large enough to hold the entire object
173  if(*valueLen >= n)
174  {
175  //Copy object value
176  memcpy(value->octetString, context->contextName, n);
177  //Return object length
178  *valueLen = n;
179  }
180  else
181  {
182  //Report an error
183  error = ERROR_BUFFER_OVERFLOW;
184  }
185 #else
186  //The empty contextName (zero length) represents the default context
187  *valueLen = 0;
188 #endif
189  }
190  //Unknown object?
191  else
192  {
193  //The specified object does not exist
194  error = ERROR_OBJECT_NOT_FOUND;
195  }
196 
197  //Return status code
198  return error;
199 }
200 
201 
202 /**
203  * @brief Get next vacmContextEntry object
204  * @param[in] object Pointer to the MIB object descriptor
205  * @param[in] oid Object identifier
206  * @param[in] oidLen Length of the OID, in bytes
207  * @param[out] nextOid OID of the next object in the MIB
208  * @param[out] nextOidLen Length of the next object identifier, in bytes
209  * @return Error code
210  **/
211 
213  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
214 {
215  error_t error;
216  size_t n;
217  SnmpAgentContext *context;
218 
219  //Point to the SNMP agent context
221  //Sanity check
222  if(context == NULL)
223  return ERROR_OBJECT_NOT_FOUND;
224 
225  //Make sure the buffer is large enough to hold the OID prefix
226  if(*nextOidLen < object->oidLen)
227  return ERROR_BUFFER_OVERFLOW;
228 
229  //Copy OID prefix
230  memcpy(nextOid, object->oid, object->oidLen);
231 
232  //Append the instance identifier to the OID prefix
233  n = object->oidLen;
234 
235 #if (SNMP_V3_SUPPORT == ENABLED)
236  //vacmContextName is used as instance identifier
237  error = mibEncodeString(nextOid, *nextOidLen, &n,
238  context->contextName, FALSE);
239 #else
240  //The empty contextName (zero length) represents the default context
241  error = mibEncodeString(nextOid, *nextOidLen, &n, "", FALSE);
242 #endif
243 
244  //Any error to report?
245  if(error)
246  return error;
247 
248  //Check whether the resulting object identifier lexicographically
249  //follows the specified OID
250  if(oidComp(nextOid, n, oid, oidLen) > 0)
251  {
252  //Save the length of the resulting object identifier
253  *nextOidLen = n;
254  //Next object found
255  return NO_ERROR;
256  }
257 
258  //The specified OID does not lexicographically precede the name
259  //of some object
260  return ERROR_OBJECT_NOT_FOUND;
261 }
262 
263 
264 /**
265  * @brief Set vacmSecurityToGroupEntry object value
266  * @param[in] object Pointer to the MIB object descriptor
267  * @param[in] oid Object identifier (object name and instance identifier)
268  * @param[in] oidLen Length of the OID, in bytes
269  * @param[in] value Object value
270  * @param[in] valueLen Length of the object value, in bytes
271  * @param[in] commit This flag tells whether the changes shall be committed
272  * to the MIB base
273  * @return Error code
274  **/
275 
277  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
278 {
279  error_t error;
280  size_t n;
281  uint_t securityModel;
282  char_t securityName[SNMP_MAX_USER_NAME_LEN + 1];
283  SnmpAgentContext *context;
284  SnmpGroupEntry *entry;
285 
286  //Point to the instance identifier
287  n = object->oidLen;
288 
289  //vacmSecurityModel is used as 1st instance identifier
290  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
291  //Invalid instance identifier?
292  if(error)
293  return error;
294 
295  //vacmSecurityName is used as 2nd instance identifier
296  error = mibDecodeString(oid, oidLen, &n, securityName,
298  //Invalid instance identifier?
299  if(error)
300  return error;
301 
302  //Sanity check
303  if(n != oidLen)
305 
306  //Make sure the security model is valid
307  if(securityModel != SNMP_SECURITY_MODEL_V1 &&
308  securityModel != SNMP_SECURITY_MODEL_V2C &&
309  securityModel != SNMP_SECURITY_MODEL_USM &&
310  securityModel != SNMP_SECURITY_MODEL_TSM)
311  {
312  //The security model is not supported
314  }
315 
316  //Make sure the security name is valid
317  if(securityName[0] == '\0')
319 
320  //Point to the SNMP agent context
322  //Sanity check
323  if(context == NULL)
325 
326  //Search the table for a matching row
327  entry = snmpFindGroupEntry(context, securityModel, securityName,
328  strlen(securityName));
329 
330  //vacmGroupName object?
331  if(!strcmp(object->name, "vacmGroupName"))
332  {
333  //Ensure the length of the group name is valid
334  if(valueLen > SNMP_MAX_GROUP_NAME_LEN)
335  return ERROR_INVALID_LENGTH;
336 
337  //Test if the conceptual row exists in the agent
338  if(entry != NULL)
339  {
340  //Commit phase?
341  if(commit)
342  {
343  //Set group name
344  memcpy(entry->groupName, value->octetString, valueLen);
345  //Properly terminate the string with a NULL character
346  entry->groupName[valueLen] = '\0';
347  }
348  }
349  else
350  {
351  //Prepare phase?
352  if(!commit)
353  {
354  //Save the group name for later use
356  value->octetString, valueLen);
357 
358  //Properly terminate the string with a NULL character
359  snmpVacmMibBase.tempGroupEntry.groupName[valueLen] = '\0';
360  }
361  }
362  }
363  //vacmSecurityToGroupStorageType object?
364  else if(!strcmp(object->name, "vacmSecurityToGroupStorageType"))
365  {
366  //The vacmSecurityToGroupStorageType object specifies the storage type
367  //for this conceptual row
368  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
369  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
370  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
371  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
372  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
373  {
374  return ERROR_WRONG_VALUE;
375  }
376  }
377  //vacmSecurityToGroupStatus object?
378  else if(!strcmp(object->name, "vacmSecurityToGroupStatus"))
379  {
380  MibRowStatus status;
381 
382  //Get row status
383  status = (MibRowStatus) value->integer;
384 
385  //Check the value specified by the set operation
386  if(status == MIB_ROW_STATUS_ACTIVE ||
388  {
389  //No matching row found?
390  if(entry == NULL)
392 
393  //Commit phase?
394  if(commit)
395  {
396  //Valid group name specified?
399 
400  //A newly created row cannot be made active until a value has been
401  //set for vacmGroupName
402  if(entry->groupName[0] == '\0')
404 
405  //Update the status of the conceptual row
406  entry->status = status;
407  }
408  }
409  else if(status == MIB_ROW_STATUS_CREATE_AND_GO)
410  {
411  //Row already instantiated?
412  if(entry != NULL)
414 
415  //Create a new row
416  entry = snmpCreateGroupEntry(context);
417  //Row creation failed?
418  if(entry == NULL)
419  return ERROR_WRITE_FAILED;
420 
421  //Commit phase?
422  if(commit)
423  {
424  //Valid group name specified?
426  {
427  //Save security model
428  entry->securityModel = (SnmpSecurityModel) securityModel;
429  //Save security name
430  strcpy(entry->securityName, securityName);
431  //Copy the group name
433 
434  //The conceptual row is now available for use by the managed device
435  entry->status = MIB_ROW_STATUS_ACTIVE;
436  }
437  else
438  {
439  //The newly created row cannot be made active
441  }
442  }
443  }
444  else if(status == MIB_ROW_STATUS_CREATE_AND_WAIT)
445  {
446  //Row already instantiated?
447  if(entry != NULL)
449 
450  //Create a new row
451  entry = snmpCreateGroupEntry(context);
452  //Row creation failed?
453  if(entry == NULL)
454  return ERROR_WRITE_FAILED;
455 
456  //Commit phase?
457  if(commit)
458  {
459  //Save security model
460  entry->securityModel = (SnmpSecurityModel) securityModel;
461  //Save security name
462  strcpy(entry->securityName, securityName);
463 
464  //Valid group name specified?
466  {
467  //Copy the group name
469 
470  //Instances of all corresponding columns are now configured
472  }
473  else
474  {
475  //Initialize columns with default values
476  entry->groupName[0] = '\0';
477 
478  //Until instances of all corresponding columns are appropriately
479  //configured, the value of the corresponding instance of the
480  //vacmSecurityToGroupStatus column is notReady
482  }
483  }
484  }
485  else if(status == MIB_ROW_STATUS_DESTROY)
486  {
487  //Test if the conceptual row exists in the agent
488  if(entry != NULL)
489  {
490  //Commit phase?
491  if(commit)
492  {
493  //Delete the conceptual row from the table
494  entry->status = MIB_ROW_STATUS_UNUSED;
495  }
496  }
497  }
498  else
499  {
500  //Unsupported action
502  }
503  }
504  //Unknown object?
505  else
506  {
507  //The specified object does not exist
508  error = ERROR_OBJECT_NOT_FOUND;
509  }
510 
511  //Return status code
512  return error;
513 }
514 
515 
516 /**
517  * @brief Get vacmSecurityToGroupEntry object value
518  * @param[in] object Pointer to the MIB object descriptor
519  * @param[in] oid Object identifier (object name and instance identifier)
520  * @param[in] oidLen Length of the OID, in bytes
521  * @param[out] value Object value
522  * @param[in,out] valueLen Length of the object value, in bytes
523  * @return Error code
524  **/
525 
527  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
528 {
529  error_t error;
530  size_t n;
531  uint_t securityModel;
532  char_t securityName[SNMP_MAX_USER_NAME_LEN + 1];
533  SnmpAgentContext *context;
534  SnmpGroupEntry *entry;
535 
536  //Point to the instance identifier
537  n = object->oidLen;
538 
539  //vacmSecurityModel is used as 1st instance identifier
540  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
541  //Invalid instance identifier?
542  if(error)
543  return error;
544 
545  //vacmSecurityName is used as 2nd instance identifier
546  error = mibDecodeString(oid, oidLen, &n, securityName,
548  //Invalid instance identifier?
549  if(error)
550  return error;
551 
552  //Sanity check
553  if(n != oidLen)
555 
556  //Point to the SNMP agent context
558  //Sanity check
559  if(context == NULL)
561 
562  //Search the table for a matching row
563  entry = snmpFindGroupEntry(context, securityModel, securityName,
564  strlen(securityName));
565  //No matching row found?
566  if(entry == NULL)
568 
569  //vacmGroupName object?
570  if(!strcmp(object->name, "vacmGroupName"))
571  {
572  //Retrieve the length of the group name
573  n = strlen(entry->groupName);
574 
575  //Make sure the buffer is large enough to hold the entire object
576  if(*valueLen >= n)
577  {
578  //Copy object value
579  memcpy(value->octetString, entry->groupName, n);
580  //Return object length
581  *valueLen = n;
582  }
583  else
584  {
585  //Report an error
586  error = ERROR_BUFFER_OVERFLOW;
587  }
588  }
589  //vacmSecurityToGroupStorageType object?
590  else if(!strcmp(object->name, "vacmSecurityToGroupStorageType"))
591  {
592  //Get the storage type for this conceptual row
593  value->integer = MIB_STORAGE_TYPE_VOLATILE;
594  }
595  //vacmSecurityToGroupStatus object?
596  else if(!strcmp(object->name, "vacmSecurityToGroupStatus"))
597  {
598  //Get the status of this conceptual row
599  value->integer = entry->status;
600  }
601  //Unknown object?
602  else
603  {
604  //The specified object does not exist
605  error = ERROR_OBJECT_NOT_FOUND;
606  }
607 
608  //Return status code
609  return error;
610 }
611 
612 
613 /**
614  * @brief Get next vacmSecurityToGroupEntry object
615  * @param[in] object Pointer to the MIB object descriptor
616  * @param[in] oid Object identifier
617  * @param[in] oidLen Length of the OID, in bytes
618  * @param[out] nextOid OID of the next object in the MIB
619  * @param[out] nextOidLen Length of the next object identifier, in bytes
620  * @return Error code
621  **/
622 
624  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
625 {
626  error_t error;
627  uint_t i;
628  size_t n;
629  bool_t acceptable;
630  SnmpAgentContext *context;
631  SnmpGroupEntry *entry;
632  SnmpGroupEntry *nextEntry;
633 
634  //Initialize variables
635  nextEntry = NULL;
636 
637  //Point to the SNMP agent context
639  //Sanity check
640  if(context == NULL)
641  return ERROR_OBJECT_NOT_FOUND;
642 
643  //Make sure the buffer is large enough to hold the OID prefix
644  if(*nextOidLen < object->oidLen)
645  return ERROR_BUFFER_OVERFLOW;
646 
647  //Copy OID prefix
648  memcpy(nextOid, object->oid, object->oidLen);
649 
650  //Loop through the list of groups
651  for(i = 0; i < SNMP_AGENT_GROUP_TABLE_SIZE; i++)
652  {
653  //Point to the current entry
654  entry = &context->groupTable[i];
655 
656  //Check the status of the row
657  if(entry->status != MIB_ROW_STATUS_UNUSED)
658  {
659  //Append the instance identifier to the OID prefix
660  n = object->oidLen;
661 
662  //vacmSecurityModel is used as 1st instance identifier
663  error = mibEncodeIndex(nextOid, *nextOidLen, &n, entry->securityModel);
664  //Any error to report?
665  if(error)
666  return error;
667 
668  //vacmSecurityName is used as 2nd instance identifier
669  error = mibEncodeString(nextOid, *nextOidLen, &n,
670  entry->securityName, FALSE);
671  //Any error to report?
672  if(error)
673  return error;
674 
675  //Check whether the resulting object identifier lexicographically
676  //follows the specified OID
677  if(oidComp(nextOid, n, oid, oidLen) > 0)
678  {
679  //Perform lexicographic comparison
680  if(nextEntry == NULL)
681  acceptable = TRUE;
682  else if(entry->securityModel < nextEntry->securityModel)
683  acceptable = TRUE;
684  else if(entry->securityModel > nextEntry->securityModel)
685  acceptable = FALSE;
686  else if(strlen(entry->securityName) < strlen(nextEntry->securityName))
687  acceptable = TRUE;
688  else if(strlen(entry->securityName) > strlen(nextEntry->securityName))
689  acceptable = FALSE;
690  else if(strcmp(entry->securityName, nextEntry->securityName) < 0)
691  acceptable = TRUE;
692  else
693  acceptable = FALSE;
694 
695  //Save the closest object identifier that follows the specified
696  //OID in lexicographic order
697  if(acceptable)
698  nextEntry = entry;
699  }
700  }
701  }
702 
703  //The specified OID does not lexicographically precede the name
704  //of some object?
705  if(nextEntry == NULL)
706  return ERROR_OBJECT_NOT_FOUND;
707 
708  //Append the instance identifier to the OID prefix
709  n = object->oidLen;
710 
711  //vacmSecurityModel is used as 1st instance identifier
712  error = mibEncodeIndex(nextOid, *nextOidLen, &n, nextEntry->securityModel);
713  //Any error to report?
714  if(error)
715  return error;
716 
717  //vacmSecurityName is used as 2nd instance identifier
718  error = mibEncodeString(nextOid, *nextOidLen, &n,
719  nextEntry->securityName, FALSE);
720  //Any error to report?
721  if(error)
722  return error;
723 
724  //Save the length of the resulting object identifier
725  *nextOidLen = n;
726  //Next object found
727  return NO_ERROR;
728 }
729 
730 
731 /**
732  * @brief Set vacmAccessEntry object value
733  * @param[in] object Pointer to the MIB object descriptor
734  * @param[in] oid Object identifier (object name and instance identifier)
735  * @param[in] oidLen Length of the OID, in bytes
736  * @param[in] value Object value
737  * @param[in] valueLen Length of the object value, in bytes
738  * @param[in] commit This flag tells whether the changes shall be committed
739  * to the MIB base
740  * @return Error code
741  **/
742 
743 error_t snmpVacmMibSetAccessEntry(const MibObject *object, const uint8_t *oid,
744  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
745 {
746  error_t error;
747  size_t n;
748  char_t groupName[SNMP_MAX_GROUP_NAME_LEN + 1];
750  uint_t securityModel;
751  uint_t securityLevel;
752  SnmpAgentContext *context;
753  SnmpAccessEntry *entry;
754 
755  //Point to the instance identifier
756  n = object->oidLen;
757 
758  //vacmGroupName is used as 1st instance identifier
759  error = mibDecodeString(oid, oidLen, &n, groupName,
761  //Invalid instance identifier?
762  if(error)
763  return error;
764 
765  //vacmAccessContextPrefix is used as 2nd instance identifier
766  error = mibDecodeString(oid, oidLen, &n, contextPrefix,
768  //Invalid instance identifier?
769  if(error)
770  return error;
771 
772  //vacmAccessSecurityModel is used as 3rd instance identifier
773  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
774  //Invalid instance identifier?
775  if(error)
776  return error;
777 
778  //vacmAccessSecurityLevel is used as 4th instance identifier
779  error = mibDecodeIndex(oid, oidLen, &n, &securityLevel);
780  //Invalid instance identifier?
781  if(error)
782  return error;
783 
784  //Sanity check
785  if(n != oidLen)
787 
788  //Make sure the group name is valid
789  if(groupName[0] == '\0')
791 
792  //Make sure the security model is valid
793  if(securityModel != SNMP_SECURITY_MODEL_ANY &&
794  securityModel != SNMP_SECURITY_MODEL_V1 &&
795  securityModel != SNMP_SECURITY_MODEL_V2C &&
796  securityModel != SNMP_SECURITY_MODEL_USM &&
797  securityModel != SNMP_SECURITY_MODEL_TSM)
798  {
799  //The security model is not supported
801  }
802 
803  //Make sure the security level is valid
804  if(securityLevel != SNMP_SECURITY_LEVEL_NO_AUTH_NO_PRIV &&
805  securityLevel != SNMP_SECURITY_LEVEL_AUTH_NO_PRIV &&
806  securityLevel != SNMP_SECURITY_LEVEL_AUTH_PRIV)
807  {
808  //The security level is not supported
810  }
811 
812  //Point to the SNMP agent context
814  //Sanity check
815  if(context == NULL)
817 
818  //Search the table for a matching row
819  entry = snmpFindAccessEntry(context, groupName, contextPrefix,
820  securityModel, securityLevel);
821 
822  //vacmAccessContextMatch object?
823  if(!strcmp(object->name, "vacmAccessContextMatch"))
824  {
825  //Ensure the value of the object is acceptable
826  if(value->integer != SNMP_CONTEXT_MATCH_EXACT &&
827  value->integer != SNMP_CONTEXT_MATCH_PREFIX)
828  {
829  return ERROR_WRONG_VALUE;
830  }
831 
832  //Test if the conceptual row exists in the agent
833  if(entry != NULL)
834  {
835  //Commit phase?
836  if(commit)
837  {
838  //Set the value of the column
839  entry->contextMatch = (SnmpContextMatch) value->integer;
840  }
841  }
842  else
843  {
844  //Prepare phase?
845  if(!commit)
846  {
847  //Save the value of the column for later use
849  }
850  }
851  }
852  //vacmAccessReadViewName object?
853  else if(!strcmp(object->name, "vacmAccessReadViewName"))
854  {
855  //Ensure the length of the read view name is valid
856  if(valueLen > SNMP_MAX_VIEW_NAME_LEN)
857  return ERROR_INVALID_LENGTH;
858 
859  //Test if the conceptual row exists in the agent
860  if(entry != NULL)
861  {
862  //Commit phase?
863  if(commit)
864  {
865  //Set read view name
866  memcpy(entry->readViewName, value->octetString, valueLen);
867  //Properly terminate the string with a NULL character
868  entry->readViewName[valueLen] = '\0';
869  }
870  }
871  else
872  {
873  //Prepare phase?
874  if(!commit)
875  {
876  //Save the read view name for later use
878  value->octetString, valueLen);
879 
880  //Properly terminate the string with a NULL character
882  }
883  }
884  }
885  //vacmAccessWriteViewName object?
886  else if(!strcmp(object->name, "vacmAccessWriteViewName"))
887  {
888  //Ensure the length of the write view name is valid
889  if(valueLen > SNMP_MAX_VIEW_NAME_LEN)
890  return ERROR_INVALID_LENGTH;
891 
892  //Test if the conceptual row exists in the agent
893  if(entry != NULL)
894  {
895  //Commit phase?
896  if(commit)
897  {
898  //Set write view name
899  memcpy(entry->writeViewName, value->octetString, valueLen);
900  //Properly terminate the string with a NULL character
901  entry->writeViewName[valueLen] = '\0';
902  }
903  }
904  else
905  {
906  //Prepare phase?
907  if(!commit)
908  {
909  //Save the write view name for later use
911  value->octetString, valueLen);
912 
913  //Properly terminate the string with a NULL character
915  }
916  }
917  }
918  //vacmAccessNotifyViewName object?
919  else if(!strcmp(object->name, "vacmAccessNotifyViewName"))
920  {
921  //Ensure the length of the notify view name is valid
922  if(valueLen > SNMP_MAX_VIEW_NAME_LEN)
923  return ERROR_INVALID_LENGTH;
924 
925  //Test if the conceptual row exists in the agent
926  if(entry != NULL)
927  {
928  //Commit phase?
929  if(commit)
930  {
931  //Set notify view name
932  memcpy(entry->notifyViewName, value->octetString, valueLen);
933  //Properly terminate the string with a NULL character
934  entry->notifyViewName[valueLen] = '\0';
935  }
936  }
937  else
938  {
939  //Prepare phase?
940  if(!commit)
941  {
942  //Save the notify view name for later use
944  value->octetString, valueLen);
945 
946  //Properly terminate the string with a NULL character
948  }
949  }
950  }
951  //vacmAccessStorageType object?
952  else if(!strcmp(object->name, "vacmAccessStorageType"))
953  {
954  //The vacmAccessStorageType object specifies the storage type
955  //for this conceptual row
956  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
957  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
958  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
959  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
960  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
961  {
962  return ERROR_WRONG_VALUE;
963  }
964  }
965  //vacmAccessStatus object?
966  else if(!strcmp(object->name, "vacmAccessStatus"))
967  {
968  MibRowStatus status;
969 
970  //Get row status
971  status = (MibRowStatus) value->integer;
972 
973  //Check the value specified by the set operation
974  if(status == MIB_ROW_STATUS_ACTIVE ||
976  {
977  //No matching row found?
978  if(entry == NULL)
980 
981  //Commit phase?
982  if(commit)
983  {
984  //Update the status of the conceptual row
985  entry->status = status;
986  }
987  }
988  else if(status == MIB_ROW_STATUS_CREATE_AND_GO ||
990  {
991  //Row already instantiated?
992  if(entry != NULL)
994 
995  //Create a new row
996  entry = snmpCreateAccessEntry(context);
997  //Row creation failed?
998  if(entry == NULL)
999  return ERROR_WRITE_FAILED;
1000 
1001  //Commit phase?
1002  if(commit)
1003  {
1004  //Save group name
1005  strcpy(entry->groupName, groupName);
1006  //Save context name prefix
1007  strcpy(entry->contextPrefix, contextPrefix);
1008  //Save security model
1009  entry->securityModel = (SnmpSecurityModel) securityModel;
1010  //Save security level
1011  entry->securityLevel = (SnmpSecurityLevel) securityLevel;
1012 
1013  //Initialize columns with default values
1015  entry->readViewName[0] = '\0';
1016  entry->writeViewName[0] = '\0';
1017  entry->notifyViewName[0] = '\0';
1018 
1019  //Valid context match specified?
1022 
1023  //Valid read view name specified?
1026 
1027  //Valid write view name specified?
1030 
1031  //Valid notify notify name specified?
1034 
1035  //The conceptual row has been successfully created
1036  if(status == MIB_ROW_STATUS_CREATE_AND_GO)
1037  entry->status = MIB_ROW_STATUS_ACTIVE;
1038  else
1040  }
1041  }
1042  else if(status == MIB_ROW_STATUS_DESTROY)
1043  {
1044  //Test if the conceptual row exists in the agent
1045  if(entry != NULL)
1046  {
1047  //Commit phase?
1048  if(commit)
1049  {
1050  //Delete the conceptual row from the table
1051  entry->status = MIB_ROW_STATUS_UNUSED;
1052  }
1053  }
1054  }
1055  else
1056  {
1057  //Unsupported action
1058  return ERROR_INCONSISTENT_VALUE;
1059  }
1060  }
1061  //Unknown object?
1062  else
1063  {
1064  //The specified object does not exist
1065  return ERROR_OBJECT_NOT_FOUND;
1066  }
1067 
1068  //Successful set operation
1069  return NO_ERROR;
1070 }
1071 
1072 
1073 /**
1074  * @brief Get vacmAccessEntry object value
1075  * @param[in] object Pointer to the MIB object descriptor
1076  * @param[in] oid Object identifier (object name and instance identifier)
1077  * @param[in] oidLen Length of the OID, in bytes
1078  * @param[out] value Object value
1079  * @param[in,out] valueLen Length of the object value, in bytes
1080  * @return Error code
1081  **/
1082 
1084  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
1085 {
1086  error_t error;
1087  size_t n;
1088  char_t groupName[SNMP_MAX_GROUP_NAME_LEN + 1];
1090  uint_t securityModel;
1091  uint_t securityLevel;
1092  SnmpAgentContext *context;
1093  SnmpAccessEntry *entry;
1094 
1095  //Point to the instance identifier
1096  n = object->oidLen;
1097 
1098  //vacmGroupName is used as 1st instance identifier
1099  error = mibDecodeString(oid, oidLen, &n, groupName,
1101  //Invalid instance identifier?
1102  if(error)
1103  return error;
1104 
1105  //vacmAccessContextPrefix is used as 2nd instance identifier
1106  error = mibDecodeString(oid, oidLen, &n, contextPrefix,
1108  //Invalid instance identifier?
1109  if(error)
1110  return error;
1111 
1112  //vacmAccessSecurityModel is used as 3rd instance identifier
1113  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
1114  //Invalid instance identifier?
1115  if(error)
1116  return error;
1117 
1118  //vacmAccessSecurityLevel is used as 4th instance identifier
1119  error = mibDecodeIndex(oid, oidLen, &n, &securityLevel);
1120  //Invalid instance identifier?
1121  if(error)
1122  return error;
1123 
1124  //Sanity check
1125  if(n != oidLen)
1126  return ERROR_INSTANCE_NOT_FOUND;
1127 
1128  //Point to the SNMP agent context
1130  //Sanity check
1131  if(context == NULL)
1132  return ERROR_INSTANCE_NOT_FOUND;
1133 
1134  //Search the table for a matching row
1135  entry = snmpFindAccessEntry(context, groupName, contextPrefix,
1136  securityModel, securityLevel);
1137  //No matching row found?
1138  if(entry == NULL)
1139  return ERROR_INSTANCE_NOT_FOUND;
1140 
1141  //vacmAccessContextMatch object?
1142  if(!strcmp(object->name, "vacmAccessContextMatch"))
1143  {
1144  //Get object value
1145  value->integer = entry->contextMatch;
1146  }
1147  //vacmAccessReadViewName object?
1148  else if(!strcmp(object->name, "vacmAccessReadViewName"))
1149  {
1150  //Retrieve the length of the read view name
1151  n = strlen(entry->readViewName);
1152 
1153  //Make sure the buffer is large enough to hold the entire object
1154  if(*valueLen >= n)
1155  {
1156  //Copy object value
1157  memcpy(value->octetString, entry->readViewName, n);
1158  //Return object length
1159  *valueLen = n;
1160  }
1161  else
1162  {
1163  //Report an error
1164  error = ERROR_BUFFER_OVERFLOW;
1165  }
1166  }
1167  //vacmAccessWriteViewName object?
1168  else if(!strcmp(object->name, "vacmAccessWriteViewName"))
1169  {
1170  //Retrieve the length of the write view name
1171  n = strlen(entry->writeViewName);
1172 
1173  //Make sure the buffer is large enough to hold the entire object
1174  if(*valueLen >= n)
1175  {
1176  //Copy object value
1177  memcpy(value->octetString, entry->writeViewName, n);
1178  //Return object length
1179  *valueLen = n;
1180  }
1181  else
1182  {
1183  //Report an error
1184  error = ERROR_BUFFER_OVERFLOW;
1185  }
1186  }
1187  //vacmAccessNotifyViewName object?
1188  else if(!strcmp(object->name, "vacmAccessNotifyViewName"))
1189  {
1190  //Retrieve the length of the notify view name
1191  n = strlen(entry->notifyViewName);
1192 
1193  //Make sure the buffer is large enough to hold the entire object
1194  if(*valueLen >= n)
1195  {
1196  //Copy object value
1197  memcpy(value->octetString, entry->notifyViewName, n);
1198  //Return object length
1199  *valueLen = n;
1200  }
1201  else
1202  {
1203  //Report an error
1204  error = ERROR_BUFFER_OVERFLOW;
1205  }
1206  }
1207  //vacmAccessStorageType object?
1208  else if(!strcmp(object->name, "vacmAccessStorageType"))
1209  {
1210  //Get the storage type for this conceptual row
1211  value->integer = MIB_STORAGE_TYPE_VOLATILE;
1212  }
1213  //vacmAccessStatus object?
1214  else if(!strcmp(object->name, "vacmAccessStatus"))
1215  {
1216  //Get the status of this conceptual row
1217  value->integer = entry->status;
1218  }
1219  //Unknown object?
1220  else
1221  {
1222  //The specified object does not exist
1223  error = ERROR_OBJECT_NOT_FOUND;
1224  }
1225 
1226  //Return status code
1227  return error;
1228 }
1229 
1230 
1231 /**
1232  * @brief Get next vacmAccessEntry object
1233  * @param[in] object Pointer to the MIB object descriptor
1234  * @param[in] oid Object identifier
1235  * @param[in] oidLen Length of the OID, in bytes
1236  * @param[out] nextOid OID of the next object in the MIB
1237  * @param[out] nextOidLen Length of the next object identifier, in bytes
1238  * @return Error code
1239  **/
1240 
1242  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
1243 {
1244  error_t error;
1245  uint_t i;
1246  size_t n;
1247  bool_t acceptable;
1248  SnmpAgentContext *context;
1249  SnmpAccessEntry *entry;
1250  SnmpAccessEntry *nextEntry;
1251 
1252  //Initialize variables
1253  nextEntry = NULL;
1254 
1255  //Point to the SNMP agent context
1257  //Sanity check
1258  if(context == NULL)
1259  return ERROR_OBJECT_NOT_FOUND;
1260 
1261  //Make sure the buffer is large enough to hold the OID prefix
1262  if(*nextOidLen < object->oidLen)
1263  return ERROR_BUFFER_OVERFLOW;
1264 
1265  //Copy OID prefix
1266  memcpy(nextOid, object->oid, object->oidLen);
1267 
1268  //Loop through the list of access rights
1269  for(i = 0; i < SNMP_AGENT_ACCESS_TABLE_SIZE; i++)
1270  {
1271  //Point to the current entry
1272  entry = &context->accessTable[i];
1273 
1274  //Check the status of the row
1275  if(entry->status != MIB_ROW_STATUS_UNUSED)
1276  {
1277  //Append the instance identifier to the OID prefix
1278  n = object->oidLen;
1279 
1280  //vacmGroupName is used as 1st instance identifier
1281  error = mibEncodeString(nextOid, *nextOidLen, &n,
1282  entry->groupName, FALSE);
1283  //Invalid instance identifier?
1284  if(error)
1285  return error;
1286 
1287  //vacmAccessContextPrefix is used as 2nd instance identifier
1288  error = mibEncodeString(nextOid, *nextOidLen, &n,
1289  entry->contextPrefix, FALSE);
1290  //Invalid instance identifier?
1291  if(error)
1292  return error;
1293 
1294  //vacmAccessSecurityModel is used as 3rd instance identifier
1295  error = mibEncodeIndex(nextOid, *nextOidLen, &n,
1296  entry->securityModel);
1297  //Invalid instance identifier?
1298  if(error)
1299  return error;
1300 
1301  //vacmAccessSecurityLevel is used as 4th instance identifier
1302  error = mibEncodeIndex(nextOid, *nextOidLen, &n,
1303  entry->securityLevel);
1304  //Invalid instance identifier?
1305  if(error)
1306  return error;
1307 
1308  //Check whether the resulting object identifier lexicographically
1309  //follows the specified OID
1310  if(oidComp(nextOid, n, oid, oidLen) > 0)
1311  {
1312  //Perform lexicographic comparison
1313  if(nextEntry == NULL)
1314  acceptable = TRUE;
1315  else if(strlen(entry->groupName) < strlen(nextEntry->groupName))
1316  acceptable = TRUE;
1317  else if(strlen(entry->groupName) > strlen(nextEntry->groupName))
1318  acceptable = FALSE;
1319  else if(strcmp(entry->groupName, nextEntry->groupName) < 0)
1320  acceptable = TRUE;
1321  else if(strcmp(entry->groupName, nextEntry->groupName) > 0)
1322  acceptable = FALSE;
1323  else if(strlen(entry->contextPrefix) < strlen(nextEntry->contextPrefix))
1324  acceptable = TRUE;
1325  else if(strlen(entry->contextPrefix) > strlen(nextEntry->contextPrefix))
1326  acceptable = FALSE;
1327  else if(strcmp(entry->contextPrefix, nextEntry->contextPrefix) < 0)
1328  acceptable = TRUE;
1329  else if(strcmp(entry->contextPrefix, nextEntry->contextPrefix) > 0)
1330  acceptable = FALSE;
1331  else if(entry->securityModel < nextEntry->securityModel)
1332  acceptable = TRUE;
1333  else if(entry->securityModel > nextEntry->securityModel)
1334  acceptable = FALSE;
1335  else if(entry->securityLevel < nextEntry->securityLevel)
1336  acceptable = TRUE;
1337  else
1338  acceptable = FALSE;
1339 
1340  //Save the closest object identifier that follows the specified
1341  //OID in lexicographic order
1342  if(acceptable)
1343  nextEntry = entry;
1344  }
1345  }
1346  }
1347 
1348  //The specified OID does not lexicographically precede the name
1349  //of some object?
1350  if(nextEntry == NULL)
1351  return ERROR_OBJECT_NOT_FOUND;
1352 
1353  //Append the instance identifier to the OID prefix
1354  n = object->oidLen;
1355 
1356  //vacmGroupName is used as 1st instance identifier
1357  error = mibEncodeString(nextOid, *nextOidLen, &n,
1358  nextEntry->groupName, FALSE);
1359  //Invalid instance identifier?
1360  if(error)
1361  return error;
1362 
1363  //vacmAccessContextPrefix is used as 2nd instance identifier
1364  error = mibEncodeString(nextOid, *nextOidLen, &n,
1365  nextEntry->contextPrefix, FALSE);
1366  //Invalid instance identifier?
1367  if(error)
1368  return error;
1369 
1370  //vacmAccessSecurityModel is used as 3rd instance identifier
1371  error = mibEncodeIndex(nextOid, *nextOidLen, &n, nextEntry->securityModel);
1372  //Invalid instance identifier?
1373  if(error)
1374  return error;
1375 
1376  //vacmAccessSecurityLevel is used as 4th instance identifier
1377  error = mibEncodeIndex(nextOid, *nextOidLen, &n, nextEntry->securityLevel);
1378  //Invalid instance identifier?
1379  if(error)
1380  return error;
1381 
1382  //Save the length of the resulting object identifier
1383  *nextOidLen = n;
1384  //Next object found
1385  return NO_ERROR;
1386 }
1387 
1388 
1389 /**
1390  * @brief Set vacmViewSpinLock object value
1391  * @param[in] object Pointer to the MIB object descriptor
1392  * @param[in] oid Object identifier (object name and instance identifier)
1393  * @param[in] oidLen Length of the OID, in bytes
1394  * @param[in] value Object value
1395  * @param[in] valueLen Length of the object value, in bytes
1396  * @param[in] commit This flag tells whether the changes shall be committed
1397  * to the MIB base
1398  * @return Error code
1399  **/
1400 
1401 error_t snmpVacmMibSetViewSpinLock(const MibObject *object, const uint8_t *oid,
1402  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
1403 {
1404  //Test and increment spin lock
1406  value->integer, commit);
1407 }
1408 
1409 
1410 /**
1411  * @brief Get vacmViewSpinLock object value
1412  * @param[in] object Pointer to the MIB object descriptor
1413  * @param[in] oid Object identifier (object name and instance identifier)
1414  * @param[in] oidLen Length of the OID, in bytes
1415  * @param[out] value Object value
1416  * @param[in,out] valueLen Length of the object value, in bytes
1417  * @return Error code
1418  **/
1419 
1421  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
1422 {
1423  //Get the current value of the spin lock
1425 
1426  //Return status code
1427  return NO_ERROR;
1428 }
1429 
1430 
1431 /**
1432  * @brief Set vacmViewTreeFamilyEntry object value
1433  * @param[in] object Pointer to the MIB object descriptor
1434  * @param[in] oid Object identifier (object name and instance identifier)
1435  * @param[in] oidLen Length of the OID, in bytes
1436  * @param[in] value Object value
1437  * @param[in] valueLen Length of the object value, in bytes
1438  * @param[in] commit This flag tells whether the changes shall be committed
1439  * to the MIB base
1440  * @return Error code
1441  **/
1442 
1444  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
1445 {
1446  error_t error;
1447  size_t n;
1448  char_t viewName[SNMP_MAX_VIEW_NAME_LEN + 1];
1449  uint8_t subtree[SNMP_MAX_OID_SIZE];
1450  size_t subtreeLen;
1451  SnmpAgentContext *context;
1452  SnmpViewEntry *entry;
1453 
1454  //Point to the instance identifier
1455  n = object->oidLen;
1456 
1457  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1458  error = mibDecodeString(oid, oidLen, &n, viewName,
1460  //Invalid instance identifier?
1461  if(error)
1462  return error;
1463 
1464  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1465  error = mibDecodeObjectIdentifier(oid, oidLen, &n, subtree,
1466  SNMP_MAX_OID_SIZE, &subtreeLen, FALSE);
1467  //Invalid instance identifier?
1468  if(error)
1469  return error;
1470 
1471  //Sanity check
1472  if(n != oidLen)
1473  return ERROR_INSTANCE_NOT_FOUND;
1474 
1475  //Make sure the view name is valid
1476  if(viewName[0] == '\0')
1477  return ERROR_INSTANCE_NOT_FOUND;
1478 
1479  //Point to the SNMP agent context
1481  //Sanity check
1482  if(context == NULL)
1483  return ERROR_INSTANCE_NOT_FOUND;
1484 
1485  //Search the table for a matching row
1486  entry = snmpFindViewEntry(context, viewName, subtree, subtreeLen);
1487 
1488  //vacmViewTreeFamilyMask object?
1489  if(!strcmp(object->name, "vacmViewTreeFamilyMask"))
1490  {
1491  //Ensure the length of the bit mask is valid
1492  if(valueLen > SNMP_MAX_BIT_MASK_SIZE)
1493  return ERROR_INVALID_LENGTH;
1494 
1495  //Test if the conceptual row exists in the agent
1496  if(entry != NULL)
1497  {
1498  //Commit phase?
1499  if(commit)
1500  {
1501  //Set the bit mask
1502  memcpy(entry->mask, value->octetString, valueLen);
1503  //Set the length of the bit mask
1504  entry->maskLen = valueLen;
1505  }
1506  }
1507  else
1508  {
1509  //Prepare phase?
1510  if(!commit)
1511  {
1512  //Save the bit mask for later use
1513  memcpy(snmpVacmMibBase.tempViewEntry.mask, value->octetString, valueLen);
1514  //Save the length of the bit mask
1516  }
1517  }
1518  }
1519  //vacmViewTreeFamilyType object?
1520  else if(!strcmp(object->name, "vacmViewTreeFamilyType"))
1521  {
1522  //Ensure the value of the object is acceptable
1523  if(value->integer != SNMP_VIEW_TYPE_INCLUDED &&
1524  value->integer != SNMP_VIEW_TYPE_EXCLUDED)
1525  {
1526  return ERROR_WRONG_VALUE;
1527  }
1528 
1529  //Test if the conceptual row exists in the agent
1530  if(entry != NULL)
1531  {
1532  //Commit phase?
1533  if(commit)
1534  {
1535  //Set the value of the column
1536  entry->type = (SnmpViewType) value->integer;
1537  }
1538  }
1539  else
1540  {
1541  //Prepare phase?
1542  if(!commit)
1543  {
1544  //Save the value of the column for later use
1546  }
1547  }
1548  }
1549  //vacmViewTreeFamilyStorageType object?
1550  else if(!strcmp(object->name, "vacmViewTreeFamilyStorageType"))
1551  {
1552  //The vacmViewTreeFamilyStorageType object specifies the storage type
1553  //for this conceptual row
1554  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
1555  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
1556  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
1557  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
1558  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
1559  {
1560  return ERROR_WRONG_VALUE;
1561  }
1562  }
1563  //vacmViewTreeFamilyStatus object?
1564  else if(!strcmp(object->name, "vacmViewTreeFamilyStatus"))
1565  {
1566  MibRowStatus status;
1567 
1568  //Get row status
1569  status = (MibRowStatus) value->integer;
1570 
1571  //Check the value specified by the set operation
1572  if(status == MIB_ROW_STATUS_ACTIVE ||
1574  {
1575  //No matching row found?
1576  if(entry == NULL)
1577  return ERROR_INCONSISTENT_VALUE;
1578 
1579  //Commit phase?
1580  if(commit)
1581  {
1582  //Update the status of the conceptual row
1583  entry->status = status;
1584  }
1585  }
1586  else if(status == MIB_ROW_STATUS_CREATE_AND_GO ||
1588  {
1589  //Row already instantiated?
1590  if(entry != NULL)
1591  return ERROR_INCONSISTENT_VALUE;
1592 
1593  //Create a new row
1594  entry = snmpCreateViewEntry(context);
1595  //Row creation failed?
1596  if(entry == NULL)
1597  return ERROR_WRITE_FAILED;
1598 
1599  //Commit phase?
1600  if(commit)
1601  {
1602  //Save view name
1603  strcpy(entry->viewName, viewName);
1604  //Save subtree
1605  memcpy(entry->subtree, subtree, subtreeLen);
1606  //Save the length of the subtree
1607  entry->subtreeLen = subtreeLen;
1608 
1609  //Initialize columns with default values
1610  entry->maskLen = 0;
1611  entry->type = SNMP_VIEW_TYPE_INCLUDED;
1612 
1613  //Valid bit mask specified?
1615  {
1616  //Copy the bit mask
1617  memcpy(entry->mask, snmpVacmMibBase.tempViewEntry.mask,
1619 
1620  //Set the length of the bit mask
1622  }
1623 
1624  //Valid type specified?
1627 
1628  //The conceptual row has been successfully created
1629  if(status == MIB_ROW_STATUS_CREATE_AND_GO)
1630  entry->status = MIB_ROW_STATUS_ACTIVE;
1631  else
1633  }
1634  }
1635  else if(status == MIB_ROW_STATUS_DESTROY)
1636  {
1637  //Test if the conceptual row exists in the agent
1638  if(entry != NULL)
1639  {
1640  //Commit phase?
1641  if(commit)
1642  {
1643  //Delete the conceptual row from the table
1644  entry->status = MIB_ROW_STATUS_UNUSED;
1645  }
1646  }
1647  }
1648  else
1649  {
1650  //Unsupported action
1651  return ERROR_INCONSISTENT_VALUE;
1652  }
1653  }
1654  //Unknown object?
1655  else
1656  {
1657  //The specified object does not exist
1658  return ERROR_OBJECT_NOT_FOUND;
1659  }
1660 
1661  //Successful set operation
1662  return NO_ERROR;
1663 }
1664 
1665 
1666 /**
1667  * @brief Get vacmViewTreeFamilyEntry object value
1668  * @param[in] object Pointer to the MIB object descriptor
1669  * @param[in] oid Object identifier (object name and instance identifier)
1670  * @param[in] oidLen Length of the OID, in bytes
1671  * @param[out] value Object value
1672  * @param[in,out] valueLen Length of the object value, in bytes
1673  * @return Error code
1674  **/
1675 
1677  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
1678 {
1679  error_t error;
1680  size_t n;
1681  char_t viewName[SNMP_MAX_VIEW_NAME_LEN + 1];
1682  uint8_t subtree[SNMP_MAX_OID_SIZE];
1683  size_t subtreeLen;
1684  SnmpAgentContext *context;
1685  SnmpViewEntry *entry;
1686 
1687  //Point to the instance identifier
1688  n = object->oidLen;
1689 
1690  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1691  error = mibDecodeString(oid, oidLen, &n, viewName,
1693  //Invalid instance identifier?
1694  if(error)
1695  return error;
1696 
1697  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1698  error = mibDecodeObjectIdentifier(oid, oidLen, &n, subtree,
1699  SNMP_MAX_OID_SIZE, &subtreeLen, FALSE);
1700  //Invalid instance identifier?
1701  if(error)
1702  return error;
1703 
1704  //Sanity check
1705  if(n != oidLen)
1706  return ERROR_INSTANCE_NOT_FOUND;
1707 
1708  //Point to the SNMP agent context
1710  //Sanity check
1711  if(context == NULL)
1712  return ERROR_INSTANCE_NOT_FOUND;
1713 
1714  //Search the table for a matching row
1715  entry = snmpFindViewEntry(context, viewName, subtree, subtreeLen);
1716  //No matching row found?
1717  if(entry == NULL)
1718  return ERROR_INSTANCE_NOT_FOUND;
1719 
1720  //vacmViewTreeFamilyMask object?
1721  if(!strcmp(object->name, "vacmViewTreeFamilyMask"))
1722  {
1723  //Make sure the buffer is large enough to hold the entire object
1724  if(*valueLen >= entry->maskLen)
1725  {
1726  //Copy object value
1727  memcpy(value->octetString, entry->mask, entry->maskLen);
1728  //Return object length
1729  *valueLen = entry->maskLen;
1730  }
1731  else
1732  {
1733  //Report an error
1734  error = ERROR_BUFFER_OVERFLOW;
1735  }
1736  }
1737  //vacmViewTreeFamilyType object?
1738  else if(!strcmp(object->name, "vacmViewTreeFamilyType"))
1739  {
1740  //This object indicates whether the corresponding instances of
1741  //vacmViewTreeFamilySubtree and vacmViewTreeFamilyMask define a family
1742  //of view subtrees which is included in or excluded from the MIB view
1743  value->integer = entry->type;
1744  }
1745  //vacmViewTreeFamilyStorageType object?
1746  else if(!strcmp(object->name, "vacmViewTreeFamilyStorageType"))
1747  {
1748  //Get the storage type for this conceptual row
1749  value->integer = MIB_STORAGE_TYPE_VOLATILE;
1750  }
1751  //vacmViewTreeFamilyStatus object?
1752  else if(!strcmp(object->name, "vacmViewTreeFamilyStatus"))
1753  {
1754  //Get the status of this conceptual row
1755  value->integer = entry->status;
1756  }
1757  //Unknown object?
1758  else
1759  {
1760  //The specified object does not exist
1761  error = ERROR_OBJECT_NOT_FOUND;
1762  }
1763 
1764  //Return status code
1765  return error;
1766 }
1767 
1768 
1769 /**
1770  * @brief Get next vacmViewTreeFamilyEntry object
1771  * @param[in] object Pointer to the MIB object descriptor
1772  * @param[in] oid Object identifier
1773  * @param[in] oidLen Length of the OID, in bytes
1774  * @param[out] nextOid OID of the next object in the MIB
1775  * @param[out] nextOidLen Length of the next object identifier, in bytes
1776  * @return Error code
1777  **/
1778 
1780  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
1781 {
1782  error_t error;
1783  uint_t i;
1784  size_t n;
1785  bool_t acceptable;
1786  SnmpAgentContext *context;
1787  SnmpViewEntry *entry;
1788  SnmpViewEntry *nextEntry;
1789 
1790  //Initialize variables
1791  nextEntry = NULL;
1792 
1793  //Point to the SNMP agent context
1795  //Sanity check
1796  if(context == NULL)
1797  return ERROR_OBJECT_NOT_FOUND;
1798 
1799  //Make sure the buffer is large enough to hold the OID prefix
1800  if(*nextOidLen < object->oidLen)
1801  return ERROR_BUFFER_OVERFLOW;
1802 
1803  //Copy OID prefix
1804  memcpy(nextOid, object->oid, object->oidLen);
1805 
1806  //Loop through the list of MIB views
1807  for(i = 0; i < SNMP_AGENT_VIEW_TABLE_SIZE; i++)
1808  {
1809  //Point to the current entry
1810  entry = &context->viewTable[i];
1811 
1812  //Check the status of the row
1813  if(entry->status != MIB_ROW_STATUS_UNUSED)
1814  {
1815  //Append the instance identifier to the OID prefix
1816  n = object->oidLen;
1817 
1818  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1819  error = mibEncodeString(nextOid, *nextOidLen, &n,
1820  entry->viewName, FALSE);
1821  //Invalid instance identifier?
1822  if(error)
1823  return error;
1824 
1825  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1826  error = mibEncodeObjectIdentifier(nextOid, *nextOidLen, &n,
1827  entry->subtree, entry->subtreeLen, FALSE);
1828  //Invalid instance identifier?
1829  if(error)
1830  return error;
1831 
1832  //Check whether the resulting object identifier lexicographically
1833  //follows the specified OID
1834  if(oidComp(nextOid, n, oid, oidLen) > 0)
1835  {
1836  //Perform lexicographic comparison
1837  if(nextEntry == NULL)
1838  acceptable = TRUE;
1839  else if(strlen(entry->viewName) < strlen(nextEntry->viewName))
1840  acceptable = TRUE;
1841  else if(strlen(entry->viewName) > strlen(nextEntry->viewName))
1842  acceptable = FALSE;
1843  else if(strcmp(entry->viewName, nextEntry->viewName) < 0)
1844  acceptable = TRUE;
1845  else if(strcmp(entry->viewName, nextEntry->viewName) > 0)
1846  acceptable = FALSE;
1847  else if(entry->subtreeLen < nextEntry->subtreeLen)
1848  acceptable = TRUE;
1849  else if(entry->subtreeLen > nextEntry->subtreeLen)
1850  acceptable = FALSE;
1851  else if(memcmp(entry->subtree, nextEntry->subtree, nextEntry->subtreeLen) < 0)
1852  acceptable = TRUE;
1853  else
1854  acceptable = FALSE;
1855 
1856  //Save the closest object identifier that follows the specified
1857  //OID in lexicographic order
1858  if(acceptable)
1859  nextEntry = entry;
1860  }
1861  }
1862  }
1863 
1864  //The specified OID does not lexicographically precede the name
1865  //of some object?
1866  if(nextEntry == NULL)
1867  return ERROR_OBJECT_NOT_FOUND;
1868 
1869  //Append the instance identifier to the OID prefix
1870  n = object->oidLen;
1871 
1872  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1873  error = mibEncodeString(nextOid, *nextOidLen, &n,
1874  nextEntry->viewName, FALSE);
1875  //Invalid instance identifier?
1876  if(error)
1877  return error;
1878 
1879  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1880  error = mibEncodeObjectIdentifier(nextOid, *nextOidLen, &n,
1881  nextEntry->subtree, nextEntry->subtreeLen, FALSE);
1882  //Invalid instance identifier?
1883  if(error)
1884  return error;
1885 
1886  //Save the length of the resulting object identifier
1887  *nextOidLen = n;
1888  //Next object found
1889  return NO_ERROR;
1890 }
1891 
1892 #endif
error_t snmpVacmMibGetAccessEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get vacmAccessEntry object value.
char_t groupName[SNMP_MAX_GROUP_NAME_LEN+1]
SnmpAccessEntry * snmpCreateAccessEntry(SnmpAgentContext *context)
Create a new access entry.
SNMP VACM MIB module implementation.
MibRowStatus status
error_t snmpVacmMibGetNextAccessEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next vacmAccessEntry object.
error_t snmpVacmMibSetViewSpinLock(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set vacmViewSpinLock object value.
error_t mibDecodeIndex(const uint8_t *oid, size_t oidLen, size_t *pos, uint_t *index)
Decode instance identifier (index)
Definition: mib_common.c:62
char char_t
Definition: compiler_port.h:41
error_t snmpVacmMibGetViewSpinLock(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get vacmViewSpinLock object value.
error_t snmpVacmMibGetNextViewTreeFamilyEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next vacmViewTreeFamilyEntry object.
#define SNMP_AGENT_ACCESS_TABLE_SIZE
Definition: snmp_agent.h:95
TCP/IP stack core.
uint8_t mask[SNMP_MAX_BIT_MASK_SIZE]
Debugging facilities.
#define SNMP_MAX_OID_SIZE
Definition: snmp_common.h:114
#define SNMP_MAX_VIEW_NAME_LEN
Definition: snmp_common.h:100
SnmpViewType type
MibRowStatus
Row status.
Definition: mib_common.h:98
User-based security model.
#define MibObject
Definition: mib_common.h:44
General definitions for cryptographic algorithms.
error_t snmpVacmMibSetAccessEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set vacmAccessEntry object value.
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.
uint8_t subtree[SNMP_MAX_OID_SIZE]
SnmpAccessEntry tempAccessEntry
#define SNMP_MAX_CONTEXT_NAME_LEN
Definition: snmp_common.h:72
error_t snmpVacmMibGetViewTreeFamilyEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get vacmViewTreeFamilyEntry object value.
char_t writeViewName[SNMP_MAX_VIEW_NAME_LEN+1]
SnmpViewType
View type.
Access table entry.
error_t snmpVacmMibSetViewTreeFamilyEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set vacmViewTreeFamilyEntry object value.
SnmpVacmMibBase snmpVacmMibBase
SNMP VACM MIB base.
#define SNMP_MAX_GROUP_NAME_LEN
Definition: snmp_common.h:93
char_t notifyViewName[SNMP_MAX_VIEW_NAME_LEN+1]
OID (Object Identifier)
SNMP VACM MIB module.
#define SNMP_MAX_BIT_MASK_SIZE
Definition: snmp_common.h:107
SnmpContextMatch contextMatch
#define TRUE
Definition: os_port.h:48
SnmpSecurityLevel securityLevel
SnmpSecurityModel securityModel
char_t securityName[SNMP_MAX_GROUP_NAME_LEN+1]
Transport security model.
#define SNMP_MAX_USER_NAME_LEN
Definition: snmp_common.h:79
size_t subtreeLen
void snmpVacmMibUnload(void *context)
Unload SNMP VACM MIB module.
ASN.1 (Abstract Syntax Notation One)
#define SNMP_AGENT_VIEW_TABLE_SIZE
Definition: snmp_agent.h:102
error_t snmpVacmMibGetNextContextEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next vacmContextEntry object.
SnmpGroupEntry * snmpFindGroupEntry(SnmpAgentContext *context, uint_t securityModel, const char_t *securityName, size_t securityNameLen)
Search the group table.
SNMP agent (Simple Network Management Protocol)
Group table entry.
char_t groupName[SNMP_MAX_GROUP_NAME_LEN+1]
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.
void snmpVacmMibLock(void)
Lock SNMP VACM MIB base.
SnmpViewEntry * snmpFindViewEntry(SnmpAgentContext *context, const char_t *viewName, const uint8_t *subtree, size_t subtreeLen)
Search the view table for a given entry.
SnmpViewEntry tempViewEntry
SnmpContextMatch
Context match.
error_t mibDecodeObjectIdentifier(const uint8_t *oid, size_t oidLen, size_t *pos, uint8_t *objectId, size_t maxObjectIdLen, size_t *objectIdLen, bool_t implied)
Decode instance identifier (object identifier)
Definition: mib_common.c:375
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:99
error_t snmpVacmMibLoad(void *context)
Load SNMP VACM MIB module.
size_t maskLen
#define TRACE_INFO(...)
Definition: debug.h:86
MibRowStatus status
error_t snmpVacmMibGetSecurityToGroupEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get vacmSecurityToGroupEntry object value.
Success.
Definition: error.h:42
int32_t netGetRandRange(int32_t min, int32_t max)
Get a random value in the specified range.
Definition: net.c:1554
MibRowStatus status
Ipv6Addr contextPrefix
Definition: ndp.h:515
error_t
Error codes.
Definition: error.h:40
char_t contextPrefix[SNMP_MAX_CONTEXT_NAME_LEN+1]
__start_packed struct @208 MibVariant
Variant data type.
unsigned int uint_t
Definition: compiler_port.h:43
error_t snmpVacmMibInit(void)
SNMP VACM MIB module initialization.
error_t mibEncodeObjectIdentifier(uint8_t *oid, size_t maxOidLen, size_t *pos, const uint8_t *objectId, size_t objectIdLen, bool_t implied)
Encode instance identifier (object identifier)
Definition: mib_common.c:295
SnmpViewEntry * snmpCreateViewEntry(SnmpAgentContext *context)
Create a new view entry.
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
error_t snmpVacmMibSetSecurityToGroupEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set vacmSecurityToGroupEntry object value.
char_t viewName[SNMP_MAX_VIEW_NAME_LEN+1]
#define SNMP_AGENT_GROUP_TABLE_SIZE
Definition: snmp_agent.h:88
SnmpSecurityModel securityModel
error_t snmpVacmMibGetContextEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get vacmContextEntry object value.
uint8_t value[]
Definition: dtls_misc.h:141
Common definitions for MIB modules.
SnmpGroupEntry * snmpCreateGroupEntry(SnmpAgentContext *context)
Create a new group entry.
SnmpSecurityModel
Security models.
char_t readViewName[SNMP_MAX_VIEW_NAME_LEN+1]
SnmpGroupEntry tempGroupEntry
#define SnmpAgentContext
Definition: snmp_agent.h:34
void snmpVacmMibUnlock(void)
Unlock SNMP VACM MIB base.
error_t mibEncodeIndex(uint8_t *oid, size_t maxOidLen, size_t *pos, uint_t index)
Encode instance identifier (index)
Definition: mib_common.c:45
error_t mibTestAndIncSpinLock(int32_t *spinLock, int32_t value, bool_t commit)
Test and increment spin lock.
Definition: mib_common.c:939
uint8_t n
uint8_t oid[1]
Definition: mib_common.h:184
#define FALSE
Definition: os_port.h:44
View table entry.
int bool_t
Definition: compiler_port.h:47
SnmpAgentContext * context
SnmpSecurityLevel
Security levels.
error_t snmpVacmMibGetNextSecurityToGroupEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next vacmSecurityToGroupEntry object.