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