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