raw_socket.c
Go to the documentation of this file.
1 /**
2  * @file raw_socket.c
3  * @brief TCP/IP raw sockets
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  * @section Description
28  *
29  * A raw socket is a type of socket that allows access to the
30  * underlying transport provider
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.4.0
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL RAW_SOCKET_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/net.h"
41 #include "core/socket.h"
42 #include "core/raw_socket.h"
43 #include "core/ethernet_misc.h"
44 #include "ipv4/ipv4.h"
45 #include "ipv4/ipv4_misc.h"
46 #include "ipv6/ipv6.h"
47 #include "ipv6/ipv6_misc.h"
48 #include "mibs/mib2_module.h"
49 #include "mibs/if_mib_module.h"
50 #include "debug.h"
51 
52 //Check TCP/IP stack configuration
53 #if (RAW_SOCKET_SUPPORT == ENABLED)
54 
55 
56 /**
57  * @brief Process incoming IP packet
58  * @param[in] interface Underlying network interface
59  * @param[in] pseudoHeader IPv4 or IPv6 pseudo header
60  * @param[in] buffer Multi-part buffer containing the IP packet
61  * @param[in] offset Offset to the first byte of the IP packet
62  * @param[in] ancillary Additional options passed to the stack along with
63  * the packet
64  * @return Error code
65  **/
66 
68  const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset,
69  const NetRxAncillary *ancillary)
70 {
71  uint_t i;
72  size_t length;
73  Socket *socket;
74  SocketQueueItem *queueItem;
75  NetBuffer *p;
76 
77  //Retrieve the length of the raw IP packet
78  length = netBufferGetLength(buffer) - offset;
79 
80  //Loop through opened sockets
81  for(i = 0; i < SOCKET_MAX_COUNT; i++)
82  {
83  //Point to the current socket
84  socket = socketTable + i;
85 
86  //Raw socket found?
87  if(socket->type != SOCKET_TYPE_RAW_IP)
88  continue;
89 
90  //Check whether the socket is bound to a particular interface
91  if(socket->interface && socket->interface != interface)
92  continue;
93 
94 #if (IPV4_SUPPORT == ENABLED)
95  //IPv4 packet received?
96  if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
97  {
98  //Check whether the socket is restricted to IPv6 communications only
99  if((socket->options & SOCKET_OPTION_IPV6_ONLY) != 0)
100  continue;
101 
102  //Check protocol field
103  if(socket->protocol != pseudoHeader->ipv4Data.protocol)
104  continue;
105 
106  //Check whether the destination address is a unicast, broadcast or
107  //multicast address
108  if(ipv4IsBroadcastAddr(interface, pseudoHeader->ipv4Data.destAddr))
109  {
110  //Check whether broadcast datagrams are accepted or not
111  if((socket->options & SOCKET_OPTION_BROADCAST) == 0)
112  continue;
113  }
114  else if(ipv4IsMulticastAddr(pseudoHeader->ipv4Data.destAddr))
115  {
116  uint_t j;
117  IpAddr *group;
118 
119  //Loop through multicast groups
120  for(j = 0; j < SOCKET_MAX_MULTICAST_GROUPS; j++)
121  {
122  //Point to the current multicast group
123  group = &socket->multicastGroups[j];
124 
125  //Matching multicast address?
126  if(group->length == sizeof(Ipv4Addr) &&
127  group->ipv4Addr == pseudoHeader->ipv4Data.destAddr)
128  {
129  break;
130  }
131  }
132 
133  //Filter out non-matching multicast addresses
135  continue;
136  }
137  else
138  {
139  //Destination IP address filtering
140  if(socket->localIpAddr.length != 0)
141  {
142  //An IPv4 address is expected
143  if(socket->localIpAddr.length != sizeof(Ipv4Addr))
144  continue;
145 
146  //Filter out non-matching addresses
147  if(socket->localIpAddr.ipv4Addr != IPV4_UNSPECIFIED_ADDR &&
148  socket->localIpAddr.ipv4Addr != pseudoHeader->ipv4Data.destAddr)
149  {
150  continue;
151  }
152  }
153  }
154 
155  //Source IP address filtering
156  if(socket->remoteIpAddr.length != 0)
157  {
158  //An IPv4 address is expected
159  if(socket->remoteIpAddr.length != sizeof(Ipv4Addr))
160  continue;
161 
162  //Filter out non-matching addresses
163  if(socket->remoteIpAddr.ipv4Addr != IPV4_UNSPECIFIED_ADDR &&
164  socket->remoteIpAddr.ipv4Addr != pseudoHeader->ipv4Data.srcAddr)
165  {
166  continue;
167  }
168  }
169  }
170  else
171 #endif
172 #if (IPV6_SUPPORT == ENABLED)
173  //IPv6 packet received?
174  if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
175  {
176  //Check protocol field
177  if(socket->protocol != pseudoHeader->ipv6Data.nextHeader)
178  continue;
179 
180  //Destination IP address filtering
181  if(socket->localIpAddr.length != 0)
182  {
183  //An IPv6 address is expected
184  if(socket->localIpAddr.length != sizeof(Ipv6Addr))
185  continue;
186 
187  //Filter out non-matching addresses
188  if(!ipv6CompAddr(&socket->localIpAddr.ipv6Addr, &IPV6_UNSPECIFIED_ADDR) &&
189  !ipv6CompAddr(&socket->localIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.destAddr))
190  {
191  continue;
192  }
193  }
194 
195  //Source IP address filtering
196  if(socket->remoteIpAddr.length != 0)
197  {
198  //An IPv6 address is expected
199  if(socket->remoteIpAddr.length != sizeof(Ipv6Addr))
200  continue;
201 
202  //Filter out non-matching addresses
203  if(!ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr, &IPV6_UNSPECIFIED_ADDR) &&
204  !ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr, &pseudoHeader->ipv6Data.srcAddr))
205  {
206  continue;
207  }
208  }
209  }
210  else
211 #endif
212  //Invalid packet received?
213  {
214  //This should never occur...
215  continue;
216  }
217 
218  //The current socket meets all the criteria
219  break;
220  }
221 
222  //Drop incoming packet if no matching socket was found
223  if(i >= SOCKET_MAX_COUNT)
225 
226  //Empty receive queue?
227  if(socket->receiveQueue == NULL)
228  {
229  //Allocate a memory buffer to hold the data and the associated descriptor
230  p = netBufferAlloc(sizeof(SocketQueueItem) + length);
231 
232  //Successful memory allocation?
233  if(p != NULL)
234  {
235  //Point to the newly created item
236  queueItem = netBufferAt(p, 0);
237  queueItem->buffer = p;
238  //Add the newly created item to the queue
239  socket->receiveQueue = queueItem;
240  }
241  else
242  {
243  //Memory allocation failed
244  queueItem = NULL;
245  }
246  }
247  else
248  {
249  //Point to the very first item
250  queueItem = socket->receiveQueue;
251 
252  //Reach the last item in the receive queue
253  for(i = 1; queueItem->next; i++)
254  {
255  queueItem = queueItem->next;
256  }
257 
258  //Check whether the receive queue is full
259  if(i >= RAW_SOCKET_RX_QUEUE_SIZE)
260  {
261  //Number of inbound packets which were chosen to be discarded even
262  //though no errors had been detected
263  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
264  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
265 
266  //Report an error
268  }
269 
270  //Allocate a memory buffer to hold the data and the associated descriptor
271  p = netBufferAlloc(sizeof(SocketQueueItem) + length);
272 
273  //Successful memory allocation?
274  if(p != NULL)
275  {
276  //Add the newly created item to the queue
277  queueItem->next = netBufferAt(p, 0);
278  //Point to the newly created item
279  queueItem = queueItem->next;
280  queueItem->buffer = p;
281  }
282  else
283  {
284  //Memory allocation failed
285  queueItem = NULL;
286  }
287  }
288 
289  //Not enough resources to properly handle the packet?
290  if(queueItem == NULL)
291  {
292  //Number of inbound packets which were chosen to be discarded even
293  //though no errors had been detected
294  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
295  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
296 
297  //Report an error
298  return ERROR_OUT_OF_MEMORY;
299  }
300 
301  //Initialize next field
302  queueItem->next = NULL;
303  //Network interface where the packet was received
304  queueItem->interface = interface;
305  //Port number is unused
306  queueItem->srcPort = 0;
307 
308 #if (IPV4_SUPPORT == ENABLED)
309  //IPv4 remote address?
310  if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
311  {
312  //Save the source IPv4 address
313  queueItem->srcIpAddr.length = sizeof(Ipv4Addr);
314  queueItem->srcIpAddr.ipv4Addr = pseudoHeader->ipv4Data.srcAddr;
315 
316  //Save the destination IPv4 address
317  queueItem->destIpAddr.length = sizeof(Ipv4Addr);
318  queueItem->destIpAddr.ipv4Addr = pseudoHeader->ipv4Data.destAddr;
319  }
320 #endif
321 #if (IPV6_SUPPORT == ENABLED)
322  //IPv6 remote address?
323  if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
324  {
325  //Save the source IPv6 address
326  queueItem->srcIpAddr.length = sizeof(Ipv6Addr);
327  queueItem->srcIpAddr.ipv6Addr = pseudoHeader->ipv6Data.srcAddr;
328 
329  //Save the destination IPv6 address
330  queueItem->destIpAddr.length = sizeof(Ipv6Addr);
331  queueItem->destIpAddr.ipv6Addr = pseudoHeader->ipv6Data.destAddr;
332  }
333 #endif
334 
335  //Offset to the raw IP packet
336  queueItem->offset = sizeof(SocketQueueItem);
337  //Copy the raw data
338  netBufferCopy(queueItem->buffer, queueItem->offset, buffer, offset, length);
339 
340  //Additional options can be passed to the stack along with the packet
341  queueItem->ancillary = *ancillary;
342 
343  //Notify user that data is available
345 
346  //Successful processing
347  return NO_ERROR;
348 }
349 
350 
351 /**
352  * @brief Process incoming Ethernet packet
353  * @param[in] interface Underlying network interface
354  * @param[in] data Pointer to the payload data
355  * @param[in] length Length of the payload data, in bytes
356  * @param[in] ancillary Additional options passed to the stack along with
357  * the packet
358  **/
359 
360 void rawSocketProcessEthPacket(NetInterface *interface, const uint8_t *data,
361  size_t length, const NetRxAncillary *ancillary)
362 {
363 #if (ETH_SUPPORT == ENABLED)
364  uint_t i;
365  Socket *socket;
366  SocketQueueItem *queueItem;
367  NetBuffer *p;
368 
369  //Loop through opened sockets
370  for(i = 0; i < SOCKET_MAX_COUNT; i++)
371  {
372  //Point to the current socket
373  socket = socketTable + i;
374 
375  //Raw socket found?
376  if(socket->type != SOCKET_TYPE_RAW_ETH)
377  continue;
378 
379  //Check whether the socket is bound to a particular interface
380  if(socket->interface && socket->interface != interface)
381  continue;
382 
383  //Check protocol field
384  if(socket->protocol == SOCKET_ETH_PROTO_ALL)
385  {
386  //Accept all EtherType values
387  }
388  else if(socket->protocol == SOCKET_ETH_PROTO_LLC)
389  {
390  //Only accept LLC frames
391  if(ancillary->ethType > ETH_MTU)
392  continue;
393  }
394  else
395  {
396  //Only accept frames with the correct EtherType value
397  if(ancillary->ethType != socket->protocol)
398  continue;
399  }
400 
401  //Empty receive queue?
402  if(socket->receiveQueue == NULL)
403  {
404  //Allocate a memory buffer to hold the data and the associated
405  //descriptor
406  p = netBufferAlloc(sizeof(SocketQueueItem) + length);
407 
408  //Successful memory allocation?
409  if(p != NULL)
410  {
411  //Point to the newly created item
412  queueItem = netBufferAt(p, 0);
413  queueItem->buffer = p;
414  //Add the newly created item to the queue
415  socket->receiveQueue = queueItem;
416  }
417  else
418  {
419  //Memory allocation failed
420  queueItem = NULL;
421  }
422  }
423  else
424  {
425  //Point to the very first item
426  queueItem = socket->receiveQueue;
427 
428  //Reach the last item in the receive queue
429  for(i = 1; queueItem->next; i++)
430  {
431  queueItem = queueItem->next;
432  }
433 
434  //Check whether the receive queue is full
435  if(i >= RAW_SOCKET_RX_QUEUE_SIZE)
436  {
437  //Number of inbound packets which were chosen to be discarded even
438  //though no errors had been detected
439  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
440  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
441 
442  //Exit immediately
443  break;
444  }
445 
446  //Allocate a memory buffer to hold the data and the associated
447  //descriptor
448  p = netBufferAlloc(sizeof(SocketQueueItem) + length);
449 
450  //Successful memory allocation?
451  if(p != NULL)
452  {
453  //Add the newly created item to the queue
454  queueItem->next = netBufferAt(p, 0);
455  //Point to the newly created item
456  queueItem = queueItem->next;
457  queueItem->buffer = p;
458  }
459  else
460  {
461  //Memory allocation failed
462  queueItem = NULL;
463  }
464  }
465 
466  //Not enough resources to properly handle the packet?
467  if(queueItem == NULL)
468  {
469  //Number of inbound packets which were chosen to be discarded even
470  //though no errors had been detected
471  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
472  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
473 
474  //Exit immediately
475  break;
476  }
477 
478  //Initialize next field
479  queueItem->next = NULL;
480  //Network interface where the packet was received
481  queueItem->interface = interface;
482 
483  //Other fields are meaningless
484  queueItem->srcPort = 0;
485  queueItem->srcIpAddr = IP_ADDR_ANY;
486  queueItem->destIpAddr = IP_ADDR_ANY;
487 
488  //Offset to the raw datagram
489  queueItem->offset = sizeof(SocketQueueItem);
490 
491  //Copy the payload
492  netBufferWrite(queueItem->buffer, queueItem->offset, data, length);
493 
494  //Additional options can be passed to the stack along with the packet
495  queueItem->ancillary = *ancillary;
496 
497  //Notify user that data is available
499  }
500 #endif
501 }
502 
503 
504 /**
505  * @brief Send a raw IP packet
506  * @param[in] socket Handle referencing the socket
507  * @param[in] message Pointer to the structure describing the raw packet
508  * @param[in] flags Set of flags that influences the behavior of this function
509  * @return Error code
510  **/
511 
513  uint_t flags)
514 {
515  error_t error;
516  size_t offset;
517  NetBuffer *buffer;
518  NetInterface *interface;
519  IpPseudoHeader pseudoHeader;
520  NetTxAncillary ancillary;
521 
522  //Select the relevant network interface
523  if(message->interface != NULL)
524  {
525  interface = message->interface;
526  }
527  else
528  {
529  interface = socket->interface;
530  }
531 
532  //Allocate a buffer to hold the raw IP datagram
533  buffer = ipAllocBuffer(0, &offset);
534  //Failed to allocate memory?
535  if(buffer == NULL)
536  return ERROR_OUT_OF_MEMORY;
537 
538  //Start of exception handling block
539  do
540  {
541  //Copy the raw data
542  error = netBufferAppend(buffer, message->data, message->length);
543  //Any error to report?
544  if(error)
545  break;
546 
547 #if (IPV4_SUPPORT == ENABLED)
548  //Destination address is an IPv4 address?
549  if(message->destIpAddr.length == sizeof(Ipv4Addr))
550  {
552 
553  //Select the source IPv4 address and the relevant network interface
554  //to use when sending data to the specified destination host
555  error = ipv4SelectSourceAddr(&interface, message->destIpAddr.ipv4Addr,
556  &srcIpAddr);
557  //Any error to report?
558  if(error)
559  break;
560 
561  //Format IPv4 pseudo header
562  pseudoHeader.length = sizeof(Ipv4PseudoHeader);
563  pseudoHeader.ipv4Data.srcAddr = srcIpAddr;
564  pseudoHeader.ipv4Data.destAddr = message->destIpAddr.ipv4Addr;
565  pseudoHeader.ipv4Data.reserved = 0;
566  pseudoHeader.ipv4Data.protocol = socket->protocol;
567  pseudoHeader.ipv4Data.length = htons(message->length);
568  }
569  else
570 #endif
571 #if (IPV6_SUPPORT == ENABLED)
572  //Destination address is an IPv6 address?
573  if(message->destIpAddr.length == sizeof(Ipv6Addr))
574  {
575  //Select the source IPv6 address and the relevant network interface
576  //to use when sending data to the specified destination host
577  error = ipv6SelectSourceAddr(&interface, &message->destIpAddr.ipv6Addr,
578  &pseudoHeader.ipv6Data.srcAddr);
579  //Any error to report?
580  if(error)
581  break;
582 
583  //Format IPv6 pseudo header
584  pseudoHeader.length = sizeof(Ipv6PseudoHeader);
585  pseudoHeader.ipv6Data.destAddr = message->destIpAddr.ipv6Addr;
586  pseudoHeader.ipv6Data.length = htonl(message->length);
587  pseudoHeader.ipv6Data.reserved[0] = 0;
588  pseudoHeader.ipv6Data.reserved[1] = 0;
589  pseudoHeader.ipv6Data.reserved[2] = 0;
590  pseudoHeader.ipv6Data.nextHeader = socket->protocol;
591  }
592  else
593 #endif
594  //Invalid destination address?
595  {
596  //An internal error has occurred
597  error = ERROR_FAILURE;
598  //Exit immediately
599  break;
600  }
601 
602  //Additional options can be passed to the stack along with the packet
603  ancillary = NET_DEFAULT_TX_ANCILLARY;
604 
605  //Set the TTL value to be used
606  if(message->ttl != 0)
607  {
608  ancillary.ttl = message->ttl;
609  }
610  else if(ipIsMulticastAddr(&message->destIpAddr))
611  {
612  ancillary.ttl = socket->multicastTtl;
613  }
614  else
615  {
616  ancillary.ttl = socket->ttl;
617  }
618 
619  //This flag can be used to send IP packets without fragmentation
620  if(message->destIpAddr.length == sizeof(Ipv4Addr) &&
621  (socket->options & SOCKET_OPTION_IPV4_DONT_FRAG) != 0)
622  {
623  ancillary.dontFrag = TRUE;
624  }
625  else if(message->destIpAddr.length == sizeof(Ipv6Addr) &&
626  (socket->options & SOCKET_OPTION_IPV6_DONT_FRAG) != 0)
627  {
628  ancillary.dontFrag = TRUE;
629  }
630  else
631  {
632  ancillary.dontFrag = message->dontFrag;
633  }
634 
635  //This flag tells the stack that the destination is on a locally attached
636  //network and not to perform a lookup of the routing table
637  if((flags & SOCKET_FLAG_DONT_ROUTE) != 0)
638  {
639  ancillary.dontRoute = TRUE;
640  }
641 
642  //Set ToS field
643  if(message->tos != 0)
644  {
645  ancillary.tos = message->tos;
646  }
647  else
648  {
649  ancillary.tos = socket->tos;
650  }
651 
652 #if (ETH_SUPPORT == ENABLED)
653  //Set source and destination MAC addresses
654  ancillary.srcMacAddr = message->srcMacAddr;
655  ancillary.destMacAddr = message->destMacAddr;
656 #endif
657 
658 #if (ETH_VLAN_SUPPORT == ENABLED)
659  //Set VLAN PCP and DEI fields
660  ancillary.vlanPcp = socket->vlanPcp;
661  ancillary.vlanDei = socket->vlanDei;
662 #endif
663 
664 #if (ETH_VMAN_SUPPORT == ENABLED)
665  //Set VMAN PCP and DEI fields
666  ancillary.vmanPcp = socket->vmanPcp;
667  ancillary.vmanDei = socket->vmanDei;
668 #endif
669 
670 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
671  //Set switch port identifier
672  ancillary.port = message->switchPort;
673 #endif
674 
675 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
676  //Unique identifier for hardware time stamping
677  ancillary.timestampId = message->timestampId;
678 #endif
679 
680  //Send raw IP datagram
681  error = ipSendDatagram(interface, &pseudoHeader, buffer, offset,
682  &ancillary);
683  //Failed to send data?
684  if(error)
685  break;
686 
687  //End of exception handling block
688  } while(0);
689 
690  //Free previously allocated memory block
691  netBufferFree(buffer);
692 
693  //Return status code
694  return error;
695 }
696 
697 
698 /**
699  * @brief Send a raw Ethernet packet
700  * @param[in] socket Handle referencing the socket
701  * @param[in] message Pointer to the structure describing the raw packet
702  * @param[in] flags Set of flags that influences the behavior of this function
703  * @return Error code
704  **/
705 
707  uint_t flags)
708 {
709  error_t error;
710 
711 #if (ETH_SUPPORT == ENABLED)
712  size_t offset;
713  NetBuffer *buffer;
714  NetInterface *interface;
715 
716  //Select the relevant network interface
717  if(message->interface != NULL)
718  {
719  interface = message->interface;
720  }
721  else if(socket->interface != NULL)
722  {
723  interface = socket->interface;
724  }
725  else
726  {
727  interface = netGetDefaultInterface();
728  }
729 
730  //Forward the frame to the physical interface
731  interface = nicGetPhysicalInterface(interface);
732 
733  //Ethernet interface?
734  if(interface->nicDriver != NULL &&
735  interface->nicDriver->type == NIC_TYPE_ETHERNET)
736  {
737  //Allocate a buffer to hold the raw Ethernet packet
738  buffer = ethAllocBuffer(0, &offset);
739  //Failed to allocate buffer?
740  if(buffer == NULL)
741  return ERROR_OUT_OF_MEMORY;
742 
743  //Copy the raw data
744  error = netBufferAppend(buffer, message->data, message->length);
745 
746  //Check status code
747  if(!error)
748  {
749  NetTxAncillary ancillary;
750 
751  //Additional options can be passed to the stack along with the packet
752  ancillary = NET_DEFAULT_TX_ANCILLARY;
753 
754  //Set source MAC address
755  ancillary.srcMacAddr = message->srcMacAddr;
756 
757 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
758  //Set switch port identifier
759  ancillary.port = message->switchPort;
760 #endif
761 
762 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
763  //Unique identifier for hardware time stamping
764  ancillary.timestampId = message->timestampId;
765 #endif
766  //Debug message
767  TRACE_DEBUG("Sending raw Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length);
768 
769  //Send raw Ethernet packet
770  error = ethSendFrame(interface, &message->destMacAddr,
771  message->ethType, buffer, offset, &ancillary);
772  }
773 
774  //Free previously allocated memory block
775  netBufferFree(buffer);
776  }
777  else
778 #endif
779  //Unknown interface type?
780  {
781  //Report an error
782  error = ERROR_INVALID_INTERFACE;
783  }
784 
785  //Return status code
786  return error;
787 }
788 
789 
790 /**
791  * @brief Receive an IP packet from a raw socket
792  * @param[in] socket Handle referencing the socket
793  * @param[out] message Received IP packet and ancillary data
794  * @param[in] flags Set of flags that influences the behavior of this function
795  * @return Error code
796  **/
797 
799  uint_t flags)
800 {
801  error_t error;
802  SocketQueueItem *queueItem;
803 
804  //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
805  if((flags & SOCKET_FLAG_DONT_WAIT) == 0)
806  {
807  //Check whether the receive queue is empty
808  if(socket->receiveQueue == NULL)
809  {
810  //Set the events the application is interested in
811  socket->eventMask = SOCKET_EVENT_RX_READY;
812 
813  //Reset the event object
814  osResetEvent(&socket->event);
815 
816  //Release exclusive access
818  //Wait until an event is triggered
819  osWaitForEvent(&socket->event, socket->timeout);
820  //Get exclusive access
822  }
823  }
824 
825  //Any packet received?
826  if(socket->receiveQueue != NULL)
827  {
828  //Point to the first item in the receive queue
829  queueItem = socket->receiveQueue;
830 
831  //Copy data to user buffer
832  message->length = netBufferRead(message->data, queueItem->buffer,
833  queueItem->offset, message->size);
834 
835  //Network interface where the packet was received
836  message->interface = queueItem->interface;
837  //Save the source IP address
838  message->srcIpAddr = queueItem->srcIpAddr;
839  //Save the source port number
840  message->srcPort = queueItem->srcPort;
841  //Save the destination IP address
842  message->destIpAddr = queueItem->destIpAddr;
843 
844  //Save TTL value
845  message->ttl = queueItem->ancillary.ttl;
846  //Save ToS field
847  message->tos = queueItem->ancillary.tos;
848 
849 #if (ETH_SUPPORT == ENABLED)
850  //Save source and destination MAC addresses
851  message->srcMacAddr = queueItem->ancillary.srcMacAddr;
852  message->destMacAddr = queueItem->ancillary.destMacAddr;
853 #endif
854 
855 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
856  //Save switch port identifier
857  message->switchPort = queueItem->ancillary.port;
858 #endif
859 
860 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
861  //Save captured time stamp
862  message->timestamp = queueItem->ancillary.timestamp;
863 #endif
864 
865  //If the SOCKET_FLAG_PEEK flag is set, the data is copied into the
866  //buffer but is not removed from the input queue
867  if((flags & SOCKET_FLAG_PEEK) == 0)
868  {
869  //Remove the item from the receive queue
870  socket->receiveQueue = queueItem->next;
871 
872  //Deallocate memory buffer
873  netBufferFree(queueItem->buffer);
874  }
875 
876  //Update the state of events
878 
879  //Successful read operation
880  error = NO_ERROR;
881  }
882  else
883  {
884  //Total number of data that have been received
885  message->length = 0;
886 
887  //Report a timeout error
888  error = ERROR_TIMEOUT;
889  }
890 
891  //Return status code
892  return error;
893 }
894 
895 
896 /**
897  * @brief Receive an Ethernet packet from a raw socket
898  * @param[in] socket Handle referencing the socket
899  * @param[out] message Received Ethernet packet and ancillary data
900  * @param[in] flags Set of flags that influences the behavior of this function
901  * @return Error code
902  **/
903 
905  uint_t flags)
906 {
907  error_t error;
908  SocketQueueItem *queueItem;
909 
910  //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
911  if((flags & SOCKET_FLAG_DONT_WAIT) == 0)
912  {
913  //Check whether the receive queue is empty
914  if(socket->receiveQueue == NULL)
915  {
916  //Set the events the application is interested in
917  socket->eventMask = SOCKET_EVENT_RX_READY;
918 
919  //Reset the event object
920  osResetEvent(&socket->event);
921 
922  //Release exclusive access
924  //Wait until an event is triggered
925  osWaitForEvent(&socket->event, socket->timeout);
926  //Get exclusive access
928  }
929  }
930 
931  //Any packet received?
932  if(socket->receiveQueue != NULL)
933  {
934  //Point to the first item in the receive queue
935  queueItem = socket->receiveQueue;
936 
937  //Copy data to user buffer
938  message->length = netBufferRead(message->data, queueItem->buffer,
939  queueItem->offset, message->size);
940 
941  //Network interface where the packet was received
942  message->interface = queueItem->interface;
943 
944 #if (ETH_SUPPORT == ENABLED)
945  //Save source and destination MAC addresses
946  message->srcMacAddr = queueItem->ancillary.srcMacAddr;
947  message->destMacAddr = queueItem->ancillary.destMacAddr;
948 
949  //Save the value of the EtherType field
950  message->ethType = queueItem->ancillary.ethType;
951 #endif
952 
953 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
954  //Save switch port identifier
955  message->switchPort = queueItem->ancillary.port;
956 #endif
957 
958 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
959  //Save captured time stamp
960  message->timestamp = queueItem->ancillary.timestamp;
961 #endif
962 
963  //If the SOCKET_FLAG_PEEK flag is set, the data is copied into the
964  //buffer but is not removed from the input queue
965  if((flags & SOCKET_FLAG_PEEK) == 0)
966  {
967  //Remove the item from the receive queue
968  socket->receiveQueue = queueItem->next;
969 
970  //Deallocate memory buffer
971  netBufferFree(queueItem->buffer);
972  }
973 
974  //Update the state of events
976 
977  //Successful read operation
978  error = NO_ERROR;
979  }
980  else
981  {
982  //Total number of data that have been received
983  message->length = 0;
984 
985  //Report a timeout error
986  error = ERROR_TIMEOUT;
987  }
988 
989  //Return status code
990  return error;
991 }
992 
993 
994 /**
995  * @brief Update event state for raw sockets
996  * @param[in] socket Handle referencing the socket
997  **/
998 
1000 {
1001  //Clear event flags
1002  socket->eventFlags = 0;
1003 
1004  //The socket is marked as readable if a datagram is pending in the queue
1005  if(socket->receiveQueue)
1006  socket->eventFlags |= SOCKET_EVENT_RX_READY;
1007 
1008  //Check whether the socket is bound to a particular network interface
1009  if(socket->interface != NULL)
1010  {
1011  //Handle link up and link down events
1012  if(socket->interface->linkState)
1013  {
1014  socket->eventFlags |= SOCKET_EVENT_LINK_UP;
1015  }
1016  else
1017  {
1018  socket->eventFlags |= SOCKET_EVENT_LINK_DOWN;
1019  }
1020  }
1021 
1022  //Mask unused events
1023  socket->eventFlags &= socket->eventMask;
1024 
1025  //Any event to signal?
1026  if(socket->eventFlags)
1027  {
1028  //Unblock I/O operations currently in waiting state
1029  osSetEvent(&socket->event);
1030 
1031  //Set user event to signaled state if necessary
1032  if(socket->userEvent != NULL)
1033  {
1034  osSetEvent(socket->userEvent);
1035  }
1036  }
1037 }
1038 
1039 #endif
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
uint8_t message[]
Definition: chap.h:154
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
#define htonl(value)
Definition: cpu_endian.h:414
#define htons(value)
Definition: cpu_endian.h:413
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_INTERFACE
Invalid interface.
Definition: error.h:53
@ ERROR_TIMEOUT
Definition: error.h:95
@ ERROR_RECEIVE_QUEUE_FULL
Definition: error.h:94
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_PROTOCOL_UNREACHABLE
Definition: error.h:84
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, uint16_t type, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an Ethernet frame.
Definition: ethernet.c:399
NetBuffer * ethAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an Ethernet frame.
Definition: ethernet.c:775
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
Helper functions for Ethernet.
Interfaces Group MIB module.
#define IF_MIB_INC_COUNTER32(name, value)
Definition: if_mib_module.h:47
const IpAddr IP_ADDR_ANY
Definition: ip.c:51
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:744
bool_t ipIsMulticastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a multicast address.
Definition: ip.c:248
error_t ipSendDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IP datagram.
Definition: ip.c:66
Ipv4Addr srcIpAddr
Definition: ipcp.h:79
IPv4 (Internet Protocol Version 4)
#define Ipv4PseudoHeader
Definition: ipv4.h:39
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:168
bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a broadcast address.
Definition: ipv4_misc.c:471
error_t ipv4SelectSourceAddr(NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4_misc.c:202
Helper functions for IPv4.
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
IPv6 (Internet Protocol Version 6)
Ipv6Addr
Definition: ipv6.h:251
#define Ipv6PseudoHeader
Definition: ipv6.h:42
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:120
error_t ipv6SelectSourceAddr(NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:895
Helper functions for IPv6.
MIB-II module.
#define MIB2_IF_INC_COUNTER32(name, value)
Definition: mib2_module.h:156
uint8_t p
Definition: ndp.h:300
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:470
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netMutex
Definition: net_legacy.h:195
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:415
error_t netBufferCopy(NetBuffer *dest, size_t destOffset, const NetBuffer *src, size_t srcOffset, size_t length)
Copy data between multi-part buffers.
Definition: net_mem.c:506
size_t netBufferWrite(NetBuffer *dest, size_t destOffset, const void *src, size_t length)
Write data to a multi-part buffer.
Definition: net_mem.c:621
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:243
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:674
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define TRUE
Definition: os_port.h:50
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t rawSocketReceiveEthPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an Ethernet packet from a raw socket.
Definition: raw_socket.c:904
void rawSocketProcessEthPacket(NetInterface *interface, const uint8_t *data, size_t length, const NetRxAncillary *ancillary)
Process incoming Ethernet packet.
Definition: raw_socket.c:360
error_t rawSocketSendIpPacket(Socket *socket, const SocketMsg *message, uint_t flags)
Send a raw IP packet.
Definition: raw_socket.c:512
error_t rawSocketSendEthPacket(Socket *socket, const SocketMsg *message, uint_t flags)
Send a raw Ethernet packet.
Definition: raw_socket.c:706
error_t rawSocketProcessIpPacket(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Process incoming IP packet.
Definition: raw_socket.c:67
error_t rawSocketReceiveIpPacket(Socket *socket, SocketMsg *message, uint_t flags)
Receive an IP packet from a raw socket.
Definition: raw_socket.c:798
void rawSocketUpdateEvents(Socket *socket)
Update event state for raw sockets.
Definition: raw_socket.c:999
TCP/IP raw sockets.
#define RAW_SOCKET_RX_QUEUE_SIZE
Definition: raw_socket.h:48
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
Socket API.
@ SOCKET_ETH_PROTO_ALL
Definition: socket.h:112
@ SOCKET_ETH_PROTO_LLC
Definition: socket.h:113
struct _SocketQueueItem SocketQueueItem
Receive queue item.
@ SOCKET_FLAG_PEEK
Definition: socket.h:126
@ SOCKET_FLAG_DONT_ROUTE
Definition: socket.h:127
@ SOCKET_FLAG_DONT_WAIT
Definition: socket.h:129
@ SOCKET_OPTION_BROADCAST
Definition: socket.h:183
@ SOCKET_OPTION_IPV6_ONLY
Definition: socket.h:190
@ SOCKET_OPTION_IPV4_DONT_FRAG
Definition: socket.h:185
@ SOCKET_OPTION_IPV6_DONT_FRAG
Definition: socket.h:191
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:87
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:88
#define Socket
Definition: socket.h:36
#define SOCKET_MAX_COUNT
Definition: socket.h:46
@ SOCKET_EVENT_RX_READY
Definition: socket.h:169
@ SOCKET_EVENT_LINK_DOWN
Definition: socket.h:172
@ SOCKET_EVENT_LINK_UP
Definition: socket.h:171
#define SOCKET_MAX_MULTICAST_GROUPS
Definition: socket.h:53
Receive queue item.
Definition: socket.h:262
NetRxAncillary ancillary
Definition: socket.h:270
uint16_t srcPort
Definition: socket.h:266
NetBuffer * buffer
Definition: socket.h:268
struct _SocketQueueItem * next
Definition: socket.h:263
IpAddr destIpAddr
Definition: socket.h:267
size_t offset
Definition: socket.h:269
IpAddr srcIpAddr
Definition: socket.h:265
NetInterface * interface
Definition: socket.h:264
IP network address.
Definition: ip.h:79
Ipv6Addr ipv6Addr
Definition: ip.h:87
Ipv4Addr ipv4Addr
Definition: ip.h:84
size_t length
Definition: ip.h:80
IP pseudo header.
Definition: ip.h:99
Ipv4PseudoHeader ipv4Data
Definition: ip.h:104
Ipv6PseudoHeader ipv6Data
Definition: ip.h:107
size_t length
Definition: ip.h:100
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Message and ancillary data.
Definition: socket.h:230
uint8_t length
Definition: tcp.h:368
uint8_t flags
Definition: tcp.h:351