net.c
Go to the documentation of this file.
1 /**
2  * @file net.c
3  * @brief TCP/IP stack core
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <stdlib.h>
36 #include "core/net.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/igmp.h"
46 #include "ipv6/ipv6.h"
47 #include "ipv6/ipv6_routing.h"
48 #include "ipv6/mld.h"
49 #include "ipv6/ndp.h"
50 #include "ipv6/ndp_router_adv.h"
51 #include "dhcp/dhcp_client.h"
52 #include "dhcp/dhcp_server.h"
53 #include "dns/dns_cache.h"
54 #include "dns/dns_client.h"
55 #include "mdns/mdns_client.h"
56 #include "mdns/mdns_responder.h"
57 #include "mdns/mdns_common.h"
58 #include "dns_sd/dns_sd.h"
59 #include "netbios/nbns_client.h"
60 #include "netbios/nbns_responder.h"
61 #include "netbios/nbns_common.h"
62 #include "llmnr/llmnr_responder.h"
63 #include "mibs/mib2_module.h"
64 #include "mibs/if_mib_module.h"
65 #include "str.h"
66 #include "debug.h"
67 
68 #if (WEB_SOCKET_SUPPORT == ENABLED)
69  #include "web_socket/web_socket.h"
70 #endif
71 
72 //TCP/IP stack handle
74 //Mutex preventing simultaneous access to the TCP/IP stack
76 //Event object to receive notifications from device drivers
78 //Network interfaces
80 
81 //TCP/IP process state
82 static bool_t netTaskRunning;
83 //Timestamp
84 static systime_t netTimestamp;
85 //Pseudo-random number generator state
86 static uint32_t prngState = 0;
87 
88 //Mutex to prevent simultaneous access to the callback table
89 static OsMutex callbackTableMutex;
90 //Table that holds the registered user callbacks
92 
93 //Check TCP/IP stack configuration
94 #if (NET_STATIC_OS_RESOURCES == ENABLED)
95 
96 //Task responsible for handling TCP/IP events
97 static OsTask netTaskInstance;
98 static uint_t netTaskStack[NET_TASK_STACK_SIZE];
99 
100 #endif
101 
102 
103 /**
104  * @brief TCP/IP stack initialization
105  * @return Error code
106  **/
107 
109 {
110  error_t error;
111  uint_t i;
112  NetInterface *interface;
113 
114  //The TCP/IP process is currently suspended
115  netTaskRunning = FALSE;
116  //Get current time
117  netTimestamp = osGetSystemTime();
118 
119  //Create a mutex to prevent simultaneous access to the TCP/IP stack
120  if(!osCreateMutex(&netMutex))
121  {
122  //Failed to create mutex
123  return ERROR_OUT_OF_RESOURCES;
124  }
125 
126  //Create a event object to receive notifications from device drivers
127  if(!osCreateEvent(&netEvent))
128  {
129  //Failed to create mutex
130  return ERROR_OUT_OF_RESOURCES;
131  }
132 
133  //Memory pool initialization
134  error = memPoolInit();
135  //Any error to report?
136  if(error)
137  return error;
138 
139  //Clear configuration data for each interface
140  memset(netInterface, 0, sizeof(netInterface));
141 
142  //Loop through network interfaces
143  for(i = 0; i < NET_INTERFACE_COUNT; i++)
144  {
145  //Point to the current interface
146  interface = &netInterface[i];
147 
148  //Default interface name
149  sprintf(interface->name, "eth%u", i);
150 
151  //Zero-based index
152  interface->index = i;
153  //Unique number identifying the interface
154  interface->id = i;
155  //Default PHY address
156  interface->phyAddr = UINT8_MAX;
157  }
158 
159  //Create a mutex to prevent simultaneous access to the callback table
160  if(!osCreateMutex(&callbackTableMutex))
161  {
162  //Failed to create mutex
163  return ERROR_OUT_OF_RESOURCES;
164  }
165 
166  //Initialize callback table
167  memset(callbackTable, 0, sizeof(callbackTable));
168 
169  //Socket related initialization
170  error = socketInit();
171  //Any error to report?
172  if(error)
173  return error;
174 
175 #if (WEB_SOCKET_SUPPORT == ENABLED)
176  //WebSocket related initialization
177  webSocketInit();
178 #endif
179 
180 #if (IPV4_SUPPORT == ENABLED && IPV4_ROUTING_SUPPORT == ENABLED)
181  //Initialize IPv4 routing table
182  error = ipv4InitRouting();
183  //Any error to report?
184  if(error)
185  return error;
186 #endif
187 
188 #if (IPV6_SUPPORT == ENABLED && IPV6_ROUTING_SUPPORT == ENABLED)
189  //Initialize IPv6 routing table
190  error = ipv6InitRouting();
191  //Any error to report?
192  if(error)
193  return error;
194 #endif
195 
196 #if (UDP_SUPPORT == ENABLED)
197  //UDP related initialization
198  error = udpInit();
199  //Any error to report?
200  if(error)
201  return error;
202 #endif
203 
204 #if (TCP_SUPPORT == ENABLED)
205  //TCP related initialization
206  error = tcpInit();
207  //Any error to report?
208  if(error)
209  return error;
210 #endif
211 
212 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
213  NBNS_CLIENT_SUPPORT == ENABLED)
214  //DNS cache initialization
215  error = dnsInit();
216  //Any error to report?
217  if(error)
218  return error;
219 #endif
220 
221  //Initialize tick counters
222  nicTickCounter = 0;
223 
224 #if (PPP_SUPPORT == ENABLED)
225  pppTickCounter = 0;
226 #endif
227 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED)
228  arpTickCounter = 0;
229 #endif
230 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
232 #endif
233 #if (IPV4_SUPPORT == ENABLED && IGMP_SUPPORT == ENABLED)
234  igmpTickCounter = 0;
235 #endif
236 #if (IPV4_SUPPORT == ENABLED && AUTO_IP_SUPPORT == ENABLED)
237  autoIpTickCounter = 0;
238 #endif
239 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
241 #endif
242 #if (IPV4_SUPPORT == ENABLED && DHCP_SERVER_SUPPORT == ENABLED)
244 #endif
245 #if (IPV6_SUPPORT == ENABLED && IPV6_FRAG_SUPPORT == ENABLED)
247 #endif
248 #if (IPV6_SUPPORT == ENABLED && MLD_SUPPORT == ENABLED)
249  mldTickCounter = 0;
250 #endif
251 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
252  ndpTickCounter = 0;
253 #endif
254 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED)
256 #endif
257 #if (IPV6_SUPPORT == ENABLED && DHCPV6_CLIENT_SUPPORT == ENABLED)
259 #endif
260 #if (TCP_SUPPORT == ENABLED)
261  tcpTickCounter = 0;
262 #endif
263 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
264  NBNS_CLIENT_SUPPORT == ENABLED)
265  dnsTickCounter = 0;
266 #endif
267 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
269 #endif
270 #if (DNS_SD_SUPPORT == ENABLED)
271  dnsSdTickCounter = 0;
272 #endif
273 
274 #if (NET_STATIC_OS_RESOURCES == ENABLED)
275  //Create a task to handle TCP/IP events
276  osCreateStaticTask(&netTaskInstance, "TCP/IP Stack", (OsTaskCode) netTask,
277  NULL, netTaskStack, NET_TASK_STACK_SIZE, NET_TASK_PRIORITY);
278 #else
279  //Create a task to handle TCP/IP events
280  netTaskHandle = osCreateTask("TCP/IP Stack", (OsTaskCode) netTask,
282 
283  //Unable to create the task?
285  return ERROR_OUT_OF_RESOURCES;
286 #endif
287 
288 #if (NET_RTOS_SUPPORT == DISABLED)
289  //The TCP/IP process is now running
290  netTaskRunning = TRUE;
291 #endif
292 
293  //Successful initialization
294  return NO_ERROR;
295 }
296 
297 
298 /**
299  * @brief Set MAC address
300  * @param[in] interface Pointer to the desired network interface
301  * @param[in] macAddr MAC address
302  * @return Error code
303  **/
304 
305 error_t netSetMacAddr(NetInterface *interface, const MacAddr *macAddr)
306 {
307 #if (ETH_SUPPORT == ENABLED)
308  //Check parameters
309  if(interface == NULL || macAddr == NULL)
311 
312  //Get exclusive access
314 
315  //Set MAC address
316  interface->macAddr = *macAddr;
317 
318  //Generate the 64-bit interface identifier
319  macAddrToEui64(macAddr, &interface->eui64);
320 
321  //Release exclusive access
323 
324  //Successful processing
325  return NO_ERROR;
326 #else
327  //Not implemented
328  return ERROR_NOT_IMPLEMENTED;
329 #endif
330 }
331 
332 
333 /**
334  * @brief Retrieve MAC address
335  * @param[in] interface Pointer to the desired network interface
336  * @param[out] macAddr MAC address
337  * @return Error code
338  **/
339 
341 {
342 #if (ETH_SUPPORT == ENABLED)
343  NetInterface *logicalInterface;
344 
345  //Check parameters
346  if(interface == NULL || macAddr == NULL)
348 
349  //Get exclusive access
351 
352  //Point to the logical interface
353  logicalInterface = nicGetLogicalInterface(interface);
354 
355  //Get MAC address
356  *macAddr = logicalInterface->macAddr;
357 
358  //Release exclusive access
360 
361  //Successful processing
362  return NO_ERROR;
363 #else
364  //Not implemented
365  return ERROR_NOT_IMPLEMENTED;
366 #endif
367 }
368 
369 
370 /**
371  * @brief Set EUI-64 interface identifier
372  * @param[in] interface Pointer to the desired network interface
373  * @param[in] eui64 Interface identifier
374  * @return Error code
375  **/
376 
377 error_t netSetEui64(NetInterface *interface, const Eui64 *eui64)
378 {
379  //Check parameters
380  if(interface == NULL || eui64 == NULL)
382 
383  //Get exclusive access
385  //Set interface identifier
386  interface->eui64 = *eui64;
387  //Release exclusive access
389 
390  //Successful processing
391  return NO_ERROR;
392 }
393 
394 
395 /**
396  * @brief Retrieve EUI-64 interface identifier
397  * @param[in] interface Pointer to the desired network interface
398  * @param[out] eui64 Interface identifier
399  * @return Error code
400  **/
401 
403 {
404  NetInterface *logicalInterface;
405 
406  //Check parameters
407  if(interface == NULL || eui64 == NULL)
409 
410  //Get exclusive access
412 
413  //Point to the logical interface
414  logicalInterface = nicGetLogicalInterface(interface);
415 
416  //Get interface identifier
417  *eui64 = logicalInterface->eui64;
418 
419  //Release exclusive access
421 
422  //Successful processing
423  return NO_ERROR;
424 }
425 
426 
427 /**
428  * @brief Set interface identifier
429  * @param[in] interface Pointer to the desired network interface
430  * @param[in] id Unique number identifying the interface
431  * @return Error code
432  **/
433 
434 error_t netSetInterfaceId(NetInterface *interface, uint32_t id)
435 {
436  //Check parameters
437  if(interface == NULL)
439 
440  //Get exclusive access
442  //Set interface identifier
443  interface->id = id;
444  //Release exclusive access
446 
447  //Successful processing
448  return NO_ERROR;
449 }
450 
451 
452 /**
453  * @brief Set interface name
454  * @param[in] interface Pointer to the desired network interface
455  * @param[in] name NULL-terminated string that contains the interface name
456  * @return Error code
457  **/
458 
460 {
461  //Check parameters
462  if(interface == NULL || name == NULL)
464 
465  //Get exclusive access
467 
468  //Set interface name
469  strSafeCopy(interface->name, name, NET_MAX_IF_NAME_LEN);
470 
471  //Release exclusive access
473 
474  //Successful processing
475  return NO_ERROR;
476 }
477 
478 
479 /**
480  * @brief Set host name
481  * @param[in] interface Pointer to the desired network interface
482  * @param[in] name NULL-terminated string that contains the host name
483  * @return Error code
484  **/
485 
487 {
488  //Check parameters
489  if(interface == NULL || name == NULL)
491 
492  //Get exclusive access
494 
495  //Set host name
496  strSafeCopy(interface->hostname, name, NET_MAX_HOSTNAME_LEN);
497 
498  //Release exclusive access
500 
501  //Successful processing
502  return NO_ERROR;
503 }
504 
505 
506 /**
507  * @brief Set proxy server
508  * @param[in] interface Pointer to the desired network interface
509  * @param[in] name Proxy server name
510  * @param[in] port Proxy server port
511  * @return Error code
512  **/
513 
514 error_t netSetProxy(NetInterface *interface, const char_t *name, uint16_t port)
515 {
516  //Check parameters
517  if(interface == NULL || name == NULL)
519 
520  //Get exclusive access
522 
523  //Set proxy server name
524  strSafeCopy(interface->proxyName, name, NET_MAX_PROXY_NAME_LEN);
525  //Set proxy server port
526  interface->proxyPort = port;
527 
528  //Release exclusive access
530 
531  //Successful processing
532  return NO_ERROR;
533 }
534 
535 
536 /**
537  * @brief Specify VLAN identifier (802.1q)
538  * @param[in] interface Pointer to the desired network interface
539  * @param[in] vlanId VLAN identifier
540  * @return Error code
541  **/
542 
543 error_t netSetVlanId(NetInterface *interface, uint16_t vlanId)
544 {
545 #if (ETH_VLAN_SUPPORT == ENABLED)
546  //Make sure the network interface is valid
547  if(interface == NULL)
549 
550  //The VID value FFF is reserved
551  if((vlanId & VLAN_VID_MASK) == VLAN_VID_MASK)
553 
554  //Get exclusive access
556  //Set VLAN identifier
557  interface->vlanId = vlanId;
558  //Release exclusive access
560 
561  //Successful processing
562  return NO_ERROR;
563 #else
564  //Not implemented
565  return ERROR_NOT_IMPLEMENTED;
566 #endif
567 }
568 
569 
570 /**
571  * @brief Specify VMAN identifier (802.1ad)
572  * @param[in] interface Pointer to the desired network interface
573  * @param[in] vmanId VMAN identifier
574  * @return Error code
575  **/
576 
577 error_t netSetVmanId(NetInterface *interface, uint16_t vmanId)
578 {
579 #if (ETH_VMAN_SUPPORT == ENABLED)
580  //Make sure the network interface is valid
581  if(interface == NULL)
583 
584  //The VID value FFF is reserved
585  if((vmanId & VLAN_VID_MASK) == VLAN_VID_MASK)
587 
588  //Get exclusive access
590  //Set VMAN identifier
591  interface->vmanId = vmanId;
592  //Release exclusive access
594 
595  //Successful processing
596  return NO_ERROR;
597 #else
598  //Not implemented
599  return ERROR_NOT_IMPLEMENTED;
600 #endif
601 }
602 
603 
604 /**
605  * @brief Specify switch port
606  * @param[in] interface Pointer to the desired network interface
607  * @param[in] port Switch port identifier
608  * @return Error code
609  **/
610 
612 {
613 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
614  //Make sure the network interface is valid
615  if(interface == NULL)
617 
618  //Get exclusive access
620  //Set switch port identifier
621  interface->port = port;
622  //Release exclusive access
624 
625  //Successful processing
626  return NO_ERROR;
627 #else
628  //Not implemented
629  return ERROR_NOT_IMPLEMENTED;
630 #endif
631 }
632 
633 
634 /**
635  * @brief Attach a virtual interface to a given physical interface
636  * @param[in] interface Pointer to the virtual interface
637  * @param[in] physicalInterface physical interface on top of which the virtual
638  * interface will run
639  * @return Error code
640  **/
641 
643  NetInterface *physicalInterface)
644 {
645 #if (ETH_VIRTUAL_IF_SUPPORT == ENABLED || ETH_VLAN_SUPPORT == ENABLED || \
646  ETH_PORT_TAGGING_SUPPORT == ENABLED)
647  //Make sure the network interface is valid
648  if(interface == NULL)
650 
651  //Get exclusive access
653  //Bind the virtual interface to the physical interface
654  interface->parent = physicalInterface;
655  //Release exclusive access
657 
658  //Successful processing
659  return NO_ERROR;
660 #else
661  //Not implemented
662  return ERROR_NOT_IMPLEMENTED;
663 #endif
664 }
665 
666 
667 /**
668  * @brief Set Ethernet MAC driver
669  * @param[in] interface Pointer to the desired network interface
670  * @param[in] driver Ethernet MAC driver
671  * @return Error code
672  **/
673 
674 error_t netSetDriver(NetInterface *interface, const NicDriver *driver)
675 {
676  //Check parameters
677  if(interface == NULL || driver == NULL)
679 
680  //Get exclusive access
682  //Set Ethernet MAC driver
683  interface->nicDriver = driver;
684  //Release exclusive access
686 
687  //Successful processing
688  return NO_ERROR;
689 }
690 
691 
692 /**
693  * @brief Set Ethernet PHY driver
694  * @param[in] interface Pointer to the desired network interface
695  * @param[in] driver Ethernet PHY driver (can be NULL for MAC + PHY controller)
696  * @return Error code
697  **/
698 
699 error_t netSetPhyDriver(NetInterface *interface, const PhyDriver *driver)
700 {
701  //Check parameters
702  if(interface == NULL || driver == NULL)
704 
705  //Get exclusive access
707  //Set Ethernet PHY driver
708  interface->phyDriver = driver;
709  //Release exclusive access
711 
712  //Successful processing
713  return NO_ERROR;
714 }
715 
716 
717 /**
718  * @brief Set Ethernet PHY address
719  * @param[in] interface Pointer to the desired network interface
720  * @param[in] phyAddr PHY address
721  * @return Error code
722  **/
723 
724 error_t netSetPhyAddr(NetInterface *interface, uint8_t phyAddr)
725 {
726  //Make sure the network interface is valid
727  if(interface == NULL)
729 
730  //Make sure the PHY address is valid
731  if(phyAddr >= 32)
732  return ERROR_OUT_OF_RANGE;
733 
734  //Get exclusive access
736  //Set PHY address
737  interface->phyAddr = phyAddr;
738  //Release exclusive access
740 
741  //Successful processing
742  return NO_ERROR;
743 }
744 
745 
746 /**
747  * @brief Set SPI driver
748  * @param[in] interface Pointer to the desired network interface
749  * @param[in] driver Underlying SPI driver
750  * @return Error code
751  **/
752 
753 error_t netSetSpiDriver(NetInterface *interface, const SpiDriver *driver)
754 {
755  //Check parameters
756  if(interface == NULL || driver == NULL)
758 
759  //Get exclusive access
761  //Set SPI driver
762  interface->spiDriver = driver;
763  //Release exclusive access
765 
766  //Successful processing
767  return NO_ERROR;
768 }
769 
770 
771 /**
772  * @brief Set UART driver
773  * @param[in] interface Pointer to the desired network interface
774  * @param[in] driver Underlying UART driver
775  * @return Error code
776  **/
777 
779 {
780  //Check parameters
781  if(interface == NULL || driver == NULL)
783 
784  //Get exclusive access
786  //Set UART driver
787  interface->uartDriver = driver;
788  //Release exclusive access
790 
791  //Successful processing
792  return NO_ERROR;
793 }
794 
795 
796 /**
797  * @brief Set external interrupt line driver
798  * @param[in] interface Pointer to the desired network interface
799  * @param[in] driver Underlying SPI driver
800  * @return Error code
801  **/
802 
804 {
805  //Check parameters
806  if(interface == NULL || driver == NULL)
808 
809  //Get exclusive access
811  //Set external interrupt line driver
812  interface->extIntDriver = driver;
813  //Release exclusive access
815 
816  //Successful processing
817  return NO_ERROR;
818 }
819 
820 
821 /**
822  * @brief Set link state (for virtual drivers only)
823  * @param[in] interface Pointer to the desired network interface
824  * @param[in] linkState Link state
825  * @return Error code
826  **/
827 
829 {
830  //Make sure the network interface is valid
831  if(interface == NULL)
833 
834  //Get exclusive access
836 
837  //Link state changed?
838  if(linkState != interface->linkState)
839  {
840  //Update link state
841  interface->linkState = linkState;
842  //Process link state change event
843  netProcessLinkChange(interface);
844  }
845 
846  //Release exclusive access
848 
849  //Successful processing
850  return NO_ERROR;
851 }
852 
853 
854 /**
855  * @brief Get link state
856  * @param[in] interface Pointer to the desired network interface
857  * @return Link state
858  **/
859 
861 {
862  bool_t linkState;
863 
864  //Make sure the network interface is valid
865  if(interface == NULL)
866  return FALSE;
867 
868  //Get exclusive access
870  //Retrieve link state
871  linkState = interface->linkState;
872  //Release exclusive access
874 
875  //Return link state
876  return linkState;
877 }
878 
879 
880 /**
881  * @brief Configure network interface
882  * @param[in] interface Network interface to configure
883  * @return Error code
884  **/
885 
887 {
888  error_t error;
889 
890  //Make sure the network interface is valid
891  if(interface == NULL)
893 
894  //Get exclusive access
896 
897  //Disable hardware interrupts
898  if(interface->nicDriver != NULL)
899  interface->nicDriver->disableIrq(interface);
900 
901  //Start of exception handling block
902  do
903  {
904  //Receive notifications when the transmitter is ready to send
905  if(!osCreateEvent(&interface->nicTxEvent))
906  {
907  //Failed to create event object
908  error = ERROR_OUT_OF_RESOURCES;
909  //Stop immediately
910  break;
911  }
912 
913  //Valid NIC driver?
914  if(interface->nicDriver != NULL)
915  {
916  //Network controller initialization
917  error = interface->nicDriver->init(interface);
918  //Any error to report?
919  if(error)
920  break;
921  }
922  else
923  {
924 #if (ETH_VIRTUAL_IF_SUPPORT == ENABLED || ETH_PORT_TAGGING_SUPPORT == ENABLED)
925  NetInterface *physicalInterface;
926 
927  //Point to the physical interface
928  physicalInterface = nicGetPhysicalInterface(interface);
929 
930  //Check whether the network interface is a virtual interface
931  if(physicalInterface != interface)
932  {
933  //Valid MAC address assigned to the virtual interface?
934  if(!macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
935  {
936  //Configure the physical interface to accept the MAC address of
937  //the virtual interface
938  error = ethAcceptMacAddr(physicalInterface, &interface->macAddr);
939  //Any error to report?
940  if(error)
941  break;
942  }
943  }
944 #endif
945  }
946 
947 #if (ETH_SUPPORT == ENABLED)
948  //Ethernet related initialization
949  error = ethInit(interface);
950  //Any error to report?
951  if(error)
952  break;
953 #endif
954 
955 #if (IPV4_SUPPORT == ENABLED)
956  //IPv4 initialization
957  error = ipv4Init(interface);
958  //Any error to report?
959  if(error)
960  break;
961 
962 #if (ETH_SUPPORT == ENABLED)
963  //ARP cache initialization
964  error = arpInit(interface);
965  //Any error to report?
966  if(error)
967  break;
968 #endif
969 
970 #if (IGMP_SUPPORT == ENABLED)
971  //IGMP related initialization
972  error = igmpInit(interface);
973  //Any error to report?
974  if(error)
975  break;
976 
977  //Join the all-systems group
978  error = ipv4JoinMulticastGroup(interface, IGMP_ALL_SYSTEMS_ADDR);
979  //Any error to report?
980  if(error)
981  break;
982 #endif
983 
984 #if (NBNS_CLIENT_SUPPORT == ENABLED || NBNS_RESPONDER_SUPPORT == ENABLED)
985  //NetBIOS Name Service related initialization
986  error = nbnsInit(interface);
987  //Any error to report?
988  if(error)
989  break;
990 #endif
991 #endif
992 
993 #if (IPV6_SUPPORT == ENABLED)
994  //IPv6 initialization
995  error = ipv6Init(interface);
996  //Any error to report?
997  if(error)
998  break;
999 
1000 #if (NDP_SUPPORT == ENABLED)
1001  //NDP related initialization
1002  error = ndpInit(interface);
1003  //Any error to report?
1004  if(error)
1005  break;
1006 #endif
1007 
1008 #if (MLD_SUPPORT == ENABLED)
1009  //MLD related initialization
1010  error = mldInit(interface);
1011  //Any error to report?
1012  if(error)
1013  break;
1014 #endif
1015 
1016  //Join the All-Nodes multicast address
1018  //Any error to report?
1019  if(error)
1020  break;
1021 #endif
1022 
1023 #if (MDNS_CLIENT_SUPPORT == ENABLED || MDNS_RESPONDER_SUPPORT == ENABLED)
1024  //mDNS related initialization
1025  error = mdnsInit(interface);
1026  //Any error to report?
1027  if(error)
1028  break;
1029 #endif
1030 
1031 #if (LLMNR_RESPONDER_SUPPORT == ENABLED)
1032  //LLMNR responder initialization
1033  error = llmnrResponderInit(interface);
1034  //Any error to report?
1035  if(error)
1036  break;
1037 #endif
1038 
1039  //End of exception handling block
1040  } while(0);
1041 
1042  //Check status code
1043  if(!error)
1044  {
1045  //The network interface is now fully configured
1046  interface->configured = TRUE;
1047 
1048  //Check whether the TCP/IP process is running
1049  if(netTaskRunning)
1050  {
1051  //Interrupts can be safely enabled
1052  if(interface->nicDriver != NULL)
1053  interface->nicDriver->enableIrq(interface);
1054  }
1055  }
1056  else
1057  {
1058  //Clean up side effects before returning
1059  osDeleteEvent(&interface->nicTxEvent);
1060  }
1061 
1062  //Release exclusive access
1064 
1065  //Return status code
1066  return error;
1067 }
1068 
1069 
1070 /**
1071  * @brief Start network interface
1072  * @param[in] interface Network interface to start
1073  * @return Error code
1074  **/
1075 
1077 {
1078  error_t error;
1079  NetInterface *physicalInterface;
1080 
1081  //Make sure the network interface is valid
1082  if(interface == NULL)
1083  return ERROR_INVALID_PARAMETER;
1084 
1085  //Initialize status code
1086  error = NO_ERROR;
1087 
1088  //Get exclusive access
1090 
1091  //Point to the physical interface
1092  physicalInterface = nicGetPhysicalInterface(interface);
1093 
1094  //Check whether the interface is enabled for operation
1095  if(!interface->configured)
1096  {
1097  //Virtual interface?
1098  if(interface != physicalInterface)
1099  {
1100 #if (ETH_SUPPORT == ENABLED)
1101  //Valid MAC address assigned to the virtual interface?
1102  if(!macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
1103  {
1104  //Configure the physical interface to accept the MAC address of
1105  //the virtual interface
1106  error = ethAcceptMacAddr(physicalInterface, &interface->macAddr);
1107  }
1108 #endif
1109  }
1110  else
1111  {
1112 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
1113  //Valid switch driver?
1114  if(interface->phyDriver != NULL &&
1115  interface->phyDriver->init != NULL &&
1116  interface->phyDriver->tagFrame != NULL &&
1117  interface->phyDriver->untagFrame != NULL)
1118  {
1119  //Reconfigure switch operation
1120  error = interface->phyDriver->init(interface);
1121  }
1122 #endif
1123  //Check status code
1124  if(!error)
1125  {
1126  //Update the MAC filter
1127  error = nicUpdateMacAddrFilter(interface);
1128  }
1129  }
1130  }
1131 
1132  //Enable network interface
1133  interface->configured = TRUE;
1134 
1135  //Check whether the TCP/IP process is running
1136  if(netTaskRunning)
1137  {
1138  //Interrupts can be safely enabled
1139  if(interface->nicDriver != NULL)
1140  interface->nicDriver->enableIrq(interface);
1141  }
1142 
1143  //Release exclusive access
1145 
1146  //Return status code
1147  return error;
1148 }
1149 
1150 
1151 /**
1152  * @brief Stop network interface
1153  * @param[in] interface Network interface to stop
1154  * @return Error code
1155  **/
1156 
1158 {
1159  NetInterface *physicalInterface;
1160 
1161  //Make sure the network interface is valid
1162  if(interface == NULL)
1163  return ERROR_INVALID_PARAMETER;
1164 
1165  //Get exclusive access
1167 
1168  //Point to the physical interface
1169  physicalInterface = nicGetPhysicalInterface(interface);
1170 
1171  //Check whether the interface is enabled for operation
1172  if(interface->configured)
1173  {
1174  //Update link state
1175  interface->linkState = FALSE;
1176  //Process link state change event
1177  netProcessLinkChange(interface);
1178 
1179  //Disable hardware interrupts
1180  if(interface->nicDriver != NULL)
1181  interface->nicDriver->disableIrq(interface);
1182 
1183  //Disable network interface
1184  interface->configured = FALSE;
1185 
1186  //Virtual interface?
1187  if(interface != physicalInterface)
1188  {
1189 #if (ETH_SUPPORT == ENABLED)
1190  //Valid MAC address assigned to the virtual interface?
1191  if(!macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
1192  {
1193  //Drop the corresponding address from the MAC filter table of
1194  //the physical interface
1195  ethDropMacAddr(physicalInterface, &interface->macAddr);
1196  }
1197 #endif
1198  }
1199  }
1200 
1201  //Release exclusive access
1203 
1204  //Successful operation
1205  return NO_ERROR;
1206 }
1207 
1208 
1209 /**
1210  * @brief Process link state change event
1211  * @param[in] interface Underlying network interface
1212  **/
1213 
1215 {
1216  uint_t i;
1217  Socket *socket;
1218 
1219  //Check link state
1220  if(interface->linkState)
1221  {
1222  //Display link state
1223  TRACE_INFO("Link is up (%s)...\r\n", interface->name);
1224 
1225  //Display link speed
1226  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
1227  {
1228  //1000BASE-T
1229  TRACE_INFO(" Link speed = 1000 Mbps\r\n");
1230  }
1231  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1232  {
1233  //100BASE-TX
1234  TRACE_INFO(" Link speed = 100 Mbps\r\n");
1235  }
1236  else if(interface->linkSpeed == NIC_LINK_SPEED_10MBPS)
1237  {
1238  //10BASE-T
1239  TRACE_INFO(" Link speed = 10 Mbps\r\n");
1240  }
1241  else if(interface->linkSpeed != NIC_LINK_SPEED_UNKNOWN)
1242  {
1243  //10BASE-T
1244  TRACE_INFO(" Link speed = %" PRIu32 " bps\r\n",
1245  interface->linkSpeed);
1246  }
1247 
1248  //Display duplex mode
1249  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1250  {
1251  //1000BASE-T
1252  TRACE_INFO(" Duplex mode = Full-Duplex\r\n");
1253  }
1254  else if(interface->duplexMode == NIC_HALF_DUPLEX_MODE)
1255  {
1256  //100BASE-TX
1257  TRACE_INFO(" Duplex mode = Half-Duplex\r\n");
1258  }
1259  }
1260  else
1261  {
1262  //Display link state
1263  TRACE_INFO("Link is down (%s)...\r\n", interface->name);
1264  }
1265 
1266  //The time at which the interface entered its current operational state
1267  MIB2_SET_TIME_TICKS(ifGroup.ifTable[interface->index].ifLastChange,
1268  osGetSystemTime() / 10);
1269  IF_MIB_SET_TIME_TICKS(ifTable[interface->index].ifLastChange,
1270  osGetSystemTime() / 10);
1271 
1272 #if (IPV4_SUPPORT == ENABLED)
1273  //Notify IPv4 of link state changes
1274  ipv4LinkChangeEvent(interface);
1275 #endif
1276 
1277 #if (IPV6_SUPPORT == ENABLED)
1278  //Notify IPv6 of link state changes
1279  ipv6LinkChangeEvent(interface);
1280 #endif
1281 
1282 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
1283  NBNS_CLIENT_SUPPORT == ENABLED)
1284  //Flush DNS cache
1285  dnsFlushCache(interface);
1286 #endif
1287 
1288 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
1289  //Perform probing and announcing
1290  mdnsResponderLinkChangeEvent(interface->mdnsResponderContext);
1291 #endif
1292 
1293 #if (DNS_SD_SUPPORT == ENABLED)
1294  //Perform probing and announcing
1295  dnsSdLinkChangeEvent(interface->dnsSdContext);
1296 #endif
1297  //Notify registered users of link state changes
1298  netInvokeLinkChangeCallback(interface, interface->linkState);
1299 
1300  //Loop through opened sockets
1301  for(i = 0; i < SOCKET_MAX_COUNT; i++)
1302  {
1303  //Point to the current socket
1304  socket = socketTable + i;
1305 
1306 #if (TCP_SUPPORT == ENABLED)
1307  //Connection-oriented socket?
1308  if(socket->type == SOCKET_TYPE_STREAM)
1309  {
1311  }
1312 #endif
1313 
1314 #if (UDP_SUPPORT == ENABLED)
1315  //Connectionless socket?
1316  if(socket->type == SOCKET_TYPE_DGRAM)
1317  {
1319  }
1320 #endif
1321 
1322 #if (RAW_SOCKET_SUPPORT == ENABLED)
1323  //Raw socket?
1324  if(socket->type == SOCKET_TYPE_RAW_IP ||
1325  socket->type == SOCKET_TYPE_RAW_ETH)
1326  {
1328  }
1329 #endif
1330  }
1331 }
1332 
1333 
1334 /**
1335  * @brief TCP/IP events handling
1336  **/
1337 
1338 void netTask(void)
1339 {
1340  uint_t i;
1341  bool_t status;
1342  systime_t time;
1343  systime_t timeout;
1344  NetInterface *interface;
1345 
1346 #if (NET_RTOS_SUPPORT == ENABLED)
1347  //Task prologue
1348  osEnterTask();
1349 
1350  //Get exclusive access
1352 
1353  //The TCP/IP process is now running
1354  netTaskRunning = TRUE;
1355 
1356  //Loop through network interfaces
1357  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1358  {
1359  //Point to the current network interface
1360  interface = &netInterface[i];
1361 
1362  //Check whether the interface is fully configured
1363  if(interface->configured)
1364  {
1365  //Interrupts can be safely enabled
1366  if(interface->nicDriver != NULL)
1367  {
1368  interface->nicDriver->enableIrq(interface);
1369  }
1370  }
1371  }
1372 
1373  //Release exclusive access
1375 
1376  //Main loop
1377  while(1)
1378  {
1379 #endif
1380  //Get current time
1381  time = osGetSystemTime();
1382 
1383  //Compute the maximum blocking time when waiting for an event
1384  if(timeCompare(time, netTimestamp) < 0)
1385  timeout = netTimestamp - time;
1386  else
1387  timeout = 0;
1388 
1389  //Receive notifications when a frame has been received, or the
1390  //link state of any network interfaces has changed
1391  status = osWaitForEvent(&netEvent, timeout);
1392 
1393  //Check whether the specified event is in signaled state
1394  if(status)
1395  {
1396  //Get exclusive access
1398 
1399  //Process events
1400  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1401  {
1402  //Point to the current network interface
1403  interface = &netInterface[i];
1404 
1405  //Check whether a NIC event is pending
1406  if(interface->nicEvent)
1407  {
1408  //Acknowledge the event by clearing the flag
1409  interface->nicEvent = FALSE;
1410 
1411  //Valid NIC driver?
1412  if(interface->nicDriver != NULL)
1413  {
1414  //Disable hardware interrupts
1415  interface->nicDriver->disableIrq(interface);
1416  //Handle NIC events
1417  interface->nicDriver->eventHandler(interface);
1418  //Re-enable hardware interrupts
1419  interface->nicDriver->enableIrq(interface);
1420  }
1421  }
1422 
1423  //Check whether a PHY event is pending
1424  if(interface->phyEvent)
1425  {
1426  //Acknowledge the event by clearing the flag
1427  interface->phyEvent = FALSE;
1428 
1429  //Valid NIC driver?
1430  if(interface->nicDriver != NULL)
1431  {
1432  //Disable hardware interrupts
1433  interface->nicDriver->disableIrq(interface);
1434  //Handle PHY events
1435  interface->phyDriver->eventHandler(interface);
1436  //Re-enable hardware interrupts
1437  interface->nicDriver->enableIrq(interface);
1438  }
1439  }
1440  }
1441 
1442  //Release exclusive access
1444  }
1445 
1446  //Get current time
1447  time = osGetSystemTime();
1448 
1449  //Check current time
1450  if(timeCompare(time, netTimestamp) >= 0)
1451  {
1452  //Get exclusive access
1454  //Handle periodic operations
1455  netTick();
1456  //Release exclusive access
1458 
1459  //Next event
1460  netTimestamp = time + NET_TICK_INTERVAL;
1461  }
1462 #if (NET_RTOS_SUPPORT == ENABLED)
1463  }
1464 #endif
1465 }
1466 
1467 
1468 /**
1469  * @brief Manage TCP/IP timers
1470  **/
1471 
1472 void netTick(void)
1473 {
1474  uint_t i;
1475 
1476  //Increment tick counter
1478 
1479  //Handle periodic operations such as polling the link state
1481  {
1482  //Loop through network interfaces
1483  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1484  {
1485  //Make sure the interface has been properly configured
1486  if(netInterface[i].configured)
1487  nicTick(&netInterface[i]);
1488  }
1489 
1490  //Reset tick counter
1491  nicTickCounter = 0;
1492  }
1493 
1494 #if (PPP_SUPPORT == ENABLED)
1495  //Increment tick counter
1497 
1498  //Manage PPP related timers
1500  {
1501  //Loop through network interfaces
1502  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1503  {
1504  //Make sure the interface has been properly configured
1505  if(netInterface[i].configured)
1506  pppTick(&netInterface[i]);
1507  }
1508 
1509  //Reset tick counter
1510  pppTickCounter = 0;
1511  }
1512 #endif
1513 
1514 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED)
1515  //Increment tick counter
1517 
1518  //Manage ARP cache
1520  {
1521  //Loop through network interfaces
1522  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1523  {
1524  //Make sure the interface has been properly configured
1525  if(netInterface[i].configured)
1526  arpTick(&netInterface[i]);
1527  }
1528 
1529  //Reset tick counter
1530  arpTickCounter = 0;
1531  }
1532 #endif
1533 
1534 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
1535  //Increment tick counter
1537 
1538  //Handle IPv4 fragment reassembly timeout
1540  {
1541  //Loop through network interfaces
1542  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1543  {
1544  //Make sure the interface has been properly configured
1545  if(netInterface[i].configured)
1547  }
1548 
1549  //Reset tick counter
1550  ipv4FragTickCounter = 0;
1551  }
1552 #endif
1553 
1554 #if (IPV4_SUPPORT == ENABLED && IGMP_SUPPORT == ENABLED)
1555  //Increment tick counter
1557 
1558  //Handle IGMP related timers
1560  {
1561  //Loop through network interfaces
1562  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1563  {
1564  //Make sure the interface has been properly configured
1565  if(netInterface[i].configured)
1566  igmpTick(&netInterface[i]);
1567  }
1568 
1569  //Reset tick counter
1570  igmpTickCounter = 0;
1571  }
1572 #endif
1573 
1574 #if (IPV4_SUPPORT == ENABLED && AUTO_IP_SUPPORT == ENABLED)
1575  //Increment tick counter
1577 
1578  //Handle Auto-IP related timers
1580  {
1581  //Loop through network interfaces
1582  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1583  autoIpTick(netInterface[i].autoIpContext);
1584 
1585  //Reset tick counter
1586  autoIpTickCounter = 0;
1587  }
1588 #endif
1589 
1590 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
1591  //Increment tick counter
1593 
1594  //Handle DHCP client related timers
1596  {
1597  //Loop through network interfaces
1598  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1599  dhcpClientTick(netInterface[i].dhcpClientContext);
1600 
1601  //Reset tick counter
1603  }
1604 #endif
1605 
1606 #if (IPV4_SUPPORT == ENABLED && DHCP_SERVER_SUPPORT == ENABLED)
1607  //Increment tick counter
1609 
1610  //Handle DHCP server related timers
1612  {
1613  //Loop through network interfaces
1614  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1615  dhcpServerTick(netInterface[i].dhcpServerContext);
1616 
1617  //Reset tick counter
1619  }
1620 #endif
1621 
1622 #if (IPV6_SUPPORT == ENABLED && IPV6_FRAG_SUPPORT == ENABLED)
1623  //Increment tick counter
1625 
1626  //Handle IPv6 fragment reassembly timeout
1628  {
1629  //Loop through network interfaces
1630  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1631  {
1632  //Make sure the interface has been properly configured
1633  if(netInterface[i].configured)
1635  }
1636 
1637  //Reset tick counter
1638  ipv6FragTickCounter = 0;
1639  }
1640 #endif
1641 
1642 #if (IPV6_SUPPORT == ENABLED && MLD_SUPPORT == ENABLED)
1643  //Increment tick counter
1645 
1646  //Handle MLD related timers
1648  {
1649  //Loop through network interfaces
1650  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1651  {
1652  //Make sure the interface has been properly configured
1653  if(netInterface[i].configured)
1654  mldTick(&netInterface[i]);
1655  }
1656 
1657  //Reset tick counter
1658  mldTickCounter = 0;
1659  }
1660 #endif
1661 
1662 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
1663  //Increment tick counter
1665 
1666  //Handle NDP related timers
1668  {
1669  //Loop through network interfaces
1670  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1671  {
1672  //Make sure the interface has been properly configured
1673  if(netInterface[i].configured)
1674  ndpTick(&netInterface[i]);
1675  }
1676 
1677  //Reset tick counter
1678  ndpTickCounter = 0;
1679  }
1680 #endif
1681 
1682 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED)
1683  //Increment tick counter
1685 
1686  //Handle RA service related timers
1688  {
1689  //Loop through network interfaces
1690  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1691  ndpRouterAdvTick(netInterface[i].ndpRouterAdvContext);
1692 
1693  //Reset tick counter
1695  }
1696 #endif
1697 
1698 #if (IPV6_SUPPORT == ENABLED && DHCPV6_CLIENT_SUPPORT == ENABLED)
1699  //Increment tick counter
1701 
1702  //Handle DHCPv6 client related timers
1704  {
1705  //Loop through network interfaces
1706  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1707  dhcpv6ClientTick(netInterface[i].dhcpv6ClientContext);
1708 
1709  //Reset tick counter
1711  }
1712 #endif
1713 
1714 #if (TCP_SUPPORT == ENABLED)
1715  //Increment tick counter
1717 
1718  //Manage TCP related timers
1720  {
1721  //TCP timer handler
1722  tcpTick();
1723  //Reset tick counter
1724  tcpTickCounter = 0;
1725  }
1726 #endif
1727 
1728 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
1729  NBNS_CLIENT_SUPPORT == ENABLED)
1730  //Increment tick counter
1732 
1733  //Manage DNS cache
1735  {
1736  //DNS timer handler
1737  dnsTick();
1738  //Reset tick counter
1739  dnsTickCounter = 0;
1740  }
1741 #endif
1742 
1743 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
1744  //Increment tick counter
1746 
1747  //Manage mDNS probing and announcing
1749  {
1750  //Loop through network interfaces
1751  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1752  mdnsResponderTick(netInterface[i].mdnsResponderContext);
1753 
1754  //Reset tick counter
1756  }
1757 #endif
1758 
1759 #if (DNS_SD_SUPPORT == ENABLED)
1760  //Increment tick counter
1762 
1763  //Manage DNS-SD probing and announcing
1765  {
1766  //Loop through network interfaces
1767  for(i = 0; i < NET_INTERFACE_COUNT; i++)
1768  dnsSdTick(netInterface[i].dnsSdContext);
1769 
1770  //Reset tick counter
1771  dnsSdTickCounter = 0;
1772  }
1773 #endif
1774 }
1775 
1776 
1777 /**
1778  * @brief Get default network interface
1779  * @return Pointer to the default network interface to be used
1780  **/
1781 
1783 {
1784  //Default network interface
1785  return &netInterface[0];
1786 }
1787 
1788 
1789 /**
1790  * @brief Seed pseudo-random number generator
1791  * @param[in] seed An integer value to be used as seed by the pseudo-random number generator
1792  * @return Error code
1793  **/
1794 
1795 error_t netInitRand(uint32_t seed)
1796 {
1797  //Seed the pseudo-random number generator
1798  prngState += seed;
1799 
1800  //Successful processing
1801  return NO_ERROR;
1802 }
1803 
1804 
1805 /**
1806  * @brief Get a random value
1807  * @return Random value
1808  **/
1809 
1810 uint32_t netGetRand(void)
1811 {
1812  uint32_t value;
1813 
1814  //Use a linear congruential generator (LCG) to update the state of the PRNG
1815  prngState *= 1103515245;
1816  prngState += 12345;
1817  value = (prngState >> 16) & 0x07FF;
1818 
1819  prngState *= 1103515245;
1820  prngState += 12345;
1821  value <<= 10;
1822  value |= (prngState >> 16) & 0x03FF;
1823 
1824  prngState *= 1103515245;
1825  prngState += 12345;
1826  value <<= 10;
1827  value |= (prngState >> 16) & 0x03FF;
1828 
1829  //Return the random value
1830  return value;
1831 }
1832 
1833 
1834 /**
1835  * @brief Get a random value in the specified range
1836  * @param[in] min Lower bound
1837  * @param[in] max Upper bound
1838  * @return Random value in the specified range
1839  **/
1840 
1841 int32_t netGetRandRange(int32_t min, int32_t max)
1842 {
1843  int32_t value;
1844 
1845  //Valid parameters?
1846  if(max > min)
1847  {
1848  //Pick up a random value in the given range
1849  value = min + (netGetRand() % (max - min + 1));
1850  }
1851  else
1852  {
1853  //Use default value
1854  value = min;
1855  }
1856 
1857  //Return the random value
1858  return value;
1859 }
1860 
1861 
1862 /**
1863  * @brief Register link change callback
1864  * @param[in] interface Underlying network interface
1865  * @param[in] callback Callback function to be called when the link state changed
1866  * @param[in] param Callback function parameter (optional)
1867  * @param[out] cookie Identifier that can be used to unregister the callback function
1868  * @return Error code
1869  **/
1870 
1872  LinkChangeCallback callback, void *param, uint_t *cookie)
1873 {
1874  uint_t i;
1875  LinkChangeCallbackDesc *entry;
1876 
1877  //Acquire exclusive access to the callback table
1878  osAcquireMutex(&callbackTableMutex);
1879 
1880  //Loop through the table
1881  for(i = 0; i < NET_CALLBACK_TABLE_SIZE; i++)
1882  {
1883  //Point to the current entry
1884  entry = &callbackTable[i];
1885 
1886  //Check whether the entry is currently in used
1887  if(entry->callback == NULL)
1888  {
1889  //Create a new entry
1890  entry->interface = interface;
1891  entry->callback = callback;
1892  entry->param = param;
1893  //We are done
1894  break;
1895  }
1896  }
1897 
1898  //Release exclusive access to the callback table
1899  osReleaseMutex(&callbackTableMutex);
1900 
1901  //Failed to attach the specified user callback?
1902  if(i >= NET_CALLBACK_TABLE_SIZE)
1903  return ERROR_OUT_OF_RESOURCES;
1904 
1905  //Return a cookie that can be used later to unregister the callback
1906  if(cookie != NULL)
1907  *cookie = i;
1908 
1909  //Successful processing
1910  return NO_ERROR;
1911 }
1912 
1913 
1914 /**
1915  * @brief Unregister link change callback
1916  * @param[in] cookie Identifier specifying the callback to be unregistered
1917  * @return Error code
1918  **/
1919 
1921 {
1922  //Make sure the cookie is valid
1924  return ERROR_INVALID_PARAMETER;
1925 
1926  //Acquire exclusive access to the callback table
1927  osAcquireMutex(&callbackTableMutex);
1928  //Unregister user callback
1929  callbackTable[cookie].callback = NULL;
1930  //Release exclusive access to the callback table
1931  osReleaseMutex(&callbackTableMutex);
1932 
1933  //Successful processing
1934  return NO_ERROR;
1935 }
1936 
1937 
1938 /**
1939  * @brief Invoke link change callback
1940  * @param[in] interface Underlying network interface
1941  * @param[in] linkState Link state
1942  **/
1943 
1945 {
1946  uint_t i;
1947  LinkChangeCallbackDesc *entry;
1948 
1949  //Acquire exclusive access to the callback table
1950  osAcquireMutex(&callbackTableMutex);
1951 
1952  //Loop through the table
1953  for(i = 0; i < NET_CALLBACK_TABLE_SIZE; i++)
1954  {
1955  //Point to the current entry
1956  entry = &callbackTable[i];
1957 
1958  //Any registered callback?
1959  if(entry->callback != NULL)
1960  {
1961  //Check whether the network interface matches the current entry
1962  if(entry->interface == NULL || entry->interface == interface)
1963  {
1964  //Invoke user callback function
1965  entry->callback(interface, linkState, entry->param);
1966  }
1967  }
1968  }
1969 
1970  //Release exclusive access to the callback table
1971  osReleaseMutex(&callbackTableMutex);
1972 }
error_t ethAcceptMacAddr(NetInterface *interface, const MacAddr *macAddr)
Add a unicast/multicast address to the MAC filter table.
Definition: ethernet.c:516
IPv6 (Internet Protocol Version 6)
error_t netInit(void)
TCP/IP stack initialization.
Definition: net.c:108
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:107
MIB-II module.
systime_t ipv4FragTickCounter
Definition: ipv4_frag.c:57
void ipv6FragTick(NetInterface *interface)
Fragment reassembly timeout handler.
Definition: ipv6_frag.c:527
#define IF_MIB_SET_TIME_TICKS(name, value)
Definition: if_mib_module.h:46
String manipulation helper functions.
int bool_t
Definition: compiler_port.h:49
@ ERROR_OUT_OF_RANGE
Definition: error.h:135
void ipv4FragTick(NetInterface *interface)
Fragment reassembly timeout handler.
Definition: ipv4_frag.c:449
@ NIC_LINK_SPEED_UNKNOWN
Definition: nic.h:104
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
error_t netSetSpiDriver(NetInterface *interface, const SpiDriver *driver)
Set SPI driver.
Definition: net.c:753
void dhcpv6ClientTick(Dhcpv6ClientContext *context)
DHCPv6 client timer handler.
DHCP client (Dynamic Host Configuration Protocol)
error_t netSetDriver(NetInterface *interface, const NicDriver *driver)
Set Ethernet MAC driver.
Definition: net.c:674
__start_packed struct @109 Eui64
EUI-64 identifier.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:119
error_t ipv4InitRouting(void)
void udpUpdateEvents(Socket *socket)
Update UDP related events.
Definition: udp.c:720
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:800
error_t netSetUartDriver(NetInterface *interface, const UartDriver *driver)
Set UART driver.
Definition: net.c:778
systime_t arpTickCounter
Definition: arp.c:51
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
systime_t igmpTickCounter
Definition: igmp.c:53
void ndpTick(NetInterface *interface)
NDP timer handler.
Definition: ndp.c:276
WebSocket API (client and server)
#define TRUE
Definition: os_port.h:50
PHY driver.
Definition: nic.h:214
UART driver.
Definition: nic.h:245
#define DNS_TICK_INTERVAL
Definition: dns_cache.h:40
Event object.
#define IPV4_FRAG_TICK_INTERVAL
Definition: ipv4_frag.h:47
External interrupt line driver.
Definition: nic.h:258
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
IGMP (Internet Group Management Protocol)
#define NET_CALLBACK_TABLE_SIZE
Definition: net.h:124
@ SOCKET_TYPE_DGRAM
Definition: socket.h:78
void ipv4LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv4.c:517
error_t netSetProxy(NetInterface *interface, const char_t *name, uint16_t port)
Set proxy server.
Definition: net.c:514
#define ARP_TICK_INTERVAL
Definition: arp.h:39
#define NET_INTERFACE_COUNT
Definition: net.h:109
error_t netDetachLinkChangeCallback(uint_t cookie)
Unregister link change callback.
Definition: net.c:1920
systime_t nicTickCounter
Definition: nic.c:43
IPv6 routing.
char_t name[]
error_t arpInit(NetInterface *interface)
ARP cache initialization.
Definition: arp.c:60
error_t netSetMacAddr(NetInterface *interface, const MacAddr *macAddr)
Set MAC address.
Definition: net.c:305
#define NET_TICK_INTERVAL
Definition: net.h:171
void(* LinkChangeCallback)(NetInterface *interface, bool_t linkState, void *param)
Link change callback.
Definition: net.h:280
SPI driver.
Definition: nic.h:230
error_t netAttachLinkChangeCallback(NetInterface *interface, LinkChangeCallback callback, void *param, uint_t *cookie)
Register link change callback.
Definition: net.c:1871
error_t netSetParentInterface(NetInterface *interface, NetInterface *physicalInterface)
Attach a virtual interface to a given physical interface.
Definition: net.c:642
void pppTick(NetInterface *interface)
PPP timer handler.
Definition: ppp.c:846
error_t ipv6Init(NetInterface *interface)
IPv6 related initialization.
Definition: ipv6.c:97
#define VLAN_VID_MASK
Definition: ethernet.h:101
void dnsFlushCache(NetInterface *interface)
Flush DNS cache.
Definition: dns_cache.c:74
#define NET_TASK_STACK_SIZE
Definition: net.h:159
@ SOCKET_TYPE_STREAM
Definition: socket.h:77
#define timeCompare(t1, t2)
Definition: os_port.h:42
void arpTick(NetInterface *interface)
ARP timer handler.
Definition: arp.c:426
systime_t ipv6FragTickCounter
Definition: ipv6_frag.c:47
systime_t dhcpClientTickCounter
Definition: dhcp_client.c:55
Ethernet.
error_t webSocketInit(void)
WebSocket related initialization.
Definition: web_socket.c:60
void dhcpServerTick(DhcpServerContext *context)
DHCP server timer handler.
Definition: dhcp_server.c:251
error_t ethDropMacAddr(NetInterface *interface, const MacAddr *macAddr)
Remove a unicast/multicast address from the MAC filter table.
Definition: ethernet.c:586
Router advertisement service.
systime_t pppTickCounter
Definition: ppp.c:51
Definitions common to mDNS client and mDNS responder.
DNS-SD (DNS-Based Service Discovery)
void mldTick(NetInterface *interface)
MLD timer handler.
Definition: mld.c:155
void ndpRouterAdvTick(NdpRouterAdvContext *context)
RA service timer handler.
systime_t ndpTickCounter
Definition: ndp.c:59
#define FALSE
Definition: os_port.h:46
NetInterface netInterface[NET_INTERFACE_COUNT]
Definition: net.c:79
Helper functions for TCP.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
systime_t ndpRouterAdvTickCounter
void autoIpTick(AutoIpContext *context)
Auto-IP timer handler.
Definition: auto_ip.c:238
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:84
#define IPV6_FRAG_TICK_INTERVAL
Definition: ipv6_frag.h:54
error_t
Error codes.
Definition: error.h:42
error_t mldInit(NetInterface *interface)
MLD initialization.
Definition: mld.c:65
Definitions common to NBNS client and NBNS responder.
error_t netSetPhyAddr(NetInterface *interface, uint8_t phyAddr)
Set Ethernet PHY address.
Definition: net.c:724
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:108
error_t mdnsInit(NetInterface *interface)
mDNS related initialization
Definition: mdns_common.c:69
NBNS client (NetBIOS Name Service)
error_t netSetEui64(NetInterface *interface, const Eui64 *eui64)
Set EUI-64 interface identifier.
Definition: net.c:377
NicLinkState
Link state.
Definition: nic.h:90
error_t netConfigInterface(NetInterface *interface)
Configure network interface.
Definition: net.c:886
const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR
Definition: ipv6.c:75
error_t udpInit(void)
UDP related initialization.
Definition: udp.c:64
error_t igmpInit(NetInterface *interface)
IGMP initialization.
Definition: igmp.c:62
void osDeleteEvent(OsEvent *event)
Delete an event object.
void dnsSdTick(DnsSdContext *context)
DNS-SD responder timer handler.
Definition: dns_sd.c:508
#define NetInterface
Definition: net.h:36
Task object.
error_t memPoolInit(void)
Memory pool initialization.
Definition: net_mem.c:70
@ NIC_LINK_SPEED_10MBPS
Definition: nic.h:105
#define DHCP_SERVER_TICK_INTERVAL
Definition: dhcp_server.h:46
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:1782
error_t netGetMacAddr(NetInterface *interface, MacAddr *macAddr)
Retrieve MAC address.
Definition: net.c:340
OsMutex netMutex
Definition: net.c:75
error_t netSetPhyDriver(NetInterface *interface, const PhyDriver *driver)
Set Ethernet PHY driver.
Definition: net.c:699
mDNS client (Multicast DNS)
@ SOCKET_TYPE_RAW_IP
Definition: socket.h:79
void tcpUpdateEvents(Socket *socket)
Update TCP related events.
Definition: tcp_misc.c:1756
OsEvent netEvent
Definition: net.c:77
error_t ipv6JoinMulticastGroup(NetInterface *interface, const Ipv6Addr *groupAddr)
Join an IPv6 multicast group.
Definition: ipv6.c:1928
#define NDP_TICK_INTERVAL
Definition: ndp.h:46
#define TRACE_INFO(...)
Definition: debug.h:94
Interfaces Group MIB module.
#define osEnterTask()
#define TCP_TICK_INTERVAL
Definition: tcp.h:47
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
void igmpTick(NetInterface *interface)
IGMP timer handler.
Definition: igmp.c:160
void rawSocketUpdateEvents(Socket *socket)
Update event state for raw sockets.
Definition: raw_socket.c:780
uint32_t netGetRand(void)
Get a random value.
Definition: net.c:1810
void mdnsResponderTick(MdnsResponderContext *context)
mDNS responder timer handler
void dnsTick(void)
DNS timer handler.
Definition: dns_cache.c:225
#define IGMP_ALL_SYSTEMS_ADDR
Definition: igmp.h:76
NDP (Neighbor Discovery Protocol)
int32_t netGetRandRange(int32_t min, int32_t max)
Get a random value in the specified range.
Definition: net.c:1841
error_t nicUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
Definition: nic.c:346
DNS client (Domain Name System)
Mutex object.
TCP/IP raw sockets.
systime_t tcpTickCounter
Definition: tcp.c:49
uint16_t port
Definition: dns_common.h:223
systime_t mldTickCounter
Definition: mld.c:56
char char_t
Definition: compiler_port.h:43
#define MDNS_RESPONDER_TICK_INTERVAL
#define DNS_SD_TICK_INTERVAL
Definition: dns_sd.h:48
systime_t dnsSdTickCounter
Definition: dns_sd.c:57
DNS cache management.
#define OS_INVALID_HANDLE
Definition: os_port.h:79
#define NIC_TICK_INTERVAL
Definition: nic.h:39
uint32_t time
error_t netSetInterfaceId(NetInterface *interface, uint32_t id)
Set interface identifier.
Definition: net.c:434
error_t ndpInit(NetInterface *interface)
Neighbor cache initialization.
Definition: ndp.c:68
error_t strSafeCopy(char_t *dest, const char_t *src, size_t destSize)
Copy string.
Definition: str.c:167
void mdnsResponderLinkChangeEvent(MdnsResponderContext *context)
Callback function for link change event.
#define NDP_ROUTER_ADV_TICK_INTERVAL
error_t tcpInit(void)
TCP related initialization.
Definition: tcp.c:60
#define NET_MAX_IF_NAME_LEN
Definition: net.h:131
void(* OsTaskCode)(void *param)
Task routine.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
#define AUTO_IP_TICK_INTERVAL
Definition: auto_ip.h:53
systime_t autoIpTickCounter
Definition: auto_ip.c:56
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
error_t netSetVmanId(NetInterface *interface, uint16_t vmanId)
Specify VMAN identifier (802.1ad)
Definition: net.c:577
systime_t dhcpv6ClientTickCounter
Definition: dhcpv6_client.c:59
#define Socket
Definition: socket.h:36
@ NIC_HALF_DUPLEX_MODE
Definition: nic.h:118
#define DHCP_CLIENT_TICK_INTERVAL
Definition: dhcp_client.h:49
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:107
error_t netSetVlanId(NetInterface *interface, uint16_t vlanId)
Specify VLAN identifier (802.1q)
Definition: net.c:543
#define DHCPV6_CLIENT_TICK_INTERVAL
Definition: dhcpv6_client.h:47
IPv4 routing.
error_t netStopInterface(NetInterface *interface)
Stop network interface.
Definition: net.c:1157
void netInvokeLinkChangeCallback(NetInterface *interface, bool_t linkState)
Invoke link change callback.
Definition: net.c:1944
#define PPP_TICK_INTERVAL
Definition: ppp.h:82
error_t netSetHostname(NetInterface *interface, const char_t *name)
Set host name.
Definition: net.c:486
uint16_t id
Definition: dns_common.h:158
#define IGMP_TICK_INTERVAL
Definition: igmp.h:46
uint8_t cookie[]
Definition: dtls_misc.h:203
Socket API.
error_t ipv6InitRouting(void)
Initialize IPv6 routing table.
Definition: ipv6_routing.c:57
error_t ethInit(NetInterface *interface)
Ethernet related initialization.
Definition: ethernet.c:67
#define NET_MAX_PROXY_NAME_LEN
Definition: net.h:145
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:80
error_t nbnsInit(NetInterface *interface)
NBNS related initialization.
Definition: nbns_common.c:56
systime_t dhcpServerTickCounter
Definition: dhcp_server.c:54
void tcpTick(void)
TCP timer handler.
Definition: tcp_timer.c:58
bool_t osCreateStaticTask(OsTask *task, const char_t *name, OsTaskCode taskCode, void *param, void *stack, size_t stackSize, int_t priority)
Create a static task.
LLMNR responder (Link-Local Multicast Name Resolution)
void dnsSdLinkChangeEvent(DnsSdContext *context)
Callback function for link change event.
Definition: dns_sd.c:669
error_t netGetEui64(NetInterface *interface, Eui64 *eui64)
Retrieve EUI-64 interface identifier.
Definition: net.c:402
void netTick(void)
Manage TCP/IP timers.
Definition: net.c:1472
#define MIB2_SET_TIME_TICKS(name, value)
Definition: mib2_module.h:155
#define MLD_TICK_INTERVAL
Definition: mld.h:46
error_t ipv4JoinMulticastGroup(NetInterface *interface, Ipv4Addr groupAddr)
Join the specified host group.
Definition: ipv4.c:1194
IPv4 (Internet Protocol Version 4)
OsTask * netTaskHandle
Definition: net.c:73
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:106
error_t netSetSwitchPort(NetInterface *interface, uint8_t port)
Specify switch port.
Definition: net.c:611
TCP timer management.
void ipv6LinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: ipv6.c:797
uint8_t value[]
Definition: dtls_misc.h:150
unsigned int uint_t
Definition: compiler_port.h:45
void nicTick(NetInterface *interface)
Network controller timer handler.
Definition: nic.c:250
error_t netStartInterface(NetInterface *interface)
Start network interface.
Definition: net.c:1076
TCP/IP stack core.
error_t netInitRand(uint32_t seed)
Seed pseudo-random number generator.
Definition: net.c:1795
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:52
error_t netSetExtIntDriver(NetInterface *interface, const ExtIntDriver *driver)
Set external interrupt line driver.
Definition: net.c:803
error_t netSetLinkState(NetInterface *interface, NicLinkState linkState)
Set link state (for virtual drivers only)
Definition: net.c:828
NIC driver.
Definition: nic.h:179
error_t dnsInit(void)
DNS cache initialization.
Definition: dns_cache.c:59
void netTask(void)
TCP/IP events handling.
Definition: net.c:1338
bool_t netGetLinkState(NetInterface *interface)
Get link state.
Definition: net.c:860
#define SOCKET_MAX_COUNT
Definition: socket.h:45
error_t llmnrResponderInit(NetInterface *interface)
LLMNR responder initialization.
systime_t mdnsResponderTickCounter
DHCP server (Dynamic Host Configuration Protocol)
ARP (Address Resolution Protocol)
#define NET_TASK_PRIORITY
Definition: net.h:166
error_t ipv4Init(NetInterface *interface)
IPv4 related initialization.
Definition: ipv4.c:72
void dhcpClientTick(DhcpClientContext *context)
DHCP client timer handler.
Definition: dhcp_client.c:284
uint32_t systime_t
Definition: compiler_port.h:46
error_t socketInit(void)
Socket related initialization.
Definition: socket.c:57
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
void netProcessLinkChange(NetInterface *interface)
Process link state change event.
Definition: net.c:1214
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define NET_MAX_HOSTNAME_LEN
Definition: net.h:138
NBNS responder (NetBIOS Name Service)
__start_packed struct @108 MacAddr
MAC address.
mDNS responder (Multicast DNS)
MLD (Multicast Listener Discovery for IPv6)
systime_t osGetSystemTime(void)
Retrieve system time.
systime_t dnsTickCounter
Definition: dns_cache.c:49
error_t netSetInterfaceName(NetInterface *interface, const char_t *name)
Set interface name.
Definition: net.c:459