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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
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
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
109 }
110 
111 
112 /**
113  * @brief Unlock SNMP VACM MIB base
114  **/
115 
117 {
118  //Clear temporary objects
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(osStrcmp(contextName, context->contextName) != 0)
166 
167  //vacmContextName object?
168  if(osStrcmp(object->name, "vacmContextName") == 0)
169  {
170 #if (SNMP_V3_SUPPORT == ENABLED)
171  //Retrieve the length of the context name
172  n = osStrlen(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  osMemcpy(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  osMemcpy(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 #if (SNMP_VACM_MIB_SET_SUPPORT == ENABLED)
282  error_t error;
283  size_t n;
284  uint_t securityModel;
285  char_t securityName[SNMP_MAX_USER_NAME_LEN + 1];
286  SnmpAgentContext *context;
287  SnmpGroupEntry *entry;
288 
289  //Point to the instance identifier
290  n = object->oidLen;
291 
292  //vacmSecurityModel is used as 1st instance identifier
293  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
294  //Invalid instance identifier?
295  if(error)
296  return error;
297 
298  //vacmSecurityName is used as 2nd instance identifier
299  error = mibDecodeString(oid, oidLen, &n, securityName,
301  //Invalid instance identifier?
302  if(error)
303  return error;
304 
305  //Sanity check
306  if(n != oidLen)
308 
309  //Make sure the security model is valid
310  if(securityModel != SNMP_SECURITY_MODEL_V1 &&
311  securityModel != SNMP_SECURITY_MODEL_V2C &&
312  securityModel != SNMP_SECURITY_MODEL_USM &&
313  securityModel != SNMP_SECURITY_MODEL_TSM)
314  {
315  //The security model is not supported
317  }
318 
319  //Make sure the security name is valid
320  if(securityName[0] == '\0')
322 
323  //Point to the SNMP agent context
325  //Sanity check
326  if(context == NULL)
328 
329  //Search the table for a matching row
330  entry = snmpFindGroupEntry(context, securityModel, securityName,
331  osStrlen(securityName));
332 
333  //vacmGroupName object?
334  if(osStrcmp(object->name, "vacmGroupName") == 0)
335  {
336  //Ensure the length of the group name is valid
337  if(valueLen > SNMP_MAX_GROUP_NAME_LEN)
338  return ERROR_WRONG_LENGTH;
339 
340  //Test if the conceptual row exists in the agent
341  if(entry != NULL)
342  {
343  //Commit phase?
344  if(commit)
345  {
346  //Set group name
347  osMemcpy(entry->groupName, value->octetString, valueLen);
348  //Properly terminate the string with a NULL character
349  entry->groupName[valueLen] = '\0';
350  }
351  }
352  else
353  {
354  //Prepare phase?
355  if(!commit)
356  {
357  //Save the group name for later use
359  value->octetString, valueLen);
360 
361  //Properly terminate the string with a NULL character
362  snmpVacmMibBase.tempGroupEntry.groupName[valueLen] = '\0';
363  }
364  }
365  }
366  //vacmSecurityToGroupStorageType object?
367  else if(osStrcmp(object->name, "vacmSecurityToGroupStorageType") == 0)
368  {
369  //The vacmSecurityToGroupStorageType object specifies the storage type
370  //for this conceptual row
371  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
372  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
373  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
374  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
375  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
376  {
377  return ERROR_WRONG_VALUE;
378  }
379  }
380  //vacmSecurityToGroupStatus object?
381  else if(osStrcmp(object->name, "vacmSecurityToGroupStatus") == 0)
382  {
383  MibRowStatus status;
384 
385  //Get row status
386  status = (MibRowStatus) value->integer;
387 
388  //Check the value specified by the set operation
389  if(status == MIB_ROW_STATUS_ACTIVE ||
391  {
392  //No matching row found?
393  if(entry == NULL)
395 
396  //Commit phase?
397  if(commit)
398  {
399  //Valid group name specified?
402 
403  //A newly created row cannot be made active until a value has been
404  //set for vacmGroupName
405  if(entry->groupName[0] == '\0')
407 
408  //Update the status of the conceptual row
409  entry->status = status;
410  }
411  }
412  else if(status == MIB_ROW_STATUS_CREATE_AND_GO)
413  {
414  //Row already instantiated?
415  if(entry != NULL)
417 
418  //Create a new row
419  entry = snmpCreateGroupEntry(context);
420  //Row creation failed?
421  if(entry == NULL)
422  return ERROR_WRITE_FAILED;
423 
424  //Commit phase?
425  if(commit)
426  {
427  //Valid group name specified?
429  {
430  //Save security model
431  entry->securityModel = (SnmpSecurityModel) securityModel;
432  //Save security name
433  osStrcpy(entry->securityName, securityName);
434  //Copy the group name
436 
437  //The conceptual row is now available for use by the managed device
438  entry->status = MIB_ROW_STATUS_ACTIVE;
439  }
440  else
441  {
442  //The newly created row cannot be made active
444  }
445  }
446  }
447  else if(status == MIB_ROW_STATUS_CREATE_AND_WAIT)
448  {
449  //Row already instantiated?
450  if(entry != NULL)
452 
453  //Create a new row
454  entry = snmpCreateGroupEntry(context);
455  //Row creation failed?
456  if(entry == NULL)
457  return ERROR_WRITE_FAILED;
458 
459  //Commit phase?
460  if(commit)
461  {
462  //Save security model
463  entry->securityModel = (SnmpSecurityModel) securityModel;
464  //Save security name
465  osStrcpy(entry->securityName, securityName);
466 
467  //Valid group name specified?
469  {
470  //Copy the group name
472 
473  //Instances of all corresponding columns are now configured
475  }
476  else
477  {
478  //Initialize columns with default values
479  entry->groupName[0] = '\0';
480 
481  //Until instances of all corresponding columns are appropriately
482  //configured, the value of the corresponding instance of the
483  //vacmSecurityToGroupStatus column is notReady
485  }
486  }
487  }
488  else if(status == MIB_ROW_STATUS_DESTROY)
489  {
490  //Test if the conceptual row exists in the agent
491  if(entry != NULL)
492  {
493  //Commit phase?
494  if(commit)
495  {
496  //Delete the conceptual row from the table
497  entry->status = MIB_ROW_STATUS_UNUSED;
498  }
499  }
500  }
501  else
502  {
503  //Unsupported action
505  }
506  }
507  //Unknown object?
508  else
509  {
510  //The specified object does not exist
511  error = ERROR_OBJECT_NOT_FOUND;
512  }
513 
514  //Return status code
515  return error;
516 #else
517  //SET operation is not supported
518  return ERROR_WRITE_FAILED;
519 #endif
520 }
521 
522 
523 /**
524  * @brief Get vacmSecurityToGroupEntry object value
525  * @param[in] object Pointer to the MIB object descriptor
526  * @param[in] oid Object identifier (object name and instance identifier)
527  * @param[in] oidLen Length of the OID, in bytes
528  * @param[out] value Object value
529  * @param[in,out] valueLen Length of the object value, in bytes
530  * @return Error code
531  **/
532 
534  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
535 {
536  error_t error;
537  size_t n;
538  uint_t securityModel;
539  char_t securityName[SNMP_MAX_USER_NAME_LEN + 1];
540  SnmpAgentContext *context;
541  SnmpGroupEntry *entry;
542 
543  //Point to the instance identifier
544  n = object->oidLen;
545 
546  //vacmSecurityModel is used as 1st instance identifier
547  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
548  //Invalid instance identifier?
549  if(error)
550  return error;
551 
552  //vacmSecurityName is used as 2nd instance identifier
553  error = mibDecodeString(oid, oidLen, &n, securityName,
555  //Invalid instance identifier?
556  if(error)
557  return error;
558 
559  //Sanity check
560  if(n != oidLen)
562 
563  //Point to the SNMP agent context
565  //Sanity check
566  if(context == NULL)
568 
569  //Search the table for a matching row
570  entry = snmpFindGroupEntry(context, securityModel, securityName,
571  osStrlen(securityName));
572  //No matching row found?
573  if(entry == NULL)
575 
576  //vacmGroupName object?
577  if(osStrcmp(object->name, "vacmGroupName") == 0)
578  {
579  //Retrieve the length of the group name
580  n = osStrlen(entry->groupName);
581 
582  //Make sure the buffer is large enough to hold the entire object
583  if(*valueLen >= n)
584  {
585  //Copy object value
586  osMemcpy(value->octetString, entry->groupName, n);
587  //Return object length
588  *valueLen = n;
589  }
590  else
591  {
592  //Report an error
593  error = ERROR_BUFFER_OVERFLOW;
594  }
595  }
596  //vacmSecurityToGroupStorageType object?
597  else if(osStrcmp(object->name, "vacmSecurityToGroupStorageType") == 0)
598  {
599  //Get the storage type for this conceptual row
600  value->integer = MIB_STORAGE_TYPE_VOLATILE;
601  }
602  //vacmSecurityToGroupStatus object?
603  else if(osStrcmp(object->name, "vacmSecurityToGroupStatus") == 0)
604  {
605  //Get the status of this conceptual row
606  value->integer = entry->status;
607  }
608  //Unknown object?
609  else
610  {
611  //The specified object does not exist
612  error = ERROR_OBJECT_NOT_FOUND;
613  }
614 
615  //Return status code
616  return error;
617 }
618 
619 
620 /**
621  * @brief Get next vacmSecurityToGroupEntry object
622  * @param[in] object Pointer to the MIB object descriptor
623  * @param[in] oid Object identifier
624  * @param[in] oidLen Length of the OID, in bytes
625  * @param[out] nextOid OID of the next object in the MIB
626  * @param[out] nextOidLen Length of the next object identifier, in bytes
627  * @return Error code
628  **/
629 
631  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
632 {
633  error_t error;
634  uint_t i;
635  size_t n;
636  bool_t acceptable;
637  SnmpAgentContext *context;
638  SnmpGroupEntry *entry;
639  SnmpGroupEntry *nextEntry;
640 
641  //Initialize variables
642  nextEntry = NULL;
643 
644  //Point to the SNMP agent context
646  //Sanity check
647  if(context == NULL)
648  return ERROR_OBJECT_NOT_FOUND;
649 
650  //Make sure the buffer is large enough to hold the OID prefix
651  if(*nextOidLen < object->oidLen)
652  return ERROR_BUFFER_OVERFLOW;
653 
654  //Copy OID prefix
655  osMemcpy(nextOid, object->oid, object->oidLen);
656 
657  //Loop through the list of groups
658  for(i = 0; i < SNMP_AGENT_GROUP_TABLE_SIZE; i++)
659  {
660  //Point to the current entry
661  entry = &context->groupTable[i];
662 
663  //Check the status of the row
664  if(entry->status != MIB_ROW_STATUS_UNUSED)
665  {
666  //Append the instance identifier to the OID prefix
667  n = object->oidLen;
668 
669  //vacmSecurityModel is used as 1st instance identifier
670  error = mibEncodeIndex(nextOid, *nextOidLen, &n, entry->securityModel);
671  //Any error to report?
672  if(error)
673  return error;
674 
675  //vacmSecurityName is used as 2nd instance identifier
676  error = mibEncodeString(nextOid, *nextOidLen, &n, entry->securityName,
677  FALSE);
678  //Any error to report?
679  if(error)
680  return error;
681 
682  //Check whether the resulting object identifier lexicographically
683  //follows the specified OID
684  if(oidComp(nextOid, n, oid, oidLen) > 0)
685  {
686  //Perform lexicographic comparison
687  if(nextEntry == NULL)
688  {
689  acceptable = TRUE;
690  }
691  else if(entry->securityModel < nextEntry->securityModel)
692  {
693  acceptable = TRUE;
694  }
695  else if(entry->securityModel > nextEntry->securityModel)
696  {
697  acceptable = FALSE;
698  }
699  else if(osStrlen(entry->securityName) < osStrlen(nextEntry->securityName))
700  {
701  acceptable = TRUE;
702  }
703  else if(osStrlen(entry->securityName) > osStrlen(nextEntry->securityName))
704  {
705  acceptable = FALSE;
706  }
707  else if(osStrcmp(entry->securityName, nextEntry->securityName) < 0)
708  {
709  acceptable = TRUE;
710  }
711  else
712  {
713  acceptable = FALSE;
714  }
715 
716  //Save the closest object identifier that follows the specified
717  //OID in lexicographic order
718  if(acceptable)
719  nextEntry = entry;
720  }
721  }
722  }
723 
724  //The specified OID does not lexicographically precede the name
725  //of some object?
726  if(nextEntry == NULL)
727  return ERROR_OBJECT_NOT_FOUND;
728 
729  //Append the instance identifier to the OID prefix
730  n = object->oidLen;
731 
732  //vacmSecurityModel is used as 1st instance identifier
733  error = mibEncodeIndex(nextOid, *nextOidLen, &n, nextEntry->securityModel);
734  //Any error to report?
735  if(error)
736  return error;
737 
738  //vacmSecurityName is used as 2nd instance identifier
739  error = mibEncodeString(nextOid, *nextOidLen, &n,
740  nextEntry->securityName, FALSE);
741  //Any error to report?
742  if(error)
743  return error;
744 
745  //Save the length of the resulting object identifier
746  *nextOidLen = n;
747  //Next object found
748  return NO_ERROR;
749 }
750 
751 
752 /**
753  * @brief Set vacmAccessEntry object value
754  * @param[in] object Pointer to the MIB object descriptor
755  * @param[in] oid Object identifier (object name and instance identifier)
756  * @param[in] oidLen Length of the OID, in bytes
757  * @param[in] value Object value
758  * @param[in] valueLen Length of the object value, in bytes
759  * @param[in] commit This flag tells whether the changes shall be committed
760  * to the MIB base
761  * @return Error code
762  **/
763 
764 error_t snmpVacmMibSetAccessEntry(const MibObject *object, const uint8_t *oid,
765  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
766 {
767 #if (SNMP_VACM_MIB_SET_SUPPORT == ENABLED)
768  error_t error;
769  size_t n;
770  char_t groupName[SNMP_MAX_GROUP_NAME_LEN + 1];
772  uint_t securityModel;
773  uint_t securityLevel;
774  SnmpAgentContext *context;
775  SnmpAccessEntry *entry;
776 
777  //Point to the instance identifier
778  n = object->oidLen;
779 
780  //vacmGroupName is used as 1st instance identifier
781  error = mibDecodeString(oid, oidLen, &n, groupName,
783  //Invalid instance identifier?
784  if(error)
785  return error;
786 
787  //vacmAccessContextPrefix is used as 2nd instance identifier
790  //Invalid instance identifier?
791  if(error)
792  return error;
793 
794  //vacmAccessSecurityModel is used as 3rd instance identifier
795  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
796  //Invalid instance identifier?
797  if(error)
798  return error;
799 
800  //vacmAccessSecurityLevel is used as 4th instance identifier
801  error = mibDecodeIndex(oid, oidLen, &n, &securityLevel);
802  //Invalid instance identifier?
803  if(error)
804  return error;
805 
806  //Sanity check
807  if(n != oidLen)
809 
810  //Make sure the group name is valid
811  if(groupName[0] == '\0')
813 
814  //Make sure the security model is valid
815  if(securityModel != SNMP_SECURITY_MODEL_ANY &&
816  securityModel != SNMP_SECURITY_MODEL_V1 &&
817  securityModel != SNMP_SECURITY_MODEL_V2C &&
818  securityModel != SNMP_SECURITY_MODEL_USM &&
819  securityModel != SNMP_SECURITY_MODEL_TSM)
820  {
821  //The security model is not supported
823  }
824 
825  //Make sure the security level is valid
826  if(securityLevel != SNMP_SECURITY_LEVEL_NO_AUTH_NO_PRIV &&
827  securityLevel != SNMP_SECURITY_LEVEL_AUTH_NO_PRIV &&
828  securityLevel != SNMP_SECURITY_LEVEL_AUTH_PRIV)
829  {
830  //The security level is not supported
832  }
833 
834  //Point to the SNMP agent context
836  //Sanity check
837  if(context == NULL)
839 
840  //Search the table for a matching row
841  entry = snmpFindAccessEntry(context, groupName, contextPrefix,
842  securityModel, securityLevel);
843 
844  //vacmAccessContextMatch object?
845  if(osStrcmp(object->name, "vacmAccessContextMatch") == 0)
846  {
847  //Ensure the value of the object is acceptable
848  if(value->integer != SNMP_CONTEXT_MATCH_EXACT &&
849  value->integer != SNMP_CONTEXT_MATCH_PREFIX)
850  {
851  return ERROR_WRONG_VALUE;
852  }
853 
854  //Test if the conceptual row exists in the agent
855  if(entry != NULL)
856  {
857  //Commit phase?
858  if(commit)
859  {
860  //Set the value of the column
861  entry->contextMatch = (SnmpContextMatch) value->integer;
862  }
863  }
864  else
865  {
866  //Prepare phase?
867  if(!commit)
868  {
869  //Save the value of the column for later use
871  }
872  }
873  }
874  //vacmAccessReadViewName object?
875  else if(osStrcmp(object->name, "vacmAccessReadViewName") == 0)
876  {
877  //Ensure the length of the read view name is valid
878  if(valueLen > SNMP_MAX_VIEW_NAME_LEN)
879  return ERROR_WRONG_LENGTH;
880 
881  //Test if the conceptual row exists in the agent
882  if(entry != NULL)
883  {
884  //Commit phase?
885  if(commit)
886  {
887  //Set read view name
888  osMemcpy(entry->readViewName, value->octetString, valueLen);
889  //Properly terminate the string with a NULL character
890  entry->readViewName[valueLen] = '\0';
891  }
892  }
893  else
894  {
895  //Prepare phase?
896  if(!commit)
897  {
898  //Save the read view name for later use
900  value->octetString, valueLen);
901 
902  //Properly terminate the string with a NULL character
904  }
905  }
906  }
907  //vacmAccessWriteViewName object?
908  else if(osStrcmp(object->name, "vacmAccessWriteViewName") == 0)
909  {
910  //Ensure the length of the write view name is valid
911  if(valueLen > SNMP_MAX_VIEW_NAME_LEN)
912  return ERROR_WRONG_LENGTH;
913 
914  //Test if the conceptual row exists in the agent
915  if(entry != NULL)
916  {
917  //Commit phase?
918  if(commit)
919  {
920  //Set write view name
921  osMemcpy(entry->writeViewName, value->octetString, valueLen);
922  //Properly terminate the string with a NULL character
923  entry->writeViewName[valueLen] = '\0';
924  }
925  }
926  else
927  {
928  //Prepare phase?
929  if(!commit)
930  {
931  //Save the write view name for later use
933  value->octetString, valueLen);
934 
935  //Properly terminate the string with a NULL character
937  }
938  }
939  }
940  //vacmAccessNotifyViewName object?
941  else if(osStrcmp(object->name, "vacmAccessNotifyViewName") == 0)
942  {
943  //Ensure the length of the notify view name is valid
944  if(valueLen > SNMP_MAX_VIEW_NAME_LEN)
945  return ERROR_WRONG_LENGTH;
946 
947  //Test if the conceptual row exists in the agent
948  if(entry != NULL)
949  {
950  //Commit phase?
951  if(commit)
952  {
953  //Set notify view name
954  osMemcpy(entry->notifyViewName, value->octetString, valueLen);
955  //Properly terminate the string with a NULL character
956  entry->notifyViewName[valueLen] = '\0';
957  }
958  }
959  else
960  {
961  //Prepare phase?
962  if(!commit)
963  {
964  //Save the notify view name for later use
966  value->octetString, valueLen);
967 
968  //Properly terminate the string with a NULL character
970  }
971  }
972  }
973  //vacmAccessStorageType object?
974  else if(osStrcmp(object->name, "vacmAccessStorageType") == 0)
975  {
976  //The vacmAccessStorageType object specifies the storage type
977  //for this conceptual row
978  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
979  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
980  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
981  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
982  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
983  {
984  return ERROR_WRONG_VALUE;
985  }
986  }
987  //vacmAccessStatus object?
988  else if(osStrcmp(object->name, "vacmAccessStatus") == 0)
989  {
990  MibRowStatus status;
991 
992  //Get row status
993  status = (MibRowStatus) value->integer;
994 
995  //Check the value specified by the set operation
996  if(status == MIB_ROW_STATUS_ACTIVE ||
998  {
999  //No matching row found?
1000  if(entry == NULL)
1001  return ERROR_INCONSISTENT_VALUE;
1002 
1003  //Commit phase?
1004  if(commit)
1005  {
1006  //Update the status of the conceptual row
1007  entry->status = status;
1008  }
1009  }
1010  else if(status == MIB_ROW_STATUS_CREATE_AND_GO ||
1012  {
1013  //Row already instantiated?
1014  if(entry != NULL)
1015  return ERROR_INCONSISTENT_VALUE;
1016 
1017  //Create a new row
1018  entry = snmpCreateAccessEntry(context);
1019  //Row creation failed?
1020  if(entry == NULL)
1021  return ERROR_WRITE_FAILED;
1022 
1023  //Commit phase?
1024  if(commit)
1025  {
1026  //Save group name
1027  osStrcpy(entry->groupName, groupName);
1028  //Save context name prefix
1030  //Save security model
1031  entry->securityModel = (SnmpSecurityModel) securityModel;
1032  //Save security level
1033  entry->securityLevel = (SnmpSecurityLevel) securityLevel;
1034 
1035  //Initialize columns with default values
1037  entry->readViewName[0] = '\0';
1038  entry->writeViewName[0] = '\0';
1039  entry->notifyViewName[0] = '\0';
1040 
1041  //Valid context match specified?
1044 
1045  //Valid read view name specified?
1048 
1049  //Valid write view name specified?
1052 
1053  //Valid notify notify name specified?
1056 
1057  //The conceptual row has been successfully created
1058  if(status == MIB_ROW_STATUS_CREATE_AND_GO)
1059  {
1060  entry->status = MIB_ROW_STATUS_ACTIVE;
1061  }
1062  else
1063  {
1065  }
1066  }
1067  }
1068  else if(status == MIB_ROW_STATUS_DESTROY)
1069  {
1070  //Test if the conceptual row exists in the agent
1071  if(entry != NULL)
1072  {
1073  //Commit phase?
1074  if(commit)
1075  {
1076  //Delete the conceptual row from the table
1077  entry->status = MIB_ROW_STATUS_UNUSED;
1078  }
1079  }
1080  }
1081  else
1082  {
1083  //Unsupported action
1084  return ERROR_INCONSISTENT_VALUE;
1085  }
1086  }
1087  //Unknown object?
1088  else
1089  {
1090  //The specified object does not exist
1091  return ERROR_OBJECT_NOT_FOUND;
1092  }
1093 
1094  //Successful processing
1095  return NO_ERROR;
1096 #else
1097  //SET operation is not supported
1098  return ERROR_WRITE_FAILED;
1099 #endif
1100 }
1101 
1102 
1103 /**
1104  * @brief Get vacmAccessEntry object value
1105  * @param[in] object Pointer to the MIB object descriptor
1106  * @param[in] oid Object identifier (object name and instance identifier)
1107  * @param[in] oidLen Length of the OID, in bytes
1108  * @param[out] value Object value
1109  * @param[in,out] valueLen Length of the object value, in bytes
1110  * @return Error code
1111  **/
1112 
1114  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
1115 {
1116  error_t error;
1117  size_t n;
1118  char_t groupName[SNMP_MAX_GROUP_NAME_LEN + 1];
1120  uint_t securityModel;
1121  uint_t securityLevel;
1122  SnmpAgentContext *context;
1123  SnmpAccessEntry *entry;
1124 
1125  //Point to the instance identifier
1126  n = object->oidLen;
1127 
1128  //vacmGroupName is used as 1st instance identifier
1129  error = mibDecodeString(oid, oidLen, &n, groupName,
1131  //Invalid instance identifier?
1132  if(error)
1133  return error;
1134 
1135  //vacmAccessContextPrefix is used as 2nd instance identifier
1138  //Invalid instance identifier?
1139  if(error)
1140  return error;
1141 
1142  //vacmAccessSecurityModel is used as 3rd instance identifier
1143  error = mibDecodeIndex(oid, oidLen, &n, &securityModel);
1144  //Invalid instance identifier?
1145  if(error)
1146  return error;
1147 
1148  //vacmAccessSecurityLevel is used as 4th instance identifier
1149  error = mibDecodeIndex(oid, oidLen, &n, &securityLevel);
1150  //Invalid instance identifier?
1151  if(error)
1152  return error;
1153 
1154  //Sanity check
1155  if(n != oidLen)
1156  return ERROR_INSTANCE_NOT_FOUND;
1157 
1158  //Point to the SNMP agent context
1160  //Sanity check
1161  if(context == NULL)
1162  return ERROR_INSTANCE_NOT_FOUND;
1163 
1164  //Search the table for a matching row
1165  entry = snmpFindAccessEntry(context, groupName, contextPrefix,
1166  securityModel, securityLevel);
1167  //No matching row found?
1168  if(entry == NULL)
1169  return ERROR_INSTANCE_NOT_FOUND;
1170 
1171  //vacmAccessContextMatch object?
1172  if(osStrcmp(object->name, "vacmAccessContextMatch") == 0)
1173  {
1174  //Get object value
1175  value->integer = entry->contextMatch;
1176  }
1177  //vacmAccessReadViewName object?
1178  else if(osStrcmp(object->name, "vacmAccessReadViewName") == 0)
1179  {
1180  //Retrieve the length of the read view name
1181  n = osStrlen(entry->readViewName);
1182 
1183  //Make sure the buffer is large enough to hold the entire object
1184  if(*valueLen >= n)
1185  {
1186  //Copy object value
1187  osMemcpy(value->octetString, entry->readViewName, n);
1188  //Return object length
1189  *valueLen = n;
1190  }
1191  else
1192  {
1193  //Report an error
1194  error = ERROR_BUFFER_OVERFLOW;
1195  }
1196  }
1197  //vacmAccessWriteViewName object?
1198  else if(osStrcmp(object->name, "vacmAccessWriteViewName") == 0)
1199  {
1200  //Retrieve the length of the write view name
1201  n = osStrlen(entry->writeViewName);
1202 
1203  //Make sure the buffer is large enough to hold the entire object
1204  if(*valueLen >= n)
1205  {
1206  //Copy object value
1207  osMemcpy(value->octetString, entry->writeViewName, n);
1208  //Return object length
1209  *valueLen = n;
1210  }
1211  else
1212  {
1213  //Report an error
1214  error = ERROR_BUFFER_OVERFLOW;
1215  }
1216  }
1217  //vacmAccessNotifyViewName object?
1218  else if(osStrcmp(object->name, "vacmAccessNotifyViewName") == 0)
1219  {
1220  //Retrieve the length of the notify view name
1221  n = osStrlen(entry->notifyViewName);
1222 
1223  //Make sure the buffer is large enough to hold the entire object
1224  if(*valueLen >= n)
1225  {
1226  //Copy object value
1227  osMemcpy(value->octetString, entry->notifyViewName, n);
1228  //Return object length
1229  *valueLen = n;
1230  }
1231  else
1232  {
1233  //Report an error
1234  error = ERROR_BUFFER_OVERFLOW;
1235  }
1236  }
1237  //vacmAccessStorageType object?
1238  else if(osStrcmp(object->name, "vacmAccessStorageType") == 0)
1239  {
1240  //Get the storage type for this conceptual row
1241  value->integer = MIB_STORAGE_TYPE_VOLATILE;
1242  }
1243  //vacmAccessStatus object?
1244  else if(osStrcmp(object->name, "vacmAccessStatus") == 0)
1245  {
1246  //Get the status of this conceptual row
1247  value->integer = entry->status;
1248  }
1249  //Unknown object?
1250  else
1251  {
1252  //The specified object does not exist
1253  error = ERROR_OBJECT_NOT_FOUND;
1254  }
1255 
1256  //Return status code
1257  return error;
1258 }
1259 
1260 
1261 /**
1262  * @brief Get next vacmAccessEntry object
1263  * @param[in] object Pointer to the MIB object descriptor
1264  * @param[in] oid Object identifier
1265  * @param[in] oidLen Length of the OID, in bytes
1266  * @param[out] nextOid OID of the next object in the MIB
1267  * @param[out] nextOidLen Length of the next object identifier, in bytes
1268  * @return Error code
1269  **/
1270 
1272  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
1273 {
1274  error_t error;
1275  uint_t i;
1276  size_t n;
1277  bool_t acceptable;
1278  SnmpAgentContext *context;
1279  SnmpAccessEntry *entry;
1280  SnmpAccessEntry *nextEntry;
1281 
1282  //Initialize variables
1283  nextEntry = NULL;
1284 
1285  //Point to the SNMP agent context
1287  //Sanity check
1288  if(context == NULL)
1289  return ERROR_OBJECT_NOT_FOUND;
1290 
1291  //Make sure the buffer is large enough to hold the OID prefix
1292  if(*nextOidLen < object->oidLen)
1293  return ERROR_BUFFER_OVERFLOW;
1294 
1295  //Copy OID prefix
1296  osMemcpy(nextOid, object->oid, object->oidLen);
1297 
1298  //Loop through the list of access rights
1299  for(i = 0; i < SNMP_AGENT_ACCESS_TABLE_SIZE; i++)
1300  {
1301  //Point to the current entry
1302  entry = &context->accessTable[i];
1303 
1304  //Check the status of the row
1305  if(entry->status != MIB_ROW_STATUS_UNUSED)
1306  {
1307  //Append the instance identifier to the OID prefix
1308  n = object->oidLen;
1309 
1310  //vacmGroupName is used as 1st instance identifier
1311  error = mibEncodeString(nextOid, *nextOidLen, &n,
1312  entry->groupName, FALSE);
1313  //Invalid instance identifier?
1314  if(error)
1315  return error;
1316 
1317  //vacmAccessContextPrefix is used as 2nd instance identifier
1318  error = mibEncodeString(nextOid, *nextOidLen, &n,
1319  entry->contextPrefix, FALSE);
1320  //Invalid instance identifier?
1321  if(error)
1322  return error;
1323 
1324  //vacmAccessSecurityModel is used as 3rd instance identifier
1325  error = mibEncodeIndex(nextOid, *nextOidLen, &n,
1326  entry->securityModel);
1327  //Invalid instance identifier?
1328  if(error)
1329  return error;
1330 
1331  //vacmAccessSecurityLevel is used as 4th instance identifier
1332  error = mibEncodeIndex(nextOid, *nextOidLen, &n,
1333  entry->securityLevel);
1334  //Invalid instance identifier?
1335  if(error)
1336  return error;
1337 
1338  //Check whether the resulting object identifier lexicographically
1339  //follows the specified OID
1340  if(oidComp(nextOid, n, oid, oidLen) > 0)
1341  {
1342  //Perform lexicographic comparison
1343  if(nextEntry == NULL)
1344  {
1345  acceptable = TRUE;
1346  }
1347  else if(osStrlen(entry->groupName) < osStrlen(nextEntry->groupName))
1348  {
1349  acceptable = TRUE;
1350  }
1351  else if(osStrlen(entry->groupName) > osStrlen(nextEntry->groupName))
1352  {
1353  acceptable = FALSE;
1354  }
1355  else if(osStrcmp(entry->groupName, nextEntry->groupName) < 0)
1356  {
1357  acceptable = TRUE;
1358  }
1359  else if(osStrcmp(entry->groupName, nextEntry->groupName) > 0)
1360  {
1361  acceptable = FALSE;
1362  }
1363  else if(osStrlen(entry->contextPrefix) < osStrlen(nextEntry->contextPrefix))
1364  {
1365  acceptable = TRUE;
1366  }
1367  else if(osStrlen(entry->contextPrefix) > osStrlen(nextEntry->contextPrefix))
1368  {
1369  acceptable = FALSE;
1370  }
1371  else if(osStrcmp(entry->contextPrefix, nextEntry->contextPrefix) < 0)
1372  {
1373  acceptable = TRUE;
1374  }
1375  else if(osStrcmp(entry->contextPrefix, nextEntry->contextPrefix) > 0)
1376  {
1377  acceptable = FALSE;
1378  }
1379  else if(entry->securityModel < nextEntry->securityModel)
1380  {
1381  acceptable = TRUE;
1382  }
1383  else if(entry->securityModel > nextEntry->securityModel)
1384  {
1385  acceptable = FALSE;
1386  }
1387  else if(entry->securityLevel < nextEntry->securityLevel)
1388  {
1389  acceptable = TRUE;
1390  }
1391  else
1392  {
1393  acceptable = FALSE;
1394  }
1395 
1396  //Save the closest object identifier that follows the specified
1397  //OID in lexicographic order
1398  if(acceptable)
1399  nextEntry = entry;
1400  }
1401  }
1402  }
1403 
1404  //The specified OID does not lexicographically precede the name
1405  //of some object?
1406  if(nextEntry == NULL)
1407  return ERROR_OBJECT_NOT_FOUND;
1408 
1409  //Append the instance identifier to the OID prefix
1410  n = object->oidLen;
1411 
1412  //vacmGroupName is used as 1st instance identifier
1413  error = mibEncodeString(nextOid, *nextOidLen, &n,
1414  nextEntry->groupName, FALSE);
1415  //Invalid instance identifier?
1416  if(error)
1417  return error;
1418 
1419  //vacmAccessContextPrefix is used as 2nd instance identifier
1420  error = mibEncodeString(nextOid, *nextOidLen, &n,
1421  nextEntry->contextPrefix, FALSE);
1422  //Invalid instance identifier?
1423  if(error)
1424  return error;
1425 
1426  //vacmAccessSecurityModel is used as 3rd instance identifier
1427  error = mibEncodeIndex(nextOid, *nextOidLen, &n, nextEntry->securityModel);
1428  //Invalid instance identifier?
1429  if(error)
1430  return error;
1431 
1432  //vacmAccessSecurityLevel is used as 4th instance identifier
1433  error = mibEncodeIndex(nextOid, *nextOidLen, &n, nextEntry->securityLevel);
1434  //Invalid instance identifier?
1435  if(error)
1436  return error;
1437 
1438  //Save the length of the resulting object identifier
1439  *nextOidLen = n;
1440  //Next object found
1441  return NO_ERROR;
1442 }
1443 
1444 
1445 /**
1446  * @brief Set vacmViewSpinLock object value
1447  * @param[in] object Pointer to the MIB object descriptor
1448  * @param[in] oid Object identifier (object name and instance identifier)
1449  * @param[in] oidLen Length of the OID, in bytes
1450  * @param[in] value Object value
1451  * @param[in] valueLen Length of the object value, in bytes
1452  * @param[in] commit This flag tells whether the changes shall be committed
1453  * to the MIB base
1454  * @return Error code
1455  **/
1456 
1457 error_t snmpVacmMibSetViewSpinLock(const MibObject *object, const uint8_t *oid,
1458  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
1459 {
1460  //Test and increment spin lock
1462  value->integer, commit);
1463 }
1464 
1465 
1466 /**
1467  * @brief Get vacmViewSpinLock object value
1468  * @param[in] object Pointer to the MIB object descriptor
1469  * @param[in] oid Object identifier (object name and instance identifier)
1470  * @param[in] oidLen Length of the OID, in bytes
1471  * @param[out] value Object value
1472  * @param[in,out] valueLen Length of the object value, in bytes
1473  * @return Error code
1474  **/
1475 
1477  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
1478 {
1479  //Get the current value of the spin lock
1481 
1482  //Successful processing
1483  return NO_ERROR;
1484 }
1485 
1486 
1487 /**
1488  * @brief Set vacmViewTreeFamilyEntry object value
1489  * @param[in] object Pointer to the MIB object descriptor
1490  * @param[in] oid Object identifier (object name and instance identifier)
1491  * @param[in] oidLen Length of the OID, in bytes
1492  * @param[in] value Object value
1493  * @param[in] valueLen Length of the object value, in bytes
1494  * @param[in] commit This flag tells whether the changes shall be committed
1495  * to the MIB base
1496  * @return Error code
1497  **/
1498 
1500  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
1501 {
1502 #if (SNMP_VACM_MIB_SET_SUPPORT == ENABLED)
1503  error_t error;
1504  size_t n;
1505  char_t viewName[SNMP_MAX_VIEW_NAME_LEN + 1];
1506  uint8_t subtree[SNMP_MAX_OID_SIZE];
1507  size_t subtreeLen;
1508  SnmpAgentContext *context;
1509  SnmpViewEntry *entry;
1510 
1511  //Point to the instance identifier
1512  n = object->oidLen;
1513 
1514  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1515  error = mibDecodeString(oid, oidLen, &n, viewName,
1517  //Invalid instance identifier?
1518  if(error)
1519  return error;
1520 
1521  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1522  error = mibDecodeObjectIdentifier(oid, oidLen, &n, subtree,
1523  SNMP_MAX_OID_SIZE, &subtreeLen, FALSE);
1524  //Invalid instance identifier?
1525  if(error)
1526  return error;
1527 
1528  //Sanity check
1529  if(n != oidLen)
1530  return ERROR_INSTANCE_NOT_FOUND;
1531 
1532  //Make sure the view name is valid
1533  if(viewName[0] == '\0')
1534  return ERROR_INSTANCE_NOT_FOUND;
1535 
1536  //Point to the SNMP agent context
1538  //Sanity check
1539  if(context == NULL)
1540  return ERROR_INSTANCE_NOT_FOUND;
1541 
1542  //Search the table for a matching row
1543  entry = snmpFindViewEntry(context, viewName, subtree, subtreeLen);
1544 
1545  //vacmViewTreeFamilyMask object?
1546  if(osStrcmp(object->name, "vacmViewTreeFamilyMask") == 0)
1547  {
1548  //Ensure the length of the bit mask is valid
1549  if(valueLen > SNMP_MAX_BIT_MASK_SIZE)
1550  return ERROR_WRONG_LENGTH;
1551 
1552  //Test if the conceptual row exists in the agent
1553  if(entry != NULL)
1554  {
1555  //Commit phase?
1556  if(commit)
1557  {
1558  //Set the bit mask
1559  osMemcpy(entry->mask, value->octetString, valueLen);
1560  //Set the length of the bit mask
1561  entry->maskLen = valueLen;
1562  }
1563  }
1564  else
1565  {
1566  //Prepare phase?
1567  if(!commit)
1568  {
1569  //Save the bit mask for later use
1570  osMemcpy(snmpVacmMibBase.tempViewEntry.mask, value->octetString, valueLen);
1571  //Save the length of the bit mask
1573  }
1574  }
1575  }
1576  //vacmViewTreeFamilyType object?
1577  else if(osStrcmp(object->name, "vacmViewTreeFamilyType") == 0)
1578  {
1579  //Ensure the value of the object is acceptable
1580  if(value->integer != SNMP_VIEW_TYPE_INCLUDED &&
1581  value->integer != SNMP_VIEW_TYPE_EXCLUDED)
1582  {
1583  return ERROR_WRONG_VALUE;
1584  }
1585 
1586  //Test if the conceptual row exists in the agent
1587  if(entry != NULL)
1588  {
1589  //Commit phase?
1590  if(commit)
1591  {
1592  //Set the value of the column
1593  entry->type = (SnmpViewType) value->integer;
1594  }
1595  }
1596  else
1597  {
1598  //Prepare phase?
1599  if(!commit)
1600  {
1601  //Save the value of the column for later use
1603  }
1604  }
1605  }
1606  //vacmViewTreeFamilyStorageType object?
1607  else if(osStrcmp(object->name, "vacmViewTreeFamilyStorageType") == 0)
1608  {
1609  //The vacmViewTreeFamilyStorageType object specifies the storage type
1610  //for this conceptual row
1611  if(value->integer != MIB_STORAGE_TYPE_OTHER &&
1612  value->integer != MIB_STORAGE_TYPE_VOLATILE &&
1613  value->integer != MIB_STORAGE_TYPE_NON_VOLATILE &&
1614  value->integer != MIB_STORAGE_TYPE_PERMANENT &&
1615  value->integer != MIB_STORAGE_TYPE_READ_ONLY)
1616  {
1617  return ERROR_WRONG_VALUE;
1618  }
1619  }
1620  //vacmViewTreeFamilyStatus object?
1621  else if(osStrcmp(object->name, "vacmViewTreeFamilyStatus") == 0)
1622  {
1623  MibRowStatus status;
1624 
1625  //Get row status
1626  status = (MibRowStatus) value->integer;
1627 
1628  //Check the value specified by the set operation
1629  if(status == MIB_ROW_STATUS_ACTIVE ||
1631  {
1632  //No matching row found?
1633  if(entry == NULL)
1634  return ERROR_INCONSISTENT_VALUE;
1635 
1636  //Commit phase?
1637  if(commit)
1638  {
1639  //Update the status of the conceptual row
1640  entry->status = status;
1641  }
1642  }
1643  else if(status == MIB_ROW_STATUS_CREATE_AND_GO ||
1645  {
1646  //Row already instantiated?
1647  if(entry != NULL)
1648  return ERROR_INCONSISTENT_VALUE;
1649 
1650  //Create a new row
1651  entry = snmpCreateViewEntry(context);
1652  //Row creation failed?
1653  if(entry == NULL)
1654  return ERROR_WRITE_FAILED;
1655 
1656  //Commit phase?
1657  if(commit)
1658  {
1659  //Save view name
1660  osStrcpy(entry->viewName, viewName);
1661  //Save subtree
1662  osMemcpy(entry->subtree, subtree, subtreeLen);
1663  //Save the length of the subtree
1664  entry->subtreeLen = subtreeLen;
1665 
1666  //Initialize columns with default values
1667  entry->maskLen = 0;
1668  entry->type = SNMP_VIEW_TYPE_INCLUDED;
1669 
1670  //Valid bit mask specified?
1672  {
1673  //Copy the bit mask
1676 
1677  //Set the length of the bit mask
1679  }
1680 
1681  //Valid type specified?
1684 
1685  //The conceptual row has been successfully created
1686  if(status == MIB_ROW_STATUS_CREATE_AND_GO)
1687  {
1688  entry->status = MIB_ROW_STATUS_ACTIVE;
1689  }
1690  else
1691  {
1693  }
1694  }
1695  }
1696  else if(status == MIB_ROW_STATUS_DESTROY)
1697  {
1698  //Test if the conceptual row exists in the agent
1699  if(entry != NULL)
1700  {
1701  //Commit phase?
1702  if(commit)
1703  {
1704  //Delete the conceptual row from the table
1705  entry->status = MIB_ROW_STATUS_UNUSED;
1706  }
1707  }
1708  }
1709  else
1710  {
1711  //Unsupported action
1712  return ERROR_INCONSISTENT_VALUE;
1713  }
1714  }
1715  //Unknown object?
1716  else
1717  {
1718  //The specified object does not exist
1719  return ERROR_OBJECT_NOT_FOUND;
1720  }
1721 
1722  //Successful processing
1723  return NO_ERROR;
1724 #else
1725  //SET operation is not supported
1726  return ERROR_WRITE_FAILED;
1727 #endif
1728 }
1729 
1730 
1731 /**
1732  * @brief Get vacmViewTreeFamilyEntry object value
1733  * @param[in] object Pointer to the MIB object descriptor
1734  * @param[in] oid Object identifier (object name and instance identifier)
1735  * @param[in] oidLen Length of the OID, in bytes
1736  * @param[out] value Object value
1737  * @param[in,out] valueLen Length of the object value, in bytes
1738  * @return Error code
1739  **/
1740 
1742  const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
1743 {
1744  error_t error;
1745  size_t n;
1746  char_t viewName[SNMP_MAX_VIEW_NAME_LEN + 1];
1747  uint8_t subtree[SNMP_MAX_OID_SIZE];
1748  size_t subtreeLen;
1749  SnmpAgentContext *context;
1750  SnmpViewEntry *entry;
1751 
1752  //Point to the instance identifier
1753  n = object->oidLen;
1754 
1755  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1756  error = mibDecodeString(oid, oidLen, &n, viewName,
1758  //Invalid instance identifier?
1759  if(error)
1760  return error;
1761 
1762  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1763  error = mibDecodeObjectIdentifier(oid, oidLen, &n, subtree,
1764  SNMP_MAX_OID_SIZE, &subtreeLen, FALSE);
1765  //Invalid instance identifier?
1766  if(error)
1767  return error;
1768 
1769  //Sanity check
1770  if(n != oidLen)
1771  return ERROR_INSTANCE_NOT_FOUND;
1772 
1773  //Point to the SNMP agent context
1775  //Sanity check
1776  if(context == NULL)
1777  return ERROR_INSTANCE_NOT_FOUND;
1778 
1779  //Search the table for a matching row
1780  entry = snmpFindViewEntry(context, viewName, subtree, subtreeLen);
1781  //No matching row found?
1782  if(entry == NULL)
1783  return ERROR_INSTANCE_NOT_FOUND;
1784 
1785  //vacmViewTreeFamilyMask object?
1786  if(osStrcmp(object->name, "vacmViewTreeFamilyMask") == 0)
1787  {
1788  //Make sure the buffer is large enough to hold the entire object
1789  if(*valueLen >= entry->maskLen)
1790  {
1791  //Copy object value
1792  osMemcpy(value->octetString, entry->mask, entry->maskLen);
1793  //Return object length
1794  *valueLen = entry->maskLen;
1795  }
1796  else
1797  {
1798  //Report an error
1799  error = ERROR_BUFFER_OVERFLOW;
1800  }
1801  }
1802  //vacmViewTreeFamilyType object?
1803  else if(osStrcmp(object->name, "vacmViewTreeFamilyType") == 0)
1804  {
1805  //This object indicates whether the corresponding instances of
1806  //vacmViewTreeFamilySubtree and vacmViewTreeFamilyMask define a family
1807  //of view subtrees which is included in or excluded from the MIB view
1808  value->integer = entry->type;
1809  }
1810  //vacmViewTreeFamilyStorageType object?
1811  else if(osStrcmp(object->name, "vacmViewTreeFamilyStorageType") == 0)
1812  {
1813  //Get the storage type for this conceptual row
1814  value->integer = MIB_STORAGE_TYPE_VOLATILE;
1815  }
1816  //vacmViewTreeFamilyStatus object?
1817  else if(osStrcmp(object->name, "vacmViewTreeFamilyStatus") == 0)
1818  {
1819  //Get the status of this conceptual row
1820  value->integer = entry->status;
1821  }
1822  //Unknown object?
1823  else
1824  {
1825  //The specified object does not exist
1826  error = ERROR_OBJECT_NOT_FOUND;
1827  }
1828 
1829  //Return status code
1830  return error;
1831 }
1832 
1833 
1834 /**
1835  * @brief Get next vacmViewTreeFamilyEntry object
1836  * @param[in] object Pointer to the MIB object descriptor
1837  * @param[in] oid Object identifier
1838  * @param[in] oidLen Length of the OID, in bytes
1839  * @param[out] nextOid OID of the next object in the MIB
1840  * @param[out] nextOidLen Length of the next object identifier, in bytes
1841  * @return Error code
1842  **/
1843 
1845  const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
1846 {
1847  error_t error;
1848  uint_t i;
1849  size_t n;
1850  bool_t acceptable;
1851  SnmpAgentContext *context;
1852  SnmpViewEntry *entry;
1853  SnmpViewEntry *nextEntry;
1854 
1855  //Initialize variables
1856  nextEntry = NULL;
1857 
1858  //Point to the SNMP agent context
1860  //Sanity check
1861  if(context == NULL)
1862  return ERROR_OBJECT_NOT_FOUND;
1863 
1864  //Make sure the buffer is large enough to hold the OID prefix
1865  if(*nextOidLen < object->oidLen)
1866  return ERROR_BUFFER_OVERFLOW;
1867 
1868  //Copy OID prefix
1869  osMemcpy(nextOid, object->oid, object->oidLen);
1870 
1871  //Loop through the list of MIB views
1872  for(i = 0; i < SNMP_AGENT_VIEW_TABLE_SIZE; i++)
1873  {
1874  //Point to the current entry
1875  entry = &context->viewTable[i];
1876 
1877  //Check the status of the row
1878  if(entry->status != MIB_ROW_STATUS_UNUSED)
1879  {
1880  //Append the instance identifier to the OID prefix
1881  n = object->oidLen;
1882 
1883  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1884  error = mibEncodeString(nextOid, *nextOidLen, &n,
1885  entry->viewName, FALSE);
1886  //Invalid instance identifier?
1887  if(error)
1888  return error;
1889 
1890  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1891  error = mibEncodeObjectIdentifier(nextOid, *nextOidLen, &n,
1892  entry->subtree, entry->subtreeLen, FALSE);
1893  //Invalid instance identifier?
1894  if(error)
1895  return error;
1896 
1897  //Check whether the resulting object identifier lexicographically
1898  //follows the specified OID
1899  if(oidComp(nextOid, n, oid, oidLen) > 0)
1900  {
1901  //Perform lexicographic comparison
1902  if(nextEntry == NULL)
1903  {
1904  acceptable = TRUE;
1905  }
1906  else if(osStrlen(entry->viewName) < osStrlen(nextEntry->viewName))
1907  {
1908  acceptable = TRUE;
1909  }
1910  else if(osStrlen(entry->viewName) > osStrlen(nextEntry->viewName))
1911  {
1912  acceptable = FALSE;
1913  }
1914  else if(osStrcmp(entry->viewName, nextEntry->viewName) < 0)
1915  {
1916  acceptable = TRUE;
1917  }
1918  else if(osStrcmp(entry->viewName, nextEntry->viewName) > 0)
1919  {
1920  acceptable = FALSE;
1921  }
1922  else if(entry->subtreeLen < nextEntry->subtreeLen)
1923  {
1924  acceptable = TRUE;
1925  }
1926  else if(entry->subtreeLen > nextEntry->subtreeLen)
1927  {
1928  acceptable = FALSE;
1929  }
1930  else if(osMemcmp(entry->subtree, nextEntry->subtree, nextEntry->subtreeLen) < 0)
1931  {
1932  acceptable = TRUE;
1933  }
1934  else
1935  {
1936  acceptable = FALSE;
1937  }
1938 
1939  //Save the closest object identifier that follows the specified
1940  //OID in lexicographic order
1941  if(acceptable)
1942  nextEntry = entry;
1943  }
1944  }
1945  }
1946 
1947  //The specified OID does not lexicographically precede the name
1948  //of some object?
1949  if(nextEntry == NULL)
1950  return ERROR_OBJECT_NOT_FOUND;
1951 
1952  //Append the instance identifier to the OID prefix
1953  n = object->oidLen;
1954 
1955  //vacmViewTreeFamilyViewName is used as 1st instance identifier
1956  error = mibEncodeString(nextOid, *nextOidLen, &n,
1957  nextEntry->viewName, FALSE);
1958  //Invalid instance identifier?
1959  if(error)
1960  return error;
1961 
1962  //vacmViewTreeFamilySubtree is used as 2nd instance identifier
1963  error = mibEncodeObjectIdentifier(nextOid, *nextOidLen, &n,
1964  nextEntry->subtree, nextEntry->subtreeLen, FALSE);
1965  //Invalid instance identifier?
1966  if(error)
1967  return error;
1968 
1969  //Save the length of the resulting object identifier
1970  *nextOidLen = n;
1971  //Next object found
1972  return NO_ERROR;
1973 }
1974 
1975 #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:53
uint32_t netGetRandRange(uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net.c:413
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:142
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
#define osMemcmp(p1, p2, length)
Definition: os_port.h:153
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:171
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:165
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:141
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:257
#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.
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:95
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:48
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:222
@ SNMP_VIEW_TYPE_INVALID
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:256
View table entry.
Access table entry.
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:369
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:50
#define osMemset(p, value, length)
Definition: os_port.h:135
TCP/IP stack core.
@ SNMP_VIEW_TYPE_EXCLUDED
#define osStrcpy(s1, s2)
Definition: os_port.h:207
@ 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