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 }