mib2_impl_ip.c
Go to the documentation of this file.
1 /**
2  * @file mib2_impl_ip.c
3  * @brief MIB-II module implementation (IP group)
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 "ipv4/arp_cache.h"
37 #include "mibs/mib_common.h"
38 #include "mibs/mib2_module.h"
39 #include "mibs/mib2_impl.h"
40 #include "mibs/mib2_impl_ip.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 (MIB2_SUPPORT == ENABLED && MIB2_IP_GROUP_SUPPORT == ENABLED)
48 
49 
50 /**
51  * @brief Get ipAddrEntry object value
52  * @param[in] object Pointer to the MIB object descriptor
53  * @param[in] oid Object identifier (object name and instance identifier)
54  * @param[in] oidLen Length of the OID, in bytes
55  * @param[out] value Object value
56  * @param[in,out] valueLen Length of the object value, in bytes
57  * @return Error code
58  **/
59 
60 error_t mib2GetIpAddrEntry(const MibObject *object, const uint8_t *oid,
61  size_t oidLen, MibVariant *value, size_t *valueLen)
62 {
63  error_t error;
64  size_t n;
65  uint_t i;
66  uint_t index;
68  Ipv4AddrEntry *entry;
69  NetInterface *interface;
70 
71  //Point to the instance identifier
72  n = object->oidLen;
73 
74  //ipAdEntAddr is used as instance identifier
75  error = mibDecodeIpv4Addr(oid, oidLen, &n, &ipAddr);
76  //Invalid instance identifier?
77  if(error)
78  return error;
79 
80  //Sanity check
81  if(n != oidLen)
83 
84  //Loop through network interfaces
85  for(index = 1; index <= NET_INTERFACE_COUNT; index++)
86  {
87  //Point to the current interface
88  interface = &netInterface[index - 1];
89 
90  //Loop through the list of IPv4 addresses assigned to the interface
91  for(i = 0; i < IPV4_ADDR_LIST_SIZE; i++)
92  {
93  //Point to the current entry
94  entry = &interface->ipv4Context.addrList[i];
95 
96  //Compare the current address against the IP address used as
97  //instance identifier
98  if(entry->state == IPV4_ADDR_STATE_VALID &&
99  entry->addr == ipAddr)
100  {
101  break;
102  }
103  }
104 
105  //IPv4 address found?
106  if(i < IPV4_ADDR_LIST_SIZE)
107  break;
108  }
109 
110  //IP address not assigned to any interface?
111  if(index > NET_INTERFACE_COUNT)
113 
114  //ipAdEntAddr object?
115  if(osStrcmp(object->name, "ipAdEntAddr") == 0)
116  {
117  //Get object value
118  ipv4CopyAddr(value->ipAddr, &entry->addr);
119  }
120  //ipAdEntIfIndex object?
121  else if(osStrcmp(object->name, "ipAdEntIfIndex") == 0)
122  {
123  //Get object value
124  value->integer = index;
125  }
126  //ipAdEntNetMask object?
127  else if(osStrcmp(object->name, "ipAdEntNetMask") == 0)
128  {
129  //Get object value
130  ipv4CopyAddr(value->ipAddr, &entry->subnetMask);
131  }
132  //ipAdEntBcastAddr object?
133  else if(osStrcmp(object->name, "ipAdEntBcastAddr") == 0)
134  {
135  //Get object value
136  value->integer = 1;
137  }
138  //ipAdEntReasmMaxSize object?
139  else if(osStrcmp(object->name, "ipAdEntReasmMaxSize") == 0)
140  {
141  //Get object value
143  }
144  //Unknown object?
145  else
146  {
147  //The specified object does not exist
148  error = ERROR_OBJECT_NOT_FOUND;
149  }
150 
151  //Return status code
152  return error;
153 }
154 
155 
156 /**
157  * @brief Get next ipAddrEntry object
158  * @param[in] object Pointer to the MIB object descriptor
159  * @param[in] oid Object identifier
160  * @param[in] oidLen Length of the OID, in bytes
161  * @param[out] nextOid OID of the next object in the MIB
162  * @param[out] nextOidLen Length of the next object identifier, in bytes
163  * @return Error code
164  **/
165 
166 error_t mib2GetNextIpAddrEntry(const MibObject *object, const uint8_t *oid,
167  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
168 {
169  error_t error;
170  uint_t i;
171  size_t n;
172  uint_t index;
173  bool_t acceptable;
175  Ipv4AddrEntry *entry;
176  NetInterface *interface;
177 
178  //Initialize IP address
180 
181  //Make sure the buffer is large enough to hold the OID prefix
182  if(*nextOidLen < object->oidLen)
183  return ERROR_BUFFER_OVERFLOW;
184 
185  //Copy OID prefix
186  osMemcpy(nextOid, object->oid, object->oidLen);
187 
188  //Loop through network interfaces
189  for(index = 1; index <= NET_INTERFACE_COUNT; index++)
190  {
191  //Point to the current interface
192  interface = &netInterface[index - 1];
193 
194  //Loop through the list of IPv4 addresses assigned to the interface
195  for(i = 0; i < IPV4_ADDR_LIST_SIZE; i++)
196  {
197  //Point to the current entry
198  entry = &interface->ipv4Context.addrList[i];
199 
200  //Valid IPv4 address?
201  if(entry->state == IPV4_ADDR_STATE_VALID)
202  {
203  //Append the instance identifier to the OID prefix
204  n = object->oidLen;
205 
206  //ipAdEntAddr is used as instance identifier
207  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, entry->addr);
208  //Any error to report?
209  if(error)
210  return error;
211 
212  //Check whether the resulting object identifier lexicographically
213  //follows the specified OID
214  if(oidComp(nextOid, n, oid, oidLen) > 0)
215  {
216  //Perform lexicographic comparison
218  {
219  acceptable = TRUE;
220  }
221  else if(ntohl(entry->addr) < ntohl(ipAddr))
222  {
223  acceptable = TRUE;
224  }
225  else
226  {
227  acceptable = FALSE;
228  }
229 
230  //Save the closest object identifier that follows the specified
231  //OID in lexicographic order
232  if(acceptable)
233  ipAddr = entry->addr;
234  }
235  }
236  }
237  }
238 
239  //The specified OID does not lexicographically precede the name
240  //of some object?
242  return ERROR_OBJECT_NOT_FOUND;
243 
244  //Append the instance identifier to the OID prefix
245  n = object->oidLen;
246 
247  //ipAdEntAddr is used as instance identifier
248  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, ipAddr);
249  //Any error to report?
250  if(error)
251  return error;
252 
253  //Save the length of the resulting object identifier
254  *nextOidLen = n;
255  //Next object found
256  return NO_ERROR;
257 }
258 
259 
260 /**
261  * @brief Set ipNetToMediaEntry object value
262  * @param[in] object Pointer to the MIB object descriptor
263  * @param[in] oid Object identifier (object name and instance identifier)
264  * @param[in] oidLen Length of the OID, in bytes
265  * @param[in] value Object value
266  * @param[in] valueLen Length of the object value, in bytes
267  * @param[in] commit This flag tells whether the changes shall be committed
268  * to the MIB base
269  * @return Error code
270  **/
271 
272 error_t mib2SetIpNetToMediaEntry(const MibObject *object, const uint8_t *oid,
273  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
274 {
275  //Not implemented
276  return ERROR_WRITE_FAILED;
277 }
278 
279 
280 /**
281  * @brief Get ipNetToMediaEntry object value
282  * @param[in] object Pointer to the MIB object descriptor
283  * @param[in] oid Object identifier (object name and instance identifier)
284  * @param[in] oidLen Length of the OID, in bytes
285  * @param[out] value Object value
286  * @param[in,out] valueLen Length of the object value, in bytes
287  * @return Error code
288  **/
289 
290 error_t mib2GetIpNetToMediaEntry(const MibObject *object, const uint8_t *oid,
291  size_t oidLen, MibVariant *value, size_t *valueLen)
292 {
293 #if (ETH_SUPPORT == ENABLED)
294  error_t error;
295  size_t n;
296  uint_t index;
298  NetInterface *interface;
299  ArpCacheEntry *entry;
300 
301  //Point to the instance identifier
302  n = object->oidLen;
303 
304  //ipNetToMediaIfIndex is used as 1st instance identifier
305  error = mibDecodeIndex(oid, oidLen, &n, &index);
306  //Invalid instance identifier?
307  if(error)
308  return error;
309 
310  //ipNetToMediaNetAddress is used as 2nd instance identifier
311  error = mibDecodeIpv4Addr(oid, oidLen, &n, &ipAddr);
312  //Invalid instance identifier?
313  if(error)
314  return error;
315 
316  //Sanity check
317  if(n != oidLen)
319 
320  //Check index range
321  if(index < 1 || index > NET_INTERFACE_COUNT)
323 
324  //Point to the network interface
325  interface = &netInterface[index - 1];
326 
327  //Search the ARP cache for the specified IP address
328  entry = arpFindEntry(interface, ipAddr);
329 
330  //No matching entry found?
331  if(entry == NULL)
333 
334  //ipNetToMediaIfIndex object?
335  if(osStrcmp(object->name, "ipNetToMediaIfIndex") == 0)
336  {
337  //Get object value
338  value->integer = index;
339  }
340  //ipNetToMediaPhysAddress object?
341  else if(osStrcmp(object->name, "ipNetToMediaPhysAddress") == 0)
342  {
343  //Make sure the buffer is large enough to hold the entire object
344  if(*valueLen >= MIB2_PHYS_ADDRESS_SIZE)
345  {
346  //Copy object value
347  macCopyAddr(value->octetString, &entry->macAddr);
348  //Return object length
349  *valueLen = MIB2_PHYS_ADDRESS_SIZE;
350  }
351  else
352  {
353  //Report an error
354  error = ERROR_BUFFER_OVERFLOW;
355  }
356  }
357  //ipNetToMediaNetAddress object?
358  else if(osStrcmp(object->name, "ipNetToMediaNetAddress") == 0)
359  {
360  //Get object value
361  ipv4CopyAddr(value->ipAddr, &entry->ipAddr);
362  }
363  //ipNetToMediaType object?
364  else if(osStrcmp(object->name, "ipNetToMediaType") == 0)
365  {
366  //Get object value
368  }
369  //Unknown object?
370  else
371  {
372  //The specified object does not exist
373  error = ERROR_OBJECT_NOT_FOUND;
374  }
375 
376  //Return status code
377  return error;
378 #else
379  //Not implemented
380  return ERROR_OBJECT_NOT_FOUND;
381 #endif
382 }
383 
384 
385 /**
386  * @brief Get next ipNetToMediaEntry object
387  * @param[in] object Pointer to the MIB object descriptor
388  * @param[in] oid Object identifier
389  * @param[in] oidLen Length of the OID, in bytes
390  * @param[out] nextOid OID of the next object in the MIB
391  * @param[out] nextOidLen Length of the next object identifier, in bytes
392  * @return Error code
393  **/
394 
395 error_t mib2GetNextIpNetToMediaEntry(const MibObject *object, const uint8_t *oid,
396  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
397 {
398 #if (ETH_SUPPORT == ENABLED)
399  error_t error;
400  uint_t i;
401  uint_t j;
402  size_t n;
403  uint_t index;
404  bool_t acceptable;
406  NetInterface *interface;
407  ArpCacheEntry *entry;
408 
409  //Initialize variables
410  index = 0;
412 
413  //Make sure the buffer is large enough to hold the OID prefix
414  if(*nextOidLen < object->oidLen)
415  return ERROR_BUFFER_OVERFLOW;
416 
417  //Copy OID prefix
418  osMemcpy(nextOid, object->oid, object->oidLen);
419 
420  //Loop through network interfaces
421  for(i = 1; i <= NET_INTERFACE_COUNT; i++)
422  {
423  //Point to the current interface
424  interface = &netInterface[i - 1];
425 
426  //Loop through ARP cache entries
427  for(j = 0; j < ARP_CACHE_SIZE; j++)
428  {
429  //Point to the current entry
430  entry = &interface->arpCache[j];
431 
432  //Valid entry?
433  if(entry->state != ARP_STATE_NONE)
434  {
435  //Append the instance identifier to the OID prefix
436  n = object->oidLen;
437 
438  //ipNetToMediaIfIndex is used as 1st instance identifier
439  error = mibEncodeIndex(nextOid, *nextOidLen, &n, i);
440  //Any error to report?
441  if(error)
442  return error;
443 
444  //ipNetToMediaNetAddress is used as 2nd instance identifier
445  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, entry->ipAddr);
446  //Any error to report?
447  if(error)
448  return error;
449 
450  //Check whether the resulting object identifier lexicographically
451  //follows the specified OID
452  if(oidComp(nextOid, n, oid, oidLen) > 0)
453  {
454  //Perform lexicographic comparison
455  if(index == 0)
456  {
457  acceptable = TRUE;
458  }
459  else if(i < index)
460  {
461  acceptable = TRUE;
462  }
463  else if(i > index)
464  {
465  acceptable = FALSE;
466  }
467  else if(ntohl(entry->ipAddr) < ntohl(ipAddr))
468  {
469  acceptable = TRUE;
470  }
471  else
472  {
473  acceptable = FALSE;
474  }
475 
476  //Save the closest object identifier that follows the specified
477  //OID in lexicographic order
478  if(acceptable)
479  {
480  index = i;
481  ipAddr = entry->ipAddr;
482  }
483  }
484  }
485  }
486  }
487 
488  //The specified OID does not lexicographically precede the name
489  //of some object?
490  if(index == 0)
491  return ERROR_OBJECT_NOT_FOUND;
492 
493  //Append the instance identifier to the OID prefix
494  n = object->oidLen;
495 
496  //ipNetToMediaIfIndex is used as 1st instance identifier
497  error = mibEncodeIndex(nextOid, *nextOidLen, &n, index);
498  //Any error to report?
499  if(error)
500  return error;
501 
502  //ipNetToMediaNetAddress is used as 2nd instance identifier
503  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, ipAddr);
504  //Any error to report?
505  if(error)
506  return error;
507 
508  //Save the length of the resulting object identifier
509  *nextOidLen = n;
510  //Next object found
511  return NO_ERROR;
512 #else
513  //Not implemented
514  return ERROR_OBJECT_NOT_FOUND;
515 #endif
516 }
517 
518 #endif
MIB-II module.
int bool_t
Definition: compiler_port.h:53
Ipv4Addr addr
IPv4 address.
Definition: ipv4.h:386
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
OID (Object Identifier)
#define MIB2_PHYS_ADDRESS_SIZE
Definition: mib2_module.h:141
#define TRUE
Definition: os_port.h:50
@ ARP_STATE_NONE
Definition: arp.h:128
#define NET_INTERFACE_COUNT
Definition: net.h:114
Ipv4AddrState state
IPv4 address state.
Definition: ipv4.h:387
#define osStrcmp(s1, s2)
Definition: os_port.h:171
error_t mib2GetIpAddrEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ipAddrEntry object value.
Definition: mib2_impl_ip.c:60
error_t mib2SetIpNetToMediaEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set ipNetToMediaEntry object value.
Definition: mib2_impl_ip.c:272
#define IPV4_MAX_FRAG_DATAGRAM_SIZE
Definition: ipv4_frag.h:69
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:297
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
#define FALSE
Definition: os_port.h:46
#define ARP_CACHE_SIZE
Definition: arp.h:46
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
#define netInterface
Definition: net_legacy.h:199
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:257
error_t mib2GetIpNetToMediaEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get ipNetToMediaEntry object value.
Definition: mib2_impl_ip.c:290
MacAddr macAddr
Link layer address associated with the IPv4 address.
Definition: arp.h:192
#define NetInterface
Definition: net.h:36
MIB-II module implementation (IP group)
General definitions for cryptographic algorithms.
#define IPV4_ADDR_LIST_SIZE
Definition: ipv4.h:69
ArpState state
Reachability state.
Definition: arp.h:190
IPv4 address entry.
Definition: ipv4.h:385
MIB-II module implementation.
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
Ipv4Addr subnetMask
Subnet mask.
Definition: ipv4.h:389
error_t mibEncodeIpv4Addr(uint8_t *oid, size_t maxOidLen, size_t *pos, Ipv4Addr ipAddr)
Encode instance identifier (IPv4 address)
Definition: mib_common.c:664
ArpCacheEntry * arpFindEntry(NetInterface *interface, Ipv4Addr ipAddr)
Search the ARP cache for a given IPv4 address.
Definition: arp_cache.c:156
Common definitions for MIB modules.
uint8_t n
@ ERROR_WRITE_FAILED
Definition: error.h:222
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:256
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:369
ARP cache entry.
Definition: arp.h:189
uint8_t oidLen
Definition: lldp_tlv.h:299
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:155
Ipv4Addr ipAddr
Definition: ipcp.h:105
ARP cache management.
error_t mibEncodeIndex(uint8_t *oid, size_t maxOidLen, size_t *pos, uint_t index)
Encode instance identifier (index)
Definition: mib_common.c:47
@ IPV4_ADDR_STATE_VALID
An address assigned to an interface whose use is unrestricted.
Definition: ipv4.h:204
error_t mibDecodeIpv4Addr(const uint8_t *oid, size_t oidLen, size_t *pos, Ipv4Addr *ipAddr)
Decode instance identifier (IPv4 address)
Definition: mib_common.c:698
MibVariant
Definition: mib_common.h:196
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
error_t mib2GetNextIpAddrEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next ipAddrEntry object.
Definition: mib2_impl_ip.c:166
@ MIB2_IP_NET_TO_MEDIA_TYPE_DYNAMIC
Definition: mib2_module.h:285
Ipv4Addr ipAddr
Unicast IPv4 address.
Definition: arp.h:191
#define ntohl(value)
Definition: cpu_endian.h:422
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
ASN.1 (Abstract Syntax Notation One)
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:117
error_t mib2GetNextIpNetToMediaEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next ipNetToMediaEntry object.
Definition: mib2_impl_ip.c:395