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