1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2019-03-18     ChenYong     First version
9  * 2025-01-04     Evlers       add statistics and more inupt parameters to ping command
10  */
11 
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 
16 #include <rtthread.h>
17 #include <rthw.h>
18 
19 #include <netdev_ipaddr.h>
20 #include <netdev.h>
21 
22 #ifdef RT_USING_SAL
23 #include <sal_netdb.h>
24 #include <sal_low_lvl.h>
25 #endif /* RT_USING_SAL */
26 
27 #define DBG_TAG              "netdev"
28 #define DBG_LVL              DBG_INFO
29 #include <rtdbg.h>
30 
31 #if defined(SAL_USING_AF_NETLINK)
32 #include <route_netlink.h>
33 #endif
34 
35 /* The list of network interface device */
36 struct netdev *netdev_list = RT_NULL;
37 /* The default network interface device */
38 struct netdev *netdev_default = RT_NULL;
39 /* The global network register callback */
40 static netdev_callback_fn g_netdev_register_callback = RT_NULL;
41 static netdev_callback_fn g_netdev_default_change_callback = RT_NULL;
42 static RT_DEFINE_SPINLOCK(_spinlock);
43 static int netdev_num;
44 
45 /**
46  * This function will register network interface device and
47  * add it to network interface device list.
48  *
49  * @param netdev the network interface device object
50  * @param name the network interface device name
51  * @param user_data user-specific data
52  *
53  * @return  0: registered successfully
54  *         -1: registered failed
55  */
netdev_register(struct netdev * netdev,const char * name,void * user_data)56 int netdev_register(struct netdev *netdev, const char *name, void *user_data)
57 {
58     rt_uint16_t flags_mask;
59     rt_uint16_t index;
60 
61     RT_ASSERT(netdev);
62     RT_ASSERT(name);
63 
64     /* clean network interface device */
65     flags_mask = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP | NETDEV_FLAG_INTERNET_UP | NETDEV_FLAG_DHCP;
66     netdev->flags &= ~flags_mask;
67 
68     ip_addr_set_zero(&(netdev->ip_addr));
69     ip_addr_set_zero(&(netdev->netmask));
70     ip_addr_set_zero(&(netdev->gw));
71 
72     IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4);
73     IP_SET_TYPE_VAL(netdev->netmask, IPADDR_TYPE_V4);
74     IP_SET_TYPE_VAL(netdev->gw, IPADDR_TYPE_V4);
75 #if NETDEV_IPV6
76     for (index = 0; index < NETDEV_IPV6_NUM_ADDRESSES; index++)
77     {
78         ip_addr_set_zero(&(netdev->ip6_addr[index]));
79         IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V6);
80     }
81 #endif /* NETDEV_IPV6 */
82     for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
83     {
84         ip_addr_set_zero(&(netdev->dns_servers[index]));
85         IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4);
86     }
87     netdev->status_callback = RT_NULL;
88     netdev->addr_callback = RT_NULL;
89 
90     if(rt_strlen(name) > RT_NAME_MAX)
91     {
92         char netdev_name[RT_NAME_MAX + 1] = {0};
93 
94         rt_strncpy(netdev_name, name, RT_NAME_MAX);
95         LOG_E("netdev name[%s] length is so long that have been cut into [%s].", name, netdev_name);
96     }
97 
98     /* fill network interface device */
99     rt_strncpy(netdev->name, name, RT_NAME_MAX);
100     netdev->user_data = user_data;
101 
102     /* initialize current network interface device single list */
103     rt_slist_init(&(netdev->list));
104 
105     rt_spin_lock(&_spinlock);
106 
107     if (netdev_list == RT_NULL)
108     {
109         netdev_list = netdev;
110     }
111     else
112     {
113         /* tail insertion */
114         rt_slist_append(&(netdev_list->list), &(netdev->list));
115     }
116 
117     netdev_num++;
118     netdev->ifindex = netdev_num;
119 
120     rt_spin_unlock(&_spinlock);
121 
122     if (netdev_default == RT_NULL)
123     {
124         netdev_set_default(netdev_list);
125     }
126 
127     /* execute netdev register callback */
128     if (g_netdev_register_callback)
129     {
130         g_netdev_register_callback(netdev, NETDEV_CB_REGISTER);
131     }
132 
133 #if defined(SAL_USING_AF_NETLINK)
134     rtnl_ip_notify(netdev, RTM_NEWLINK);
135 #endif
136 
137     return RT_EOK;
138 }
139 
140 /**
141  * This function will unregister network interface device and
142  * delete it from network interface device list.
143  *
144  * @param netdev the network interface device object
145  *
146  * @return  0: unregistered successfully
147  *         -1: unregistered failed
148  */
netdev_unregister(struct netdev * netdev)149 int netdev_unregister(struct netdev *netdev)
150 {
151     rt_slist_t *node = RT_NULL;
152     struct netdev *cur_netdev = RT_NULL;
153 
154     RT_ASSERT(netdev);
155 
156     if (netdev_list == RT_NULL)
157     {
158         return -RT_ERROR;
159     }
160 
161     rt_spin_lock(&_spinlock);
162 
163     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
164     {
165         cur_netdev = rt_slist_entry(node, struct netdev, list);
166         if (cur_netdev == netdev)
167         {
168             /* find this network interface device in network interface device list */
169             if (netdev_list == netdev)
170             {
171                 rt_slist_t *next = rt_slist_next(node);
172                 if (next)
173                 {
174                     netdev_list = rt_slist_entry(next, struct netdev, list);
175                 }
176                 else
177                 {
178                     netdev_list = RT_NULL;
179                 }
180             }
181             else
182             {
183                 rt_slist_remove(&(netdev_list->list), &(cur_netdev->list));
184             }
185             if (netdev_default == netdev)
186             {
187                 netdev_default = RT_NULL;
188             }
189             break;
190         }
191     }
192     rt_spin_unlock(&_spinlock);
193 
194 #if defined(SAL_USING_AF_NETLINK)
195     rtnl_ip_notify(netdev, RTM_DELLINK);
196 #endif
197 
198     if (netdev_default == RT_NULL)
199     {
200         netdev_set_default(netdev_list);
201     }
202 
203     if (cur_netdev == netdev)
204     {
205 #ifdef RT_USING_SAL
206         extern int sal_netdev_cleanup(struct netdev *netdev);
207         sal_netdev_cleanup(netdev);
208 #endif
209         rt_memset(netdev, 0, sizeof(*netdev));
210     }
211 
212     return -RT_ERROR;
213 }
214 
215 /**
216  * This function will set register callback
217  *
218  * @param register_callback the network register callback
219  *
220  */
netdev_set_register_callback(netdev_callback_fn register_callback)221 void netdev_set_register_callback(netdev_callback_fn register_callback)
222 {
223     g_netdev_register_callback = register_callback;
224 }
225 
226 /**
227  * This function will get the first network interface device
228  * with the flags in network interface device list.
229  *
230  * @param flags the network interface device flags
231  *
232  * @return != NULL: network interface device object
233  *            NULL: get failed
234  */
netdev_get_first_by_flags(uint16_t flags)235 struct netdev *netdev_get_first_by_flags(uint16_t flags)
236 {
237     rt_slist_t *node = RT_NULL;
238     struct netdev *netdev = RT_NULL;
239 
240     if (netdev_list == RT_NULL)
241     {
242         return RT_NULL;
243     }
244 
245     rt_spin_lock(&_spinlock);
246 
247     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
248     {
249         netdev = rt_slist_entry(node, struct netdev, list);
250         if (netdev && (netdev->flags & flags) != 0)
251         {
252             rt_spin_unlock(&_spinlock);
253             return netdev;
254         }
255     }
256 
257     rt_spin_unlock(&_spinlock);
258 
259     return RT_NULL;
260 }
261 
262 /**
263  * This function will get the first network interface device
264  * in network interface device list by IP address.
265  *
266  * @param ip_addr the network interface device IP address
267  *
268  * @return != NULL: network interface device object
269  *            NULL: get failed
270  */
netdev_get_by_ipaddr(ip_addr_t * ip_addr)271 struct netdev *netdev_get_by_ipaddr(ip_addr_t *ip_addr)
272 {
273     rt_slist_t *node = RT_NULL;
274     struct netdev *netdev = RT_NULL;
275 
276     if (netdev_list == RT_NULL)
277     {
278         return RT_NULL;
279     }
280 
281     rt_spin_lock(&_spinlock);
282 
283     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
284     {
285         netdev = rt_slist_entry(node, struct netdev, list);
286         if (netdev && ip_addr_cmp(&(netdev->ip_addr), ip_addr))
287         {
288             rt_spin_unlock(&_spinlock);
289             return netdev;
290         }
291     }
292 
293     rt_spin_unlock(&_spinlock);
294 
295     return RT_NULL;
296 }
297 
298 /**
299  * This function will get network interface device
300  * in network interface device list by netdev name.
301  *
302  * @param name the network interface device name
303  *
304  * @return != NULL: network interface device object
305  *            NULL: get failed
306  */
netdev_get_by_name(const char * name)307 struct netdev *netdev_get_by_name(const char *name)
308 {
309     rt_slist_t *node = RT_NULL;
310     struct netdev *netdev = RT_NULL;
311 
312     if (netdev_list == RT_NULL)
313     {
314         return RT_NULL;
315     }
316 
317     rt_spin_lock(&_spinlock);
318 
319     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
320     {
321         netdev = rt_slist_entry(node, struct netdev, list);
322         if (netdev && (rt_strncmp(netdev->name, name, rt_strlen(name) < RT_NAME_MAX ? rt_strlen(name) : RT_NAME_MAX) == 0))
323         {
324             rt_spin_unlock(&_spinlock);
325             return netdev;
326         }
327     }
328 
329     rt_spin_unlock(&_spinlock);
330 
331     return RT_NULL;
332 }
333 
334 /**
335  * This function will get network interface device
336  * in network interface device list by netdev ifindex.
337  *
338  * @param ifindex the ifindex of network interface device
339  *
340  * @return != NULL: network interface device object
341  *            NULL: get failed
342  */
netdev_get_by_ifindex(int ifindex)343 struct netdev *netdev_get_by_ifindex(int ifindex)
344 {
345     rt_slist_t *node = RT_NULL;
346     struct netdev *netdev = RT_NULL;
347 
348     if (netdev_list == RT_NULL)
349     {
350         return RT_NULL;
351     }
352 
353     rt_spin_lock(&_spinlock);
354 
355     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
356     {
357         netdev = rt_slist_entry(node, struct netdev, list);
358         if (netdev && (netdev->ifindex == ifindex))
359         {
360             rt_spin_unlock(&_spinlock);
361             return netdev;
362         }
363     }
364 
365     rt_spin_unlock(&_spinlock);
366 
367     return RT_NULL;
368 }
369 
370 #ifdef RT_USING_SAL
371 /**
372  * This function will get the first network interface device
373  * in network interface device list by protocol family type.
374  *
375  * @param family the network interface device protocol family type
376  *
377  * @return != NULL: network interface device object
378  *            NULL: get failed
379  */
netdev_get_by_family(int family)380 struct netdev *netdev_get_by_family(int family)
381 {
382     rt_slist_t *node = RT_NULL;
383     struct netdev *netdev = RT_NULL;
384     struct sal_proto_family *pf = RT_NULL;
385 
386     if (netdev_list == RT_NULL)
387     {
388         return RT_NULL;
389     }
390 
391     rt_spin_lock(&_spinlock);
392 
393     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
394     {
395         netdev = rt_slist_entry(node, struct netdev, list);
396         pf = (struct sal_proto_family *) netdev->sal_user_data;
397         if (pf && pf->skt_ops && pf->family == family && netdev_is_up(netdev))
398         {
399             rt_spin_unlock(&_spinlock);
400             return netdev;
401         }
402     }
403 
404     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
405     {
406         netdev = rt_slist_entry(node, struct netdev, list);
407         pf = (struct sal_proto_family *) netdev->sal_user_data;
408         if (pf && pf->skt_ops && pf->sec_family == family && netdev_is_up(netdev))
409         {
410             rt_spin_unlock(&_spinlock);
411             return netdev;
412         }
413     }
414 
415     rt_spin_unlock(&_spinlock);
416 
417     return RT_NULL;
418 }
419 
420 /**
421  * This function will get the family type from network interface device
422  *
423  * @param netdev network interface device object
424  *
425  * @return the network interface device family type
426  */
netdev_family_get(struct netdev * netdev)427 int netdev_family_get(struct netdev *netdev)
428 {
429     RT_ASSERT(netdev);
430 
431     return ((struct sal_proto_family *)netdev->sal_user_data)->family;
432 }
433 
434 #endif /* RT_USING_SAL */
435 
436 #if defined(SAL_USING_AF_NETLINK)
netdev_getnetdev(struct msg_buf * msg,int (* cb)(struct msg_buf * m_buf,struct netdev * nd,int nd_num,int index,int ipvx))437 int netdev_getnetdev(struct msg_buf *msg, int (*cb)(struct msg_buf *m_buf, struct netdev *nd, int nd_num, int index, int ipvx))
438 {
439     struct netdev *cur_nd_list = netdev_list;
440     struct netdev *nd_node;
441     int nd_num = 0;
442     int err = 0;
443 
444     if (cur_nd_list == RT_NULL)
445         return 0;
446 
447     rt_spin_lock(&_spinlock);
448     nd_num = rt_slist_len(&cur_nd_list->list) + 1;
449     rt_spin_unlock(&_spinlock);
450 
451     err = cb(msg, cur_nd_list, nd_num, nd.ifindex, ROUTE_IPV4_TRUE);
452     if (err < 0)
453         return err;
454 
455 
456     rt_spin_lock(&_spinlock);
457     rt_slist_for_each_entry(nd_node, &(cur_nd_list->list), list)
458     {
459         rt_spin_unlock(&_spinlock);
460         err = cb(msg, nd_node, nd_num, nd.ifindex, ROUTE_IPV4_TRUE);
461         if (err < 0)
462         {
463             return err;
464         }
465 
466         rt_spin_lock(&_spinlock);
467     }
468     rt_spin_unlock(&_spinlock);
469 
470     return 0;
471 }
472 #endif
473 
474 /**
475  * This function will set default network interface device.
476  *
477  * @param netdev the network interface device to change
478  */
netdev_set_default(struct netdev * netdev)479 void netdev_set_default(struct netdev *netdev)
480 {
481     if (netdev && (netdev != netdev_default))
482     {
483         netdev_default = netdev;
484 
485         /* execture the default network interface device in the current network stack */
486         if (netdev->ops && netdev->ops->set_default)
487         {
488             netdev->ops->set_default(netdev);
489         }
490 
491         /* execture application netdev default change callback */
492         if (g_netdev_default_change_callback)
493         {
494             g_netdev_default_change_callback(netdev, NETDEV_CB_DEFAULT_CHANGE);
495         }
496         LOG_D("Setting default network interface device name(%s) successfully.", netdev->name);
497     }
498 }
499 
500 /**
501  * This function will set defalut netdev change callback
502  *
503  * @param register_callback the network default change callback
504  *
505  */
netdev_set_default_change_callback(netdev_callback_fn register_callback)506 void netdev_set_default_change_callback(netdev_callback_fn register_callback)
507 {
508     g_netdev_default_change_callback = register_callback;
509 }
510 
511 /**
512  * This function will enable network interface device .
513  *
514  * @param netdev the network interface device to change
515  *
516  * @return  0: set status successfully
517  *         -1: set status failed
518  */
netdev_set_up(struct netdev * netdev)519 int netdev_set_up(struct netdev *netdev)
520 {
521     int err = 0;
522 
523     RT_ASSERT(netdev);
524 
525     if (!netdev->ops || !netdev->ops->set_up)
526     {
527         LOG_E("The network interface device(%s) not support to set status.", netdev->name);
528         return -RT_ERROR;
529     }
530 
531     /* network interface device status flags check */
532     if (netdev_is_up(netdev))
533     {
534         return RT_EOK;
535     }
536 
537     /* execute enable network interface device operations by network interface device driver */
538     err = netdev->ops->set_up(netdev);
539 
540 #if defined(SAL_USING_AF_NETLINK)
541     if (err)
542         rtnl_ip_notify(netdev, RTM_NEWLINK);
543 #endif
544 
545     return err;
546 }
547 /**
548  * This function will disable network interface device.
549  *
550  * @param netdev the network interface device to change
551  *
552  * @return  0: set status successfully
553  *         -1: set sttaus failed
554  */
netdev_set_down(struct netdev * netdev)555 int netdev_set_down(struct netdev *netdev)
556 {
557     int err;
558 
559     RT_ASSERT(netdev);
560 
561     if (!netdev->ops || !netdev->ops->set_down)
562     {
563         LOG_E("The network interface device(%s) not support to set status.", netdev->name);
564         return -RT_ERROR;
565     }
566 
567     /* network interface device status flags check */
568     if (!netdev_is_up(netdev))
569     {
570         return RT_EOK;
571     }
572 
573     /* execute disable network interface device operations by network interface driver */
574     err = netdev->ops->set_down(netdev);
575 #if defined(SAL_USING_AF_NETLINK)
576     if (err)
577         rtnl_ip_notify(netdev, RTM_NEWLINK);
578 #endif
579 
580     return err;
581 }
582 
583 #ifdef RT_LWIP_DHCP
584 /**
585  * This function will control network interface device DHCP capability enable or disable.
586  *
587  * @param netdev the network interface device device to change
588  * @param is_enable the new DHCP status
589  *
590  * @return  0: set DHCP status successfully
591  *         -1: set DHCP status failed
592  */
netdev_dhcp_enabled(struct netdev * netdev,rt_bool_t is_enabled)593 int netdev_dhcp_enabled(struct netdev *netdev, rt_bool_t is_enabled)
594 {
595     RT_ASSERT(netdev);
596 
597     if (!netdev->ops || !netdev->ops->set_dhcp)
598     {
599         LOG_E("The network interface device(%s) not support to set DHCP status.", netdev->name);
600         return -RT_ERROR;
601     }
602 
603     /* network interface device DHCP flags check */
604     if (netdev_is_dhcp_enabled(netdev) == is_enabled)
605     {
606         return RT_EOK;
607     }
608 
609     /* execute network interface device DHCP capability control operations */
610     return netdev->ops->set_dhcp(netdev, is_enabled);
611 }
612 
netdev_dhcp_open(char * netdev_name)613 int netdev_dhcp_open(char *netdev_name)
614 {
615     struct netdev *netdev = RT_NULL;
616     netdev                = netdev_get_by_name(netdev_name);
617     if (netdev == RT_NULL)
618     {
619         rt_kprintf("bad network interface device name(%s).\n", netdev_name);
620         return -1;
621     }
622     netdev_dhcp_enabled(netdev, RT_TRUE);
623     return 0;
624 }
625 
netdev_dhcp_close(char * netdev_name)626 int netdev_dhcp_close(char *netdev_name)
627 {
628     struct netdev *netdev = RT_NULL;
629 
630     netdev = netdev_get_by_name(netdev_name);
631     if (netdev == RT_NULL)
632     {
633         rt_kprintf("bad network interface device name(%s).\n", netdev_name);
634         return -1;
635     }
636     netdev_dhcp_enabled(netdev, RT_FALSE);
637     return 0;
638 }
639 #endif /* RT_LWIP_DHCP */
640 
641 /**
642  * This function will set network interface device IP address.
643  *
644  * @param netdev the network interface device to change
645  * @param ip_addr the new IP address
646  *
647  * @return  0: set IP address successfully
648  *         -1: set IP address failed
649  */
netdev_set_ipaddr(struct netdev * netdev,const ip_addr_t * ip_addr)650 int netdev_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr)
651 {
652     int err;
653     RT_ASSERT(netdev);
654     RT_ASSERT(ip_addr);
655 
656     if (!netdev->ops || !netdev->ops->set_addr_info)
657     {
658         LOG_E("The network interface device(%s) not support to set IP address.", netdev->name);
659         return -RT_ERROR;
660     }
661 
662     if (netdev_is_dhcp_enabled(netdev))
663     {
664         LOG_E("The network interface device(%s) DHCP capability is enable, not support set IP address.", netdev->name);
665         return -RT_ERROR;
666     }
667 
668      /* execute network interface device set IP address operations */
669     err = netdev->ops->set_addr_info(netdev, (ip_addr_t *)ip_addr, RT_NULL, RT_NULL);
670 
671 #if defined(SAL_USING_AF_NETLINK)
672     if (err == 0)
673         rtnl_ip_notify(netdev, RTM_SETLINK);
674 #endif
675 
676 
677     return err;
678 }
679 
680 /**
681  * This function will set network interface device netmask address.
682  *
683  * @param netdev the network interface device to change
684  * @param netmask the new netmask address
685  *
686  * @return  0: set netmask address successfully
687  *         -1: set netmask address failed
688  */
netdev_set_netmask(struct netdev * netdev,const ip_addr_t * netmask)689 int netdev_set_netmask(struct netdev *netdev, const ip_addr_t *netmask)
690 {
691     RT_ASSERT(netdev);
692     RT_ASSERT(netmask);
693 
694     if (!netdev->ops || !netdev->ops->set_addr_info)
695     {
696         LOG_E("The network interface device(%s) not support to set netmask address.", netdev->name);
697         return -RT_ERROR;
698     }
699 
700     if (netdev_is_dhcp_enabled(netdev))
701     {
702         LOG_E("The network interface device(%s) DHCP capability is enable, not support set netmask address.", netdev->name);
703         return -RT_ERROR;
704     }
705 
706     /* execute network interface device set netmask address operations */
707     return netdev->ops->set_addr_info(netdev, RT_NULL, (ip_addr_t *)netmask, RT_NULL);
708 }
709 
710 /**
711  * This function will set network interface device gateway address.
712  *
713  * @param netdev the network interface device to change
714  * @param gw the new gateway address
715  *
716  * @return  0: set gateway address successfully
717  *         -1: set gateway address failed
718  */
netdev_set_gw(struct netdev * netdev,const ip_addr_t * gw)719 int netdev_set_gw(struct netdev *netdev, const ip_addr_t *gw)
720 {
721     RT_ASSERT(netdev);
722     RT_ASSERT(gw);
723 
724     if (!netdev->ops || !netdev->ops->set_addr_info)
725     {
726         LOG_E("The network interface device(%s) not support to set gateway address.", netdev->name);
727         return -RT_ERROR;
728     }
729 
730     if (netdev_is_dhcp_enabled(netdev))
731     {
732         LOG_E("The network interface device(%s) DHCP capability is enable, not support set gateway address.", netdev->name);
733         return -RT_ERROR;
734     }
735 
736     /* execute network interface device set gateway address operations */
737     return netdev->ops->set_addr_info(netdev, RT_NULL, RT_NULL, (ip_addr_t *)gw);
738 }
739 
740 /**
741  * This function will try to get network device and set DNS server address.
742  *
743  * @param netdev_name the network interface device name
744  * @param dns_num the number of the DNS server
745  * @param dns_server the new DNS server address
746  */
netdev_set_dns(char * netdev_name,uint8_t dns_num,char * dns_server)747 void netdev_set_dns(char *netdev_name, uint8_t dns_num, char *dns_server)
748 {
749     struct netdev *netdev = RT_NULL;
750     ip_addr_t      dns_addr;
751 
752     netdev = netdev_get_by_name(netdev_name);
753     if (netdev == RT_NULL)
754     {
755         rt_kprintf("bad network interface device name(%s).\n", netdev_name);
756         return;
757     }
758 
759     inet_aton(dns_server, &dns_addr);
760     if (netdev_set_dns_server(netdev, dns_num, &dns_addr) == RT_EOK)
761     {
762         rt_kprintf("set network interface device(%s) dns server #%d: %s\n", netdev_name, dns_num, dns_server);
763     }
764 }
765 
766 /**
767  * This function will set network interface device DNS server address.
768  *
769  * @param netdev the network interface device to change
770  * @param dns_num the number of the DNS server
771  * @param dns_server the new DNS server address
772  *
773  * @return  0: set netmask address successfully
774  *         -1: set netmask address failed
775  */
netdev_set_dns_server(struct netdev * netdev,uint8_t dns_num,const ip_addr_t * dns_server)776 int netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server)
777 {
778     RT_ASSERT(netdev);
779     RT_ASSERT(dns_server);
780 
781     if (dns_num >= NETDEV_DNS_SERVERS_NUM)
782     {
783         LOG_E("The number of DNS servers(%d) set exceeds the maximum number(%d).", dns_num + 1, NETDEV_DNS_SERVERS_NUM);
784         return -RT_ERROR;
785     }
786 
787     if (!netdev->ops || !netdev->ops->set_dns_server)
788     {
789         LOG_E("The network interface device(%s) not support to set DNS server address.", netdev->name);
790         return -RT_ERROR;
791     }
792 
793     /* execute network interface device set DNS server address operations */
794     return netdev->ops->set_dns_server(netdev, dns_num, (ip_addr_t *)dns_server);
795 }
796 
797 /**
798  * This function will set network interface device IP, gateway and netmask address according to device name.
799  *
800  * @param netdev_name the network interface device name
801  * @param ip_addr the new IP address
802  * @param gw_addr the new gateway address
803  * @param nm_addr the new netmask address
804  */
netdev_set_if(char * netdev_name,char * ip_addr,char * gw_addr,char * nm_addr)805 void netdev_set_if(char *netdev_name, char *ip_addr, char *gw_addr, char *nm_addr)
806 {
807     struct netdev *netdev = RT_NULL;
808     ip_addr_t      addr;
809 
810     netdev = netdev_get_by_name(netdev_name);
811     if (netdev == RT_NULL)
812     {
813         rt_kprintf("bad network interface device name(%s).\n", netdev_name);
814         return;
815     }
816 
817 #ifdef RT_LWIP_DHCP
818     netdev_dhcp_close(netdev_name);
819 #endif
820 
821     /* set IP address */
822     if ((ip_addr != RT_NULL) && inet_aton(ip_addr, &addr))
823     {
824         netdev_set_ipaddr(netdev, &addr);
825     }
826 
827     /* set gateway address */
828     if ((gw_addr != RT_NULL) && inet_aton(gw_addr, &addr))
829     {
830         netdev_set_gw(netdev, &addr);
831     }
832 
833     /* set netmask address */
834     if ((nm_addr != RT_NULL) && inet_aton(nm_addr, &addr))
835     {
836         netdev_set_netmask(netdev, &addr);
837     }
838 }
839 
840 /**
841  * This function will set callback to be called when the network interface device status has been changed.
842  *
843  * @param netdev the network interface device to change
844  * @param status_callback the callback be called when the status has been changed.
845  */
netdev_set_status_callback(struct netdev * netdev,netdev_callback_fn status_callback)846 void netdev_set_status_callback(struct netdev *netdev, netdev_callback_fn status_callback)
847 {
848     RT_ASSERT(netdev);
849     RT_ASSERT(status_callback);
850 
851     netdev->status_callback = status_callback;
852 }
853 
854 /**
855  * This function will set callback to be called when the network interface device address has been changed.
856  *
857  * @param netdev the network interface device to change
858  * @param addr_callback the callback be called when the address has been changed.
859  */
netdev_set_addr_callback(struct netdev * netdev,netdev_callback_fn addr_callback)860 void netdev_set_addr_callback(struct netdev *netdev, netdev_callback_fn addr_callback)
861 {
862     RT_ASSERT(netdev);
863     RT_ASSERT(addr_callback);
864 
865     netdev->addr_callback = addr_callback;
866 }
867 
868 
869 /**
870  * This function will set network interface device IP address.
871  * @NOTE it can only be called in the network interface device driver.
872  *
873  * @param netdev the network interface device to change
874  * @param ip_addr the new IP address
875  */
netdev_low_level_set_ipaddr(struct netdev * netdev,const ip_addr_t * ip_addr)876 void netdev_low_level_set_ipaddr(struct netdev *netdev, const ip_addr_t *ip_addr)
877 {
878     RT_ASSERT(ip_addr);
879 
880     if (netdev && ip_addr_cmp(&(netdev->ip_addr), ip_addr) == 0)
881     {
882         ip_addr_copy(netdev->ip_addr, *ip_addr);
883 
884 #ifdef RT_USING_SAL
885         /* set network interface device flags to internet up */
886         if (netdev_is_up(netdev) && netdev_is_link_up(netdev))
887         {
888             sal_check_netdev_internet_up(netdev);
889         }
890 #endif /* RT_USING_SAL */
891 
892         /* execute IP address change callback function */
893         if (netdev->addr_callback)
894         {
895             netdev->addr_callback(netdev, NETDEV_CB_ADDR_IP);
896         }
897     }
898 }
899 
900 /**
901  * This function will set network interface device netmask address.
902  * @NOTE it can only be called in the network interface device driver.
903  *
904  * @param netdev the network interface device to change
905  * @param netmask the new netmask address
906  */
netdev_low_level_set_netmask(struct netdev * netdev,const ip_addr_t * netmask)907 void netdev_low_level_set_netmask(struct netdev *netdev, const ip_addr_t *netmask)
908 {
909     RT_ASSERT(netmask);
910 
911     if (netdev && ip_addr_cmp(&(netdev->netmask), netmask) == 0)
912     {
913         ip_addr_copy(netdev->netmask, *netmask);
914 
915 #ifdef RT_USING_SAL
916         /* set network interface device flags to internet up */
917         if (netdev_is_up(netdev) && netdev_is_link_up(netdev) &&
918                 !ip_addr_isany(&(netdev->ip_addr)))
919         {
920             sal_check_netdev_internet_up(netdev);
921         }
922 #endif /* RT_USING_SAL */
923 
924         /* execute netmask address change callback function */
925         if (netdev->addr_callback)
926         {
927             netdev->addr_callback(netdev, NETDEV_CB_ADDR_NETMASK);
928         }
929     }
930 }
931 
932 /**
933  * This function will set network interface device gateway address.
934  * @NOTE it can only be called in the network interface device driver.
935  *
936  * @param netdev the network interface device to change
937  * @param gw the new gateway address
938  */
netdev_low_level_set_gw(struct netdev * netdev,const ip_addr_t * gw)939 void netdev_low_level_set_gw(struct netdev *netdev, const ip_addr_t *gw)
940 {
941     RT_ASSERT(gw);
942 
943     if (netdev && ip_addr_cmp(&(netdev->gw), gw) == 0)
944     {
945         ip_addr_copy(netdev->gw, *gw);
946 
947 #ifdef RT_USING_SAL
948         /* set network interface device flags to internet up */
949         if (netdev_is_up(netdev) && netdev_is_link_up(netdev) &&
950                 !ip_addr_isany(&(netdev->ip_addr)))
951         {
952             sal_check_netdev_internet_up(netdev);
953         }
954 #endif /* RT_USING_SAL */
955 
956         /* execute gateway address change callback function */
957         if (netdev->addr_callback)
958         {
959             netdev->addr_callback(netdev, NETDEV_CB_ADDR_GATEWAY);
960         }
961     }
962 }
963 
964 /**
965  * This function will set network interface device DNS server address.
966  * @NOTE it can only be called in the network interface device driver.
967  *
968  * @param netdev the network interface device to change
969  * @param dns_num the number of the DNS server
970  * @param dns_server the new DNS server address
971  *
972  */
netdev_low_level_set_dns_server(struct netdev * netdev,uint8_t dns_num,const ip_addr_t * dns_server)973 void netdev_low_level_set_dns_server(struct netdev *netdev, uint8_t dns_num, const ip_addr_t *dns_server)
974 {
975     unsigned int index;
976 
977     RT_ASSERT(dns_server);
978 
979     if (netdev == RT_NULL)
980     {
981         return;
982     }
983     /* check DNS servers is exist */
984     for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
985     {
986         if (ip_addr_cmp(&(netdev->dns_servers[index]), dns_server))
987         {
988             return;
989         }
990     }
991 
992     if (dns_num < NETDEV_DNS_SERVERS_NUM)
993     {
994         ip_addr_copy(netdev->dns_servers[dns_num], *dns_server);
995 
996         /* execute DNS servers address change callback function */
997         if (netdev->addr_callback)
998         {
999             netdev->addr_callback(netdev, NETDEV_CB_ADDR_DNS_SERVER);
1000         }
1001     }
1002 }
1003 
1004 #ifdef NETDEV_USING_AUTO_DEFAULT
1005 /* Change to the first link_up network interface device automatically */
netdev_auto_change_default(struct netdev * netdev)1006 static void netdev_auto_change_default(struct netdev *netdev)
1007 {
1008     struct netdev *new_netdev = RT_NULL;
1009 
1010     if (netdev->flags & NETDEV_FLAG_LINK_UP)
1011     {
1012         if (!(netdev_default->flags & NETDEV_FLAG_LINK_UP))
1013         {
1014             netdev_set_default(netdev);
1015         }
1016         return;
1017     }
1018     if (rt_memcmp(netdev, netdev_default, sizeof(struct netdev)) == 0)
1019     {
1020         new_netdev = netdev_get_first_by_flags(NETDEV_FLAG_LINK_UP);
1021         if (new_netdev)
1022         {
1023             netdev_set_default(new_netdev);
1024         }
1025     }
1026 }
1027 #endif /* NETDEV_USING_AUTO_DEFAULT */
1028 
1029 /**
1030  * This function will set network interface device status.
1031  * @NOTE it can only be called in the network interface device driver.
1032  *
1033  * @param netdev the network interface device to change
1034  * @param is_up the new status
1035  */
netdev_low_level_set_status(struct netdev * netdev,rt_bool_t is_up)1036 void netdev_low_level_set_status(struct netdev *netdev, rt_bool_t is_up)
1037 {
1038     if (netdev && netdev_is_up(netdev) != is_up)
1039     {
1040         if (is_up)
1041         {
1042             netdev->flags |= NETDEV_FLAG_UP;
1043         }
1044         else
1045         {
1046             netdev->flags &= ~NETDEV_FLAG_UP;
1047 
1048 #ifdef NETDEV_USING_AUTO_DEFAULT
1049             /* change to the first link_up network interface device automatically */
1050             netdev_auto_change_default(netdev);
1051 #endif /* NETDEV_USING_AUTO_DEFAULT */
1052         }
1053 
1054         /* execute  network interface device status change callback function */
1055         if (netdev->status_callback)
1056         {
1057             netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_UP : NETDEV_CB_STATUS_DOWN);
1058         }
1059     }
1060 }
1061 
1062 /**
1063  * This function will set network interface device active link status.
1064  * @NOTE it can only be called in the network interface device driver.
1065  *
1066  * @param netdev the network interface device to change
1067  * @param is_up the new link status
1068  */
netdev_low_level_set_link_status(struct netdev * netdev,rt_bool_t is_up)1069 void netdev_low_level_set_link_status(struct netdev *netdev, rt_bool_t is_up)
1070 {
1071     if (netdev && netdev_is_link_up(netdev) != is_up)
1072     {
1073         if (is_up)
1074         {
1075             netdev->flags |= NETDEV_FLAG_LINK_UP;
1076 
1077 #ifdef RT_USING_SAL
1078             /* set network interface device flags to internet up */
1079             if (netdev_is_up(netdev) && !ip_addr_isany(&(netdev->ip_addr)))
1080             {
1081                 sal_check_netdev_internet_up(netdev);
1082             }
1083 #endif /* RT_USING_SAL */
1084         }
1085         else
1086         {
1087             netdev->flags &= ~NETDEV_FLAG_LINK_UP;
1088 
1089             /* set network interface device flags to internet down */
1090             netdev->flags &= ~NETDEV_FLAG_INTERNET_UP;
1091 
1092 #ifdef NETDEV_USING_AUTO_DEFAULT
1093             /* change to the first link_up network interface device automatically */
1094             netdev_auto_change_default(netdev);
1095 #endif /* NETDEV_USING_AUTO_DEFAULT */
1096         }
1097 
1098         /* execute link status change callback function */
1099         if (netdev->status_callback)
1100         {
1101             netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_LINK_UP : NETDEV_CB_STATUS_LINK_DOWN);
1102         }
1103     }
1104 }
1105 
1106 /**
1107  * This function will set network interface device active internet status.
1108  * @NOTE it can only be called in the network interface device driver.
1109  *
1110  * @param netdev the network interface device to change
1111  * @param is_up the new internet status
1112  */
netdev_low_level_set_internet_status(struct netdev * netdev,rt_bool_t is_up)1113 void netdev_low_level_set_internet_status(struct netdev *netdev, rt_bool_t is_up)
1114 {
1115     if (netdev && netdev_is_internet_up(netdev) != is_up)
1116     {
1117         if (is_up)
1118         {
1119             netdev->flags |= NETDEV_FLAG_INTERNET_UP;
1120         }
1121         else
1122         {
1123             netdev->flags &= ~NETDEV_FLAG_INTERNET_UP;
1124         }
1125 
1126         /* execute  network interface device status change callback function */
1127         if (netdev->status_callback)
1128         {
1129             netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_INTERNET_UP : NETDEV_CB_STATUS_INTERNET_DOWN);
1130         }
1131     }
1132 }
1133 
1134 /**
1135  * This function will set network interface device DHCP status.
1136  * @NOTE it can only be called in the network interface device driver.
1137  *
1138  * @param netdev the network interface device to change
1139  * @param is_up the new DHCP status
1140  */
netdev_low_level_set_dhcp_status(struct netdev * netdev,rt_bool_t is_enable)1141 void netdev_low_level_set_dhcp_status(struct netdev *netdev, rt_bool_t is_enable)
1142 {
1143     if (netdev && netdev_is_dhcp_enabled(netdev) != is_enable)
1144     {
1145         if (is_enable)
1146         {
1147             netdev->flags |= NETDEV_FLAG_DHCP;
1148         }
1149         else
1150         {
1151             netdev->flags &= ~NETDEV_FLAG_DHCP;
1152         }
1153 
1154         /* execute DHCP status change callback function */
1155         if (netdev->status_callback)
1156         {
1157             netdev->status_callback(netdev, is_enable ? NETDEV_CB_STATUS_DHCP_ENABLE : NETDEV_CB_STATUS_DHCP_DISABLE);
1158         }
1159     }
1160 }
1161 
1162 #ifdef RT_USING_FINSH
1163 
1164 #include <finsh.h>
1165 
1166 #ifdef NETDEV_USING_IFCONFIG
netdev_list_if(void)1167 static void netdev_list_if(void)
1168 {
1169 #define NETDEV_IFCONFIG_MAC_MAX_LEN    6
1170 #define NETDEV_IFCONFIG_IMEI_MAX_LEN   8
1171 
1172     rt_ubase_t index;
1173     rt_slist_t *node  = RT_NULL;
1174     struct netdev *netdev = RT_NULL;
1175     struct netdev *cur_netdev_list = netdev_list;
1176 
1177     if (cur_netdev_list == RT_NULL)
1178     {
1179         rt_kprintf("ifconfig: network interface device list error.\n");
1180         return;
1181     }
1182 
1183     for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
1184     {
1185         netdev = rt_list_entry(node, struct netdev, list);
1186 
1187         rt_kprintf("network interface device: %.*s%s\n",
1188                    RT_NAME_MAX, netdev->name,
1189                    (netdev == netdev_default) ? " (Default)" : "");
1190         rt_kprintf("MTU: %d\n", netdev->mtu);
1191 
1192         /* 6 - MAC address, 8 - IEMI */
1193         if (netdev->hwaddr_len == NETDEV_IFCONFIG_MAC_MAX_LEN)
1194         {
1195             rt_kprintf("MAC: ");
1196             for (index = 0; index < netdev->hwaddr_len; index++)
1197             {
1198                 rt_kprintf("%02x ", netdev->hwaddr[index]);
1199             }
1200         }
1201         else if (netdev->hwaddr_len == NETDEV_IFCONFIG_IMEI_MAX_LEN)
1202         {
1203             rt_kprintf("IMEI: ");
1204             for (index = 0; index < netdev->hwaddr_len; index++)
1205             {
1206                 /* two numbers are displayed at one time*/
1207                 if (netdev->hwaddr[index] < 10 && index != netdev->hwaddr_len - 1)
1208                 {
1209                     rt_kprintf("%02d", netdev->hwaddr[index]);
1210                 }
1211                 else
1212                 {
1213                     rt_kprintf("%d", netdev->hwaddr[index]);
1214                 }
1215 
1216 
1217             }
1218         }
1219 
1220         rt_kprintf("\nFLAGS:");
1221         if (netdev->flags & NETDEV_FLAG_UP) rt_kprintf(" UP");
1222         else rt_kprintf(" DOWN");
1223         if (netdev->flags & NETDEV_FLAG_LINK_UP) rt_kprintf(" LINK_UP");
1224         else rt_kprintf(" LINK_DOWN");
1225 #ifdef SAL_INTERNET_CHECK
1226         if (netdev->flags & NETDEV_FLAG_INTERNET_UP) rt_kprintf(" INTERNET_UP");
1227         else rt_kprintf(" INTERNET_DOWN");
1228 #endif
1229         if (netdev->flags & NETDEV_FLAG_DHCP) rt_kprintf(" DHCP_ENABLE");
1230         else rt_kprintf(" DHCP_DISABLE");
1231         if (netdev->flags & NETDEV_FLAG_ETHARP) rt_kprintf(" ETHARP");
1232         if (netdev->flags & NETDEV_FLAG_BROADCAST) rt_kprintf(" BROADCAST");
1233         if (netdev->flags & NETDEV_FLAG_IGMP) rt_kprintf(" IGMP");
1234         rt_kprintf("\n");
1235         rt_kprintf("ip address: %s\n", inet_ntoa(netdev->ip_addr));
1236         rt_kprintf("gw address: %s\n", inet_ntoa(netdev->gw));
1237         rt_kprintf("net mask  : %s\n", inet_ntoa(netdev->netmask));
1238 
1239 #if NETDEV_IPV6
1240         {
1241             ip_addr_t *addr;
1242             int i;
1243 
1244             addr = &netdev->ip6_addr[0];
1245 
1246             if (!ip_addr_isany(addr))
1247             {
1248                 rt_kprintf("ipv6 link-local: %s %s\n", inet_ntoa(*addr),
1249                         !ip_addr_isany(addr) ? "VALID" : "INVALID");
1250 
1251                 for (i = 1; i < NETDEV_IPV6_NUM_ADDRESSES; i++)
1252                 {
1253                     addr = &netdev->ip6_addr[i];
1254                     rt_kprintf("ipv6[%d] address: %s %s\n", i, inet_ntoa(*addr),
1255                             !ip_addr_isany(addr) ? "VALID" : "INVALID");
1256                 }
1257             }
1258         }
1259 #endif /* NETDEV_IPV6 */
1260 
1261         for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
1262         {
1263             rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index]));
1264         }
1265 
1266         if (rt_slist_next(node))
1267         {
1268             rt_kprintf("\n");
1269         }
1270     }
1271 }
1272 
netdev_ifconfig(int argc,char ** argv)1273 int netdev_ifconfig(int argc, char **argv)
1274 {
1275     if (argc == 1)
1276     {
1277         netdev_list_if();
1278     }
1279 #ifdef RT_LWIP_DHCP
1280     else if(argc == 3)
1281     {
1282         if (!strcmp(argv[2], "dhcp"))
1283         {
1284             netdev_dhcp_open(argv[1]);
1285         }
1286     }
1287 #endif
1288     else if (argc == 5)
1289     {
1290         rt_kprintf("config : %s\n", argv[1]);
1291         rt_kprintf("IP addr: %s\n", argv[2]);
1292         rt_kprintf("Gateway: %s\n", argv[3]);
1293         rt_kprintf("netmask: %s\n", argv[4]);
1294         netdev_set_if(argv[1], argv[2], argv[3], argv[4]);
1295     }
1296     else
1297     {
1298         rt_kprintf("bad parameter! e.g: ifconfig e0 192.168.1.30 192.168.1.1 255.255.255.0\n");
1299 #ifdef RT_LWIP_DHCP
1300         rt_kprintf("bad parameter! e.g: ifconfig e0 dhcp\n");
1301 #endif
1302     }
1303 
1304     return 0;
1305 }
1306 MSH_CMD_EXPORT_ALIAS(netdev_ifconfig, ifconfig, list the information of all network interfaces);
1307 #endif /* NETDEV_USING_IFCONFIG */
1308 
1309 #ifdef NETDEV_USING_PING
netdev_cmd_ping(char * target_name,char * netdev_name,rt_uint32_t times,rt_size_t size)1310 int netdev_cmd_ping(char* target_name, char *netdev_name, rt_uint32_t times, rt_size_t size)
1311 {
1312 #define NETDEV_PING_DATA_SIZE       32
1313 /** ping receive timeout - in milliseconds */
1314 #define NETDEV_PING_RECV_TIMEO      (2 * RT_TICK_PER_SECOND)
1315 /** ping delay - in milliseconds */
1316 #define NETDEV_PING_DELAY           (1 * RT_TICK_PER_SECOND)
1317 /* check netdev ping options */
1318 #define NETDEV_PING_IS_COMMONICABLE(netdev) \
1319     ((netdev) && (netdev)->ops && (netdev)->ops->ping && \
1320         netdev_is_up(netdev) && netdev_is_link_up(netdev)) \
1321 
1322     struct netdev *netdev = RT_NULL;
1323     struct netdev_ping_resp ping_resp;
1324     rt_uint32_t index, received, loss, max_time, min_time, avg_time;
1325     int ret = 0;
1326     rt_bool_t isbind = RT_FALSE;
1327 
1328     if (size == 0)
1329     {
1330         size = NETDEV_PING_DATA_SIZE;
1331     }
1332 
1333     if (netdev_name != RT_NULL)
1334     {
1335         netdev = netdev_get_by_name(netdev_name);
1336         isbind = RT_TRUE;
1337     }
1338 
1339     if (netdev == RT_NULL)
1340     {
1341         netdev = netdev_default;
1342         rt_kprintf("ping: not found specified netif, using default netdev %s.\n", netdev->name);
1343     }
1344 
1345     if (!NETDEV_PING_IS_COMMONICABLE(netdev))
1346     {
1347         if (netdev == RT_NULL)
1348         {
1349             rt_kprintf("ping: not found available network interface device.\n");
1350             return -RT_ERROR;
1351         }
1352         else if (netdev->ops == RT_NULL || netdev->ops->ping == RT_NULL)
1353         {
1354             rt_kprintf("ping: network interface device(%s) not support ping feature.\n", netdev->name);
1355             return -RT_ERROR;
1356         }
1357         else if (!netdev_is_up(netdev) || !netdev_is_link_up(netdev))
1358         {
1359             rt_kprintf("ping: network interface device(%s) status error.\n", netdev->name);
1360             return -RT_ERROR;
1361         }
1362     }
1363 
1364     max_time = avg_time = received = 0;
1365     min_time = 0xFFFFFFFF;
1366     for (index = 0; index < times; index++)
1367     {
1368         int delay_tick = 0;
1369         rt_tick_t start_tick = 0;
1370 
1371         rt_memset(&ping_resp, 0x00, sizeof(struct netdev_ping_resp));
1372         start_tick = rt_tick_get();
1373         ret = netdev->ops->ping(netdev, (const char *)target_name, size, NETDEV_PING_RECV_TIMEO, &ping_resp, isbind);
1374         if (ret == -RT_ETIMEOUT)
1375         {
1376             rt_kprintf("ping: from %s icmp_seq=%d timeout\n",
1377                 (ip_addr_isany(&(ping_resp.ip_addr))) ? target_name : inet_ntoa(ping_resp.ip_addr), index + 1);
1378         }
1379         else if (ret == -RT_ERROR)
1380         {
1381             rt_kprintf("ping: unknown %s %s\n",
1382                 (ip_addr_isany(&(ping_resp.ip_addr))) ? "host" : "address",
1383                     (ip_addr_isany(&(ping_resp.ip_addr))) ? target_name : inet_ntoa(ping_resp.ip_addr));
1384         }
1385         else
1386         {
1387             if (ping_resp.ttl == 0)
1388             {
1389                 rt_kprintf("%d bytes from %s icmp_seq=%d time=%d ms\n",
1390                             ping_resp.data_len, inet_ntoa(ping_resp.ip_addr), index + 1, ping_resp.ticks);
1391             }
1392             else
1393             {
1394                 rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n",
1395                             ping_resp.data_len, inet_ntoa(ping_resp.ip_addr), index + 1, ping_resp.ttl, ping_resp.ticks);
1396             }
1397             received += 1;
1398             if (ping_resp.ticks > max_time)
1399             {
1400                 max_time = ping_resp.ticks;
1401             }
1402             else if (ping_resp.ticks < min_time)
1403             {
1404                 min_time = ping_resp.ticks;
1405             }
1406             avg_time += ping_resp.ticks;
1407         }
1408 
1409         /* if the response time is more than NETDEV_PING_DELAY, no need to delay */
1410         delay_tick = ((rt_tick_get() - start_tick) > NETDEV_PING_DELAY) || (index == times) ? 0 : NETDEV_PING_DELAY;
1411         rt_thread_delay(delay_tick);
1412     }
1413 
1414     /* print ping statistics */
1415     loss = (uint32_t)((1 - ((float)received) / index) * 100);
1416     avg_time = (uint32_t)(avg_time / received);
1417 #if NETDEV_IPV4 && NETDEV_IPV6
1418     if (IP_IS_V4_VAL(&ping_resp.ip_addr))
1419     {
1420         rt_kprintf("\n--- %s ping statistics ---\n", inet_ntoa(*ip_2_ip4(&ping_resp.ip_addr)));
1421     }
1422     else
1423     {
1424         rt_kprintf("\n--- %s ping statistics ---\n", inet6_ntoa(*ip_2_ip6(&ping_resp.ip_addr)));
1425     }
1426 #elif NETDEV_IPV4
1427     rt_kprintf("\n--- %s ping statistics ---\n", inet_ntoa(ping_resp.ip_addr));
1428 #elif NETDEV_IPV6
1429     rt_kprintf("\n--- %s ping statistics ---\n", inet6_ntoa(ping_resp.ip_addr));
1430 #endif
1431     rt_kprintf("%d packets transmitted, %d received, %d%% packet loss\n", index, received, loss);
1432     if (received > 0)
1433     {
1434         rt_kprintf("minimum = %dms, maximum = %dms, average = %dms\n", min_time, max_time, avg_time);
1435     }
1436 
1437     return RT_EOK;
1438 }
1439 
netdev_ping(int argc,char ** argv)1440 int netdev_ping(int argc, char **argv)
1441 {
1442     if (argc == 1)
1443     {
1444         rt_kprintf("Please input: ping <host address> [netdev name] [times] [data size]\n");
1445     }
1446     else if (argc == 2)
1447     {
1448         netdev_cmd_ping(argv[1], RT_NULL, 4, 0);
1449     }
1450     else if (argc == 3)
1451     {
1452         netdev_cmd_ping(argv[1], argv[2], 4, 0);
1453     }
1454     else if (argc == 4)
1455     {
1456         netdev_cmd_ping(argv[1], argv[2], atoi(argv[3]), 0);
1457     }
1458     else if (argc == 5)
1459     {
1460         netdev_cmd_ping(argv[1], argv[2], atoi(argv[3]), atoi(argv[4]));
1461     }
1462 
1463     return 0;
1464 }
1465 MSH_CMD_EXPORT_ALIAS(netdev_ping, ping, ping network host);
1466 #endif /* NETDEV_USING_PING */
1467 
netdev_list_dns(void)1468 static void netdev_list_dns(void)
1469 {
1470     unsigned int index = 0;
1471     struct netdev *netdev = RT_NULL;
1472     rt_slist_t *node  = RT_NULL;
1473 
1474     for (node = &(netdev_list->list); node; node = rt_slist_next(node))
1475     {
1476         netdev = rt_list_entry(node, struct netdev, list);
1477 
1478         rt_kprintf("network interface device: %.*s%s\n",
1479                 RT_NAME_MAX, netdev->name,
1480                 (netdev == netdev_default)?" (Default)":"");
1481 
1482         for(index = 0; index < NETDEV_DNS_SERVERS_NUM; index++)
1483         {
1484             rt_kprintf("dns server #%d: %s\n", index, inet_ntoa(netdev->dns_servers[index]));
1485         }
1486 
1487         if (rt_slist_next(node))
1488         {
1489             rt_kprintf("\n");
1490         }
1491     }
1492 }
1493 
netdev_dns(int argc,char ** argv)1494 int netdev_dns(int argc, char **argv)
1495 {
1496     if (argc == 1)
1497     {
1498         netdev_list_dns();
1499     }
1500     else if (argc == 3)
1501     {
1502         netdev_set_dns(argv[1], 0, argv[2]);
1503     }
1504     else if (argc == 4)
1505     {
1506         netdev_set_dns(argv[1], atoi(argv[2]), argv[3]);
1507     }
1508     else
1509     {
1510         rt_kprintf("bad parameter! input: dns <netdev_name> [dns_num] <dns_server>\n");
1511         return -1;
1512     }
1513 
1514     return 0;
1515 }
1516 MSH_CMD_EXPORT_ALIAS(netdev_dns, dns, list and set the information of dns);
1517 
1518 #ifdef NETDEV_USING_NETSTAT
netdev_cmd_netstat(void)1519 static void netdev_cmd_netstat(void)
1520 {
1521     rt_slist_t *node  = RT_NULL;
1522     struct netdev *netdev = RT_NULL;
1523     struct netdev *cur_netdev_list = netdev_list;
1524 
1525     if (cur_netdev_list == RT_NULL)
1526     {
1527         rt_kprintf("netstat: network interface device list error.\n");
1528         return;
1529     }
1530 
1531     for (node = &(cur_netdev_list->list); node; node = rt_slist_next(node))
1532     {
1533         netdev = rt_list_entry(node, struct netdev, list);
1534 
1535         if (netdev && netdev->ops && netdev->ops->netstat)
1536         {
1537             break;
1538         }
1539     }
1540 
1541     if (netdev->ops->netstat != RT_NULL)
1542     {
1543         netdev->ops->netstat(netdev);
1544     }
1545     else
1546     {
1547         rt_kprintf("netstat: this command is not supported!\n");
1548     }
1549 }
1550 
netdev_netstat(int argc,char ** argv)1551 int netdev_netstat(int argc, char **argv)
1552 {
1553     if (argc != 1)
1554     {
1555         rt_kprintf("Please input: netstat \n");
1556     }
1557     else
1558     {
1559         netdev_cmd_netstat();
1560     }
1561 
1562     return 0;
1563 }
1564 MSH_CMD_EXPORT_ALIAS(netdev_netstat, netstat, list the information of TCP / IP);
1565 #endif /* NETDEV_USING_NETSTAT */
1566 
1567 #endif /* RT_USING_FINSH */
1568