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