udp.c
Go to the documentation of this file.
1 /**
2  * @file udp.c
3  * @brief UDP (User Datagram Protocol)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL UDP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/ip.h"
37 #include "core/udp.h"
38 #include "core/socket.h"
39 #include "core/socket_misc.h"
40 #include "ipv4/ipv4.h"
41 #include "ipv4/ipv4_misc.h"
42 #include "ipv6/ipv6.h"
43 #include "ipv6/ipv6_misc.h"
44 #include "mibs/mib2_module.h"
45 #include "mibs/udp_mib_module.h"
46 #include "debug.h"
47 
48 //Check TCP/IP stack configuration
49 #if (UDP_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief UDP related initialization
54  * @param[in] context Pointer to the TCP/IP stack context
55  * @return Error code
56  **/
57 
59 {
60  //Reset ephemeral port number
61  context->udpDynamicPort = 0;
62 
63  //Initialize callback table
64  osMemset(context->udpCallbackTable, 0,
66 
67  //Successful initialization
68  return NO_ERROR;
69 }
70 
71 
72 /**
73  * @brief Get an ephemeral port number
74  * @param[in] context Pointer to the TCP/IP stack context
75  * @return Ephemeral port
76  **/
77 
78 uint16_t udpGetDynamicPort(NetContext *context)
79 {
80  uint_t port;
81 
82  //Retrieve current port number
83  port = context->udpDynamicPort;
84 
85  //Invalid port number?
86  if(port < SOCKET_EPHEMERAL_PORT_MIN || port > SOCKET_EPHEMERAL_PORT_MAX)
87  {
88  //Generate a random port number
91  }
92 
93  //Next dynamic port to use
95  {
96  //Increment port number
97  context->udpDynamicPort = port + 1;
98  }
99  else
100  {
101  //Wrap around if necessary
102  context->udpDynamicPort = SOCKET_EPHEMERAL_PORT_MIN;
103  }
104 
105  //Return an ephemeral port number
106  return port;
107 }
108 
109 
110 /**
111  * @brief Incoming UDP datagram processing
112  * @param[in] interface Underlying network interface
113  * @param[in] pseudoHeader UDP pseudo header
114  * @param[in] buffer Multi-part buffer containing the incoming UDP datagram
115  * @param[in] offset Offset to the first byte of the UDP header
116  * @param[in] ancillary Additional options passed to the stack along with
117  * the packet
118  * @return Error code
119  **/
120 
122  const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset,
123  const NetRxAncillary *ancillary)
124 {
125  error_t error;
126  uint_t i;
127  size_t length;
128  NetContext *context;
129  UdpHeader *header;
130  Socket *socket;
131  SocketQueueItem *queueItem;
132  NetBuffer *p;
133 
134  //Point to the TCP/IP stack context
135  context = interface->netContext;
136 
137  //Retrieve the length of the UDP datagram
138  length = netBufferGetLength(buffer) - offset;
139 
140  //Ensure the UDP header is valid
141  if(length < sizeof(UdpHeader))
142  {
143  //Number of received UDP datagrams that could not be delivered for
144  //reasons other than the lack of an application at the destination port
145  MIB2_UDP_INC_COUNTER32(udpInErrors, 1);
146  UDP_MIB_INC_COUNTER32(udpInErrors, 1);
147 
148  //Report an error
149  return ERROR_INVALID_HEADER;
150  }
151 
152  //Point to the UDP header
153  header = netBufferAt(buffer, offset, sizeof(UdpHeader));
154  //Malformed UDP datagram?
155  if(header == NULL)
156  return ERROR_FAILURE;
157 
158  //Debug message
159  TRACE_INFO("UDP datagram received (%" PRIuSIZE " bytes)...\r\n", length);
160  //Dump UDP header contents for debugging purpose
161  udpDumpHeader(header);
162 
163  //Make sure the length field is correct
164  if(ntohs(header->length) < sizeof(UdpHeader) ||
165  ntohs(header->length) > length)
166  {
167  //Number of received UDP datagrams that could not be delivered for
168  //reasons other than the lack of an application at the destination port
169  MIB2_UDP_INC_COUNTER32(udpInErrors, 1);
170  UDP_MIB_INC_COUNTER32(udpInErrors, 1);
171 
172  //Report an error
173  return ERROR_INVALID_HEADER;
174  }
175 
176  //Convert the length field from network byte order
177  length = ntohs(header->length);
178 
179  //When UDP runs over IPv6, the checksum is mandatory
180  if(header->checksum != 0x0000 ||
181  pseudoHeader->length == sizeof(Ipv6PseudoHeader))
182  {
183  //Check whether UDP checksums should be verified
184  if(!ancillary->ignoreUdpChecksum)
185  {
186  //Verify UDP checksum
187  if(ipCalcUpperLayerChecksumEx(pseudoHeader->data,
188  pseudoHeader->length, buffer, offset, length) != 0x0000)
189  {
190  //Debug message
191  TRACE_WARNING("Wrong UDP header checksum!\r\n");
192 
193  //Number of received UDP datagrams that could not be delivered for
194  //reasons other than the lack of an application at the destination port
195  MIB2_UDP_INC_COUNTER32(udpInErrors, 1);
196  UDP_MIB_INC_COUNTER32(udpInErrors, 1);
197 
198  //Report an error
199  return ERROR_WRONG_CHECKSUM;
200  }
201  }
202  }
203 
204  //Loop through opened sockets
205  for(i = 0; i < SOCKET_MAX_COUNT; i++)
206  {
207  //Point to the current socket
208  socket = &context->socketTable[i];
209 
210  //UDP socket found?
211  if(socket->type != SOCKET_TYPE_DGRAM)
212  continue;
213 
214  //Check whether the socket is bound to a particular interface
215  if(socket->interface != NULL && socket->interface != interface)
216  continue;
217 
218  //Check destination port number
219  if(socket->localPort == 0 || socket->localPort != ntohs(header->destPort))
220  continue;
221 
222  //Source port number filtering
223  if(socket->remotePort != 0 && socket->remotePort != ntohs(header->srcPort))
224  continue;
225 
226 #if (IPV4_SUPPORT == ENABLED)
227  //IPv4 packet received?
228  if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
229  {
230  //Check whether the socket is restricted to IPv6 communications only
231  if((socket->options & SOCKET_OPTION_IPV6_ONLY) != 0)
232  continue;
233 
234  //Check whether the destination address is a unicast, broadcast or
235  //multicast address
236  if(ipv4IsBroadcastAddr(interface, pseudoHeader->ipv4Data.destAddr))
237  {
238  //Check whether broadcast datagrams are accepted or not
239  if((socket->options & SOCKET_OPTION_BROADCAST) == 0)
240  continue;
241  }
242  else if(ipv4IsMulticastAddr(pseudoHeader->ipv4Data.destAddr))
243  {
244  IpAddr srcAddr;
246 
247  //Get source IPv4 address
248  srcAddr.length = sizeof(Ipv4Addr);
249  srcAddr.ipv4Addr = pseudoHeader->ipv4Data.srcAddr;
250 
251  //Get destination IPv4 address
252  destAddr.length = sizeof(Ipv4Addr);
253  destAddr.ipv4Addr = pseudoHeader->ipv4Data.destAddr;
254 
255  //Multicast address filtering
257  {
258  continue;
259  }
260  }
261  else
262  {
263  //Destination IP address filtering
264  if(socket->localIpAddr.length != 0)
265  {
266  //An IPv4 address is expected
267  if(socket->localIpAddr.length != sizeof(Ipv4Addr))
268  continue;
269 
270  //Filter out non-matching addresses
271  if(socket->localIpAddr.ipv4Addr != IPV4_UNSPECIFIED_ADDR &&
272  socket->localIpAddr.ipv4Addr != pseudoHeader->ipv4Data.destAddr)
273  {
274  continue;
275  }
276  }
277  }
278 
279  //Source IP address filtering
280  if(socket->remoteIpAddr.length != 0)
281  {
282  //An IPv4 address is expected
283  if(socket->remoteIpAddr.length != sizeof(Ipv4Addr))
284  continue;
285 
286  //Filter out non-matching addresses
287  if(socket->remoteIpAddr.ipv4Addr != IPV4_UNSPECIFIED_ADDR &&
288  socket->remoteIpAddr.ipv4Addr != pseudoHeader->ipv4Data.srcAddr)
289  {
290  continue;
291  }
292  }
293  }
294  else
295 #endif
296 #if (IPV6_SUPPORT == ENABLED)
297  //IPv6 packet received?
298  if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
299  {
300  //Check whether the destination address is a unicast or multicast
301  //address
302  if(ipv6IsMulticastAddr(&pseudoHeader->ipv6Data.destAddr))
303  {
304  IpAddr srcAddr;
306 
307  //Get source IPv6 address
308  srcAddr.length = sizeof(Ipv6Addr);
309  srcAddr.ipv6Addr = pseudoHeader->ipv6Data.srcAddr;
310 
311  //Get destination IPv6 address
312  destAddr.length = sizeof(Ipv6Addr);
313  destAddr.ipv6Addr = pseudoHeader->ipv6Data.destAddr;
314 
315  //Multicast address filtering
317  {
318  continue;
319  }
320  }
321  else
322  {
323  //Destination IP address filtering
324  if(socket->localIpAddr.length != 0)
325  {
326  //An IPv6 address is expected
327  if(socket->localIpAddr.length != sizeof(Ipv6Addr))
328  continue;
329 
330  //Filter out non-matching addresses
331  if(!ipv6CompAddr(&socket->localIpAddr.ipv6Addr,
333  !ipv6CompAddr(&socket->localIpAddr.ipv6Addr,
334  &pseudoHeader->ipv6Data.destAddr))
335  {
336  continue;
337  }
338  }
339  }
340 
341  //Source IP address filtering
342  if(socket->remoteIpAddr.length != 0)
343  {
344  //An IPv6 address is expected
345  if(socket->remoteIpAddr.length != sizeof(Ipv6Addr))
346  continue;
347 
348  //Filter out non-matching addresses
349  if(!ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr,
351  !ipv6CompAddr(&socket->remoteIpAddr.ipv6Addr,
352  &pseudoHeader->ipv6Data.srcAddr))
353  {
354  continue;
355  }
356  }
357  }
358  else
359 #endif
360  //Invalid packet received?
361  {
362  //This should never occur...
363  continue;
364  }
365 
366  //The current socket meets all the criteria
367  break;
368  }
369 
370  //Point to the payload
371  offset += sizeof(UdpHeader);
372  length -= sizeof(UdpHeader);
373 
374  //No matching socket found?
375  if(i >= SOCKET_MAX_COUNT)
376  {
377  //Invoke user callback, if any
378  error = udpInvokeRxCallback(interface, pseudoHeader, header, buffer,
379  offset, ancillary);
380  //Return status code
381  return error;
382  }
383 
384  //Empty receive queue?
385  if(socket->receiveQueue == NULL)
386  {
387  //Allocate a memory buffer to hold the data and the associated descriptor
388  p = netBufferAlloc(sizeof(SocketQueueItem) + length);
389 
390  //Successful memory allocation?
391  if(p != NULL)
392  {
393  //Point to the newly created item
394  queueItem = netBufferAt(p, 0, 0);
395  queueItem->buffer = p;
396 
397  //Add the newly created item to the queue
398  socket->receiveQueue = queueItem;
399  }
400  else
401  {
402  //Memory allocation failed
403  queueItem = NULL;
404  }
405  }
406  else
407  {
408  //Point to the very first item
409  queueItem = socket->receiveQueue;
410 
411  //Reach the last item in the receive queue
412  for(i = 1; queueItem->next; i++)
413  {
414  queueItem = queueItem->next;
415  }
416 
417  //Check whether the receive queue is full
418  if(i >= UDP_RX_QUEUE_SIZE)
419  {
420  //Number of inbound packets which were chosen to be discarded even
421  //though no errors had been detected
422  NET_IF_STATS_INC_COUNTER32(inDiscards, 1);
423 
424  //Report an error
426  }
427 
428  //Allocate a memory buffer to hold the data and the associated descriptor
429  p = netBufferAlloc(sizeof(SocketQueueItem) + length);
430 
431  //Successful memory allocation?
432  if(p != NULL)
433  {
434  //Add the newly created item to the queue
435  queueItem->next = netBufferAt(p, 0, 0);
436 
437  //Point to the newly created item
438  queueItem = queueItem->next;
439  queueItem->buffer = p;
440  }
441  else
442  {
443  //Memory allocation failed
444  queueItem = NULL;
445  }
446  }
447 
448  //Not enough resources to properly handle the packet?
449  if(queueItem == NULL)
450  {
451  //Number of inbound packets which were chosen to be discarded even
452  //though no errors had been detected
453  NET_IF_STATS_INC_COUNTER32(inDiscards, 1);
454 
455  //Report an error
456  return ERROR_OUT_OF_MEMORY;
457  }
458 
459  //Initialize next field
460  queueItem->next = NULL;
461  //Network interface where the packet was received
462  queueItem->interface = interface;
463  //Record the source port number
464  queueItem->srcPort = ntohs(header->srcPort);
465 
466 #if (IPV4_SUPPORT == ENABLED)
467  //IPv4 remote address?
468  if(pseudoHeader->length == sizeof(Ipv4PseudoHeader))
469  {
470  //Save the source IPv4 address
471  queueItem->srcIpAddr.length = sizeof(Ipv4Addr);
472  queueItem->srcIpAddr.ipv4Addr = pseudoHeader->ipv4Data.srcAddr;
473 
474  //Save the destination IPv4 address
475  queueItem->destIpAddr.length = sizeof(Ipv4Addr);
476  queueItem->destIpAddr.ipv4Addr = pseudoHeader->ipv4Data.destAddr;
477  }
478 #endif
479 #if (IPV6_SUPPORT == ENABLED)
480  //IPv6 remote address?
481  if(pseudoHeader->length == sizeof(Ipv6PseudoHeader))
482  {
483  //Save the source IPv6 address
484  queueItem->srcIpAddr.length = sizeof(Ipv6Addr);
485  queueItem->srcIpAddr.ipv6Addr = pseudoHeader->ipv6Data.srcAddr;
486 
487  //Save the destination IPv6 address
488  queueItem->destIpAddr.length = sizeof(Ipv6Addr);
489  queueItem->destIpAddr.ipv6Addr = pseudoHeader->ipv6Data.destAddr;
490  }
491 #endif
492 
493  //Offset to the payload
494  queueItem->offset = sizeof(SocketQueueItem);
495  //Copy the payload
496  netBufferCopy(queueItem->buffer, queueItem->offset, buffer, offset, length);
497 
498  //Additional options can be passed to the stack along with the packet
499  queueItem->ancillary = *ancillary;
500 
501  //Notify user that data is available
503 
504  //Total number of UDP datagrams delivered to UDP users
505  MIB2_UDP_INC_COUNTER32(udpInDatagrams, 1);
506  UDP_MIB_INC_COUNTER32(udpInDatagrams, 1);
507  UDP_MIB_INC_COUNTER64(udpHCInDatagrams, 1);
508 
509  //Successful processing
510  return NO_ERROR;
511 }
512 
513 
514 /**
515  * @brief Send a UDP datagram
516  * @param[in] socket Handle referencing the socket
517  * @param[in] message Pointer to the structure describing the datagram
518  * @param[in] flags Set of flags that influences the behavior of this function
519  * @return Error code
520  **/
521 
523 {
524  error_t error;
525  size_t offset;
526  NetBuffer *buffer;
528  NetTxAncillary ancillary;
529 
530  //Select the relevant network interface
531  if(message->interface != NULL)
532  {
533  interface = message->interface;
534  }
535  else
536  {
537  interface = socket->interface;
538  }
539 
540  //Allocate a memory buffer to hold the UDP datagram
541  buffer = udpAllocBuffer(0, &offset);
542  //Failed to allocate buffer?
543  if(buffer == NULL)
544  return ERROR_OUT_OF_MEMORY;
545 
546  //Copy data payload
547  error = netBufferAppend(buffer, message->data, message->length);
548 
549  //Successful processing?
550  if(!error)
551  {
552  //Additional options can be passed to the stack along with the packet
553  ancillary = NET_DEFAULT_TX_ANCILLARY;
554 
555  //This option allows UDP checksum generation to be bypassed
556  if((socket->options & SOCKET_OPTION_UDP_NO_CHECKSUM) != 0)
557  {
558  ancillary.noChecksum = TRUE;
559  }
560 
561  //Set the TTL value to be used
562  if(message->ttl != 0)
563  {
564  ancillary.ttl = message->ttl;
565  }
566  else if(ipIsMulticastAddr(&message->destIpAddr))
567  {
568  ancillary.ttl = socket->multicastTtl;
569  }
570  else
571  {
572  ancillary.ttl = socket->ttl;
573  }
574 
575  //Set ToS field
576  if(message->tos != 0)
577  {
578  ancillary.tos = message->tos;
579  }
580  else
581  {
582  ancillary.tos = socket->tos;
583  }
584 
585  //This flag can be used to send IP packets without fragmentation
586  if(message->destIpAddr.length == sizeof(Ipv4Addr) &&
587  (socket->options & SOCKET_OPTION_IPV4_DONT_FRAG) != 0)
588  {
589  ancillary.dontFrag = TRUE;
590  }
591  else if(message->destIpAddr.length == sizeof(Ipv6Addr) &&
592  (socket->options & SOCKET_OPTION_IPV6_DONT_FRAG) != 0)
593  {
594  ancillary.dontFrag = TRUE;
595  }
596  else
597  {
598  ancillary.dontFrag = message->dontFrag;
599  }
600 
601  //This flag tells the stack that the destination is on a locally attached
602  //network and not to perform a lookup of the routing table
603  if((flags & SOCKET_FLAG_DONT_ROUTE) != 0)
604  {
605  ancillary.dontRoute = TRUE;
606  }
607 
608 #if (ETH_SUPPORT == ENABLED)
609  //Set source and destination MAC addresses
610  ancillary.srcMacAddr = message->srcMacAddr;
611  ancillary.destMacAddr = message->destMacAddr;
612 #endif
613 
614 #if (ETH_VLAN_SUPPORT == ENABLED)
615  //Set VLAN PCP and DEI fields
616  ancillary.vlanPcp = socket->vlanPcp;
617  ancillary.vlanDei = socket->vlanDei;
618 #endif
619 
620 #if (ETH_VMAN_SUPPORT == ENABLED)
621  //Set VMAN PCP and DEI fields
622  ancillary.vmanPcp = socket->vmanPcp;
623  ancillary.vmanDei = socket->vmanDei;
624 #endif
625 
626 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
627  //Set switch port identifier
628  ancillary.port = message->switchPort;
629 #endif
630 
631 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
632  //Unique identifier for hardware time stamping
633  ancillary.timestampId = message->timestampId;
634 #endif
635 
636  //Send UDP datagram
637  error = udpSendBuffer(socket->netContext, interface, &message->srcIpAddr,
638  socket->localPort, &message->destIpAddr, message->destPort, buffer,
639  offset, &ancillary);
640  }
641 
642  //Free previously allocated memory
643  netBufferFree(buffer);
644 
645  //Return status code
646  return error;
647 }
648 
649 
650 /**
651  * @brief Send a UDP datagram
652  * @param[in] context Pointer to the TCP/IP stack context
653  * @param[in] interface Underlying network interface
654  * @param[in] srcIpAddr Source IP address (optional parameter)
655  * @param[in] srcPort Source port
656  * @param[in] destIpAddr IP address of the target host
657  * @param[in] destPort Target port number
658  * @param[in] buffer Multi-part buffer containing the payload
659  * @param[in] offset Offset to the first payload byte
660  * @param[in] ancillary Additional options passed to the stack along with
661  * the packet
662  * @return Error code
663  **/
664 
666  const IpAddr *srcIpAddr, uint16_t srcPort, const IpAddr *destIpAddr,
667  uint16_t destPort, NetBuffer *buffer, size_t offset,
668  NetTxAncillary *ancillary)
669 {
670  error_t error;
671  size_t length;
672  UdpHeader *header;
673  IpPseudoHeader pseudoHeader;
674 
675  //Make room for the UDP header
676  offset -= sizeof(UdpHeader);
677  //Retrieve the length of the datagram
678  length = netBufferGetLength(buffer) - offset;
679 
680  //Check the length of the payload
681  if(length > UINT16_MAX)
682  return ERROR_INVALID_LENGTH;
683 
684  //Point to the UDP header
685  header = netBufferAt(buffer, offset, sizeof(UdpHeader));
686  //Malformed UDP datagram?
687  if(header == NULL)
688  return ERROR_FAILURE;
689 
690  //Format UDP header
691  header->srcPort = htons(srcPort);
692  header->destPort = htons(destPort);
693  header->length = htons(length);
694  header->checksum = 0;
695 
696 #if (IPV4_SUPPORT == ENABLED)
697  //Destination address is an IPv4 address?
698  if(destIpAddr->length == sizeof(Ipv4Addr))
699  {
700  //Valid source IP address?
701  if(srcIpAddr != NULL && srcIpAddr->length == sizeof(Ipv4Addr))
702  {
703  //Use default network interface?
704  if(interface == NULL)
705  {
706  interface = netGetDefaultInterface(context);
707  }
708 
709  //Copy the source IP address
710  pseudoHeader.ipv4Data.srcAddr = srcIpAddr->ipv4Addr;
711  }
712  else
713  {
715 
716  //Select the source IPv4 address and the relevant network interface
717  //to use when sending data to the specified destination host
718  error = ipv4SelectSourceAddr(context, &interface, destIpAddr->ipv4Addr,
719  &ipAddr);
720 
721  //Check status code
722  if(!error)
723  {
724  //Copy the resulting source IP address
725  pseudoHeader.ipv4Data.srcAddr = ipAddr;
726  }
727  else
728  {
729  //Handle the special case where the destination address is the
730  //broadcast address
731  if(destIpAddr->ipv4Addr == IPV4_BROADCAST_ADDR && interface != NULL)
732  {
733  //Use the unspecified address as source address
734  pseudoHeader.ipv4Data.srcAddr = IPV4_UNSPECIFIED_ADDR;
735  }
736  else
737  {
738  //Source address selection failed
739  return error;
740  }
741  }
742  }
743 
744  //Format IPv4 pseudo header
745  pseudoHeader.length = sizeof(Ipv4PseudoHeader);
746  pseudoHeader.ipv4Data.destAddr = destIpAddr->ipv4Addr;
747  pseudoHeader.ipv4Data.reserved = 0;
748  pseudoHeader.ipv4Data.protocol = IPV4_PROTOCOL_UDP;
749  pseudoHeader.ipv4Data.length = htons(length);
750 
751  //UDP checksum is optional for IPv4
752  if(!ancillary->noChecksum)
753  {
754  //Calculate UDP header checksum
755  header->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader.ipv4Data,
756  sizeof(Ipv4PseudoHeader), buffer, offset, length);
757 
758  //If the computed checksum is zero, it is transmitted as all ones.
759  //An all zero transmitted checksum value means that the transmitter
760  //generated no checksum (refer to RFC 768)
761  if(header->checksum == 0)
762  {
763  header->checksum = 0xFFFF;
764  }
765  }
766  }
767  else
768 #endif
769 #if (IPV6_SUPPORT == ENABLED)
770  //Destination address is an IPv6 address?
771  if(destIpAddr->length == sizeof(Ipv6Addr))
772  {
773  //Valid source IP address?
774  if(srcIpAddr != NULL && srcIpAddr->length == sizeof(Ipv6Addr))
775  {
776  //Use default network interface?
777  if(interface == NULL)
778  {
779  interface = netGetDefaultInterface(context);
780  }
781 
782  //Copy the source IP address
783  pseudoHeader.ipv6Data.srcAddr = srcIpAddr->ipv6Addr;
784  }
785  else
786  {
787  //Select the source IPv6 address and the relevant network interface
788  //to use when sending data to the specified destination host
789  error = ipv6SelectSourceAddr(context, &interface, &destIpAddr->ipv6Addr,
790  &pseudoHeader.ipv6Data.srcAddr);
791  //Any error to report?
792  if(error)
793  return error;
794  }
795 
796  //Format IPv6 pseudo header
797  pseudoHeader.length = sizeof(Ipv6PseudoHeader);
798  pseudoHeader.ipv6Data.destAddr = destIpAddr->ipv6Addr;
799  pseudoHeader.ipv6Data.length = htonl(length);
800  pseudoHeader.ipv6Data.reserved[0] = 0;
801  pseudoHeader.ipv6Data.reserved[1] = 0;
802  pseudoHeader.ipv6Data.reserved[2] = 0;
803  pseudoHeader.ipv6Data.nextHeader = IPV6_UDP_HEADER;
804 
805  //Unlike IPv4, when UDP packets are originated by an IPv6 node, the UDP
806  //checksum is not optional (refer to RFC 2460, section 8.1)
807  header->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader.ipv6Data,
808  sizeof(Ipv6PseudoHeader), buffer, offset, length);
809 
810  //If that computation yields a result of zero, it must be changed to hex
811  //FFFF for placement in the UDP header
812  if(header->checksum == 0)
813  {
814  header->checksum = 0xFFFF;
815  }
816  }
817  else
818 #endif
819  //Invalid destination address?
820  {
821  //An internal error has occurred
822  return ERROR_FAILURE;
823  }
824 
825  //Total number of UDP datagrams sent from this entity
826  MIB2_UDP_INC_COUNTER32(udpOutDatagrams, 1);
827  UDP_MIB_INC_COUNTER32(udpOutDatagrams, 1);
828  UDP_MIB_INC_COUNTER64(udpHCOutDatagrams, 1);
829 
830  //Debug message
831  TRACE_INFO("Sending UDP datagram (%" PRIuSIZE " bytes)\r\n", length);
832  //Dump UDP header contents for debugging purpose
833  udpDumpHeader(header);
834 
835  //Send UDP datagram
836  error = ipSendDatagram(interface, &pseudoHeader, buffer, offset, ancillary);
837 
838  //Return status code
839  return error;
840 }
841 
842 
843 /**
844  * @brief Receive data from a UDP socket
845  * @param[in] socket Handle referencing the socket
846  * @param[out] message Received UDP datagram and ancillary data
847  * @param[in] flags Set of flags that influences the behavior of this function
848  * @return Error code
849  **/
850 
852 {
853  error_t error;
854  SocketQueueItem *queueItem;
855 
856  //The SOCKET_FLAG_DONT_WAIT enables non-blocking operation
857  if((flags & SOCKET_FLAG_DONT_WAIT) == 0)
858  {
859  //Check whether the receive queue is empty
860  if(socket->receiveQueue == NULL)
861  {
862  //Set the events the application is interested in
863  socket->eventMask = SOCKET_EVENT_RX_READY;
864 
865  //Reset the event object
866  osResetEvent(&socket->event);
867 
868  //Release exclusive access
869  netUnlock(socket->netContext);
870  //Wait until an event is triggered
871  osWaitForEvent(&socket->event, socket->timeout);
872  //Get exclusive access
873  netLock(socket->netContext);
874  }
875  }
876 
877  //Any datagram received?
878  if(socket->receiveQueue != NULL)
879  {
880  //Point to the first item in the receive queue
881  queueItem = socket->receiveQueue;
882 
883  //Copy data to user buffer
884  message->length = netBufferRead(message->data, queueItem->buffer,
885  queueItem->offset, message->size);
886 
887  //Network interface where the packet was received
888  message->interface = queueItem->interface;
889 
890  //Save the source IP address and port
891  message->srcIpAddr = queueItem->srcIpAddr;
892  message->srcPort = queueItem->srcPort;
893 
894  //Save the destination IP address and port
895  message->destIpAddr = queueItem->destIpAddr;
896  message->destPort = socket->localPort;
897 
898  //Save TTL value
899  message->ttl = queueItem->ancillary.ttl;
900  //Save ToS field
901  message->tos = queueItem->ancillary.tos;
902 
903 #if (ETH_SUPPORT == ENABLED)
904  //Save source and destination MAC addresses
905  message->srcMacAddr = queueItem->ancillary.srcMacAddr;
906  message->destMacAddr = queueItem->ancillary.destMacAddr;
907 #endif
908 
909 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
910  //Save switch port identifier
911  message->switchPort = queueItem->ancillary.port;
912 #endif
913 
914 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
915  //Save captured time stamp
916  message->timestamp = queueItem->ancillary.timestamp;
917 #endif
918 
919  //If the SOCKET_FLAG_PEEK flag is set, the data is copied into the
920  //buffer but is not removed from the input queue
921  if((flags & SOCKET_FLAG_PEEK) == 0)
922  {
923  //Remove the item from the receive queue
924  socket->receiveQueue = queueItem->next;
925 
926  //Deallocate memory buffer
927  netBufferFree(queueItem->buffer);
928  }
929 
930  //Update the state of events
932 
933  //Successful read operation
934  error = NO_ERROR;
935  }
936  else
937  {
938  //Total number of data that have been received
939  message->length = 0;
940 
941  //Report a timeout error
942  error = ERROR_TIMEOUT;
943  }
944 
945  //Return status code
946  return error;
947 }
948 
949 
950 /**
951  * @brief Allocate a buffer to hold a UDP packet
952  * @param[in] length Desired payload length
953  * @param[out] offset Offset to the first byte of the payload
954  * @return The function returns a pointer to the newly allocated
955  * buffer. If the system is out of resources, NULL is returned
956  **/
957 
958 NetBuffer *udpAllocBuffer(size_t length, size_t *offset)
959 {
960  NetBuffer *buffer;
961 
962  //Allocate a buffer to hold the UDP header and the payload
963  buffer = ipAllocBuffer(length + sizeof(UdpHeader), offset);
964  //Failed to allocate buffer?
965  if(buffer == NULL)
966  return NULL;
967 
968  //Offset to the first byte of the payload
969  *offset += sizeof(UdpHeader);
970 
971  //Return a pointer to the freshly allocated buffer
972  return buffer;
973 }
974 
975 
976 /**
977  * @brief Update UDP related events
978  * @param[in] socket Handle referencing the socket
979  **/
980 
982 {
983  //Clear event flags
984  socket->eventFlags = 0;
985 
986  //The socket is marked as readable if a datagram is pending in the queue
987  if(socket->receiveQueue)
988  socket->eventFlags |= SOCKET_EVENT_RX_READY;
989 
990  //Check whether the socket is bound to a particular network interface
991  if(socket->interface != NULL)
992  {
993  //Handle link up and link down events
994  if(socket->interface->linkState)
995  {
996  socket->eventFlags |= SOCKET_EVENT_LINK_UP;
997  }
998  else
999  {
1000  socket->eventFlags |= SOCKET_EVENT_LINK_DOWN;
1001  }
1002  }
1003 
1004  //Mask unused events
1005  socket->eventFlags &= socket->eventMask;
1006 
1007  //Any event to signal?
1008  if(socket->eventFlags)
1009  {
1010  //Unblock I/O operations currently in waiting state
1011  osSetEvent(&socket->event);
1012 
1013  //Set user event to signaled state if necessary
1014  if(socket->userEvent != NULL)
1015  {
1016  osSetEvent(socket->userEvent);
1017  }
1018  }
1019 }
1020 
1021 
1022 /**
1023  * @brief Register user callback
1024  * @param[in] interface Underlying network interface
1025  * @param[in] port UDP port number
1026  * @param[in] callback Callback function to be called when a datagram is received
1027  * @param[in] param Callback function parameter (optional)
1028  * @return Error code
1029  **/
1030 
1032  UdpRxCallback callback, void *param)
1033 {
1034  uint_t i;
1035  NetContext *context;
1036  UdpRxCallbackEntry *entry;
1037 
1038  //Check parameters
1039  if(interface == NULL || callback == NULL)
1040  return ERROR_INVALID_PARAMETER;
1041 
1042  //Point to the TCP/IP stack context
1043  context = interface->netContext;
1044 
1045  //Loop through the table
1046  for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
1047  {
1048  //Point to the current entry
1049  entry = &context->udpCallbackTable[i];
1050 
1051  //Check whether the entry is currently in use
1052  if(entry->callback == NULL)
1053  {
1054  //Create a new entry
1055  entry->interface = interface;
1056  entry->port = port;
1057  entry->callback = callback;
1058  entry->param = param;
1059  //We are done
1060  break;
1061  }
1062  }
1063 
1064  //Failed to attach the specified user callback?
1065  if(i >= UDP_CALLBACK_TABLE_SIZE)
1066  return ERROR_OUT_OF_RESOURCES;
1067 
1068  //Successful processing
1069  return NO_ERROR;
1070 }
1071 
1072 
1073 /**
1074  * @brief Unregister user callback
1075  * @param[in] interface Underlying network interface
1076  * @param[in] port UDP port number
1077  * @return Error code
1078  **/
1079 
1081 {
1082  error_t error;
1083  uint_t i;
1084  NetContext *context;
1085  UdpRxCallbackEntry *entry;
1086 
1087  //Check parameters
1088  if(interface == NULL)
1089  return ERROR_INVALID_PARAMETER;
1090 
1091  //Point to the TCP/IP stack context
1092  context = interface->netContext;
1093 
1094  //Initialize status code
1095  error = ERROR_FAILURE;
1096 
1097  //Loop through the table
1098  for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
1099  {
1100  //Point to the current entry
1101  entry = &context->udpCallbackTable[i];
1102 
1103  //Check whether the entry is currently in use
1104  if(entry->callback != NULL)
1105  {
1106  //Does the specified port number match the current entry?
1107  if(entry->port == port && entry->interface == interface)
1108  {
1109  //Unregister user callback
1110  entry->callback = NULL;
1111  //A matching entry has been found
1112  error = NO_ERROR;
1113  }
1114  }
1115  }
1116 
1117  //Return status code
1118  return error;
1119 }
1120 
1121 
1122 /**
1123  * @brief Invoke user callback
1124  * @param[in] interface Underlying network interface
1125  * @param[in] pseudoHeader UDP pseudo header
1126  * @param[in] header UDP header
1127  * @param[in] buffer Multi-part buffer containing the payload
1128  * @param[in] offset Offset to the first byte of the payload
1129  * @param[in] ancillary Additional options passed to the stack along with
1130  * the packet
1131  * @return Error code
1132  **/
1133 
1135  const IpPseudoHeader *pseudoHeader, const UdpHeader *header,
1136  const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
1137 {
1138  error_t error;
1139  uint_t i;
1140  NetContext *context;
1141  UdpRxCallbackEntry *entry;
1142 
1143  //Point to the TCP/IP stack context
1144  context = interface->netContext;
1145 
1146  //Initialize status code
1147  error = ERROR_PORT_UNREACHABLE;
1148 
1149  //Loop through the table
1150  for(i = 0; i < UDP_CALLBACK_TABLE_SIZE; i++)
1151  {
1152  //Point to the current entry
1153  entry = &context->udpCallbackTable[i];
1154 
1155  //Check whether the entry is currently in use
1156  if(entry->callback != NULL)
1157  {
1158  //Bound to a particular interface?
1159  if(entry->interface == NULL || entry->interface == interface)
1160  {
1161  //Does the specified port number match the current entry?
1162  if(entry->port == ntohs(header->destPort))
1163  {
1164  //Invoke user callback function
1165  entry->callback(interface, pseudoHeader, header, buffer, offset,
1166  ancillary, entry->param);
1167 
1168  //A matching entry has been found
1169  error = NO_ERROR;
1170  }
1171  }
1172  }
1173  }
1174 
1175  //Check status code
1176  if(error)
1177  {
1178  //Total number of received UDP datagrams for which there was
1179  //no application at the destination port
1180  MIB2_UDP_INC_COUNTER32(udpNoPorts, 1);
1181  UDP_MIB_INC_COUNTER32(udpNoPorts, 1);
1182  }
1183  else
1184  {
1185  //Total number of UDP datagrams delivered to UDP users
1186  MIB2_UDP_INC_COUNTER32(udpInDatagrams, 1);
1187  UDP_MIB_INC_COUNTER32(udpInDatagrams, 1);
1188  UDP_MIB_INC_COUNTER64(udpHCInDatagrams, 1);
1189  }
1190 
1191  //Return status code
1192  return error;
1193 }
1194 
1195 
1196 /**
1197  * @brief Dump UDP header for debugging purpose
1198  * @param[in] datagram Pointer to the UDP header
1199  **/
1200 
1201 void udpDumpHeader(const UdpHeader *datagram)
1202 {
1203  //Dump UDP header contents
1204  TRACE_DEBUG(" Source Port = %" PRIu16 "\r\n", ntohs(datagram->srcPort));
1205  TRACE_DEBUG(" Destination Port = %" PRIu16 "\r\n", ntohs(datagram->destPort));
1206  TRACE_DEBUG(" Length = %" PRIu16 "\r\n", ntohs(datagram->length));
1207  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(datagram->checksum));
1208 }
1209 
1210 #endif
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:187
#define htons(value)
Definition: cpu_endian.h:413
IPv6 (Internet Protocol Version 6)
MIB-II module.
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
#define NetContext
Definition: net.h:36
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:716
error_t udpUnregisterRxCallback(NetInterface *interface, uint16_t port)
Unregister user callback.
Definition: udp.c:1080
Ipv4Addr destAddr
Definition: ipv4.h:356
struct _SocketQueueItem SocketQueueItem
Receive queue item.
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:70
void udpUpdateEvents(Socket *socket)
Update UDP related events.
Definition: udp.c:981
IP network address.
Definition: ip.h:94
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
uint8_t p
Definition: ndp.h:300
@ SOCKET_FLAG_DONT_ROUTE
Definition: socket.h:137
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t message[]
Definition: chap.h:154
bool_t ipv4IsBroadcastAddr(NetInterface *interface, Ipv4Addr ipAddr)
Check whether an IPv4 address is a broadcast address.
Definition: ipv4_misc.c:482
#define TRUE
Definition: os_port.h:50
Message and ancillary data.
Definition: socket.h:241
error_t ipSendDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IP datagram.
Definition: ip.c:68
@ ERROR_INVALID_HEADER
Definition: error.h:87
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
uint16_t srcPort
Definition: socket.h:292
Ipv6Addr
Definition: ipv6.h:282
uint16_t port
Definition: udp.h:113
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
@ SOCKET_OPTION_IPV6_ONLY
Definition: socket.h:200
IpAddr srcIpAddr
Definition: socket.h:291
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:136
uint16_t destPort
Definition: tcp.h:347
error_t udpProcessDatagram(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Incoming UDP datagram processing.
Definition: udp.c:121
#define UDP_MIB_INC_COUNTER64(name, value)
Ipv4Addr srcIpAddr
Definition: ipcp.h:79
struct _SocketQueueItem * next
Definition: socket.h:289
@ SOCKET_OPTION_IPV6_DONT_FRAG
Definition: socket.h:201
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:324
#define SOCKET_EPHEMERAL_PORT_MIN
Definition: socket.h:67
error_t udpReceiveDatagram(Socket *socket, SocketMsg *message, uint_t flags)
Receive data from a UDP socket.
Definition: udp.c:851
@ SOCKET_FLAG_PEEK
Definition: socket.h:136
#define MIB2_UDP_INC_COUNTER32(name, value)
Definition: mib2_module.h:162
error_t udpInvokeRxCallback(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const UdpHeader *header, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary)
Invoke user callback.
Definition: udp.c:1134
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:148
#define UDP_MIB_INC_COUNTER32(name, value)
NetRxAncillary ancillary
Definition: socket.h:296
Helper functions for IPv4.
#define SOCKET_EPHEMERAL_PORT_MAX
Definition: socket.h:74
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define htonl(value)
Definition: cpu_endian.h:414
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
void * param
Definition: udp.h:115
void(* UdpRxCallback)(NetInterface *interface, const IpPseudoHeader *pseudoHeader, const UdpHeader *header, const NetBuffer *buffer, size_t offset, const NetRxAncillary *ancillary, void *param)
UDP receive callback.
Definition: udp.h:100
UDP MIB module.
error_t
Error codes.
Definition: error.h:43
bool_t ipIsMulticastAddr(const IpAddr *ipAddr)
Determine whether an IP address is a multicast address.
Definition: ip.c:251
#define Ipv6PseudoHeader
Definition: ipv6.h:44
UdpRxCallback callback
Definition: udp.h:114
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
UDP receive callback entry.
Definition: udp.h:111
@ IPV6_UDP_HEADER
Definition: ipv6.h:210
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
NetInterface * interface
Definition: udp.h:112
@ SOCKET_EVENT_LINK_DOWN
Definition: socket.h:182
error_t ipv4SelectSourceAddr(NetContext *context, NetInterface **interface, Ipv4Addr destAddr, Ipv4Addr *srcAddr)
IPv4 source address selection.
Definition: ipv4_misc.c:173
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
NetInterface * interface
Definition: tcp.h:409
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ SOCKET_OPTION_IPV4_DONT_FRAG
Definition: socket.h:195
uint32_t netGenerateRandRange(NetContext *context, uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net_misc.c:989
Helper functions for IPv6.
@ SOCKET_OPTION_BROADCAST
Definition: socket.h:193
#define NetTxAncillary
Definition: net_misc.h:36
error_t udpSendBuffer(NetContext *context, NetInterface *interface, const IpAddr *srcIpAddr, uint16_t srcPort, const IpAddr *destIpAddr, uint16_t destPort, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a UDP datagram.
Definition: udp.c:665
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
IpAddr destIpAddr
Definition: socket.h:293
error_t udpSendDatagram(Socket *socket, const SocketMsg *message, uint_t flags)
Send a UDP datagram.
Definition: udp.c:522
error_t netBufferCopy(NetBuffer *dest, size_t destOffset, const NetBuffer *src, size_t srcOffset, size_t length)
Copy data between multi-part buffers.
Definition: net_mem.c:522
#define Ipv4PseudoHeader
Definition: ipv4.h:40
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
NetBuffer * udpAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold a UDP packet.
Definition: udp.c:958
size_t length
Definition: ip.h:95
#define UDP_CALLBACK_TABLE_SIZE
Definition: udp.h:48
#define IPV4_BROADCAST_ADDR
Definition: ipv4.h:131
@ SOCKET_EVENT_LINK_UP
Definition: socket.h:181
UdpHeader
Definition: udp.h:85
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:243
uint16_t udpGetDynamicPort(NetContext *context)
Get an ephemeral port number.
Definition: udp.c:78
uint16_t port
Definition: dns_common.h:272
#define ntohs(value)
Definition: cpu_endian.h:421
Receive queue item.
Definition: socket.h:288
#define TRACE_WARNING(...)
Definition: debug.h:93
#define TRACE_DEBUG(...)
Definition: debug.h:119
@ ERROR_TIMEOUT
Definition: error.h:95
Ipv4Addr ipv4Addr
Definition: ip.h:99
uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader, size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP upper-layer checksum over a multi-part buffer.
Definition: ip.c:691
Helper functions for sockets.
#define UDP_RX_QUEUE_SIZE
Definition: udp.h:55
IPv4 and IPv6 common routines.
@ SOCKET_EVENT_RX_READY
Definition: socket.h:179
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
error_t udpInit(NetContext *context)
UDP related initialization.
Definition: udp.c:58
#define IpPseudoHeader
Definition: ip.h:36
@ IPV4_PROTOCOL_UDP
Definition: ipv4.h:279
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:604
UDP (User Datagram Protocol)
#define Socket
Definition: socket.h:36
MacAddr srcAddr
Definition: ethernet.h:222
Socket API.
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
@ ERROR_RECEIVE_QUEUE_FULL
Definition: error.h:94
NetInterface * interface
Definition: socket.h:290
void * netBufferAt(const NetBuffer *buffer, size_t offset, size_t length)
Returns a pointer to a data segment.
Definition: net_mem.c:418
Ipv4Addr ipAddr
Definition: ipcp.h:105
@ ERROR_WRONG_CHECKSUM
Definition: error.h:88
bool_t socketMulticastFilter(Socket *socket, const IpAddr *destAddr, const IpAddr *srcAddr)
Filter out incoming multicast traffic.
Definition: socket_misc.c:313
IPv4 (Internet Protocol Version 4)
error_t udpRegisterRxCallback(NetInterface *interface, uint16_t port, UdpRxCallback callback, void *param)
Register user callback.
Definition: udp.c:1031
uint8_t flags
Definition: tcp.h:358
Ipv6Addr ipv6Addr
Definition: ip.h:102
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
@ SOCKET_FLAG_DONT_WAIT
Definition: socket.h:139
@ ERROR_PORT_UNREACHABLE
Definition: error.h:85
void udpDumpHeader(const UdpHeader *datagram)
Dump UDP header for debugging purpose.
Definition: udp.c:1201
#define osMemset(p, value, length)
Definition: os_port.h:141
TCP/IP stack core.
#define SOCKET_MAX_COUNT
Definition: socket.h:46
#define NET_IF_STATS_INC_COUNTER32(name, value)
Definition: net.h:203
NetBuffer * buffer
Definition: socket.h:294
error_t ipv6SelectSourceAddr(NetContext *context, NetInterface **interface, const Ipv6Addr *destAddr, Ipv6Addr *srcAddr)
IPv6 source address selection.
Definition: ipv6_misc.c:891
@ SOCKET_OPTION_UDP_NO_CHECKSUM
Definition: socket.h:206
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
size_t offset
Definition: socket.h:295
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:129
Ipv4Addr destIpAddr
Definition: ipcp.h:80