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