net_misc.c
Go to the documentation of this file.
1 /**
2  * @file net_misc.c
3  * @brief Helper functions for TCP/IP stack
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 NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/net_misc.h"
37 #include "core/socket.h"
38 #include "core/raw_socket.h"
39 #include "core/tcp_timer.h"
40 #include "core/tcp_misc.h"
41 #include "core/ethernet.h"
42 #include "ipv4/arp.h"
43 #include "ipv4/ipv4.h"
44 #include "ipv4/ipv4_routing.h"
45 #include "ipv4/auto_ip_misc.h"
46 #include "igmp/igmp_host.h"
47 #include "dhcp/dhcp_client_misc.h"
48 #include "dhcp/dhcp_server_misc.h"
49 #include "nat/nat_misc.h"
50 #include "ipv6/ipv6.h"
51 #include "ipv6/ipv6_routing.h"
52 #include "ipv6/ndp.h"
54 #include "mld/mld_node.h"
56 #include "dns/dns_cache.h"
57 #include "dns/dns_client.h"
58 #include "mdns/mdns_client.h"
59 #include "mdns/mdns_responder.h"
60 #include "mdns/mdns_common.h"
62 #include "netbios/nbns_client.h"
63 #include "netbios/nbns_responder.h"
64 #include "netbios/nbns_common.h"
65 #include "llmnr/llmnr_client.h"
66 #include "llmnr/llmnr_responder.h"
67 #include "debug.h"
68 
69 //Default options passed to the stack (TX path)
71 {
72 #if (UDP_SUPPORT == ENABLED)
73  FALSE, //Disable UDP checksum generation
74 #endif
75  0, //Time-to-live value
76  0, //Type-of-service value
77  IP_DEFAULT_DF, //Do not fragment the IP packet
78  FALSE, //Do not send the packet via a router
79  FALSE, //Do not add an IP Router Alert option
80 #if (ETH_SUPPORT == ENABLED)
81  {{{0}}}, //Source MAC address
82  {{{0}}}, //Destination MAC address
83 #endif
84 #if (ETH_VLAN_SUPPORT == ENABLED)
85  -1, //VLAN priority (802.1Q)
86  -1, //Drop eligible indicator
87 #endif
88 #if (ETH_VMAN_SUPPORT == ENABLED)
89  -1, //VMAN priority (802.1ad)
90  -1, //Drop eligible indicator
91 #endif
92 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
93  0, //Egress port identifier
94  0, //Egress port map
95  FALSE, //Override port state
96 #endif
97 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
98  -1, //Unique identifier for hardware time stamping
99 #endif
100 };
101 
102 //Default options passed to the stack (RX path)
104 {
105  0, //Time-to-live value
106  0, //Type-of-service value
107 #if (ETH_SUPPORT == ENABLED)
108  {{{0}}}, //Source MAC address
109  {{{0}}}, //Destination MAC address
110  0, //Ethernet type field
111 #endif
112 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
113  0, //Ingress port identifier
114 #endif
115 #if (ETH_TIMESTAMP_SUPPORT == ENABLED)
116  {0}, //Captured time stamp
117 #endif
118  FALSE, //Disable TCP checksum verification
119  FALSE, //Disable UDP checksum verification
120 };
121 
122 
123 /**
124  * @brief Register link change callback
125  * @param[in] context Pointer to the TCP/IP stack context
126  * @param[in] interface Underlying network interface
127  * @param[in] callback Callback function to be called when the link state changed
128  * @param[in] param Callback function parameter
129  * @return Error code
130  **/
131 
133  NetInterface *interface, NetLinkChangeCallback callback, void *param)
134 {
135  uint_t i;
137 
138  //Loop through the table
139  for(i = 0; i < NET_MAX_LINK_CHANGE_CALLBACKS; i++)
140  {
141  //Point to the current entry
142  entry = &context->linkChangeCallbacks[i];
143 
144  //Check whether the entry is available
145  if(entry->callback == NULL)
146  {
147  //Create a new entry
148  entry->interface = interface;
149  entry->callback = callback;
150  entry->param = param;
151 
152  //Successful processing
153  return NO_ERROR;
154  }
155  }
156 
157  //The table runs out of space
158  return ERROR_OUT_OF_RESOURCES;
159 }
160 
161 
162 /**
163  * @brief Unregister link change callback
164  * @param[in] context Pointer to the TCP/IP stack context
165  * @param[in] interface Underlying network interface
166  * @param[in] callback Callback function to be unregistered
167  * @param[in] param Callback function parameter
168  * @return Error code
169  **/
170 
172  NetInterface *interface, NetLinkChangeCallback callback, void *param)
173 {
174  uint_t i;
176 
177  //Loop through the table
178  for(i = 0; i < NET_MAX_LINK_CHANGE_CALLBACKS; i++)
179  {
180  //Point to the current entry
181  entry = &context->linkChangeCallbacks[i];
182 
183  //Check whether the current entry matches the specified callback function
184  if(entry->interface == interface && entry->callback == callback &&
185  entry->param == param)
186  {
187  //Unregister callback function
188  entry->interface = NULL;
189  entry->callback = NULL;
190  entry->param = NULL;
191  }
192  }
193 
194  //Successful processing
195  return NO_ERROR;
196 }
197 
198 
199 /**
200  * @brief Process link state change event
201  * @param[in] interface Underlying network interface
202  **/
203 
205 {
206  uint_t i;
207  NetContext *context;
208  Socket *socket;
209 
210  //Point to the TCP/IP stack context
211  context = interface->netContext;
212 
213  //Check link state
214  if(interface->linkState)
215  {
216  //Display link state
217  TRACE_INFO("Link is up (%s)...\r\n", interface->name);
218 
219  //Display link speed
220  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
221  {
222  //1000BASE-T
223  TRACE_INFO(" Link speed = 1000 Mbps\r\n");
224  }
225  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
226  {
227  //100BASE-TX
228  TRACE_INFO(" Link speed = 100 Mbps\r\n");
229  }
230  else if(interface->linkSpeed == NIC_LINK_SPEED_10MBPS)
231  {
232  //10BASE-T
233  TRACE_INFO(" Link speed = 10 Mbps\r\n");
234  }
235  else if(interface->linkSpeed != NIC_LINK_SPEED_UNKNOWN)
236  {
237  //10BASE-T
238  TRACE_INFO(" Link speed = %" PRIu32 " bps\r\n",
239  interface->linkSpeed);
240  }
241 
242  //Display duplex mode
243  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
244  {
245  //1000BASE-T
246  TRACE_INFO(" Duplex mode = Full-Duplex\r\n");
247  }
248  else if(interface->duplexMode == NIC_HALF_DUPLEX_MODE)
249  {
250  //100BASE-TX
251  TRACE_INFO(" Duplex mode = Half-Duplex\r\n");
252  }
253  }
254  else
255  {
256  //Display link state
257  TRACE_INFO("Link is down (%s)...\r\n", interface->name);
258  }
259 
260  //The time at which the interface entered its current operational state
262 
263 #if (IPV4_SUPPORT == ENABLED)
264  //Notify IPv4 of link state changes
265  ipv4LinkChangeEvent(interface);
266 #endif
267 
268 #if (IPV6_SUPPORT == ENABLED)
269  //Notify IPv6 of link state changes
270  ipv6LinkChangeEvent(interface);
271 #endif
272 
273 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
274  NBNS_CLIENT_SUPPORT == ENABLED)
275  //Flush DNS cache
276  dnsFlushCache(interface);
277 #endif
278 
279 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
280  //Perform probing and announcing
281  mdnsResponderLinkChangeEvent(interface->mdnsResponderContext);
282 #endif
283 
284 #if (DNS_SD_RESPONDER_SUPPORT == ENABLED)
285  //Perform probing and announcing
286  dnsSdResponderLinkChangeEvent(interface->dnsSdResponderContext);
287 #endif
288 
289  //Loop through the link change callback table
290  for(i = 0; i < NET_MAX_LINK_CHANGE_CALLBACKS; i++)
291  {
293 
294  //Point to the current entry
295  entry = &context->linkChangeCallbacks[i];
296 
297  //Any registered callback?
298  if(entry->callback != NULL)
299  {
300  //Check whether the network interface matches the current entry
301  if(entry->interface == NULL || entry->interface == interface)
302  {
303  //Invoke user callback function
304  entry->callback(interface, interface->linkState, entry->param);
305  }
306  }
307  }
308 
309  //Loop through opened sockets
310  for(i = 0; i < SOCKET_MAX_COUNT; i++)
311  {
312  //Point to the current socket
313  socket = &context->socketTable[i];
314 
315 #if (TCP_SUPPORT == ENABLED)
316  //Connection-oriented socket?
317  if(socket->type == SOCKET_TYPE_STREAM)
318  {
320  }
321 #endif
322 
323 #if (UDP_SUPPORT == ENABLED)
324  //Connectionless socket?
325  if(socket->type == SOCKET_TYPE_DGRAM)
326  {
328  }
329 #endif
330 
331 #if (RAW_SOCKET_SUPPORT == ENABLED)
332  //Raw socket?
333  if(socket->type == SOCKET_TYPE_RAW_IP ||
334  socket->type == SOCKET_TYPE_RAW_ETH)
335  {
337  }
338 #endif
339  }
340 }
341 
342 
343 /**
344  * @brief Register timer callback
345  * @param[in] context Pointer to the TCP/IP stack context
346  * @param[in] period Timer reload value, in milliseconds
347  * @param[in] callback Callback function to be called when the timer expires
348  * @param[in] param Callback function parameter
349  * @return Error code
350  **/
351 
353  NetTimerCallback callback, void *param)
354 {
355  uint_t i;
356  NetTimerCallbackEntry *entry;
357 
358  //Loop through the table
359  for(i = 0; i < NET_MAX_TIMER_CALLBACKS; i++)
360  {
361  //Point to the current entry
362  entry = &context->timerCallbacks[i];
363 
364  //Check whether the entry is available
365  if(entry->callback == NULL)
366  {
367  //Create a new entry
368  entry->timerValue = 0;
369  entry->timerPeriod = period;
370  entry->callback = callback;
371  entry->param = param;
372 
373  //Successful processing
374  return NO_ERROR;
375  }
376  }
377 
378  //The table runs out of space
379  return ERROR_OUT_OF_RESOURCES;
380 }
381 
382 
383 /**
384  * @brief Unregister timer callback
385  * @param[in] context Pointer to the TCP/IP stack context
386  * @param[in] callback Callback function to be unregistered
387  * @param[in] param Callback function parameter
388  * @return Error code
389  **/
390 
392  void *param)
393 {
394  uint_t i;
395  NetTimerCallbackEntry *entry;
396 
397  //Loop through the table
398  for(i = 0; i < NET_MAX_TIMER_CALLBACKS; i++)
399  {
400  //Point to the current entry
401  entry = &context->timerCallbacks[i];
402 
403  //Check whether the current entry matches the specified callback function
404  if(entry->callback == callback && entry->param == param)
405  {
406  //Unregister callback function
407  entry->timerValue = 0;
408  entry->timerPeriod = 0;
409  entry->callback = NULL;
410  entry->param = NULL;
411  }
412  }
413 
414  //Successful processing
415  return NO_ERROR;
416 }
417 
418 
419 /**
420  * @brief Manage TCP/IP timers
421  * @param[in] context Pointer to the TCP/IP stack context
422  **/
423 
424 void netTick(NetContext *context)
425 {
426  uint_t i;
427  NetTimerCallbackEntry *entry;
428 
429  //Increment tick counter
430  context->nicTickCounter += NET_TICK_INTERVAL;
431 
432  //Handle periodic operations such as polling the link state
433  if(context->nicTickCounter >= NIC_TICK_INTERVAL)
434  {
435  //Loop through network interfaces
436  for(i = 0; i < context->numInterfaces; i++)
437  {
438  //Make sure the interface has been properly configured
439  if(context->interfaces[i].configured)
440  {
441  nicTick(&context->interfaces[i]);
442  }
443  }
444 
445  //Reset tick counter
446  context->nicTickCounter = 0;
447  }
448 
449 #if (PPP_SUPPORT == ENABLED)
450  //Increment tick counter
451  context->pppTickCounter += NET_TICK_INTERVAL;
452 
453  //Manage PPP related timers
454  if(context->pppTickCounter >= PPP_TICK_INTERVAL)
455  {
456  //Loop through network interfaces
457  for(i = 0; i < context->numInterfaces; i++)
458  {
459  //Make sure the interface has been properly configured
460  if(context->interfaces[i].configured)
461  {
462  pppTick(&context->interfaces[i]);
463  }
464  }
465 
466  //Reset tick counter
467  context->pppTickCounter = 0;
468  }
469 #endif
470 
471 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED)
472  //Increment tick counter
473  context->arpTickCounter += NET_TICK_INTERVAL;
474 
475  //Manage ARP cache
476  if(context->arpTickCounter >= ARP_TICK_INTERVAL)
477  {
478  //Loop through network interfaces
479  for(i = 0; i < context->numInterfaces; i++)
480  {
481  //Make sure the interface has been properly configured
482  if(context->interfaces[i].configured)
483  {
484  arpTick(&context->interfaces[i]);
485  }
486  }
487 
488  //Reset tick counter
489  context->arpTickCounter = 0;
490  }
491 #endif
492 
493 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
494  //Increment tick counter
495  context->ipv4FragTickCounter += NET_TICK_INTERVAL;
496 
497  //Handle IPv4 fragment reassembly timeout
498  if(context->ipv4FragTickCounter >= IPV4_FRAG_TICK_INTERVAL)
499  {
500  //Loop through network interfaces
501  for(i = 0; i < context->numInterfaces; i++)
502  {
503  //Make sure the interface has been properly configured
504  if(context->interfaces[i].configured)
505  {
506  ipv4FragTick(&context->interfaces[i]);
507  }
508  }
509 
510  //Reset tick counter
511  context->ipv4FragTickCounter = 0;
512  }
513 #endif
514 
515 #if (IPV4_SUPPORT == ENABLED && (IGMP_HOST_SUPPORT == ENABLED || \
516  IGMP_ROUTER_SUPPORT == ENABLED || IGMP_SNOOPING_SUPPORT == ENABLED))
517  //Increment tick counter
518  context->igmpTickCounter += NET_TICK_INTERVAL;
519 
520  //Handle IGMP related timers
521  if(context->igmpTickCounter >= IGMP_TICK_INTERVAL)
522  {
523  //Loop through network interfaces
524  for(i = 0; i < context->numInterfaces; i++)
525  {
526  //Make sure the interface has been properly configured
527  if(context->interfaces[i].configured)
528  {
529  igmpTick(&context->interfaces[i]);
530  }
531  }
532 
533  //Reset tick counter
534  context->igmpTickCounter = 0;
535  }
536 #endif
537 
538 #if (IPV4_SUPPORT == ENABLED && AUTO_IP_SUPPORT == ENABLED)
539  //Increment tick counter
540  context->autoIpTickCounter += NET_TICK_INTERVAL;
541 
542  //Handle Auto-IP related timers
543  if(context->autoIpTickCounter >= AUTO_IP_TICK_INTERVAL)
544  {
545  //Loop through network interfaces
546  for(i = 0; i < context->numInterfaces; i++)
547  {
548  autoIpTick(context->interfaces[i].autoIpContext);
549  }
550 
551  //Reset tick counter
552  context->autoIpTickCounter = 0;
553  }
554 #endif
555 
556 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
557  //Increment tick counter
558  context->dhcpClientTickCounter += NET_TICK_INTERVAL;
559 
560  //Handle DHCP client related timers
561  if(context->dhcpClientTickCounter >= DHCP_CLIENT_TICK_INTERVAL)
562  {
563  //Loop through network interfaces
564  for(i = 0; i < context->numInterfaces; i++)
565  {
566  dhcpClientTick(context->interfaces[i].dhcpClientContext);
567  }
568 
569  //Reset tick counter
570  context->dhcpClientTickCounter = 0;
571  }
572 #endif
573 
574 #if (IPV4_SUPPORT == ENABLED && DHCP_SERVER_SUPPORT == ENABLED)
575  //Increment tick counter
576  context->dhcpServerTickCounter += NET_TICK_INTERVAL;
577 
578  //Handle DHCP server related timers
579  if(context->dhcpServerTickCounter >= DHCP_SERVER_TICK_INTERVAL)
580  {
581  //Loop through network interfaces
582  for(i = 0; i < context->numInterfaces; i++)
583  {
584  dhcpServerTick(context->interfaces[i].dhcpServerContext);
585  }
586 
587  //Reset tick counter
588  context->dhcpServerTickCounter = 0;
589  }
590 #endif
591 
592 #if (IPV4_SUPPORT == ENABLED && NAT_SUPPORT == ENABLED)
593  //Increment tick counter
594  context->natTickCounter += NET_TICK_INTERVAL;
595 
596  //Manage NAT related timers
597  if(context->natTickCounter >= NAT_TICK_INTERVAL)
598  {
599  //NAT timer handler
600  natTick(context->natContext);
601  //Reset tick counter
602  context->natTickCounter = 0;
603  }
604 #endif
605 
606 #if (IPV6_SUPPORT == ENABLED && IPV6_FRAG_SUPPORT == ENABLED)
607  //Increment tick counter
608  context->ipv6FragTickCounter += NET_TICK_INTERVAL;
609 
610  //Handle IPv6 fragment reassembly timeout
611  if(context->ipv6FragTickCounter >= IPV6_FRAG_TICK_INTERVAL)
612  {
613  //Loop through network interfaces
614  for(i = 0; i < context->numInterfaces; i++)
615  {
616  //Make sure the interface has been properly configured
617  if(context->interfaces[i].configured)
618  {
619  ipv6FragTick(&context->interfaces[i]);
620  }
621  }
622 
623  //Reset tick counter
624  context->ipv6FragTickCounter = 0;
625  }
626 #endif
627 
628 #if (IPV6_SUPPORT == ENABLED && MLD_NODE_SUPPORT == ENABLED)
629  //Increment tick counter
630  context->mldTickCounter += NET_TICK_INTERVAL;
631 
632  //Handle MLD related timers
633  if(context->mldTickCounter >= MLD_TICK_INTERVAL)
634  {
635  //Loop through network interfaces
636  for(i = 0; i < context->numInterfaces; i++)
637  {
638  //Make sure the interface has been properly configured
639  if(context->interfaces[i].configured)
640  {
641  mldTick(&context->interfaces[i]);
642  }
643  }
644 
645  //Reset tick counter
646  context->mldTickCounter = 0;
647  }
648 #endif
649 
650 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
651  //Increment tick counter
652  context->ndpTickCounter += NET_TICK_INTERVAL;
653 
654  //Handle NDP related timers
655  if(context->ndpTickCounter >= NDP_TICK_INTERVAL)
656  {
657  //Loop through network interfaces
658  for(i = 0; i < context->numInterfaces; i++)
659  {
660  //Make sure the interface has been properly configured
661  if(context->interfaces[i].configured)
662  {
663  ndpTick(&context->interfaces[i]);
664  }
665  }
666 
667  //Reset tick counter
668  context->ndpTickCounter = 0;
669  }
670 #endif
671 
672 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED)
673  //Increment tick counter
674  context->ndpRouterAdvTickCounter += NET_TICK_INTERVAL;
675 
676  //Handle RA service related timers
677  if(context->ndpRouterAdvTickCounter >= NDP_ROUTER_ADV_TICK_INTERVAL)
678  {
679  //Loop through network interfaces
680  for(i = 0; i < context->numInterfaces; i++)
681  {
682  ndpRouterAdvTick(context->interfaces[i].ndpRouterAdvContext);
683  }
684 
685  //Reset tick counter
686  context->ndpRouterAdvTickCounter = 0;
687  }
688 #endif
689 
690 #if (IPV6_SUPPORT == ENABLED && DHCPV6_CLIENT_SUPPORT == ENABLED)
691  //Increment tick counter
692  context->dhcpv6ClientTickCounter += NET_TICK_INTERVAL;
693 
694  //Handle DHCPv6 client related timers
695  if(context->dhcpv6ClientTickCounter >= DHCPV6_CLIENT_TICK_INTERVAL)
696  {
697  //Loop through network interfaces
698  for(i = 0; i < context->numInterfaces; i++)
699  {
700  dhcpv6ClientTick(context->interfaces[i].dhcpv6ClientContext);
701  }
702 
703  //Reset tick counter
704  context->dhcpv6ClientTickCounter = 0;
705  }
706 #endif
707 
708 #if (TCP_SUPPORT == ENABLED)
709  //Increment tick counter
710  context->tcpTickCounter += NET_TICK_INTERVAL;
711 
712  //Manage TCP related timers
713  if(context->tcpTickCounter >= TCP_TICK_INTERVAL)
714  {
715  //TCP timer handler
716  tcpTick(context);
717  //Reset tick counter
718  context->tcpTickCounter = 0;
719  }
720 #endif
721 
722 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
723  NBNS_CLIENT_SUPPORT == ENABLED || LLMNR_CLIENT_SUPPORT == ENABLED)
724  //Increment tick counter
725  context->dnsTickCounter += NET_TICK_INTERVAL;
726 
727  //Manage DNS cache
728  if(context->dnsTickCounter >= DNS_TICK_INTERVAL)
729  {
730  //DNS timer handler
731  dnsTick(context);
732  //Reset tick counter
733  context->dnsTickCounter = 0;
734  }
735 #endif
736 
737 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
738  //Increment tick counter
739  context->mdnsResponderTickCounter += NET_TICK_INTERVAL;
740 
741  //Manage mDNS probing and announcing
742  if(context->mdnsResponderTickCounter >= MDNS_RESPONDER_TICK_INTERVAL)
743  {
744  //Loop through network interfaces
745  for(i = 0; i < context->numInterfaces; i++)
746  {
747  mdnsResponderTick(context->interfaces[i].mdnsResponderContext);
748  }
749 
750  //Reset tick counter
751  context->mdnsResponderTickCounter = 0;
752  }
753 #endif
754 
755 #if (DNS_SD_RESPONDER_SUPPORT == ENABLED)
756  //Increment tick counter
757  context->dnsSdResponderTickCounter += NET_TICK_INTERVAL;
758 
759  //Manage DNS-SD probing and announcing
760  if(context->dnsSdResponderTickCounter >= DNS_SD_RESPONDER_TICK_INTERVAL)
761  {
762  //Loop through network interfaces
763  for(i = 0; i < context->numInterfaces; i++)
764  {
765  dnsSdResponderTick(context->interfaces[i].dnsSdResponderContext);
766  }
767 
768  //Reset tick counter
769  context->dnsSdResponderTickCounter = 0;
770  }
771 #endif
772 
773  //Loop through the timer callback table
774  for(i = 0; i < NET_MAX_TIMER_CALLBACKS; i++)
775  {
776  //Point to the current entry
777  entry = &context->timerCallbacks[i];
778 
779  //Any registered callback?
780  if(entry->callback != NULL)
781  {
782  //Increment timer value
783  entry->timerValue += NET_TICK_INTERVAL;
784 
785  //Timer period elapsed?
786  if(entry->timerValue >= entry->timerPeriod)
787  {
788  //Invoke user callback function
789  entry->callback(entry->param);
790  //Reload timer
791  entry->timerValue = 0;
792  }
793  }
794  }
795 }
796 
797 
798 /**
799  * @brief Start timer
800  * @param[in] timer Pointer to the timer structure
801  * @param[in] interval Time interval
802  **/
803 
804 void netStartTimer(NetTimer *timer, systime_t interval)
805 {
806  //Start timer
807  timer->startTime = osGetSystemTime();
808  timer->interval = interval;
809  timer->running = TRUE;
810 }
811 
812 
813 /**
814  * @brief Stop timer
815  * @param[in] timer Pointer to the timer structure
816  **/
817 
818 void netStopTimer(NetTimer *timer)
819 {
820  //Stop timer
821  timer->running = FALSE;
822 }
823 
824 
825 /**
826  * @brief Check whether the timer is running
827  * @param[in] timer Pointer to the timer structure
828  * @return TRUE if the timer is running, else FALSE
829  **/
830 
832 {
833  //Return TRUE if the timer is running
834  return timer->running;
835 }
836 
837 
838 /**
839  * @brief Check whether the timer has expired
840  * @param[in] timer Pointer to the timer structure
841  * @return TRUE if the timer has expired, else FALSE
842  **/
843 
845 {
846  bool_t expired;
847  systime_t time;
848 
849  //Initialize flag
850  expired = FALSE;
851  //Get current time
852  time = osGetSystemTime();
853 
854  //Check whether the timer is running
855  if(timer->running)
856  {
857  //Check whether the specified time interval has elapsed
858  if((time - timer->startTime) >= timer->interval)
859  {
860  expired = TRUE;
861  }
862  }
863 
864  //Return TRUE if the timer has expired
865  return expired;
866 }
867 
868 
869 /**
870  * @brief Get the remaining value of the running timer
871  * @param[in] timer Pointer to the timer structure
872  * @return Remaining time
873  **/
874 
876 {
877  systime_t time;
878  systime_t remaining;
879 
880  //Initialize variable
881  remaining = 0;
882  //Get current time
883  time = osGetSystemTime();
884 
885  //Check whether the timer is running
886  if(timer->running)
887  {
888  //Calculate remaining time
889  if((time - timer->startTime) < timer->interval)
890  {
891  remaining = timer->startTime + timer->interval - time;
892  }
893  }
894 
895  //Return remaining time
896  return remaining;
897 }
898 
899 
900 /**
901  * @brief Initialize random number generator
902  * @param[in] context Pointer to the TCP/IP stack context
903  **/
904 
905 void netInitRand(NetContext *context)
906 {
907  uint_t i;
908  NetRandState *state;
909  uint8_t iv[10];
910 
911  //Point to the PRNG state
912  state = &context->randState;
913 
914  //Increment invocation counter
915  state->counter++;
916 
917  //Copy the EUI-64 identifier of the default interface
918  eui64CopyAddr(iv, &context->interfaces[0].eui64);
919  //Append the invocation counter
920  STORE16BE(state->counter, iv + sizeof(Eui64));
921 
922  //Clear the 288-bit internal state
923  osMemset(state->s, 0, 36);
924 
925  //Let (s1, s2, ..., s93) = (K1, ..., K80, 0, ..., 0)
926  for(i = 0; i < 10; i++)
927  {
928  state->s[i] = context->randSeed[i];
929  }
930 
931  //Load the 80-bit initialization vector
932  for(i = 0; i < 10; i++)
933  {
934  state->s[12 + i] = iv[i];
935  }
936 
937  //Let (s94, s95, ..., s177) = (IV1, ..., IV80, 0, ..., 0)
938  for(i = 11; i < 22; i++)
939  {
940  state->s[i] = (state->s[i + 1] << 5) | (state->s[i] >> 3);
941  }
942 
943  //Let (s178, s279, ..., s288) = (0, ..., 0, 1, 1, 1)
944  NET_RAND_STATE_SET_BIT(state->s, 286, 1);
945  NET_RAND_STATE_SET_BIT(state->s, 287, 1);
946  NET_RAND_STATE_SET_BIT(state->s, 288, 1);
947 
948  //The state is rotated over 4 full cycles, without generating key stream bit
949  for(i = 0; i < (4 * 288); i++)
950  {
951  netGenerateRandBit(state);
952  }
953 }
954 
955 
956 /**
957  * @brief Generate a random 32-bit value
958  * @param[in] context Pointer to the TCP/IP stack context
959  * @return Random value
960  **/
961 
962 uint32_t netGenerateRand(NetContext *context)
963 {
964  uint_t i;
965  uint32_t value;
966 
967  //Initialize value
968  value = 0;
969 
970  //Generate a random 32-bit value
971  for(i = 0; i < 32; i++)
972  {
973  value |= netGenerateRandBit(&context->randState) << i;
974  }
975 
976  //Return the random value
977  return value + context->entropy;
978 }
979 
980 
981 /**
982  * @brief Generate a random value in the specified range
983  * @param[in] context Pointer to the TCP/IP stack context
984  * @param[in] min Lower bound
985  * @param[in] max Upper bound
986  * @return Random value in the specified range
987  **/
988 
989 uint32_t netGenerateRandRange(NetContext *context, uint32_t min, uint32_t max)
990 {
991  uint32_t value;
992 
993  //Valid parameters?
994  if(max > min)
995  {
996  //Pick up a random value in the given range
997  value = min + (netGenerateRand(context) % (max - min + 1));
998  }
999  else
1000  {
1001  //Use default value
1002  value = min;
1003  }
1004 
1005  //Return the random value
1006  return value;
1007 }
1008 
1009 
1010 /**
1011  * @brief Get a string of random data
1012  * @param[in] context Pointer to the TCP/IP stack context
1013  * @param[out] data Buffer where to store random data
1014  * @param[in] length Number of random bytes to generate
1015  **/
1016 
1017 void netGenerateRandData(NetContext *context, uint8_t *data, size_t length)
1018 {
1019  size_t i;
1020  size_t j;
1021 
1022  //Generate a string of random data
1023  for(i = 0; i < length; i++)
1024  {
1025  //Initialize value
1026  data[i] = 0;
1027 
1028  //Generate a random 8-bit value
1029  for(j = 0; j < 8; j++)
1030  {
1031  data[i] |= netGenerateRandBit(&context->randState) << j;
1032  }
1033 
1034  data[i] += context->entropy;
1035  }
1036 }
1037 
1038 
1039 /**
1040  * @brief Generate one random bit
1041  * @param[in] state Pointer to the PRNG state
1042  * @return Key stream bit
1043  **/
1044 
1046 {
1047  uint_t i;
1048  uint8_t t1;
1049  uint8_t t2;
1050  uint8_t t3;
1051  uint8_t z;
1052 
1053  //Let t1 = s66 + s93
1054  t1 = NET_RAND_GET_BIT(state->s, 66);
1055  t1 ^= NET_RAND_GET_BIT(state->s, 93);
1056 
1057  //Let t2 = s162 + s177
1058  t2 = NET_RAND_GET_BIT(state->s, 162);
1059  t2 ^= NET_RAND_GET_BIT(state->s, 177);
1060 
1061  //Let t3 = s243 + s288
1062  t3 = NET_RAND_GET_BIT(state->s, 243);
1063  t3 ^= NET_RAND_GET_BIT(state->s, 288);
1064 
1065  //Generate a key stream bit z
1066  z = t1 ^ t2 ^ t3;
1067 
1068  //Let t1 = t1 + s91.s92 + s171
1069  t1 ^= NET_RAND_GET_BIT(state->s, 91) & NET_RAND_GET_BIT(state->s, 92);
1070  t1 ^= NET_RAND_GET_BIT(state->s, 171);
1071 
1072  //Let t2 = t2 + s175.s176 + s264
1073  t2 ^= NET_RAND_GET_BIT(state->s, 175) & NET_RAND_GET_BIT(state->s, 176);
1074  t2 ^= NET_RAND_GET_BIT(state->s, 264);
1075 
1076  //Let t3 = t3 + s286.s287 + s69
1077  t3 ^= NET_RAND_GET_BIT(state->s, 286) & NET_RAND_GET_BIT(state->s, 287);
1078  t3 ^= NET_RAND_GET_BIT(state->s, 69);
1079 
1080  //Rotate the internal state
1081  for(i = 35; i > 0; i--)
1082  {
1083  state->s[i] = (state->s[i] << 1) | (state->s[i - 1] >> 7);
1084  }
1085 
1086  state->s[0] = state->s[0] << 1;
1087 
1088  //Let s1 = t3
1089  NET_RAND_STATE_SET_BIT(state->s, 1, t3);
1090  //Let s94 = t1
1091  NET_RAND_STATE_SET_BIT(state->s, 94, t1);
1092  //Let s178 = t2
1093  NET_RAND_STATE_SET_BIT(state->s, 178, t2);
1094 
1095  //Return one bit of key stream
1096  return z;
1097 }
IPv6 (Internet Protocol Version 6)
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
NetTimerCallback callback
Definition: net_misc.h:95
void netStartTimer(NetTimer *timer, systime_t interval)
Start timer.
Definition: net_misc.c:804
#define NetContext
Definition: net.h:36
void ipv6FragTick(NetInterface *interface)
Fragment reassembly timeout handler.
Definition: ipv6_frag.c:547
int bool_t
Definition: compiler_port.h:63
void ipv4FragTick(NetInterface *interface)
Fragment reassembly timeout handler.
Definition: ipv4_frag.c:469
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:110
bool_t running
Definition: net_misc.h:178
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:70
systime_t timerPeriod
Definition: net_misc.h:94
bool_t netTimerRunning(NetTimer *timer)
Check whether the timer is running.
Definition: net_misc.c:831
error_t netDetachTimerCallback(NetContext *context, NetTimerCallback callback, void *param)
Unregister timer callback.
Definition: net_misc.c:391
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
systime_t netGetRemainingTime(NetTimer *timer)
Get the remaining value of the running timer.
Definition: net_misc.c:875
#define NET_RAND_STATE_SET_BIT(s, n, v)
Definition: net_misc.h:51
void udpUpdateEvents(Socket *socket)
Update UDP related events.
Definition: udp.c:981
Eui64
Definition: ethernet.h:212
systime_t timerValue
Definition: net_misc.h:93
void ndpTick(NetInterface *interface)
NDP timer handler.
Definition: ndp.c:543
#define TRUE
Definition: os_port.h:50
error_t netDetachLinkChangeCallback(NetContext *context, NetInterface *interface, NetLinkChangeCallback callback, void *param)
Unregister link change callback.
Definition: net_misc.c:171
uint32_t netGenerateRand(NetContext *context)
Generate a random 32-bit value.
Definition: net_misc.c:962
uint16_t counter
Definition: net_misc.h:190
uint8_t data[]
Definition: ethernet.h:224
#define DNS_TICK_INTERVAL
Definition: dns_cache.h:40
#define IPV4_FRAG_TICK_INTERVAL
Definition: ipv4_frag.h:54
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
@ SOCKET_TYPE_DGRAM
Definition: socket.h:93
void ipv4LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv4.c:554
void ndpRouterAdvTick(NdpRouterAdvContext *context)
RA service timer handler.
#define ARP_TICK_INTERVAL
Definition: arp.h:39
IPv6 routing.
void * param
Definition: net_misc.h:96
#define NET_TICK_INTERVAL
Definition: net.h:190
void mldTick(NetInterface *interface)
MLD node timer handler.
Definition: mld_common.c:101
void pppTick(NetInterface *interface)
PPP timer handler.
Definition: ppp.c:865
#define IP_DEFAULT_DF
Definition: ip.h:44
void * param
Definition: net_misc.h:76
Helper functions for DHCPv6 client.
void dnsFlushCache(NetInterface *interface)
Flush DNS cache.
Definition: dns_cache.c:70
@ SOCKET_TYPE_STREAM
Definition: socket.h:92
Helper functions for DHCP client.
void arpTick(NetInterface *interface)
ARP timer handler.
Definition: arp.c:519
Pseudo-random number generator state.
Definition: net_misc.h:189
Helper functions for DHCP server.
Ethernet.
#define NET_MAX_LINK_CHANGE_CALLBACKS
Definition: net.h:143
void netInitRand(NetContext *context)
Initialize random number generator.
Definition: net_misc.c:905
Definitions common to mDNS client and mDNS responder.
void dnsSdResponderTick(DnsSdResponderContext *context)
DNS-SD responder timer handler.
uint8_t s[36]
Definition: net_misc.h:191
void(* NetLinkChangeCallback)(NetInterface *interface, bool_t linkState, void *param)
Link change callback.
Definition: net_misc.h:64
uint32_t netGenerateRandBit(NetRandState *state)
Generate one random bit.
Definition: net_misc.c:1045
#define FALSE
Definition: os_port.h:46
Helper functions for TCP.
#define IPV6_FRAG_TICK_INTERVAL
Definition: ipv6_frag.h:54
error_t
Error codes.
Definition: error.h:43
void dhcpv6ClientTick(Dhcpv6ClientContext *context)
DHCPv6 client timer handler.
#define eui64CopyAddr(destEui64Addr, srcEui64Addr)
Definition: ethernet.h:136
void netStopTimer(NetTimer *timer)
Stop timer.
Definition: net_misc.c:818
Definitions common to NBNS client and NBNS responder.
DNS-SD responder (DNS-Based Service Discovery)
Timer callback entry.
Definition: net_misc.h:92
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
NBNS client (NetBIOS Name Service)
#define IGMP_TICK_INTERVAL
Definition: igmp_common.h:39
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
Timer.
Definition: net_misc.h:177
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:40
error_t netAttachTimerCallback(NetContext *context, systime_t period, NetTimerCallback callback, void *param)
Register timer callback.
Definition: net_misc.c:352
void netTick(NetContext *context)
Manage TCP/IP timers.
Definition: net_misc.c:424
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:111
#define DHCP_SERVER_TICK_INTERVAL
Definition: dhcp_server.h:46
NetInterface * interface
Definition: net_misc.h:74
uint32_t netGenerateRandRange(NetContext *context, uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net_misc.c:989
#define NET_RAND_GET_BIT(s, n)
Definition: net_misc.h:48
#define NetTxAncillary
Definition: net_misc.h:36
#define NAT_TICK_INTERVAL
Definition: nat.h:53
mDNS client (Multicast DNS)
systime_t startTime
Definition: net_misc.h:179
uint8_t iv[]
Definition: ike.h:1695
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:94
void tcpUpdateEvents(Socket *socket)
Update TCP related events.
Definition: tcp_misc.c:2171
#define NDP_TICK_INTERVAL
Definition: ndp.h:46
uint32_t t2
#define TRACE_INFO(...)
Definition: debug.h:105
IGMP host.
uint8_t length
Definition: tcp.h:375
void natTick(NatContext *context)
NAT timer handler.
Definition: nat_misc.c:51
void netProcessLinkChange(NetInterface *interface)
Process link state change event.
Definition: net_misc.c:204
#define TCP_TICK_INTERVAL
Definition: tcp.h:47
void dnsTick(NetContext *context)
DNS timer handler.
Definition: dns_cache.c:233
Helper functions for NAT.
void rawSocketUpdateEvents(Socket *socket)
Update event state for raw sockets.
Definition: raw_socket.c:1035
void mdnsResponderTick(MdnsResponderContext *context)
mDNS responder timer handler
NDP (Neighbor Discovery Protocol)
DNS client (Domain Name System)
TCP/IP raw sockets.
uint8_t z
Definition: dns_common.h:196
uint32_t systime_t
System time.
#define NET_MAX_TIMER_CALLBACKS
Definition: net.h:150
MLD node (Multicast Listener Discovery for IPv6)
LLMNR client (Link-Local Multicast Name Resolution)
#define MDNS_RESPONDER_TICK_INTERVAL
NetLinkChangeCallback callback
Definition: net_misc.h:75
DNS cache management.
#define NIC_TICK_INTERVAL
Definition: nic.h:39
uint32_t time
void mdnsResponderLinkChangeEvent(MdnsResponderContext *context)
Callback function for link change event.
uint32_t t1
#define NDP_ROUTER_ADV_TICK_INTERVAL
#define AUTO_IP_TICK_INTERVAL
Definition: auto_ip.h:53
#define NET_IF_STATS_SET_TIME_TICKS(name, value)
Definition: net.h:202
Link change callback entry.
Definition: net_misc.h:73
#define Socket
Definition: socket.h:36
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:124
#define DHCP_CLIENT_TICK_INTERVAL
Definition: dhcp_client.h:49
void netGenerateRandData(NetContext *context, uint8_t *data, size_t length)
Get a string of random data.
Definition: net_misc.c:1017
#define MLD_TICK_INTERVAL
Definition: mld_common.h:39
uint8_t value[]
Definition: tcp.h:376
#define DHCPV6_CLIENT_TICK_INTERVAL
Definition: dhcpv6_client.h:47
IPv4 routing.
#define PPP_TICK_INTERVAL
Definition: ppp.h:82
#define osGetSystemTime64()
Socket API.
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:95
void autoIpTick(AutoIpContext *context)
Auto-IP timer handler.
Definition: auto_ip_misc.c:56
Helper functions for Auto-IP.
LLMNR responder (Link-Local Multicast Name Resolution)
void dhcpClientTick(DhcpClientContext *context)
DHCP client timer handler.
error_t netAttachLinkChangeCallback(NetContext *context, NetInterface *interface, NetLinkChangeCallback callback, void *param)
Register link change callback.
Definition: net_misc.c:132
void tcpTick(NetContext *context)
TCP timer handler.
Definition: tcp_timer.c:57
IPv4 (Internet Protocol Version 4)
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
TCP timer management.
void ipv6LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv6.c:891
unsigned int uint_t
Definition: compiler_port.h:57
void nicTick(NetInterface *interface)
Network controller timer handler.
Definition: nic.c:273
void igmpTick(NetInterface *interface)
IGMP timer handler.
Definition: igmp_common.c:105
Helper functions for router advertisement service.
#define osMemset(p, value, length)
Definition: os_port.h:141
TCP/IP stack core.
#define SOCKET_MAX_COUNT
Definition: socket.h:46
bool_t netTimerExpired(NetTimer *timer)
Check whether the timer has expired.
Definition: net_misc.c:844
ARP (Address Resolution Protocol)
#define DNS_SD_RESPONDER_TICK_INTERVAL
Helper functions for TCP/IP stack.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void dnsSdResponderLinkChangeEvent(DnsSdResponderContext *context)
Callback function for link change event.
void(* NetTimerCallback)(void *param)
Timer callback.
Definition: net_misc.h:84
NBNS responder (NetBIOS Name Service)
mDNS responder (Multicast DNS)
void dhcpServerTick(DhcpServerContext *context)
DHCP server timer handler.
systime_t interval
Definition: net_misc.h:180
systime_t osGetSystemTime(void)
Retrieve system time.