Go to the documentation of this file.
1 /**
2  * @file udp_mib_impl.c
3  * @brief UDP 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"
37 #include "mibs/udp_mib_module.h"
38 #include "mibs/udp_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 (UDP_MIB_SUPPORT == ENABLED && UDP_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief UDP MIB module initialization
50  * @return Error code
51  **/
52 
54 {
55  //Debug message
56  TRACE_INFO("Initializing UDP-MIB base...\r\n");
57 
58  //Clear UDP MIB base
59  osMemset(&udpMibBase, 0, sizeof(udpMibBase));
60 
61  //Successful processing
62  return NO_ERROR;
63 }
64 
65 
66 /**
67  * @brief Get udpEndpointEntry 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 udpMibGetUdpEndpointEntry(const MibObject *object, const uint8_t *oid,
77  size_t oidLen, MibVariant *value, size_t *valueLen)
78 {
79  error_t error;
80  uint_t i;
81  size_t n;
82  IpAddr localIpAddr;
83  uint16_t localPort;
84  IpAddr remoteIpAddr;
85  uint16_t remotePort;
86  uint32_t instance;
87 
88  //Point to the instance identifier
89  n = object->oidLen;
90 
91  //udpEndpointLocalAddressType and udpEndpointLocalAddress are used
92  //as 1st and 2nd instance identifiers
93  error = mibDecodeIpAddr(oid, oidLen, &n, &localIpAddr);
94  //Invalid instance identifier?
95  if(error)
96  return error;
97 
98  //udpEndpointLocalPort is used as 3rd instance identifier
99  error = mibDecodePort(oid, oidLen, &n, &localPort);
100  //Invalid instance identifier?
101  if(error)
102  return error;
103 
104  //udpEndpointRemoteAddressType and udpEndpointRemoteAddress are used
105  //as 4th and 5th instance identifiers
106  error = mibDecodeIpAddr(oid, oidLen, &n, &remoteIpAddr);
107  //Invalid instance identifier?
108  if(error)
109  return error;
110 
111  //udpEndpointRemotePort is used as 6th instance identifier
112  error = mibDecodePort(oid, oidLen, &n, &remotePort);
113  //Invalid instance identifier?
114  if(error)
115  return error;
116 
117  //udpEndpointInstance is used as 7th instance identifier
118  error = mibDecodeUnsigned32(oid, oidLen, &n, &instance);
119  //Invalid instance identifier?
120  if(error)
121  return error;
122 
123  //Sanity check
124  if(n != oidLen)
126 
127  //Loop through socket descriptors
128  for(i = 0; i < SOCKET_MAX_COUNT; i++)
129  {
130  //Point to current socket
131  Socket *socket = &socketTable[i];
132 
133  //UDP socket?
134  if(socket->type == SOCKET_TYPE_DGRAM)
135  {
136  //Check local IP address
137  if(!ipCompAddr(&socket->localIpAddr, &localIpAddr))
138  continue;
139  //Check local port number
140  if(socket->localPort != localPort)
141  continue;
142  //Check remote IP address
143  if(!ipCompAddr(&socket->remoteIpAddr, &remoteIpAddr))
144  continue;
145  //Check local port number
146  if(socket->remotePort != remotePort)
147  continue;
148 
149  //A matching socket has been found
150  break;
151  }
152  }
153 
154  //No matching connection found in socket table?
155  if(i >= SOCKET_MAX_COUNT)
156  {
157  //Loop through the UDP callback table
158  for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
159  {
160  //Point to the current entry
162 
163  //Check whether the entry is currently in use
164  if(entry->callback != NULL)
165  {
166  //Check local port number
167  if(entry->port == localPort)
168  break;
169  }
170  }
171 
172  //No matching connection found in UDP callback table?
173  if(i >= UDP_CALLBACK_TABLE_SIZE)
175  }
176 
177  //udpEndpointProcess object?
178  if(osStrcmp(object->name, "udpEndpointProcess") == 0)
179  {
180  //ID of the process associated with this endpoint
181  value->unsigned32 = 0;
182  }
183  //Unknown object?
184  else
185  {
186  //The specified object does not exist
187  error = ERROR_OBJECT_NOT_FOUND;
188  }
189 
190  //Return status code
191  return error;
192 }
193 
194 
195 /**
196  * @brief Get next udpEndpointEntry object
197  * @param[in] object Pointer to the MIB object descriptor
198  * @param[in] oid Object identifier
199  * @param[in] oidLen Length of the OID, in bytes
200  * @param[out] nextOid OID of the next object in the MIB
201  * @param[out] nextOidLen Length of the next object identifier, in bytes
202  * @return Error code
203  **/
204 
205 error_t udpMibGetNextUdpEndpointEntry(const MibObject *object, const uint8_t *oid,
206  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
207 {
208  error_t error;
209  uint_t i;
210  size_t n;
211  bool_t acceptable;
212  IpAddr localIpAddr;
213  uint16_t localPort;
214  IpAddr remoteIpAddr;
215  uint16_t remotePort;
216  uint32_t instance;
217 
218  //Initialize variables
219  localIpAddr = IP_ADDR_ANY;
220  localPort = 0;
221  remoteIpAddr = IP_ADDR_ANY;
222  remotePort = 0;
223  instance = 1;
224 
225  //Make sure the buffer is large enough to hold the OID prefix
226  if(*nextOidLen < object->oidLen)
227  return ERROR_BUFFER_OVERFLOW;
228 
229  //Copy OID prefix
230  osMemcpy(nextOid, object->oid, object->oidLen);
231 
232  //Loop through socket descriptors
233  for(i = 0; i < SOCKET_MAX_COUNT; i++)
234  {
235  //Point to current socket
236  Socket *socket = &socketTable[i];
237 
238  //UDP socket?
239  if(socket->type == SOCKET_TYPE_DGRAM)
240  {
241  //Append the instance identifier to the OID prefix
242  n = object->oidLen;
243 
244  //udpEndpointLocalAddressType and udpEndpointLocalAddress are used
245  //as 1st and 2nd instance identifiers
246  error = mibEncodeIpAddr(nextOid, *nextOidLen, &n, &socket->localIpAddr);
247  //Any error to report?
248  if(error)
249  return error;
250 
251  //udpEndpointLocalPort is used as 3rd instance identifier
252  error = mibEncodePort(nextOid, *nextOidLen, &n, socket->localPort);
253  //Any error to report?
254  if(error)
255  return error;
256 
257  //udpEndpointRemoteAddressType and udpEndpointRemoteAddress are used
258  //as 4th and 5th instance identifiers
259  error = mibEncodeIpAddr(nextOid, *nextOidLen, &n, &socket->remoteIpAddr);
260  //Any error to report?
261  if(error)
262  return error;
263 
264  //udpEndpointRemotePort is used as 6th instance identifier
265  error = mibEncodePort(nextOid, *nextOidLen, &n, socket->remotePort);
266  //Any error to report?
267  if(error)
268  return error;
269 
270  //udpEndpointInstance is used as 7th instance identifier
271  error = mibEncodeUnsigned32(nextOid, *nextOidLen, &n, instance);
272  //Any error to report?
273  if(error)
274  return error;
275 
276  //Check whether the resulting object identifier lexicographically
277  //follows the specified OID
278  if(oidComp(nextOid, n, oid, oidLen) > 0)
279  {
280  //Perform lexicographic comparison
281  if(localPort == 0 && remotePort == 0)
282  {
283  acceptable = TRUE;
284  }
285  else if(mibCompIpAddr(&socket->localIpAddr, &localIpAddr) < 0)
286  {
287  acceptable = TRUE;
288  }
289  else if(mibCompIpAddr(&socket->localIpAddr, &localIpAddr) > 0)
290  {
291  acceptable = FALSE;
292  }
293  else if(socket->localPort < localPort)
294  {
295  acceptable = TRUE;
296  }
297  else if(socket->localPort > localPort)
298  {
299  acceptable = FALSE;
300  }
301  else if(mibCompIpAddr(&socket->remoteIpAddr, &remoteIpAddr) < 0)
302  {
303  acceptable = TRUE;
304  }
305  else if(mibCompIpAddr(&socket->remoteIpAddr, &remoteIpAddr) > 0)
306  {
307  acceptable = FALSE;
308  }
309  else if(socket->remotePort < remotePort)
310  {
311  acceptable = TRUE;
312  }
313  else
314  {
315  acceptable = FALSE;
316  }
317 
318  //Save the closest object identifier that follows the specified
319  //OID in lexicographic order
320  if(acceptable)
321  {
322  localIpAddr = socket->localIpAddr;
323  localPort = socket->localPort;
324  remoteIpAddr = socket->remoteIpAddr;
325  remotePort = socket->remotePort;
326  }
327  }
328  }
329  }
330 
331  //Loop through the UDP callback table
332  for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
333  {
334  //Point to the current entry
336 
337  //Check whether the entry is currently in use
338  if(entry->callback != NULL)
339  {
340  //Append the instance identifier to the OID prefix
341  n = object->oidLen;
342 
343  //udpEndpointLocalAddressType and udpEndpointLocalAddress are used
344  //as 1st and 2nd instance identifiers
345  error = mibEncodeIpAddr(nextOid, *nextOidLen, &n, &IP_ADDR_ANY);
346  //Any error to report?
347  if(error)
348  return error;
349 
350  //udpEndpointLocalPort is used as 3rd instance identifier
351  error = mibEncodePort(nextOid, *nextOidLen, &n, entry->port);
352  //Any error to report?
353  if(error)
354  return error;
355 
356  //udpEndpointRemoteAddressType and udpEndpointRemoteAddress are used
357  //as 4th and 5th instance identifiers
358  error = mibEncodeIpAddr(nextOid, *nextOidLen, &n, &IP_ADDR_ANY);
359  //Any error to report?
360  if(error)
361  return error;
362 
363  //udpEndpointRemotePort is used as 6th instance identifier
364  error = mibEncodePort(nextOid, *nextOidLen, &n, 0);
365  //Any error to report?
366  if(error)
367  return error;
368 
369  //udpEndpointInstance is used as 7th instance identifier
370  error = mibEncodeUnsigned32(nextOid, *nextOidLen, &n, instance);
371  //Any error to report?
372  if(error)
373  return error;
374 
375  //Check whether the resulting object identifier lexicographically
376  //follows the specified OID
377  if(oidComp(nextOid, n, oid, oidLen) > 0)
378  {
379  //Perform lexicographic comparison
380  if(localPort == 0 && remotePort == 0)
381  {
382  acceptable = TRUE;
383  }
384  else if(mibCompIpAddr(&IP_ADDR_ANY, &localIpAddr) < 0)
385  {
386  acceptable = TRUE;
387  }
388  else if(mibCompIpAddr(&IP_ADDR_ANY, &localIpAddr) > 0)
389  {
390  acceptable = FALSE;
391  }
392  else if(entry->port < localPort)
393  {
394  acceptable = TRUE;
395  }
396  else if(entry->port > localPort)
397  {
398  acceptable = FALSE;
399  }
400  else if(mibCompIpAddr(&IP_ADDR_ANY, &remoteIpAddr) < 0)
401  {
402  acceptable = TRUE;
403  }
404  else if(mibCompIpAddr(&IP_ADDR_ANY, &remoteIpAddr) > 0)
405  {
406  acceptable = FALSE;
407  }
408  else if(0 < remotePort)
409  {
410  acceptable = TRUE;
411  }
412  else
413  {
414  acceptable = FALSE;
415  }
416 
417  //Save the closest object identifier that follows the specified
418  //OID in lexicographic order
419  if(acceptable)
420  {
421  localIpAddr = IP_ADDR_ANY;
422  localPort = entry->port;
423  remoteIpAddr = IP_ADDR_ANY;
424  remotePort = 0;
425  }
426  }
427  }
428  }
429 
430  //The specified OID does not lexicographically precede the name
431  //of some object?
432  if(localPort == 0 && remotePort == 0)
433  return ERROR_OBJECT_NOT_FOUND;
434 
435  //Append the instance identifier to the OID prefix
436  n = object->oidLen;
437 
438  //udpEndpointLocalAddressType and udpEndpointLocalAddress are used
439  //as 1st and 2nd instance identifiers
440  error = mibEncodeIpAddr(nextOid, *nextOidLen, &n, &localIpAddr);
441  //Any error to report?
442  if(error)
443  return error;
444 
445  //udpEndpointLocalPort is used as 3rd instance identifier
446  error = mibEncodePort(nextOid, *nextOidLen, &n, localPort);
447  //Any error to report?
448  if(error)
449  return error;
450 
451  //udpEndpointRemoteAddressType and udpEndpointRemoteAddress are used
452  //as 4th and 5th instance identifiers
453  error = mibEncodeIpAddr(nextOid, *nextOidLen, &n, &remoteIpAddr);
454  //Any error to report?
455  if(error)
456  return error;
457 
458  //udpEndpointRemotePort is used as 6th instance identifier
459  error = mibEncodePort(nextOid, *nextOidLen, &n, remotePort);
460  //Any error to report?
461  if(error)
462  return error;
463 
464  //udpEndpointInstance is used as 7th instance identifier
465  error = mibEncodeUnsigned32(nextOid, *nextOidLen, &n, instance);
466  //Any error to report?
467  if(error)
468  return error;
469 
470  //Save the length of the resulting object identifier
471  *nextOidLen = n;
472  //Next object found
473  return NO_ERROR;
474 }
475 
476 #endif
error_t mibEncodeIpAddr(uint8_t *oid, size_t maxOidLen, size_t *pos, const IpAddr *ipAddr)
Encode instance identifier (IP address)
Definition: mib_common.c:808
int bool_t
Definition: compiler_port.h:53
IP network address.
Definition: ip.h:90
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
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
uint16_t port
Definition: udp.h:113
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
#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 udpMibGetNextUdpEndpointEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next udpEndpointEntry object.
Definition: udp_mib_impl.c:205
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
UdpMibBase udpMibBase
UDP MIB base.
const IpAddr IP_ADDR_ANY
Definition: ip.c:53
int_t mibCompIpAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: mib_common.c:968
#define FALSE
Definition: os_port.h:46
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
UDP MIB module.
error_t
Error codes.
Definition: error.h:43
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:317
@ ERROR_INSTANCE_NOT_FOUND
Definition: error.h:257
UdpRxCallback callback
Definition: udp.h:114
int_t socket(int_t family, int_t type, int_t protocol)
Create a socket that is bound to a specific transport service provider.
Definition: bsd_socket.c:65
UDP receive callback entry.
Definition: udp.h:111
General definitions for cryptographic algorithms.
#define TRACE_INFO(...)
Definition: debug.h:95
error_t udpMibInit(void)
UDP MIB module initialization.
Definition: udp_mib_impl.c:53
#define UDP_CALLBACK_TABLE_SIZE
Definition: udp.h:48
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
Common definitions for MIB modules.
uint8_t n
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:256
#define Socket
Definition: socket.h:36
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:369
uint8_t oidLen
Definition: lldp_tlv.h:299
error_t mibDecodeIpAddr(const uint8_t *oid, size_t oidLen, size_t *pos, IpAddr *ipAddr)
Decode instance identifier (IP address)
Definition: mib_common.c:886
error_t mibDecodeUnsigned32(const uint8_t *oid, size_t oidLen, size_t *pos, uint32_t *value)
Decode instance identifier (unsigned 32-bit integer)
Definition: mib_common.c:111
UdpRxCallbackEntry udpCallbackTable[UDP_CALLBACK_TABLE_SIZE]
Definition: udp.c:55
UDP MIB module implementation.
error_t mibEncodeUnsigned32(uint8_t *oid, size_t maxOidLen, size_t *pos, uint32_t value)
Encode instance identifier (unsigned 32-bit integer)
Definition: mib_common.c:94
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.
#define SOCKET_MAX_COUNT
Definition: socket.h:46
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
ASN.1 (Abstract Syntax Notation One)
error_t udpMibGetUdpEndpointEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get udpEndpointEntry object value.
Definition: udp_mib_impl.c:76