mib2_impl_tcp.c
Go to the documentation of this file.
1 /**
2  * @file mib2_impl_tcp.c
3  * @brief MIB-II module implementation (TCP 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 "mibs/mib_common.h"
37 #include "mibs/mib2_module.h"
38 #include "mibs/mib2_impl.h"
39 #include "mibs/mib2_impl_tcp.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 (MIB2_SUPPORT == ENABLED && MIB2_TCP_GROUP_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Get tcpCurrEstab 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[out] value Object value
55  * @param[in,out] valueLen Length of the object value, in bytes
56  * @return Error code
57  **/
58 
59 error_t mib2GetTcpCurrEstab(const MibObject *object, const uint8_t *oid,
60  size_t oidLen, MibVariant *value, size_t *valueLen)
61 {
62  uint_t i;
63  Socket *socket;
64 
65  //Initialize object value
66  value->gauge32 = 0;
67 
68  //Loop through socket descriptors
69  for(i = 0; i < SOCKET_MAX_COUNT; i++)
70  {
71  //Point to current socket
72  socket = &socketTable[i];
73 
74  //TCP socket?
75  if(socket->type == SOCKET_TYPE_STREAM)
76  {
77  //Filter out IPv6 connections
78  if(socket->localIpAddr.length != sizeof(Ipv6Addr) &&
79  socket->remoteIpAddr.length != sizeof(Ipv6Addr))
80  {
81  //Check current state
82  if(socket->state == TCP_STATE_ESTABLISHED ||
83  socket->state == TCP_STATE_CLOSE_WAIT)
84  {
85  //Number of TCP connections for which the current state
86  //is either ESTABLISHED or CLOSE-WAIT
87  value->gauge32++;
88  }
89  }
90  }
91  }
92 
93  //Successful processing
94  return NO_ERROR;
95 }
96 
97 
98 /**
99  * @brief Set tcpConnEntry object value
100  * @param[in] object Pointer to the MIB object descriptor
101  * @param[in] oid Object identifier (object name and instance identifier)
102  * @param[in] oidLen Length of the OID, in bytes
103  * @param[out] value Object value
104  * @param[in] valueLen Length of the object value, in bytes
105  * @param[in] commit This flag tells whether the changes shall be committed
106  * to the MIB base
107  * @return Error code
108  **/
109 
110 error_t mib2SetTcpConnEntry(const MibObject *object, const uint8_t *oid,
111  size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
112 {
113  //Not implemented
114  return ERROR_WRITE_FAILED;
115 }
116 
117 
118 /**
119  * @brief Get tcpConnEntry object value
120  * @param[in] object Pointer to the MIB object descriptor
121  * @param[in] oid Object identifier (object name and instance identifier)
122  * @param[in] oidLen Length of the OID, in bytes
123  * @param[out] value Object value
124  * @param[in,out] valueLen Length of the object value, in bytes
125  * @return Error code
126  **/
127 
128 error_t mib2GetTcpConnEntry(const MibObject *object, const uint8_t *oid,
129  size_t oidLen, MibVariant *value, size_t *valueLen)
130 {
131  error_t error;
132  uint_t i;
133  size_t n;
134  Ipv4Addr localIpAddr;
135  uint16_t localPort;
136  Ipv4Addr remoteIpAddr;
137  uint16_t remotePort;
138  Socket *socket;
139 
140  //Point to the instance identifier
141  n = object->oidLen;
142 
143  //tcpConnLocalAddress is used as 1st instance identifier
144  error = mibDecodeIpv4Addr(oid, oidLen, &n, &localIpAddr);
145  //Invalid instance identifier?
146  if(error)
147  return error;
148 
149  //tcpConnLocalPort is used as 2nd instance identifier
150  error = mibDecodePort(oid, oidLen, &n, &localPort);
151  //Invalid instance identifier?
152  if(error)
153  return error;
154 
155  //tcpConnRemAddress is used as 3rd instance identifier
156  error = mibDecodeIpv4Addr(oid, oidLen, &n, &remoteIpAddr);
157  //Invalid instance identifier?
158  if(error)
159  return error;
160 
161  //tcpConnRemPort is used as 4th instance identifier
162  error = mibDecodePort(oid, oidLen, &n, &remotePort);
163  //Invalid instance identifier?
164  if(error)
165  return error;
166 
167  //Sanity check
168  if(n != oidLen)
170 
171  //Loop through socket descriptors
172  for(i = 0; i < SOCKET_MAX_COUNT; i++)
173  {
174  //Point to current socket
175  socket = &socketTable[i];
176 
177  //TCP socket?
178  if(socket->type == SOCKET_TYPE_STREAM)
179  {
180  //Check local IP address
181  if(socket->localIpAddr.length == sizeof(Ipv6Addr))
182  continue;
183  if(socket->localIpAddr.ipv4Addr != localIpAddr)
184  continue;
185  //Check local port number
186  if(socket->localPort != localPort)
187  continue;
188  //Check remote IP address
189  if(socket->remoteIpAddr.length == sizeof(Ipv6Addr))
190  continue;
191  if(socket->remoteIpAddr.ipv4Addr != remoteIpAddr)
192  continue;
193  //Check remote port number
194  if(socket->remotePort != remotePort)
195  continue;
196 
197  //A matching socket has been found
198  break;
199  }
200  }
201 
202  //No matching connection found in socket table?
203  if(i >= SOCKET_MAX_COUNT)
205 
206  //tcpConnState object?
207  if(osStrcmp(object->name, "tcpConnState") == 0)
208  {
209  //Get object value
210  switch(socket->state)
211  {
212  case TCP_STATE_CLOSED:
214  break;
215  case TCP_STATE_LISTEN:
217  break;
218  case TCP_STATE_SYN_SENT:
220  break;
223  break;
226  break;
229  break;
232  break;
235  break;
236  case TCP_STATE_LAST_ACK:
238  break;
239  case TCP_STATE_CLOSING:
241  break;
242  case TCP_STATE_TIME_WAIT:
244  break;
245  default:
246  value->integer = 0;
247  break;
248  }
249  }
250  //tcpConnLocalAddress object?
251  else if(osStrcmp(object->name, "tcpConnLocalAddress") == 0)
252  {
253  //Get object value
254  ipv4CopyAddr(value->ipAddr, &socket->localIpAddr.ipv4Addr);
255  }
256  //tcpConnLocalPort object?
257  else if(osStrcmp(object->name, "tcpConnLocalPort") == 0)
258  {
259  //Get object value
260  value->integer = socket->localPort;
261  }
262  //tcpConnRemAddress object?
263  else if(osStrcmp(object->name, "tcpConnRemAddress") == 0)
264  {
265  //Get object value
266  ipv4CopyAddr(value->ipAddr, &socket->remoteIpAddr.ipv4Addr);
267  }
268  //tcpConnRemPort object?
269  else if(osStrcmp(object->name, "tcpConnRemPort") == 0)
270  {
271  //Get object value
272  value->integer = socket->remotePort;
273  }
274  //Unknown object?
275  else
276  {
277  //The specified object does not exist
278  error = ERROR_OBJECT_NOT_FOUND;
279  }
280 
281  //Return status code
282  return error;
283 }
284 
285 
286 /**
287  * @brief Get next tcpConnEntry object
288  * @param[in] object Pointer to the MIB object descriptor
289  * @param[in] oid Object identifier
290  * @param[in] oidLen Length of the OID, in bytes
291  * @param[out] nextOid OID of the next object in the MIB
292  * @param[out] nextOidLen Length of the next object identifier, in bytes
293  * @return Error code
294  **/
295 
296 error_t mib2GetNextTcpConnEntry(const MibObject *object, const uint8_t *oid,
297  size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
298 {
299  error_t error;
300  uint_t i;
301  size_t n;
302  bool_t acceptable;
303  Ipv4Addr localIpAddr;
304  uint16_t localPort;
305  Ipv4Addr remoteIpAddr;
306  uint16_t remotePort;
307  Socket *socket;
308 
309  //Initialize variables
310  localIpAddr = IPV4_UNSPECIFIED_ADDR;
311  localPort = 0;
312  remoteIpAddr = IPV4_UNSPECIFIED_ADDR;
313  remotePort = 0;
314 
315  //Make sure the buffer is large enough to hold the OID prefix
316  if(*nextOidLen < object->oidLen)
317  return ERROR_BUFFER_OVERFLOW;
318 
319  //Copy OID prefix
320  osMemcpy(nextOid, object->oid, object->oidLen);
321 
322  //Loop through socket descriptors
323  for(i = 0; i < SOCKET_MAX_COUNT; i++)
324  {
325  //Point to current socket
326  socket = &socketTable[i];
327 
328  //TCP socket?
329  if(socket->type == SOCKET_TYPE_STREAM)
330  {
331  //Filter out IPv6 connections
332  if(socket->localIpAddr.length != sizeof(Ipv6Addr) &&
333  socket->remoteIpAddr.length != sizeof(Ipv6Addr))
334  {
335  //Append the instance identifier to the OID prefix
336  n = object->oidLen;
337 
338  //tcpConnLocalAddress is used as 1st instance identifier
339  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, socket->localIpAddr.ipv4Addr);
340  //Any error to report?
341  if(error)
342  return error;
343 
344  //tcpConnLocalPort is used as 2nd instance identifier
345  error = mibEncodePort(nextOid, *nextOidLen, &n, socket->localPort);
346  //Any error to report?
347  if(error)
348  return error;
349 
350  //tcpConnRemAddress is used as 3rd instance identifier
351  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, socket->remoteIpAddr.ipv4Addr);
352  //Any error to report?
353  if(error)
354  return error;
355 
356  //tcpConnRemPort is used as 4th instance identifier
357  error = mibEncodePort(nextOid, *nextOidLen, &n, socket->remotePort);
358  //Any error to report?
359  if(error)
360  return error;
361 
362  //Check whether the resulting object identifier lexicographically
363  //follows the specified OID
364  if(oidComp(nextOid, n, oid, oidLen) > 0)
365  {
366  //Perform lexicographic comparison
367  if(localPort == 0 && remotePort == 0)
368  {
369  acceptable = TRUE;
370  }
371  else if(ntohl(socket->localIpAddr.ipv4Addr) < ntohl(localIpAddr))
372  {
373  acceptable = TRUE;
374  }
375  else if(ntohl(socket->localIpAddr.ipv4Addr) > ntohl(localIpAddr))
376  {
377  acceptable = FALSE;
378  }
379  else if(socket->localPort < localPort)
380  {
381  acceptable = TRUE;
382  }
383  else if(socket->localPort > localPort)
384  {
385  acceptable = FALSE;
386  }
387  else if(ntohl(socket->remoteIpAddr.ipv4Addr) < ntohl(remoteIpAddr))
388  {
389  acceptable = TRUE;
390  }
391  else if(ntohl(socket->remoteIpAddr.ipv4Addr) > ntohl(remoteIpAddr))
392  {
393  acceptable = FALSE;
394  }
395  else if(socket->remotePort < remotePort)
396  {
397  acceptable = TRUE;
398  }
399  else
400  {
401  acceptable = FALSE;
402  }
403 
404  //Save the closest object identifier that follows the specified
405  //OID in lexicographic order
406  if(acceptable)
407  {
408  localIpAddr = socket->localIpAddr.ipv4Addr;
409  localPort = socket->localPort;
410  remoteIpAddr = socket->remoteIpAddr.ipv4Addr;
411  remotePort = socket->remotePort;
412  }
413  }
414  }
415  }
416  }
417 
418  //The specified OID does not lexicographically precede the name
419  //of some object?
420  if(localPort == 0 && remotePort == 0)
421  return ERROR_OBJECT_NOT_FOUND;
422 
423  //Append the instance identifier to the OID prefix
424  n = object->oidLen;
425 
426  //tcpConnLocalAddress is used as 1st instance identifier
427  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, localIpAddr);
428  //Any error to report?
429  if(error)
430  return error;
431 
432  //tcpConnLocalPort is used as 2nd instance identifier
433  error = mibEncodePort(nextOid, *nextOidLen, &n, localPort);
434  //Any error to report?
435  if(error)
436  return error;
437 
438  //tcpConnRemAddress is used as 3rd instance identifier
439  error = mibEncodeIpv4Addr(nextOid, *nextOidLen, &n, remoteIpAddr);
440  //Any error to report?
441  if(error)
442  return error;
443 
444  //tcpConnRemPort is used as 4th instance identifier
445  error = mibEncodePort(nextOid, *nextOidLen, &n, remotePort);
446  //Any error to report?
447  if(error)
448  return error;
449 
450  //Save the length of the resulting object identifier
451  *nextOidLen = n;
452  //Next object found
453  return NO_ERROR;
454 }
455 
456 #endif
MIB-II module.
@ TCP_STATE_TIME_WAIT
Definition: tcp.h:278
int bool_t
Definition: compiler_port.h:53
@ MIB2_TCP_CONN_STATE_FIN_WAIT_2
Definition: mib2_module.h:315
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:142
@ MIB2_TCP_CONN_STATE_CLOSE_WAIT
Definition: mib2_module.h:316
OID (Object Identifier)
@ TCP_STATE_FIN_WAIT_1
Definition: tcp.h:275
#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
@ MIB2_TCP_CONN_STATE_CLOSING
Definition: mib2_module.h:318
Ipv6Addr
Definition: ipv6.h:260
@ TCP_STATE_CLOSE_WAIT
Definition: tcp.h:273
#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
@ MIB2_TCP_CONN_STATE_LISTEN
Definition: mib2_module.h:310
@ SOCKET_TYPE_STREAM
Definition: socket.h:92
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
error_t mib2GetTcpConnEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get tcpConnEntry object value.
#define FALSE
Definition: os_port.h:46
#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
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
@ MIB2_TCP_CONN_STATE_FIN_WAIT_1
Definition: mib2_module.h:314
@ MIB2_TCP_CONN_STATE_LAST_ACK
Definition: mib2_module.h:317
General definitions for cryptographic algorithms.
@ TCP_STATE_SYN_SENT
Definition: tcp.h:270
@ TCP_STATE_LAST_ACK
Definition: tcp.h:274
@ TCP_STATE_CLOSING
Definition: tcp.h:277
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
@ MIB2_TCP_CONN_STATE_CLOSED
Definition: mib2_module.h:309
@ TCP_STATE_CLOSED
Definition: tcp.h:268
@ TCP_STATE_LISTEN
Definition: tcp.h:269
MIB-II module implementation.
error_t mibEncodeIpv4Addr(uint8_t *oid, size_t maxOidLen, size_t *pos, Ipv4Addr ipAddr)
Encode instance identifier (IPv4 address)
Definition: mib_common.c:664
Common definitions for MIB modules.
uint8_t n
@ ERROR_WRITE_FAILED
Definition: error.h:222
@ ERROR_OBJECT_NOT_FOUND
Definition: error.h:256
#define Socket
Definition: socket.h:36
@ TCP_STATE_FIN_WAIT_2
Definition: tcp.h:276
#define MibObject
Definition: mib_common.h:46
uint8_t value[]
Definition: tcp.h:369
uint8_t oidLen
Definition: lldp_tlv.h:299
@ MIB2_TCP_CONN_STATE_TIME_WAIT
Definition: mib2_module.h:319
@ TCP_STATE_SYN_RECEIVED
Definition: tcp.h:271
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:155
error_t mib2GetNextTcpConnEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, uint8_t *nextOid, size_t *nextOidLen)
Get next tcpConnEntry object.
error_t mib2SetTcpConnEntry(const MibObject *object, const uint8_t *oid, size_t oidLen, const MibVariant *value, size_t valueLen, bool_t commit)
Set tcpConnEntry object value.
MIB-II module implementation (TCP group)
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
@ MIB2_TCP_CONN_STATE_SYN_SENT
Definition: mib2_module.h:311
MibVariant
Definition: mib_common.h:196
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
@ MIB2_TCP_CONN_STATE_ESTABLISHED
Definition: mib2_module.h:313
#define SOCKET_MAX_COUNT
Definition: socket.h:46
@ MIB2_TCP_CONN_STATE_SYN_RECEIVED
Definition: mib2_module.h:312
#define ntohl(value)
Definition: cpu_endian.h:422
@ TCP_STATE_ESTABLISHED
Definition: tcp.h:272
@ 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 mib2GetTcpCurrEstab(const MibObject *object, const uint8_t *oid, size_t oidLen, MibVariant *value, size_t *valueLen)
Get tcpCurrEstab object value.
Definition: mib2_impl_tcp.c:59