bridge_mib_impl_static.c
Go to the documentation of this file.
1 /**
2  * @file bridge_mib_impl.c
3  * @brief Bridge MIB module implementation (dot1dStatic subtree)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2019-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSTP 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"
37 #include "bridge_mib_module.h"
38 #include "bridge_mib_impl.h"
39 #include "bridge_mib_impl_static.h"
40 #include "core/crypto.h"
41 #include "encoding/asn1.h"
42 #include "encoding/oid.h"
43 #include "debug.h"
44 
45 //Check TCP/IP stack configuration
46 #if (BRIDGE_MIB_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Set dot1dStaticEntry object value
51  * @param[in] object Pointer to the MIB object descriptor
52  * @param[in] oid Object identifier (object name and instance identifier)
53  * @param[in] oidLen Length of the OID, in bytes
54  * @param[in] value Object value
55  * @param[in] valueLen Length of the object value, in bytes
56  * @param[in] commit This flag tells whether the changes shall be committed
57  * to the MIB base
58  * @return Error code
59  **/
60 
61 error_t bridgeMibSetDot1dStaticEntry(const MibObject *object, const uint8_t *oid,
62  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
63 {
64 #if (BRIDGE_MIB_SET_SUPPORT == ENABLED)
65  error_t error;
66  uint_t i;
67  size_t n;
68  bool_t found;
69  SwitchFdbEntry entry;
70  MacAddr dot1dStaticAddress;
71  uint16_t dot1dStaticReceivePort;
72  NetInterface *interface;
73 
74  //Make sure the network interface is valid
75  if(bridgeMibBase.interface == NULL)
76  return ERROR_WRITE_FAILED;
77 
78  //Point to the underlying interface
79  interface = bridgeMibBase.interface;
80 
81  //Point to the instance identifier
82  n = object->oidLen;
83 
84  //dot1dStaticAddress is used as 1st instance identifier
85  error = mibDecodeMacAddr(oid, oidLen, &n, &dot1dStaticAddress);
86  //Invalid instance identifier?
87  if(error)
88  return error;
89 
90  //dot1dStaticReceivePort is used as 2nd instance identifier
91  error = mibDecodePort(oid, oidLen, &n, &dot1dStaticReceivePort);
92  //Invalid instance identifier?
93  if(error)
94  return error;
95 
96  //Sanity check
97  if(n != oidLen)
99 
100  //Search the static MAC table for a matching row
101  for(found = FALSE, i = 0; !error; i++)
102  {
103  //Get the next entry
104  error = interface->switchDriver->getStaticFdbEntry(interface, i, &entry);
105 
106  //Check status code
107  if(error == NO_ERROR)
108  {
109  //Check whether the current entry matches the specified address and
110  //port number
111  if(macCompAddr(&entry.macAddr, &dot1dStaticAddress) &&
112  entry.srcPort == dot1dStaticReceivePort)
113  {
114  found = TRUE;
115  break;
116  }
117  }
118  else if(error == ERROR_INVALID_ENTRY)
119  {
120  //Skip current entry
121  error = NO_ERROR;
122  }
123  else
124  {
125  //Exit immediately
126  }
127  }
128 
129  //Initialize status code
130  error = NO_ERROR;
131 
132  //Prepare phase?
133  if(!commit)
134  {
135  //Reset the cached entry if necessary
136  if(!macCompAddr(&bridgeMibBase.dot1dStaticAddress, &dot1dStaticAddress) ||
137  bridgeMibBase.dot1dStaticReceivePort != dot1dStaticReceivePort)
138  {
139  bridgeMibBase.dot1dStaticAddress = dot1dStaticAddress;
140  bridgeMibBase.dot1dStaticReceivePort = dot1dStaticReceivePort;
142  }
143  }
144 
145  //dot1dStaticAddress object?
146  if(osStrcmp(object->name, "dot1dStaticAddress") == 0)
147  {
148  //Ensure the length of the MAC address is valid
149  if(valueLen != sizeof(MacAddr))
150  return ERROR_WRONG_LENGTH;
151 
152  //This object indicates the destination MAC address in a frame to which
153  //this entry's filtering information applies
154  if(!macCompAddr(value->octetString, &dot1dStaticAddress))
156  }
157  //dot1dStaticReceivePort object?
158  else if(osStrcmp(object->name, "dot1dStaticReceivePort") == 0)
159  {
160  //This object indicates the port number of the port from which a frame
161  //must be received in order for this entry's filtering information to
162  //apply. A value of zero indicates that this entry applies on all ports
163  //of the bridge for which there is no other applicable entry
164  if(value->integer != dot1dStaticReceivePort)
166  }
167  //dot1dStaticAllowedToGoTo object?
168  else if(osStrcmp(object->name, "dot1dStaticAllowedToGoTo") == 0)
169  {
170  //Initialize the value of the dot1dStaticAllowedToGoTo object
172 
173  //This object specifies the set of ports to which frames received from a
174  //specific port and destined for a specific MAC address, are allowed to
175  //be forwarded
176  for(i = 0; i < 32 && i < (8 * valueLen); i++)
177  {
178  //Each port of the bridge is represented by a single bit within the
179  //value of this object
180  if((value->octetString[i / 8] & (1 << (7 - (i % 8)))) != 0)
181  {
183  }
184  }
185 
186  //Test if the matching row exists in the agent
187  if(found && commit)
188  {
189  //Modify the forwarding database entry
191 
192  //Update the static MAC table
193  error = interface->switchDriver->addStaticFdbEntry(interface, &entry);
194 
195  //Check status code
196  if(error)
197  {
198  //Failed to modify the static MAC entry
199  error = ERROR_WRITE_FAILED;
200  }
201  }
202  }
203  //dot1dStaticStatus object?
204  else if(osStrcmp(object->name, "dot1dStaticStatus") == 0)
205  {
206  //This object indicates the status of this entry
207  if(value->integer == BRIDGE_MIB_STATIC_STATUS_OTHER)
208  {
209  //Do not create any entry
210  }
211  else if(value->integer == BRIDGE_MIB_STATIC_STATUS_INVALID)
212  {
213  //Test if a matching row exists in the agent
214  if(found && commit)
215  {
216  //Remove the entry from the static MAC table
217  interface->switchDriver->deleteStaticFdbEntry(interface, &entry);
218  }
219  }
220  else if(value->integer == BRIDGE_MIB_STATIC_STATUS_PERMANENT ||
223  {
224  //No matching row found?
225  if(!found && commit)
226  {
227  //Format forwarding database entry
229  entry.srcPort = (uint8_t) bridgeMibBase.dot1dStaticReceivePort;
231  entry.override = FALSE;
232 
233  //Add a new entry to the static MAC table
234  error = interface->switchDriver->addStaticFdbEntry(interface, &entry);
235 
236  //Check status code
237  if(error)
238  {
239  //Failed to create a new MAC entry
240  error = ERROR_WRITE_FAILED;
241  }
242  }
243  }
244  else
245  {
246  //Report an error
247  error = ERROR_WRONG_VALUE;
248  }
249  }
250  //Unknown object?
251  else
252  {
253  //The specified object does not exist
254  error = ERROR_OBJECT_NOT_FOUND;
255  }
256 
257  //Return status code
258  return error;
259 #else
260  //SET operation is not supported
261  return ERROR_WRITE_FAILED;
262 #endif
263 }
264 
265 
266 /**
267  * @brief Get dot1dStaticEntry 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[out] value Object value
272  * @param[in,out] valueLen Length of the object value, in bytes
273  * @return Error code
274  **/
275 
276 error_t bridgeMibGetDot1dStaticEntry(const MibObject *object, const uint8_t *oid,
277  size_t oidLen, MibVariant *value, size_t *valueLen)
278 {
279  error_t error;
280  uint_t i;
281  size_t n;
282  SwitchFdbEntry entry;
283  MacAddr dot1dStaticAddress;
284  uint16_t dot1dStaticReceivePort;
285  NetInterface *interface;
286 
287  //Make sure the network interface is valid
288  if(bridgeMibBase.interface == NULL)
289  return ERROR_READ_FAILED;
290 
291  //Point to the underlying interface
292  interface = bridgeMibBase.interface;
293 
294  //Point to the instance identifier
295  n = object->oidLen;
296 
297  //dot1dStaticAddress is used as 1st instance identifier
298  error = mibDecodeMacAddr(oid, oidLen, &n, &dot1dStaticAddress);
299  //Invalid instance identifier?
300  if(error)
301  return error;
302 
303  //dot1dStaticReceivePort is used as 2nd instance identifier
304  error = mibDecodePort(oid, oidLen, &n, &dot1dStaticReceivePort);
305  //Invalid instance identifier?
306  if(error)
307  return error;
308 
309  //Sanity check
310  if(n != oidLen)
312 
313  //Search the static MAC table for a matching row
314  for(i = 0; !error; i++)
315  {
316  //Get the next entry
317  error = interface->switchDriver->getStaticFdbEntry(interface, i, &entry);
318 
319  //Check status code
320  if(error == NO_ERROR)
321  {
322  //Check whether the current entry matches the specified address and
323  //port number
324  if(macCompAddr(&entry.macAddr, &dot1dStaticAddress) &&
325  entry.srcPort == dot1dStaticReceivePort)
326  {
327  break;
328  }
329  }
330  else if(error == ERROR_INVALID_ENTRY)
331  {
332  //Skip current entry
333  error = NO_ERROR;
334  }
335  else
336  {
337  //Exit immediately
338  }
339  }
340 
341  //No matching entry?
342  if(error)
344 
345  //dot1dStaticAddress object?
346  if(osStrcmp(object->name, "dot1dStaticAddress") == 0)
347  {
348  //Make sure the buffer is large enough to hold the entire object
349  if(*valueLen >= sizeof(MacAddr))
350  {
351  //This object indicates the destination MAC address in a frame to
352  //which this entry's filtering information applies
353  macCopyAddr(value->octetString, &entry.macAddr);
354 
355  //A MAC address shall be encoded as six octets
356  *valueLen = sizeof(MacAddr);
357  }
358  else
359  {
360  //Report an error
361  error = ERROR_BUFFER_OVERFLOW;
362  }
363  }
364  //dot1dStaticReceivePort object?
365  else if(osStrcmp(object->name, "dot1dStaticReceivePort") == 0)
366  {
367  //This object indicates the port number of the port from which a frame
368  //must be received in order for this entry's filtering information to
369  //apply. A value of zero indicates that this entry applies on all ports
370  //of the bridge for which there is no other applicable entry
371  value->integer = entry.srcPort;
372  }
373  //dot1dStaticAllowedToGoTo object?
374  else if(osStrcmp(object->name, "dot1dStaticAllowedToGoTo") == 0)
375  {
376  uint8_t buffer[4];
377 
378  //Initialize buffer
379  osMemset(buffer, 0, sizeof(buffer));
380 
381  //This object specifies the set of ports to which frames received from a
382  //specific port and destined for a specific MAC address, are allowed to
383  //be forwarded
384  for(i = 0; i < 32 && entry.destPorts != 0; i++)
385  {
386  //Each port of the bridge is represented by a single bit within the
387  //value of this object
388  if((entry.destPorts & (1 << i)) != 0)
389  {
390  buffer[i / 8] |= 1 << (7 - (i % 8));
391  entry.destPorts &= ~(1 << i);
392  }
393  }
394 
395  //Each octet within the value of this object specifies a set of eight
396  //ports
397  n = (i + 7) / 8;
398 
399  //Make sure the buffer is large enough to hold the entire object
400  if(*valueLen >= n)
401  {
402  //Copy object value
403  osMemcpy(value->octetString, buffer, n);
404  //Return object length
405  *valueLen = n;
406  }
407  else
408  {
409  //Report an error
410  error = ERROR_BUFFER_OVERFLOW;
411  }
412  }
413  //dot1dStaticStatus object?
414  else if(osStrcmp(object->name, "dot1dStaticStatus") == 0)
415  {
416  //This object indicates the status of this entry
418  }
419  //Unknown object?
420  else
421  {
422  //The specified object does not exist
423  error = ERROR_OBJECT_NOT_FOUND;
424  }
425 
426  //Return status code
427  return error;
428 }
429 
430 
431 /**
432  * @brief Get next dot1dStaticEntry object
433  * @param[in] object Pointer to the MIB object descriptor
434  * @param[in] oid Object identifier
435  * @param[in] oidLen Length of the OID, in bytes
436  * @param[out] nextOid OID of the next object in the MIB
437  * @param[out] nextOidLen Length of the next object identifier, in bytes
438  * @return Error code
439  **/
440 
442  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
443 {
444  error_t error;
445  uint_t i;
446  size_t n;
447  bool_t acceptable;
448  uint16_t srcPort;
449  MacAddr macAddr;
450  SwitchFdbEntry entry;
451  NetInterface *interface;
452 
453  //Initialize variable
454  macAddr = MAC_UNSPECIFIED_ADDR;
455  srcPort = 0;
456 
457  //Make sure the network interface is valid
458  if(bridgeMibBase.interface == NULL)
459  return ERROR_OBJECT_NOT_FOUND;
460 
461  //Point to the underlying interface
462  interface = bridgeMibBase.interface;
463 
464  //Make sure the buffer is large enough to hold the OID prefix
465  if(*nextOidLen < object->oidLen)
466  return ERROR_BUFFER_OVERFLOW;
467 
468  //Copy OID prefix
469  osMemcpy(nextOid, object->oid, object->oidLen);
470 
471  //Initialize status code
472  error = NO_ERROR;
473 
474  //Loop through the static MAC table
475  for(i = 0; !error; i++)
476  {
477  //Get the next entry
478  error = interface->switchDriver->getStaticFdbEntry(interface, i, &entry);
479 
480  //Check status code
481  if(error == NO_ERROR)
482  {
483  //Append the instance identifier to the OID prefix
484  n = object->oidLen;
485 
486  //dot1dStaticAddress is used as 1st instance identifier
487  error = mibEncodeMacAddr(nextOid, *nextOidLen, &n, &entry.macAddr);
488  //Invalid instance identifier?
489  if(error)
490  return error;
491 
492  //dot1dStaticReceivePort is used as 2nd instance identifier
493  error = mibEncodePort(nextOid, *nextOidLen, &n, entry.srcPort);
494  //Invalid instance identifier?
495  if(error)
496  return error;
497 
498  //Check whether the resulting object identifier lexicographically
499  //follows the specified OID
500  if(oidComp(nextOid, n, oid, oidLen) > 0)
501  {
502  //Perform lexicographic comparison
503  if(mibCompMacAddr(&macAddr, &MAC_UNSPECIFIED_ADDR) == 0)
504  {
505  acceptable = TRUE;
506  }
507  else if(mibCompMacAddr(&entry.macAddr, &macAddr) < 0)
508  {
509  acceptable = TRUE;
510  }
511  else if(mibCompMacAddr(&entry.macAddr, &macAddr) > 0)
512  {
513  acceptable = FALSE;
514  }
515  else if(entry.srcPort < srcPort)
516  {
517  acceptable = TRUE;
518  }
519  else
520  {
521  acceptable = FALSE;
522  }
523 
524  //Save the closest object identifier that follows the specified
525  //OID in lexicographic order
526  if(acceptable)
527  {
528  macAddr = entry.macAddr;
529  srcPort = entry.srcPort;
530  }
531  }
532  }
533  else if(error == ERROR_INVALID_ENTRY)
534  {
535  //Skip current entry
536  error = NO_ERROR;
537  }
538  else
539  {
540  //Exit immediately
541  }
542  }
543 
544  //The specified OID does not lexicographically precede the name
545  //of some object?
546  if(mibCompMacAddr(&macAddr, &MAC_UNSPECIFIED_ADDR) == 0)
547  return ERROR_OBJECT_NOT_FOUND;
548 
549  //Append the instance identifier to the OID prefix
550  n = object->oidLen;
551 
552  //dot1dStaticAddress is used as 1st instance identifier
553  error = mibEncodeMacAddr(nextOid, *nextOidLen, &n, &macAddr);
554  //Invalid instance identifier?
555  if(error)
556  return error;
557 
558  //dot1dStaticReceivePort is used as 2nd instance identifier
559  error = mibEncodePort(nextOid, *nextOidLen, &n, srcPort);
560  //Invalid instance identifier?
561  if(error)
562  return error;
563 
564  //Save the length of the resulting object identifier
565  *nextOidLen = n;
566  //Next object found
567  return NO_ERROR;
568 }
569 
570 #endif
MacAddr dot1dStaticAddress
int bool_t
Definition: compiler_port.h:53
uint32_t destPorts
Definition: nic.h:152
uint16_t dot1dStaticReceivePort
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
error_t mibEncodeMacAddr(uint8_t *oid, size_t maxOidLen, size_t *pos, const MacAddr *macAddr)
Encode instance identifier (MAC address)
Definition: mib_common.c:528
OID (Object Identifier)
#define TRUE
Definition: os_port.h:50
error_t mibEncodePort(uint8_t *oid, size_t maxOidLen, size_t *pos, uint16_t port)
Encode instance identifier (port number)
Definition: mib_common.c:478
Bridge MIB module implementation.
error_t bridgeMibSetDot1dStaticEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set dot1dStaticEntry object value.
#define osStrcmp(s1, s2)
Definition: os_port.h:171
error_t mibDecodePort(const uint8_t *oid, size_t oidLen, size_t *pos, uint16_t *port)
Decode instance identifier (port number)
Definition: mib_common.c:495
error_t bridgeMibGetDot1dStaticEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get dot1dStaticEntry object value.
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
#define macCopyAddr(destMacAddr, srcMacAddr)
Definition: ethernet.h:127
uint32_t dot1dStaticAllowedToGoTo
#define FALSE
Definition: os_port.h:46
@ BRIDGE_MIB_STATIC_STATUS_PERMANENT
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:257
@ BRIDGE_MIB_STATIC_STATUS_INVALID
@ BRIDGE_MIB_STATIC_STATUS_DELETE_ON_RESET
#define NetInterface
Definition: net.h:36
General definitions for cryptographic algorithms.
int_t mibCompMacAddr(const MacAddr *macAddr1, const MacAddr *macAddr2)
Compare MAC addresses.
Definition: mib_common.c:954
@ ERROR_WRONG_LENGTH
Definition: error.h:120
MacAddr
Definition: ethernet.h:195
Common definitions for MIB modules.
uint8_t n
@ ERROR_WRONG_VALUE
Definition: error.h:123
@ ERROR_READ_FAILED
Definition: error.h:223
@ ERROR_INVALID_ENTRY
Definition: error.h:289
error_t mibDecodeMacAddr(const uint8_t *oid, size_t oidLen, size_t *pos, MacAddr *macAddr)
Decode instance identifier (MAC address)
Definition: mib_common.c:558
@ ERROR_WRITE_FAILED
Definition: error.h:222
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:256
MacAddr macAddr
Definition: nic.h:150
uint8_t srcPort
Definition: nic.h:151
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:369
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
uint8_t oidLen
Definition: lldp_tlv.h:299
@ BRIDGE_MIB_STATIC_STATUS_OTHER
NetInterface * interface
@ BRIDGE_MIB_STATIC_STATUS_DELETE_ON_TIMEOUT
MibVariant
Definition: mib_common.h:196
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
TCP/IP stack core.
error_t bridgeMibGetNextDot1dStaticEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next dot1dStaticEntry object.
Bridge MIB module.
BridgeMibBase bridgeMibBase
Bridge MIB base.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ ERROR_INCONSISTENT_VALUE
Definition: error.h:124
@ NO_ERROR
Success.
Definition: error.h:44
bool_t override
Definition: nic.h:153
Debugging facilities.
ASN.1 (Abstract Syntax Notation One)
Forwarding database entry.
Definition: nic.h:149