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