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