You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

741 lines
18 KiB

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