if_mib_impl.c
Go to the documentation of this file.
1 /**
2  * @file if_mib_impl.c
3  * @brief Interfaces Group 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"
37 #include "mibs/if_mib_module.h"
38 #include "mibs/if_mib_impl.h"
39 #include "core/crypto.h"
40 #include "encoding/asn1.h"
41 #include "encoding/oid.h"
42 #include "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (IF_MIB_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Interfaces Group MIB module initialization
50  * @return Error code
51  **/
52 
54 {
55  //Debug message
56  TRACE_INFO("Initializing IF-MIB base...\r\n");
57 
58  //Clear Interfaces Group MIB base
59  osMemset(&ifMibBase, 0, sizeof(ifMibBase));
60 
61  //Successful processing
62  return NO_ERROR;
63 }
64 
65 
66 /**
67  * @brief Get ifNumber object value
68  * @param[in] object Pointer to the MIB object descriptor
69  * @param[in] oid Object identifier (object name and instance identifier)
70  * @param[in] oidLen Length of the OID, in bytes
71  * @param[out] value Object value
72  * @param[in,out] valueLen Length of the object value, in bytes
73  * @return Error code
74  **/
75 
76 error_t ifMibGetIfNumber(const MibObject *object, const uint8_t *oid,
77  size_t oidLen, MibVariant *value, size_t *valueLen)
78 {
79  NetContext *context;
80 
81  //Point to the TCP/IP stack context
82  context = netGetDefaultContext();
83 
84  //Number of network interfaces present on this system
85  value->integer = context->numInterfaces;
86 
87  //Return status code
88  return NO_ERROR;
89 }
90 
91 
92 /**
93  * @brief Set ifEntry object value
94  * @param[in] object Pointer to the MIB object descriptor
95  * @param[in] oid Object identifier (object name and instance identifier)
96  * @param[in] oidLen Length of the OID, in bytes
97  * @param[in] value Object value
98  * @param[in] valueLen Length of the object value, in bytes
99  * @param[in] commit This flag tells whether the changes shall be committed
100  * to the MIB base
101  * @return Error code
102  **/
103 
104 error_t ifMibSetIfEntry(const MibObject *object, const uint8_t *oid,
105  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
106 {
107  //Not implemented
108  return ERROR_WRITE_FAILED;
109 }
110 
111 
112 /**
113  * @brief Get ifEntry object value
114  * @param[in] object Pointer to the MIB object descriptor
115  * @param[in] oid Object identifier (object name and instance identifier)
116  * @param[in] oidLen Length of the OID, in bytes
117  * @param[out] value Object value
118  * @param[in,out] valueLen Length of the object value, in bytes
119  * @return Error code
120  **/
121 
122 error_t ifMibGetIfEntry(const MibObject *object, const uint8_t *oid,
123  size_t oidLen, MibVariant *value, size_t *valueLen)
124 {
125  error_t error;
126  size_t n;
127  uint_t index;
128  NetContext *context;
129  NetInterface *interface;
130  NetInterface *physicalInterface;
131 
132  //Point to the TCP/IP stack context
133  context = netGetDefaultContext();
134 
135  //Point to the instance identifier
136  n = object->oidLen;
137 
138  //ifIndex is used as instance identifier
139  error = mibDecodeIndex(oid, oidLen, &n, &index);
140  //Invalid instance identifier?
141  if(error)
142  return error;
143 
144  //Sanity check
145  if(n != oidLen)
147 
148  //Check index range
149  if(index < 1 || index > context->numInterfaces)
151 
152  //Point to the underlying interface
153  interface = &context->interfaces[index - 1];
154  //Point to the physical interface
155  physicalInterface = nicGetPhysicalInterface(interface);
156 
157  //ifIndex object?
158  if(osStrcmp(object->name, "ifIndex") == 0)
159  {
160  //Get object value
161  value->integer = index;
162  }
163  //ifDescr object?
164  else if(osStrcmp(object->name, "ifDescr") == 0)
165  {
166  //Retrieve the length of the interface name
167  n = osStrlen(interface->name);
168 
169  //Make sure the buffer is large enough to hold the entire object
170  if(*valueLen >= n)
171  {
172  //Copy object value
173  osMemcpy(value->octetString, interface->name, n);
174  //Return object length
175  *valueLen = n;
176  }
177  else
178  {
179  //Report an error
180  error = ERROR_BUFFER_OVERFLOW;
181  }
182  }
183  //ifType object?
184  else if(osStrcmp(object->name, "ifType") == 0)
185  {
186 #if (ETH_VLAN_SUPPORT == ENABLED)
187  //VLAN interface?
188  if(interface->vlanId != 0)
189  {
190  //Layer 2 virtual LAN using 802.1Q
191  value->integer = IF_MIB_IF_TYPE_L2_VLAN;
192  }
193  else
194 #endif
195  {
196  //Sanity check
197  if(physicalInterface->nicDriver != NULL)
198  {
199  //Get interface type
200  switch(physicalInterface->nicDriver->type)
201  {
202  //Ethernet interface
203  case NIC_TYPE_ETHERNET:
205  break;
206 
207  //PPP interface
208  case NIC_TYPE_PPP:
209  value->integer = IF_MIB_IF_TYPE_PPP;
210  break;
211 
212  //IEEE 802.15.4 WPAN interface
213  case NIC_TYPE_6LOWPAN:
215  break;
216 
217  //Unknown interface type
218  default:
219  value->integer = IF_MIB_IF_TYPE_OTHER;
220  break;
221  }
222  }
223  else
224  {
225  //Unknown interface type
226  value->integer = IF_MIB_IF_TYPE_OTHER;
227  }
228  }
229  }
230  //ifMtu object?
231  else if(osStrcmp(object->name, "ifMtu") == 0)
232  {
233  //Get interface MTU
234  if(physicalInterface->nicDriver != NULL)
235  {
236  value->integer = physicalInterface->nicDriver->mtu;
237  }
238  else
239  {
240  value->integer = 0;
241  }
242  }
243  //ifSpeed object?
244  else if(osStrcmp(object->name, "ifSpeed") == 0)
245  {
246  //Get interface's current bandwidth
247  value->gauge32 = interface->linkSpeed;
248  }
249 #if (ETH_SUPPORT == ENABLED)
250  //ifPhysAddress object?
251  else if(osStrcmp(object->name, "ifPhysAddress") == 0)
252  {
253  NetInterface *logicalInterface;
254 
255  //Point to the logical interface
256  logicalInterface = nicGetLogicalInterface(interface);
257 
258  //Make sure the buffer is large enough to hold the entire object
259  if(*valueLen >= sizeof(MacAddr))
260  {
261  //Copy object value
262  macCopyAddr(value->octetString, &logicalInterface->macAddr);
263  //Return object length
264  *valueLen = sizeof(MacAddr);
265  }
266  else
267  {
268  //Report an error
269  error = ERROR_BUFFER_OVERFLOW;
270  }
271  }
272 #endif
273  //ifAdminStatus object?
274  else if(osStrcmp(object->name, "ifAdminStatus") == 0)
275  {
276  //Check whether the interface is enabled for operation
277  if(physicalInterface->nicDriver != NULL)
278  {
279  value->integer = IF_MIB_IF_ADMIN_STATUS_UP;
280  }
281  else
282  {
284  }
285  }
286  //ifOperStatus object?
287  else if(osStrcmp(object->name, "ifOperStatus") == 0)
288  {
289  //Get the current operational state of the interface
290  if(interface->linkState)
291  {
292  value->integer = IF_MIB_IF_OPER_STATUS_UP;
293  }
294  else
295  {
297  }
298  }
299  //ifLastChange object?
300  else if(osStrcmp(object->name, "ifLastChange") == 0)
301  {
302  //Get object value
303  value->timeTicks = interface->ifStats.lastChange;
304  }
305  //ifInOctets object?
306  else if(osStrcmp(object->name, "ifInOctets") == 0)
307  {
308  //Get object value
309  value->counter32 = (uint32_t) interface->ifStats.inOctets;
310  }
311  //ifInUcastPkts object?
312  else if(osStrcmp(object->name, "ifInUcastPkts") == 0)
313  {
314  //Get object value
315  value->counter32 = (uint32_t) interface->ifStats.inUcastPkts;
316  }
317  //ifInDiscards object?
318  else if(osStrcmp(object->name, "ifInDiscards") == 0)
319  {
320  //Get object value
321  value->counter32 = interface->ifStats.inDiscards;
322  }
323  //ifInErrors object?
324  else if(osStrcmp(object->name, "ifInErrors") == 0)
325  {
326  //Get object value
327  value->counter32 = interface->ifStats.inErrors;
328  }
329  //ifInUnknownProtos object?
330  else if(osStrcmp(object->name, "ifInUnknownProtos") == 0)
331  {
332  //Get object value
333  value->counter32 = interface->ifStats.inUnknownProtos;
334  }
335  //ifOutOctets object?
336  else if(osStrcmp(object->name, "ifOutOctets") == 0)
337  {
338  //Get object value
339  value->counter32 = (uint32_t) interface->ifStats.outOctets;
340  }
341  //ifOutUcastPkts object?
342  else if(osStrcmp(object->name, "ifOutUcastPkts") == 0)
343  {
344  //Get object value
345  value->counter32 = (uint32_t) interface->ifStats.outUcastPkts;
346  }
347  //ifOutDiscards object?
348  else if(osStrcmp(object->name, "ifOutDiscards") == 0)
349  {
350  //Get object value
351  value->counter32 = interface->ifStats.outDiscards;
352  }
353  //ifOutErrors object?
354  else if(osStrcmp(object->name, "ifOutErrors") == 0)
355  {
356  //Get object value
357  value->counter32 = interface->ifStats.outErrors;
358  }
359  //Unknown object?
360  else
361  {
362  //The specified object does not exist
363  error = ERROR_OBJECT_NOT_FOUND;
364  }
365 
366  //Return status code
367  return error;
368 }
369 
370 
371 /**
372  * @brief Get next ifEntry object
373  * @param[in] object Pointer to the MIB object descriptor
374  * @param[in] oid Object identifier
375  * @param[in] oidLen Length of the OID, in bytes
376  * @param[out] nextOid OID of the next object in the MIB
377  * @param[out] nextOidLen Length of the next object identifier, in bytes
378  * @return Error code
379  **/
380 
381 error_t ifMibGetNextIfEntry(const MibObject *object, const uint8_t *oid,
382  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
383 {
384  error_t error;
385  size_t n;
386  uint_t index;
387  NetContext *context;
388 
389  //Point to the TCP/IP stack context
390  context = netGetDefaultContext();
391 
392  //Make sure the buffer is large enough to hold the OID prefix
393  if(*nextOidLen < object->oidLen)
394  return ERROR_BUFFER_OVERFLOW;
395 
396  //Copy OID prefix
397  osMemcpy(nextOid, object->oid, object->oidLen);
398 
399  //Loop through network interfaces
400  for(index = 1; index <= context->numInterfaces; index++)
401  {
402  //Append the instance identifier to the OID prefix
403  n = object->oidLen;
404 
405  //ifIndex is used as instance identifier
406  error = mibEncodeIndex(nextOid, *nextOidLen, &n, index);
407  //Any error to report?
408  if(error)
409  return error;
410 
411  //Check whether the resulting object identifier lexicographically
412  //follows the specified OID
413  if(oidComp(nextOid, n, oid, oidLen) > 0)
414  {
415  //Save the length of the resulting object identifier
416  *nextOidLen = n;
417  //Next object found
418  return NO_ERROR;
419  }
420  }
421 
422  //The specified OID does not lexicographically precede the name
423  //of some object
424  return ERROR_OBJECT_NOT_FOUND;
425 }
426 
427 
428 /**
429  * @brief Set ifXEntry object value
430  * @param[in] object Pointer to the MIB object descriptor
431  * @param[in] oid Object identifier (object name and instance identifier)
432  * @param[in] oidLen Length of the OID, in bytes
433  * @param[in] value Object value
434  * @param[in] valueLen Length of the object value, in bytes
435  * @param[in] commit This flag tells whether the changes shall be committed
436  * to the MIB base
437  * @return Error code
438  **/
439 
440 error_t ifMibSetIfXEntry(const MibObject *object, const uint8_t *oid,
441  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
442 {
443  //Not implemented
444  return ERROR_WRITE_FAILED;
445 }
446 
447 
448 /**
449  * @brief Get ifXEntry object value
450  * @param[in] object Pointer to the MIB object descriptor
451  * @param[in] oid Object identifier (object name and instance identifier)
452  * @param[in] oidLen Length of the OID, in bytes
453  * @param[out] value Object value
454  * @param[in,out] valueLen Length of the object value, in bytes
455  * @return Error code
456  **/
457 
458 error_t ifMibGetIfXEntry(const MibObject *object, const uint8_t *oid,
459  size_t oidLen, MibVariant *value, size_t *valueLen)
460 {
461  error_t error;
462  size_t n;
463  uint_t index;
464  NetContext *context;
465  NetInterface *interface;
466 
467  //Point to the TCP/IP stack context
468  context = netGetDefaultContext();
469 
470  //Point to the instance identifier
471  n = object->oidLen;
472 
473  //ifIndex is used as instance identifier
474  error = mibDecodeIndex(oid, oidLen, &n, &index);
475  //Invalid instance identifier?
476  if(error)
477  return error;
478 
479  //Sanity check
480  if(n != oidLen)
482 
483  //Check index range
484  if(index < 1 || index > context->numInterfaces)
486 
487  //Point to the underlying interface
488  interface = &context->interfaces[index - 1];
489 
490  //ifName object?
491  if(osStrcmp(object->name, "ifName") == 0)
492  {
493  //Retrieve the length of the interface name
494  n = osStrlen(interface->name);
495 
496  //Make sure the buffer is large enough to hold the entire object
497  if(*valueLen >= n)
498  {
499  //Copy object value
500  osMemcpy(value->octetString, interface->name, n);
501  //Return object length
502  *valueLen = n;
503  }
504  else
505  {
506  //Report an error
507  error = ERROR_BUFFER_OVERFLOW;
508  }
509  }
510  //ifInMulticastPkts object?
511  else if(osStrcmp(object->name, "ifInMulticastPkts") == 0)
512  {
513  //Get object value
514  value->counter32 = (uint32_t) interface->ifStats.inMulticastPkts;
515  }
516  //ifInBroadcastPkts object?
517  else if(osStrcmp(object->name, "ifInBroadcastPkts") == 0)
518  {
519  //Get object value
520  value->counter32 = (uint32_t) interface->ifStats.inBroadcastPkts;
521  }
522  //ifOutMulticastPkts object?
523  else if(osStrcmp(object->name, "ifOutMulticastPkts") == 0)
524  {
525  //Get object value
526  value->counter32 = (uint32_t) interface->ifStats.outMulticastPkts;
527  }
528  //ifOutBroadcastPkts object?
529  else if(osStrcmp(object->name, "ifOutBroadcastPkts") == 0)
530  {
531  //Get object value
532  value->counter32 = (uint32_t) interface->ifStats.outBroadcastPkts;
533  }
534  //ifHCInOctets object?
535  else if(osStrcmp(object->name, "ifHCInOctets") == 0)
536  {
537  //Get object value
538  value->counter64 = interface->ifStats.inOctets;
539  }
540  //ifHCInUcastPkts object?
541  else if(osStrcmp(object->name, "ifHCInUcastPkts") == 0)
542  {
543  //Get object value
544  value->counter64 = interface->ifStats.inUcastPkts;
545  }
546  //ifHCInMulticastPkts object?
547  else if(osStrcmp(object->name, "ifHCInMulticastPkts") == 0)
548  {
549  //Get object value
550  value->counter64 = interface->ifStats.inMulticastPkts;
551  }
552  //ifHCInBroadcastPkts object?
553  else if(osStrcmp(object->name, "ifHCInBroadcastPkts") == 0)
554  {
555  //Get object value
556  value->counter64 = interface->ifStats.inBroadcastPkts;
557  }
558  //ifHCOutOctets object?
559  else if(osStrcmp(object->name, "ifHCOutOctets") == 0)
560  {
561  //Get object value
562  value->counter64 = interface->ifStats.outOctets;
563  }
564  //ifHCOutUcastPkts object?
565  else if(osStrcmp(object->name, "ifHCOutUcastPkts") == 0)
566  {
567  //Get object value
568  value->counter64 = interface->ifStats.outUcastPkts;
569  }
570  //ifHCOutMulticastPkts object?
571  else if(osStrcmp(object->name, "ifHCOutMulticastPkts") == 0)
572  {
573  //Get object value
574  value->counter64 = interface->ifStats.outMulticastPkts;
575  }
576  //ifHCOutBroadcastPkts object?
577  else if(osStrcmp(object->name, "ifHCOutBroadcastPkts") == 0)
578  {
579  //Get object value
580  value->counter64 = interface->ifStats.outBroadcastPkts;
581  }
582  //ifLinkUpDownTrapEnable object?
583  else if(osStrcmp(object->name, "ifLinkUpDownTrapEnable") == 0)
584  {
585  //This object indicates whether link-up/link-down traps should be
586  //generated for this interface
588  }
589  //ifHighSpeed object?
590  else if(osStrcmp(object->name, "ifHighSpeed") == 0)
591  {
592  //Estimate of the interface's current bandwidth
593  value->gauge32 = interface->linkSpeed / 1000000;
594  }
595  //ifPromiscuousMode object?
596  else if(osStrcmp(object->name, "ifPromiscuousMode") == 0)
597  {
598 #if (ETH_SUPPORT == ENABLED)
599  //Check whether promiscuous mode is enable
600  if(interface->promiscuous)
601  {
602  //This object has a value of true(1) when the station accepts all
603  //packets/frames transmitted on the media
604  value->integer = MIB_TRUTH_VALUE_TRUE;
605  }
606  else
607 #endif
608  {
609  //This object has a value of false if this interface only accepts
610  //packets/frames that are addressed to this station
611  value->integer = MIB_TRUTH_VALUE_FALSE;
612  }
613  }
614  //ifConnectorPresent object?
615  else if(osStrcmp(object->name, "ifConnectorPresent") == 0)
616  {
617  //This object has the value true if the interface sublayer has a physical
618  //connector and the value false otherwise
619  value->integer = MIB_TRUTH_VALUE_TRUE;
620  }
621  //ifAlias object?
622  else if(osStrcmp(object->name, "ifAlias") == 0)
623  {
624  //On the first instantiation of an interface, the value of ifAlias
625  //associated with that interface is the zero-length string
626  *valueLen = 0;
627  }
628  //ifCounterDiscontinuityTime object?
629  else if(osStrcmp(object->name, "ifCounterDiscontinuityTime") == 0)
630  {
631  //Value of sysUpTime on the most recent occasion at which any one or more
632  //of this interface's counters suffered a discontinuity
633  value->timeTicks = 0;
634  }
635  //Unknown object?
636  else
637  {
638  //The specified object does not exist
639  error = ERROR_OBJECT_NOT_FOUND;
640  }
641 
642  //Return status code
643  return error;
644 }
645 
646 
647 /**
648  * @brief Get next ifXEntry object
649  * @param[in] object Pointer to the MIB object descriptor
650  * @param[in] oid Object identifier
651  * @param[in] oidLen Length of the OID, in bytes
652  * @param[out] nextOid OID of the next object in the MIB
653  * @param[out] nextOidLen Length of the next object identifier, in bytes
654  * @return Error code
655  **/
656 
657 error_t ifMibGetNextIfXEntry(const MibObject *object, const uint8_t *oid,
658  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
659 {
660  error_t error;
661  size_t n;
662  uint_t index;
663  NetContext *context;
664 
665  //Point to the TCP/IP stack context
666  context = netGetDefaultContext();
667 
668  //Make sure the buffer is large enough to hold the OID prefix
669  if(*nextOidLen < object->oidLen)
670  return ERROR_BUFFER_OVERFLOW;
671 
672  //Copy OID prefix
673  osMemcpy(nextOid, object->oid, object->oidLen);
674 
675  //Loop through network interfaces
676  for(index = 1; index <= context->numInterfaces; index++)
677  {
678  //Append the instance identifier to the OID prefix
679  n = object->oidLen;
680 
681  //ifIndex is used as instance identifier
682  error = mibEncodeIndex(nextOid, *nextOidLen, &n, index);
683  //Any error to report?
684  if(error)
685  return error;
686 
687  //Check whether the resulting object identifier lexicographically
688  //follows the specified OID
689  if(oidComp(nextOid, n, oid, oidLen) > 0)
690  {
691  //Save the length of the resulting object identifier
692  *nextOidLen = n;
693  //Next object found
694  return NO_ERROR;
695  }
696  }
697 
698  //The specified OID does not lexicographically precede the name
699  //of some object
700  return ERROR_OBJECT_NOT_FOUND;
701 }
702 
703 
704 /**
705  * @brief Set ifStackEntry object value
706  * @param[in] object Pointer to the MIB object descriptor
707  * @param[in] oid Object identifier (object name and instance identifier)
708  * @param[in] oidLen Length of the OID, in bytes
709  * @param[in] value Object value
710  * @param[in] valueLen Length of the object value, in bytes
711  * @param[in] commit This flag tells whether the changes shall be committed
712  * to the MIB base
713  * @return Error code
714  **/
715 
716 error_t ifMibSetIfStackEntry(const MibObject *object, const uint8_t *oid,
717  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
718 {
719  //Not implemented
720  return ERROR_WRITE_FAILED;
721 }
722 
723 
724 /**
725  * @brief Get ifStackEntry object value
726  * @param[in] object Pointer to the MIB object descriptor
727  * @param[in] oid Object identifier (object name and instance identifier)
728  * @param[in] oidLen Length of the OID, in bytes
729  * @param[out] value Object value
730  * @param[in,out] valueLen Length of the object value, in bytes
731  * @return Error code
732  **/
733 
734 error_t ifMibGetIfStackEntry(const MibObject *object, const uint8_t *oid,
735  size_t oidLen, MibVariant *value, size_t *valueLen)
736 {
737  error_t error;
738  size_t n;
739  uint_t index;
740  uint_t higherLayer;
741  uint_t lowerLayer;
742  NetContext *context;
743 
744  //Point to the TCP/IP stack context
745  context = netGetDefaultContext();
746 
747  //Point to the instance identifier
748  n = object->oidLen;
749 
750  //ifStackHigherLayer is used as 1st instance identifier
751  error = mibDecodeIndex(oid, oidLen, &n, &higherLayer);
752  //Invalid instance identifier?
753  if(error)
754  return error;
755 
756  //ifStackLowerLayer is used as 2nd instance identifier
757  error = mibDecodeIndex(oid, oidLen, &n, &lowerLayer);
758  //Invalid instance identifier?
759  if(error)
760  return error;
761 
762  //Sanity check
763  if(n != oidLen)
765 
766  //Loop through network interfaces
767  for(index = 1; index <= context->numInterfaces; index++)
768  {
769  //Check higher and lower sub-layers
770  if(higherLayer == 0 && lowerLayer == index)
771  {
772  break;
773  }
774  else if(higherLayer == index && lowerLayer == 0)
775  {
776  break;
777  }
778  }
779 
780  //No matching interface?
781  if(index > context->numInterfaces)
783 
784  //ifStackStatus object?
785  if(osStrcmp(object->name, "ifStackStatus") == 0)
786  {
787  //status of the relationship between the two sub-layers
788  value->integer = MIB_ROW_STATUS_ACTIVE;
789  }
790  //Unknown object?
791  else
792  {
793  //The specified object does not exist
794  error = ERROR_OBJECT_NOT_FOUND;
795  }
796 
797  //Return status code
798  return error;
799 }
800 
801 
802 /**
803  * @brief Get next ifStackEntry object
804  * @param[in] object Pointer to the MIB object descriptor
805  * @param[in] oid Object identifier
806  * @param[in] oidLen Length of the OID, in bytes
807  * @param[out] nextOid OID of the next object in the MIB
808  * @param[out] nextOidLen Length of the next object identifier, in bytes
809  * @return Error code
810  **/
811 
812 error_t ifMibGetNextIfStackEntry(const MibObject *object, const uint8_t *oid,
813  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
814 {
815  error_t error;
816  uint_t k;
817  size_t n;
818  uint_t index;
819  uint_t higherLayer;
820  uint_t lowerLayer;
821  NetContext *context;
822 
823  //Point to the TCP/IP stack context
824  context = netGetDefaultContext();
825 
826  //Make sure the buffer is large enough to hold the OID prefix
827  if(*nextOidLen < object->oidLen)
828  return ERROR_BUFFER_OVERFLOW;
829 
830  //Copy OID prefix
831  osMemcpy(nextOid, object->oid, object->oidLen);
832 
833  //two rows exist even for an interface which has no others stacked
834  //on top or below it
835  for(k = 0; k < 2; k++)
836  {
837  //Loop through network interfaces
838  for(index = 1; index <= context->numInterfaces; index++)
839  {
840  //Append the instance identifier to the OID prefix
841  n = object->oidLen;
842 
843  //Higher and lower sub-layers
844  if(k == 0)
845  {
846  higherLayer = 0;
847  lowerLayer = index;
848  }
849  else
850  {
851  higherLayer = index;
852  lowerLayer = 0;
853  }
854 
855  //ifStackHigherLayer is used as 1st instance identifier
856  error = mibEncodeIndex(nextOid, *nextOidLen, &n, higherLayer);
857  //Any error to report?
858  if(error)
859  return error;
860 
861  //ifStackLowerLayer is used as 2nd instance identifier
862  error = mibEncodeIndex(nextOid, *nextOidLen, &n, lowerLayer);
863  //Any error to report?
864  if(error)
865  return error;
866 
867  //Check whether the resulting object identifier lexicographically
868  //follows the specified OID
869  if(oidComp(nextOid, n, oid, oidLen) > 0)
870  {
871  //Save the length of the resulting object identifier
872  *nextOidLen = n;
873  //Next object found
874  return NO_ERROR;
875  }
876  }
877  }
878 
879  //The specified OID does not lexicographically precede the name
880  //of some object
881  return ERROR_OBJECT_NOT_FOUND;
882 }
883 
884 
885 /**
886  * @brief Set ifRcvAddressEntry object value
887  * @param[in] object Pointer to the MIB object descriptor
888  * @param[in] oid Object identifier (object name and instance identifier)
889  * @param[in] oidLen Length of the OID, in bytes
890  * @param[in] value Object value
891  * @param[in] valueLen Length of the object value, in bytes
892  * @param[in] commit This flag tells whether the changes shall be committed
893  * to the MIB base
894  * @return Error code
895  **/
896 
897 error_t ifMibSetIfRcvAddressEntry(const MibObject *object, const uint8_t *oid,
898  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
899 {
900  //Not implemented
901  return ERROR_WRITE_FAILED;
902 }
903 
904 
905 /**
906  * @brief Get ifRcvAddressEntry object value
907  * @param[in] object Pointer to the MIB object descriptor
908  * @param[in] oid Object identifier (object name and instance identifier)
909  * @param[in] oidLen Length of the OID, in bytes
910  * @param[out] value Object value
911  * @param[in,out] valueLen Length of the object value, in bytes
912  * @return Error code
913  **/
914 
915 error_t ifMibGetIfRcvAddressEntry(const MibObject *object, const uint8_t *oid,
916  size_t oidLen, MibVariant *value, size_t *valueLen)
917 {
918 #if (ETH_SUPPORT == ENABLED)
919  error_t error;
920  uint_t i;
921  size_t n;
922  uint_t index;
923  MacAddr macAddr;
924  NetContext *context;
925  NetInterface *interface;
926  NetInterface *logicalInterface;
927 
928  //Point to the TCP/IP stack context
929  context = netGetDefaultContext();
930 
931  //Point to the instance identifier
932  n = object->oidLen;
933 
934  //ifIndex is used as 1st instance identifier
935  error = mibDecodeIndex(oid, oidLen, &n, &index);
936  //Invalid instance identifier?
937  if(error)
938  return error;
939 
940  //ifRcvAddressAddress is used as 2nd instance identifier
941  error = mibDecodePhysAddr(oid, oidLen, &n, &macAddr);
942  //Invalid instance identifier?
943  if(error)
944  return error;
945 
946  //Sanity check
947  if(n != oidLen)
949 
950  //Check index range
951  if(index < 1 || index > context->numInterfaces)
953 
954  //Point to the underlying interface
955  interface = &context->interfaces[index - 1];
956  //Point to the logical interface
957  logicalInterface = nicGetLogicalInterface(interface);
958 
959  //Initialize status code
960  error = ERROR_INSTANCE_NOT_FOUND;
961 
962  //Interface MAC address?
963  if(macCompAddr(&macAddr, &logicalInterface->macAddr))
964  {
965  //The MAC address is acceptable
966  error = NO_ERROR;
967  }
968  //Broadcast address?
969  else if(macCompAddr(&macAddr, &MAC_BROADCAST_ADDR))
970  {
971  //The MAC address is acceptable
972  error = NO_ERROR;
973  }
974  //Multicast address?
975  else if(macIsMulticastAddr(&macAddr))
976  {
977  //Go through the MAC filter table
978  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
979  {
980  //Valid entry?
981  if(interface->macAddrFilter[i].refCount > 0)
982  {
983  //Check whether the MAC address matches a relevant multicast address
984  if(macCompAddr(&macAddr, &interface->macAddrFilter[i].addr))
985  {
986  //The MAC address is acceptable
987  error = NO_ERROR;
988  }
989  }
990  }
991  }
992 
993  //Check whether the MAC address is acceptable
994  if(!error)
995  {
996  //ifRcvAddressStatus object?
997  if(osStrcmp(object->name, "ifRcvAddressStatus") == 0)
998  {
999  //Get object value
1000  value->integer = MIB_ROW_STATUS_ACTIVE;
1001  }
1002  //ifRcvAddressType object?
1003  else if(osStrcmp(object->name, "ifRcvAddressType") == 0)
1004  {
1005  //Get object value
1006  if(macCompAddr(&macAddr, &logicalInterface->macAddr) ||
1007  macCompAddr(&macAddr, &MAC_BROADCAST_ADDR))
1008  {
1009  //The entry is not volatile
1011  }
1012  else
1013  {
1014  //The entry is volatile
1016  }
1017  }
1018  //Unknown object?
1019  else
1020  {
1021  //The specified object does not exist
1022  error = ERROR_OBJECT_NOT_FOUND;
1023  }
1024  }
1025 
1026  //Return status code
1027  return error;
1028 #else
1029  //Not implemented
1030  return ERROR_OBJECT_NOT_FOUND;
1031 #endif
1032 }
1033 
1034 
1035 /**
1036  * @brief Get next ifRcvAddressEntry object
1037  * @param[in] object Pointer to the MIB object descriptor
1038  * @param[in] oid Object identifier
1039  * @param[in] oidLen Length of the OID, in bytes
1040  * @param[out] nextOid OID of the next object in the MIB
1041  * @param[out] nextOidLen Length of the next object identifier, in bytes
1042  * @return Error code
1043  **/
1044 
1045 error_t ifMibGetNextIfRcvAddressEntry(const MibObject *object, const uint8_t *oid,
1046  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
1047 {
1048 #if (ETH_SUPPORT == ENABLED)
1049  error_t error;
1050  int_t i;
1051  size_t n;
1052  uint_t index;
1053  uint_t curIndex;
1054  bool_t acceptable;
1055  MacAddr macAddr;
1056  MacAddr curMacAddr;
1057  NetContext *context;
1058  NetInterface *interface;
1059  NetInterface *logicalInterface;
1060 
1061  //Point to the TCP/IP stack context
1062  context = netGetDefaultContext();
1063 
1064  //Initialize variables
1065  index = 0;
1066  macAddr = MAC_UNSPECIFIED_ADDR;
1067 
1068  //Make sure the buffer is large enough to hold the OID prefix
1069  if(*nextOidLen < object->oidLen)
1070  return ERROR_BUFFER_OVERFLOW;
1071 
1072  //Copy OID prefix
1073  osMemcpy(nextOid, object->oid, object->oidLen);
1074 
1075  //Loop through network interfaces
1076  for(curIndex = 1; curIndex <= context->numInterfaces; curIndex++)
1077  {
1078  //Point to the underlying interface
1079  interface = &context->interfaces[curIndex - 1];
1080  //Point to the logical interface
1081  logicalInterface = nicGetLogicalInterface(interface);
1082 
1083  //Go through the MAC filter table
1084  for(i = -2; i < MAC_ADDR_FILTER_SIZE; i++)
1085  {
1086  if(i == -2)
1087  {
1088  //Get interface MAC address
1089  curMacAddr = logicalInterface->macAddr;
1090  }
1091  else if(i == -1)
1092  {
1093  //Get broadcast address
1094  curMacAddr = MAC_BROADCAST_ADDR;
1095  }
1096  else
1097  {
1098  //Get multicast address
1099  if(interface->macAddrFilter[i].refCount > 0)
1100  {
1101  curMacAddr = interface->macAddrFilter[i].addr;
1102  }
1103  else
1104  {
1105  curMacAddr = MAC_UNSPECIFIED_ADDR;
1106  }
1107  }
1108 
1109  //Valid MAC address?
1110  if(!macCompAddr(&curMacAddr, &MAC_UNSPECIFIED_ADDR))
1111  {
1112  //Append the instance identifier to the OID prefix
1113  n = object->oidLen;
1114 
1115  //ifIndex is used as 1st instance identifier
1116  error = mibEncodeIndex(nextOid, *nextOidLen, &n, curIndex);
1117  //Invalid instance identifier?
1118  if(error)
1119  return error;
1120 
1121  //ifRcvAddressAddress is used as 2nd instance identifier
1122  error = mibEncodePhysAddr(nextOid, *nextOidLen, &n, &curMacAddr);
1123  //Invalid instance identifier?
1124  if(error)
1125  return error;
1126 
1127  //Check whether the resulting object identifier lexicographically
1128  //follows the specified OID
1129  if(oidComp(nextOid, n, oid, oidLen) > 0)
1130  {
1131  //Perform lexicographic comparison
1132  if(index == 0)
1133  {
1134  acceptable = TRUE;
1135  }
1136  else if(curIndex < index)
1137  {
1138  acceptable = TRUE;
1139  }
1140  else if(curIndex > index)
1141  {
1142  acceptable = FALSE;
1143  }
1144  else if(osMemcmp(&curMacAddr, &macAddr, sizeof(MacAddr)) < 0)
1145  {
1146  acceptable = TRUE;
1147  }
1148  else
1149  {
1150  acceptable = FALSE;
1151  }
1152 
1153  //Save the closest object identifier that follows the specified
1154  //OID in lexicographic order
1155  if(acceptable)
1156  {
1157  macAddr = curMacAddr;
1158  index = curIndex;
1159  }
1160  }
1161  }
1162  }
1163  }
1164 
1165  //The specified OID does not lexicographically precede the name
1166  //of some object?
1167  if(index == 0)
1168  return ERROR_OBJECT_NOT_FOUND;
1169 
1170  //Append the instance identifier to the OID prefix
1171  n = object->oidLen;
1172 
1173  //ifIndex is used as 1st instance identifier
1174  error = mibEncodeIndex(nextOid, *nextOidLen, &n, index);
1175  //Invalid instance identifier?
1176  if(error)
1177  return error;
1178 
1179  //ifRcvAddressAddress is used as 2nd instance identifier
1180  error = mibEncodePhysAddr(nextOid, *nextOidLen, &n, &macAddr);
1181  //Invalid instance identifier?
1182  if(error)
1183  return error;
1184 
1185  //Save the length of the resulting object identifier
1186  *nextOidLen = n;
1187  //Next object found
1188  return NO_ERROR;
1189 #else
1190  //Not implemented
1191  return ERROR_OBJECT_NOT_FOUND;
1192 #endif
1193 }
1194 
1195 #endif
error_t ifMibSetIfStackEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set ifStackEntry object value.
Definition: if_mib_impl.c:716
error_t ifMibGetIfEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ifEntry object value.
Definition: if_mib_impl.c:122
@ IF_MIB_IF_TYPE_L2_VLAN
Definition: if_mib_module.h:67
@ IF_MIB_IF_ADMIN_STATUS_DOWN
Definition: if_mib_module.h:82
#define NetContext
Definition: net.h:36
error_t ifMibGetNextIfXEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next ifXEntry object.
Definition: if_mib_impl.c:657
int bool_t
Definition: compiler_port.h:63
error_t mibEncodePhysAddr(uint8_t *oid, size_t maxOidLen, size_t *pos, const MacAddr *macAddr)
Encode instance identifier (physical address)
Definition: mib_common.c:596
signed int int_t
Definition: compiler_port.h:56
error_t mibDecodePhysAddr(const uint8_t *oid, size_t oidLen, size_t *pos, MacAddr *macAddr)
Decode instance identifier (physical address)
Definition: mib_common.c:625
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:143
error_t ifMibSetIfRcvAddressEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set ifRcvAddressEntry object value.
Definition: if_mib_impl.c:897
OID (Object Identifier)
error_t ifMibSetIfXEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set ifXEntry object value.
Definition: if_mib_impl.c:440
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
error_t ifMibGetIfStackEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ifStackEntry object value.
Definition: if_mib_impl.c:734
#define TRUE
Definition: os_port.h:50
@ MIB_TRUTH_VALUE_TRUE
Definition: mib_common.h:91
@ IF_MIB_RCV_ADDRESS_TYPE_VOLATILE
#define osMemcmp(p1, p2, length)
Definition: os_port.h:156
IfMibBase ifMibBase
Interfaces Group MIB base.
Definition: if_mib_module.c:59
@ IF_MIB_IF_LINK_UP_DOWN_TRAP_DISABLED
#define osStrcmp(s1, s2)
Definition: os_port.h:174
#define osStrlen(s)
Definition: os_port.h:168
error_t ifMibGetNextIfStackEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next ifStackEntry object.
Definition: if_mib_impl.c:812
Interfaces Group MIB module implementation.
@ IF_MIB_IF_TYPE_ETHERNET_CSMACD
Definition: if_mib_module.h:57
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
uint8_t oid[]
Definition: lldp_tlv.h:300
error_t ifMibGetNextIfEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next ifEntry object.
Definition: if_mib_impl.c:381
#define macCopyAddr(destMacAddr, srcMacAddr)
Definition: ethernet.h:127
error_t ifMibInit(void)
Interfaces Group MIB module initialization.
Definition: if_mib_impl.c:53
#define FALSE
Definition: os_port.h:46
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:87
error_t
Error codes.
Definition: error.h:43
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:258
error_t ifMibSetIfEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set ifEntry object value.
Definition: if_mib_impl.c:104
@ IF_MIB_IF_TYPE_PPP
Definition: if_mib_module.h:59
@ IF_MIB_IF_TYPE_OTHER
Definition: if_mib_module.h:56
#define NetInterface
Definition: net.h:40
General definitions for cryptographic algorithms.
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
error_t ifMibGetIfRcvAddressEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ifRcvAddressEntry object value.
Definition: if_mib_impl.c:915
@ IF_MIB_RCV_ADDRESS_TYPE_NON_VOLATILE
#define TRACE_INFO(...)
Definition: debug.h:105
@ IF_MIB_IF_OPER_STATUS_UP
Definition: if_mib_module.h:93
Interfaces Group MIB module.
MacAddr
Definition: ethernet.h:197
@ NIC_TYPE_PPP
PPP interface.
Definition: nic.h:84
@ MIB_TRUTH_VALUE_FALSE
Definition: mib_common.h:92
@ MIB_ROW_STATUS_ACTIVE
Definition: mib_common.h:103
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
@ IF_MIB_IF_OPER_STATUS_DOWN
Definition: if_mib_module.h:94
Common definitions for MIB modules.
uint8_t n
error_t ifMibGetIfXEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ifXEntry object value.
Definition: if_mib_impl.c:458
@ ERROR_WRITE_FAILED
Definition: error.h:223
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:257
error_t ifMibGetIfNumber(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ifNumber object value.
Definition: if_mib_impl.c:76
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:376
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
uint8_t oidLen
Definition: lldp_tlv.h:299
error_t ifMibGetNextIfRcvAddressEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next ifRcvAddressEntry object.
Definition: if_mib_impl.c:1045
@ IF_MIB_IF_ADMIN_STATUS_UP
Definition: if_mib_module.h:81
error_t mibEncodeIndex(uint8_t *oid, size_t maxOidLen, size_t *pos, uint_t index)
Encode instance identifier (index)
Definition: mib_common.c:47
MibVariant
Definition: mib_common.h:196
@ IF_MIB_IF_TYPE_IEEE_802_15_4
Definition: if_mib_module.h:71
@ NIC_TYPE_6LOWPAN
6LoWPAN interface
Definition: nic.h:87
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
TCP/IP stack core.
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:51
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
ASN.1 (Abstract Syntax Notation One)
const MacAddr MAC_BROADCAST_ADDR
Definition: ethernet.c:53
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83