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