xref: /OK3568_Linux_fs/app/forlinx/quectelCM/libmnl/ifutils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* This example is placed in the public domain. */
2 #include <netinet/in.h>
3 #include <arpa/inet.h>
4 #include <time.h>
5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <strings.h>
10 #include <net/if.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <sys/fcntl.h>
14 #include <sys/ioctl.h>
15 
16 #include <linux/if_link.h>
17 #include <linux/if_ether.h>
18 #include <linux/rtnetlink.h>
19 #include <linux/if.h>
20 
21 #include "libmnl.h"
22 #include "ifutils.h"
23 
24 #define ERRMSG(v...) printf("%s-%d: error=%s %s\n", __func__, __LINE__, strerror(errno), ##v)
25 
mask_to_prefix_v4(uint32_t mask)26 int mask_to_prefix_v4(uint32_t mask)
27 {
28     int ret = 0;
29     while (mask)
30     {
31         mask = mask & (mask - 1);
32         ret++;
33     }
34     return ret;
35 }
36 
ipaddr_to_string_v4(in_addr_t ipaddr)37 const char *ipaddr_to_string_v4(in_addr_t ipaddr)
38 {
39     static char buf[INET6_ADDRSTRLEN] = {'\0'};
40     buf[0] = '\0';
41     uint32_t addr = ipaddr;
42     return inet_ntop(AF_INET, &addr, buf, sizeof(buf));
43 }
44 
ipaddr_to_string_v6(uint8_t * ipaddr)45 const char *ipaddr_to_string_v6(uint8_t *ipaddr)
46 {
47     static char buf[INET6_ADDRSTRLEN] = {'\0'};
48     buf[0] = '\0';
49     return inet_ntop(AF_INET6, ipaddr, buf, sizeof(buf));
50 }
51 
ifc_init_ifr(const char * name,struct ifreq * ifr)52 static void ifc_init_ifr(const char *name, struct ifreq *ifr)
53 {
54     memset(ifr, 0, sizeof(struct ifreq));
55     strncpy(ifr->ifr_name, name, IFNAMSIZ);
56     ifr->ifr_name[IFNAMSIZ - 1] = 0;
57 }
58 
if_get_hwaddr(const char * name,void * ptr)59 int if_get_hwaddr(const char *name, void *ptr)
60 {
61     int r;
62     struct ifreq ifr;
63     ifc_init_ifr(name, &ifr);
64 
65     int ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
66     if (ifc_ctl_sock < 0)
67     {
68         return -1;
69     }
70     r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
71     if (r < 0)
72         return -1;
73 
74     memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
75     return 0;
76 }
77 
if_act_on_link(const char * ifname,int state)78 static int if_act_on_link(const char *ifname, int state)
79 {
80     struct mnl_socket *nl;
81     char buf[MNL_SOCKET_BUFFER_SIZE];
82     struct nlmsghdr *nlh;
83     struct ifinfomsg *ifm;
84     int ret;
85     unsigned int seq, portid, change = 0, flags = 0;
86     static int oldstate = -1;
87 
88     if (state == oldstate)
89         return 0;
90     oldstate = state;
91 
92     if (state)
93     {
94         change |= IFF_UP;
95         flags |= IFF_UP;
96     }
97     else
98     {
99         change |= IFF_UP;
100         flags &= ~IFF_UP;
101     }
102 
103     nlh = mnl_nlmsg_put_header(buf);
104     nlh->nlmsg_type = RTM_NEWLINK;
105     nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
106     nlh->nlmsg_seq = seq = time(NULL);
107     ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
108     ifm->ifi_family = AF_UNSPEC;
109     ifm->ifi_change = change;
110     ifm->ifi_flags = flags;
111 
112     mnl_attr_put_str(nlh, IFLA_IFNAME, ifname);
113 
114     nl = mnl_socket_open(NETLINK_ROUTE);
115     if (nl == NULL)
116     {
117         ERRMSG("mnl_socket_open");
118         return -1;
119     }
120 
121     if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
122     {
123         ERRMSG(" mnl_socket_bind");
124         return -1;
125     }
126     portid = mnl_socket_get_portid(nl);
127 
128     if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
129     {
130         ERRMSG(" mnl_socket_sendto");
131         return -1;
132     }
133 
134     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
135     if (ret == -1)
136     {
137         ERRMSG(" mnl_socket_recvfrom");
138         return -1;
139     }
140 
141     ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
142     if (ret == -1)
143     {
144         ERRMSG(" mnl_cb_run");
145         return -1;
146     }
147 
148     mnl_socket_close(nl);
149 
150     return 0;
151 }
152 
if_link_up(const char * ifname)153 int if_link_up(const char *ifname)
154 {
155     return if_act_on_link(ifname, 1);
156 }
157 
if_link_down(const char * ifname)158 int if_link_down(const char *ifname)
159 {
160     return if_act_on_link(ifname, 0);
161 }
162 
if_set_mtu(const char * ifname,uint32_t mtu)163 int if_set_mtu(const char *ifname, uint32_t mtu)
164 {
165     char buf[MNL_SOCKET_BUFFER_SIZE];
166     unsigned int seq, portid;
167     struct mnl_socket *nl;
168     struct nlmsghdr *nlh;
169     struct ifinfomsg *ifm;
170     int ret;
171     int iface;
172     static uint32_t oldmtu = 1500;
173 
174     if (mtu == oldmtu)
175         return 0;
176     oldmtu = mtu;
177 
178     iface = if_nametoindex(ifname);
179     if (iface == 0)
180     {
181         ERRMSG(" if_nametoindex");
182         return -1;
183     }
184 
185     nlh = mnl_nlmsg_put_header(buf);
186     nlh->nlmsg_type = RTM_NEWLINK;
187     nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
188     nlh->nlmsg_seq = seq = time(NULL);
189     ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifinfomsg));
190     ifm->ifi_family = AF_UNSPEC;
191     ifm->ifi_index = iface;
192     ifm->ifi_change = 0xFFFFFFFF;
193     ifm->ifi_type = ifm->ifi_flags = 0;
194 
195     mnl_attr_put_u32(nlh, IFLA_MTU, mtu);
196 
197     nl = mnl_socket_open(NETLINK_ROUTE);
198     if (nl == NULL)
199     {
200         ERRMSG(" mnl_socket_open");
201         return -1;
202     }
203 
204     if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
205     {
206         ERRMSG(" mnl_socket_bind");
207         return -1;
208     }
209     portid = mnl_socket_get_portid(nl);
210 
211     if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
212     {
213         ERRMSG(" mnl_socket_sendto");
214         return -1;
215     }
216 
217     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
218     if (ret == -1)
219     {
220         ERRMSG(" mnl_socket_recvfrom");
221         return -1;
222     }
223 
224     ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
225     if (ret == -1)
226     {
227         ERRMSG(" mnl_cb_run");
228         return -1;
229     }
230 
231     mnl_socket_close(nl);
232 
233     return 0;
234 }
235 
236 /**
237  * @brief Set the ip addr object
238  *
239  * @param operate
240  *  0 -> add address on interface
241  *  1 -> delete address on interface
242  * @param ifname
243  * @param ipaddr
244  * @param prefix
245  * @return int
246  */
if_act_on_addr(bool operate,int proto,const char * ifname,addr_t * ipaddr,uint32_t prefix)247 static int if_act_on_addr(bool operate, int proto, const char *ifname, addr_t *ipaddr, uint32_t prefix)
248 {
249     struct mnl_socket *nl;
250     char buf[MNL_SOCKET_BUFFER_SIZE];
251     struct nlmsghdr *nlh;
252     struct ifaddrmsg *ifm;
253     uint32_t seq, portid;
254     int ret, family = proto;
255 
256     int iface;
257 
258     iface = if_nametoindex(ifname);
259     if (iface == 0)
260     {
261         ERRMSG(" if_nametoindex");
262         return -1;
263     }
264 
265     nlh = mnl_nlmsg_put_header(buf);
266     if (operate)
267         nlh->nlmsg_type = RTM_NEWADDR;
268     else
269         nlh->nlmsg_type = RTM_DELADDR;
270 
271     nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE | NLM_F_ACK;
272     nlh->nlmsg_seq = seq = time(NULL);
273 
274     ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct ifaddrmsg));
275 
276     ifm->ifa_family = family;
277     ifm->ifa_prefixlen = prefix;
278     ifm->ifa_flags = IFA_F_PERMANENT;
279 
280     ifm->ifa_scope = RT_SCOPE_UNIVERSE;
281     ifm->ifa_index = iface;
282 
283     /*
284 	 * The exact meaning of IFA_LOCAL and IFA_ADDRESS depend
285 	 * on the address family being used and the device type.
286 	 * For broadcast devices (like the interfaces we use),
287 	 * for IPv4 we specify both and they are used interchangeably.
288 	 * For IPv6, only IFA_ADDRESS needs to be set.
289 	 */
290     if (family == AF_INET)
291     {
292         mnl_attr_put_u32(nlh, IFA_LOCAL, ipaddr->ip);
293         mnl_attr_put_u32(nlh, IFA_ADDRESS, ipaddr->ip);
294     }
295     else
296     {
297         mnl_attr_put(nlh, IFA_ADDRESS, sizeof(struct in6_addr), ipaddr);
298     }
299 
300     nl = mnl_socket_open(NETLINK_ROUTE);
301     if (nl == NULL)
302     {
303         ERRMSG(" mnl_socket_open");
304         return -1;
305     }
306 
307     if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
308     {
309         ERRMSG(" mnl_socket_bind");
310         return -1;
311     }
312     portid = mnl_socket_get_portid(nl);
313 
314     if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
315     {
316         ERRMSG(" mnl_socket_sendto");
317         return -1;
318     }
319 
320     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
321     if (ret < 0)
322     {
323         ERRMSG(" mnl_socket_recvfrom");
324         return -1;
325     }
326 
327     ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
328     if (ret < 0)
329     {
330         ERRMSG(" mnl_cb_run");
331         return -1;
332     }
333 
334     mnl_socket_close(nl);
335 
336     return 0;
337 }
338 
if_set_addr_v4(const char * ifname,in_addr_t ipaddr,uint32_t prefix)339 int if_set_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix)
340 {
341     addr_t addr;
342     addr.ip = ipaddr;
343     return if_act_on_addr(1, AF_INET, ifname, &addr, prefix);
344 }
345 
if_del_addr_v4(const char * ifname,in_addr_t ipaddr,uint32_t prefix)346 int if_del_addr_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix)
347 {
348     addr_t addr;
349     addr.ip = ipaddr;
350     return if_act_on_addr(0, AF_INET, ifname, &addr, prefix);
351 }
352 
if_set_addr_v6(const char * ifname,uint8_t * ipaddr,uint32_t prefix)353 int if_set_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix)
354 {
355     addr_t addr;
356     memcpy(&addr.ip6, ipaddr, 16);
357     return if_act_on_addr(1, AF_INET6, ifname, &addr, prefix);
358 }
359 
if_del_addr_v6(const char * ifname,uint8_t * ipaddr,uint32_t prefix)360 int if_del_addr_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix)
361 {
362     addr_t addr;
363     memcpy(&addr.ip6, ipaddr, 16);
364     return if_act_on_addr(0, AF_INET6, ifname, &addr, prefix);
365 }
366 
data_attr_cb(const struct nlattr * attr,void * data)367 static int data_attr_cb(const struct nlattr *attr, void *data)
368 {
369     const struct nlattr **tb = data;
370     int type = mnl_attr_get_type(attr);
371 
372     /* skip unsupported attribute in user-space */
373     if (mnl_attr_type_valid(attr, IFA_MAX) < 0)
374         return MNL_CB_OK;
375 
376     switch (type)
377     {
378     case IFA_ADDRESS:
379         if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
380         {
381             ERRMSG(" mnl_attr_validate");
382             return MNL_CB_ERROR;
383         }
384         break;
385     }
386     tb[type] = attr;
387     return MNL_CB_OK;
388 }
389 
data_cb(const struct nlmsghdr * nlh,void * data)390 static int data_cb(const struct nlmsghdr *nlh, void *data)
391 {
392     struct nlattr *tb[IFA_MAX + 1] = {};
393     struct ifaddrmsg *ifa = mnl_nlmsg_get_payload(nlh);
394     struct addrinfo_t *addrinfo = (struct addrinfo_t *)data;
395     void *addr = NULL;
396 
397     mnl_attr_parse(nlh, sizeof(*ifa), data_attr_cb, tb);
398     if (tb[IFA_ADDRESS])
399     {
400         char out[INET6_ADDRSTRLEN];
401 
402         addr = mnl_attr_get_payload(tb[IFLA_ADDRESS]);
403         addr = mnl_attr_get_payload(tb[IFA_ADDRESS]);
404         if (!inet_ntop(ifa->ifa_family, addr, out, sizeof(out)))
405             ERRMSG("inet_ntop");
406         // printf("%d %d-> %d %s\n", addrinfo->iface, ifa->ifa_index, ifa->ifa_scope, out);
407 
408         addrinfo->addrs[addrinfo->num].prefix = ifa->ifa_prefixlen;
409         if (ifa->ifa_index == (unsigned int)addrinfo->iface)
410         {
411             if (ifa->ifa_family == AF_INET6)
412                 memcpy(addrinfo->addrs[addrinfo->num].address.ip6.s6_addr, addr, 16);
413             if (ifa->ifa_family == AF_INET)
414                 memcpy(&(addrinfo->addrs[addrinfo->num].address.ip), addr, 4);
415             addrinfo->num++;
416         }
417     }
418 
419     // ifa->ifa_scope
420     // 0: global
421     // 200: site
422     // 253: link
423     // 254: host
424     // 255: nowhere
425 
426     return MNL_CB_OK;
427 }
428 
429 /**
430  * @brief
431  *
432  * @param ifname
433  * @param proto
434  *  AF_INET -> for IPv4
435  *  AF_INET6 -> for IPv6
436  * @return int
437  */
if_get_addr(const char * ifname,int proto,struct addrinfo_t * addrinfo)438 static int if_get_addr(const char *ifname, int proto, struct addrinfo_t *addrinfo)
439 {
440     char buf[MNL_SOCKET_BUFFER_SIZE];
441     unsigned int seq, portid;
442     struct mnl_socket *nl;
443     struct nlmsghdr *nlh;
444     struct rtgenmsg *rt;
445     int ret;
446 
447     addrinfo->iface = if_nametoindex(ifname);
448     if (addrinfo->iface == 0)
449     {
450         ERRMSG(" if_nametoindex");
451         return -1;
452     }
453 
454     nlh = mnl_nlmsg_put_header(buf);
455     nlh->nlmsg_type = RTM_GETADDR;
456     nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
457     nlh->nlmsg_seq = seq = time(NULL);
458     rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
459     if (proto == AF_INET)
460         rt->rtgen_family = AF_INET;
461     else if (proto == AF_INET6)
462         rt->rtgen_family = AF_INET6;
463 
464     nl = mnl_socket_open(NETLINK_ROUTE);
465     if (nl == NULL)
466     {
467         ERRMSG(" mnl_socket_open");
468         return -1;
469     }
470 
471     if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
472     {
473         ERRMSG(" mnl_socket_bind");
474         return -1;
475     }
476     portid = mnl_socket_get_portid(nl);
477 
478     if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
479     {
480         ERRMSG(" mnl_socket_sendto");
481         return -1;
482     }
483 
484     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
485     while (ret > 0)
486     {
487         ret = mnl_cb_run(buf, ret, seq, portid, data_cb, addrinfo);
488         if (ret <= MNL_CB_STOP)
489             break;
490         ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
491     }
492     if (ret == -1)
493     {
494         ERRMSG(" error");
495         return -1;
496     }
497     mnl_socket_close(nl);
498 
499     return 0;
500 }
501 
if_flush_v4_addr(const char * ifname)502 int if_flush_v4_addr(const char *ifname)
503 {
504     struct addrinfo_t addrinfo;
505     int i = 0;
506 
507     memset(&addrinfo, 0, sizeof(struct addrinfo_t));
508     if_get_addr(ifname, AF_INET, &addrinfo);
509     for (; i < addrinfo.num; i++)
510     {
511         // printf("remove address: %s\n", ipaddr_to_string_v4(addrinfo.addrs[i].address.ip));
512         if_del_addr_v4(ifname, addrinfo.addrs[i].address.ip, addrinfo.addrs[i].prefix);
513     }
514     return 0;
515 }
516 
if_flush_v6_addr(const char * ifname)517 int if_flush_v6_addr(const char *ifname)
518 {
519     struct addrinfo_t addrinfo;
520     int i = 0;
521 
522     memset(&addrinfo, 0, sizeof(struct addrinfo_t));
523     if_get_addr(ifname, AF_INET6, &addrinfo);
524     for (; i < addrinfo.num; i++)
525     {
526         // printf("remove address: %s\n", ipaddr_to_string_v6(addrinfo.addrs[i].address.ip6.s6_addr));
527         if_del_addr_v6(ifname, addrinfo.addrs[i].address.ip6.s6_addr, addrinfo.addrs[i].prefix);
528     }
529     return 0;
530 }
531 
532 /**
533  * @brief Set the route addr object
534  *   Usage:
535  *      iface destination cidr [gateway]
536  *   Example:
537  *      eth0 10.0.1.12 32 10.0.1.11
538  *      eth0 ffff::10.0.1.12 128 fdff::1
539  * @param operate
540  *  add or del
541  * @param ifname
542  * @param dstaddr
543  * @param prefix
544  * @param gwaddr
545  * @return int
546  */
if_act_on_route(bool operate,int proto,const char * ifname,addr_t * dstaddr,uint32_t prefix,addr_t * gwaddr)547 int if_act_on_route(bool operate, int proto, const char *ifname, addr_t *dstaddr, uint32_t prefix, addr_t *gwaddr)
548 {
549     struct mnl_socket *nl;
550     char buf[MNL_SOCKET_BUFFER_SIZE];
551     struct nlmsghdr *nlh;
552     struct rtmsg *rtm;
553     uint32_t seq, portid;
554     int iface, ret, family = proto;
555 
556     iface = if_nametoindex(ifname);
557     if (iface == 0)
558     {
559         ERRMSG(" if_nametoindex");
560         return -1;
561     }
562 
563     nlh = mnl_nlmsg_put_header(buf);
564     if (operate)
565         nlh->nlmsg_type = RTM_NEWROUTE;
566     else
567         nlh->nlmsg_type = RTM_DELROUTE;
568 
569     nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
570     nlh->nlmsg_seq = seq = time(NULL);
571 
572     rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
573     rtm->rtm_family = family;
574     rtm->rtm_dst_len = prefix;
575     rtm->rtm_src_len = 0;
576     rtm->rtm_tos = 0;
577     rtm->rtm_protocol = RTPROT_STATIC;
578     rtm->rtm_table = RT_TABLE_MAIN;
579     rtm->rtm_type = RTN_UNICAST;
580     /* is there any gateway? */
581     rtm->rtm_scope = gwaddr ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
582     rtm->rtm_flags = 0;
583 
584     if (family == AF_INET)
585         mnl_attr_put_u32(nlh, RTA_DST, dstaddr->ip);
586     else
587         mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), dstaddr);
588 
589     mnl_attr_put_u32(nlh, RTA_OIF, iface);
590     if (gwaddr)
591     {
592         if (family == AF_INET)
593             mnl_attr_put_u32(nlh, RTA_GATEWAY, gwaddr->ip);
594         else
595         {
596             mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr), gwaddr);
597         }
598     }
599 
600     nl = mnl_socket_open(NETLINK_ROUTE);
601     if (nl == NULL)
602     {
603         ERRMSG(" mnl_socket_open");
604         return -1;
605     }
606 
607     if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
608     {
609         ERRMSG(" mnl_socket_bind");
610         return -1;
611     }
612     portid = mnl_socket_get_portid(nl);
613 
614     if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
615     {
616         ERRMSG(" mnl_socket_sendto");
617         return -1;
618     }
619 
620     ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
621     if (ret < 0)
622     {
623         ERRMSG(" mnl_socket_recvfrom");
624         return -1;
625     }
626 
627     ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
628     if (ret < 0)
629     {
630         ERRMSG(" mnl_cb_run");
631         return -1;
632     }
633 
634     mnl_socket_close(nl);
635 
636     return 0;
637 }
638 
if_set_default_route_v4(const char * ifname)639 int if_set_default_route_v4(const char *ifname)
640 {
641     return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL);
642 }
643 
if_del_default_route_v4(const char * ifname)644 int if_del_default_route_v4(const char *ifname)
645 {
646     return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, NULL);
647 }
648 
if_set_default_route_v6(const char * ifname)649 int if_set_default_route_v6(const char *ifname)
650 {
651     return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL);
652 }
653 
if_del_default_route_v6(const char * ifname)654 int if_del_default_route_v6(const char *ifname)
655 {
656     return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, NULL);
657 }
658 
659 /**
660  * @brief Set the default gwaddr object
661  *  set default gw
662  * @param operate
663  * @param ifname
664  * @param gwaddr
665  *  gateway ip
666  * @return int
667  */
if_set_route_gw_v4(const char * ifname,in_addr_t gwaddr)668 int if_set_route_gw_v4(const char *ifname, in_addr_t gwaddr)
669 {
670     addr_t addr;
671     memset(&addr, 0, sizeof(addr_t));
672     addr.ip = gwaddr;
673     return if_act_on_route(1, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr);
674 }
675 
if_del_route_gw_v4(const char * ifname,in_addr_t gwaddr)676 int if_del_route_gw_v4(const char *ifname, in_addr_t gwaddr)
677 {
678     addr_t addr;
679     memset(&addr, 0, sizeof(addr_t));
680     addr.ip = gwaddr;
681     return if_act_on_route(0, AF_INET, ifname, (addr_t *)&in6addr_any, 0, &addr);
682 }
683 
if_set_route_gw_v6(const char * ifname,uint8_t * gwaddr)684 int if_set_route_gw_v6(const char *ifname, uint8_t *gwaddr)
685 {
686     addr_t addr;
687     memset(&addr, 0, sizeof(addr_t));
688     memcpy(&addr.ip6, gwaddr, 16);
689     return if_act_on_route(1, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr);
690 }
691 
if_del_route_gw_v6(const char * ifname,uint8_t * gwaddr)692 int if_del_route_gw_v6(const char *ifname, uint8_t *gwaddr)
693 {
694     addr_t addr;
695     memset(&addr, 0, sizeof(addr_t));
696     memcpy(&addr.ip6, gwaddr, 16);
697     return if_act_on_route(0, AF_INET6, ifname, (addr_t *)&in6addr_any, 0, &addr);
698 }
699 
if_set_dns(const char * dns1,const char * dns2)700 int if_set_dns(const char *dns1, const char *dns2)
701 {
702     int ret = 0;
703     char buf[128] = {'\0'};
704     int fd = open("/etc/resolv.conf", O_CREAT | O_WRONLY | O_TRUNC);
705     if (fd < 0)
706     {
707         ERRMSG(" fail to open /etc/resolv.conf");
708         return -1;
709     }
710 
711     if (dns1)
712         snprintf(buf, sizeof(buf), "nameserver %s\n", dns1);
713     if (dns2)
714         snprintf(buf, sizeof(buf), "nameserver %s\n", dns2);
715     ret = write(fd, buf, strlen(buf));
716     if (ret < 0)
717     {
718         ERRMSG(" write dns");
719     }
720     close(fd);
721     return ret > 0 ? 0 : -1;
722 }
723 
if_set_network_v4(const char * ifname,in_addr_t ipaddr,uint32_t prefix,in_addr_t gwaddr,in_addr_t dns1,in_addr_t dns2)724 int if_set_network_v4(const char *ifname, in_addr_t ipaddr, uint32_t prefix,
725                       in_addr_t gwaddr, in_addr_t dns1, in_addr_t dns2)
726 {
727     (void)gwaddr;
728     if_link_up(ifname);
729     if_set_addr_v4(ifname, ipaddr, prefix);
730     if_set_default_route_v4(ifname);
731     if_set_dns(ipaddr_to_string_v4(dns1), ipaddr_to_string_v4(dns2));
732     return 0;
733 }
734 
if_set_network_v6(const char * ifname,uint8_t * ipaddr,uint32_t prefix,uint8_t * gwaddr,uint8_t * dns1,uint8_t * dns2)735 int if_set_network_v6(const char *ifname, uint8_t *ipaddr, uint32_t prefix,
736                       uint8_t *gwaddr, uint8_t *dns1, uint8_t *dns2)
737 {
738     (void)gwaddr;
739     if_link_up(ifname);
740     if_set_addr_v6(ifname, ipaddr, prefix);
741     if_set_default_route_v6(ifname);
742     if_set_dns(ipaddr_to_string_v6(dns1), ipaddr_to_string_v6(dns2));
743     return 0;
744 }