1ec214349SKristof Provost /*
2ec214349SKristof Provost * Copyright (c) 1983, 1993
3ec214349SKristof Provost * The Regents of the University of California. All rights reserved.
4b1d757bcSAlan Somers * Copyright (c) 2016-2017, Marie Helene Kvello-Aune. All rights reserved.
5ec214349SKristof Provost *
6ec214349SKristof Provost * Redistribution and use in source and binary forms, with or without
7ec214349SKristof Provost * modification, are permitted provided that the following conditions
8ec214349SKristof Provost * are met:
9ec214349SKristof Provost * 1. Redistributions of source code must retain the above copyright
10ec214349SKristof Provost * notice, this list of conditions and the following disclaimer.
11ec214349SKristof Provost * 2. Redistributions in binary form must reproduce the above copyright
12ec214349SKristof Provost * notice, this list of conditions and the following disclaimer in the
13ec214349SKristof Provost * documentation and/or other materials provided with the distribution.
14fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
15ec214349SKristof Provost * may be used to endorse or promote products derived from this software
16ec214349SKristof Provost * without specific prior written permission.
17ec214349SKristof Provost *
18ec214349SKristof Provost * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19ec214349SKristof Provost * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ec214349SKristof Provost * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ec214349SKristof Provost * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22ec214349SKristof Provost * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ec214349SKristof Provost * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ec214349SKristof Provost * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ec214349SKristof Provost * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ec214349SKristof Provost * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ec214349SKristof Provost * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ec214349SKristof Provost * SUCH DAMAGE.
29ec214349SKristof Provost */
30ec214349SKristof Provost
31c2803f1aSAndriy Voskoboinyk #include <sys/types.h>
32ec214349SKristof Provost #include <sys/ioctl.h>
33c2803f1aSAndriy Voskoboinyk #include <sys/sysctl.h>
34ec214349SKristof Provost
35ec214349SKristof Provost #include <net/if.h>
36c2803f1aSAndriy Voskoboinyk #include <net/if_mib.h>
37b1d757bcSAlan Somers #include <netinet/in.h>
38b1d757bcSAlan Somers #include <netinet6/in6_var.h>
39b1d757bcSAlan Somers #include <netinet6/nd6.h>
40ec214349SKristof Provost
41ec214349SKristof Provost #include <err.h>
42ec214349SKristof Provost #include <errno.h>
43ec214349SKristof Provost #include <fcntl.h>
44b1d757bcSAlan Somers #include <ifaddrs.h>
45b1d757bcSAlan Somers #include <stdbool.h>
46ec214349SKristof Provost #include <stdio.h>
47ec214349SKristof Provost #include <stdlib.h>
48ec214349SKristof Provost #include <string.h>
49ec214349SKristof Provost #include <unistd.h>
50ec214349SKristof Provost
51b1d757bcSAlan Somers #include <net/if_vlan_var.h>
52b1d757bcSAlan Somers
53ec214349SKristof Provost #include "libifconfig.h"
54ec214349SKristof Provost #include "libifconfig_internal.h"
55ec214349SKristof Provost
56b1d757bcSAlan Somers #define NOTAG ((u_short) -1)
57b1d757bcSAlan Somers
58b1d757bcSAlan Somers static bool
isnd6defif(ifconfig_handle_t * h,const char * name)59b1d757bcSAlan Somers isnd6defif(ifconfig_handle_t *h, const char *name)
60b1d757bcSAlan Somers {
61b1d757bcSAlan Somers struct in6_ndifreq ndifreq;
62b1d757bcSAlan Somers unsigned int ifindex;
63b1d757bcSAlan Somers
64b1d757bcSAlan Somers memset(&ndifreq, 0, sizeof(ndifreq));
65b1d757bcSAlan Somers strlcpy(ndifreq.ifname, name, sizeof(ndifreq.ifname));
66b1d757bcSAlan Somers ifindex = if_nametoindex(ndifreq.ifname);
67b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_INET6, SIOCGDEFIFACE_IN6, &ndifreq) < 0) {
68b1d757bcSAlan Somers return (false);
69b1d757bcSAlan Somers }
70b1d757bcSAlan Somers h->error.errtype = OK;
71b1d757bcSAlan Somers return (ndifreq.ifindex == ifindex);
72b1d757bcSAlan Somers }
73ec214349SKristof Provost
74ec214349SKristof Provost ifconfig_handle_t *
ifconfig_open(void)75ec214349SKristof Provost ifconfig_open(void)
76ec214349SKristof Provost {
77b1d757bcSAlan Somers ifconfig_handle_t *h;
78ec214349SKristof Provost
799a2ff315SKristof Provost h = calloc(1, sizeof(*h));
80b1d757bcSAlan Somers
81b1d757bcSAlan Somers if (h == NULL) {
82b1d757bcSAlan Somers return (NULL);
83b1d757bcSAlan Somers }
84ec214349SKristof Provost for (int i = 0; i <= AF_MAX; i++) {
85ec214349SKristof Provost h->sockets[i] = -1;
86ec214349SKristof Provost }
87b1d757bcSAlan Somers
88ec214349SKristof Provost return (h);
89ec214349SKristof Provost }
90ec214349SKristof Provost
91ec214349SKristof Provost void
ifconfig_close(ifconfig_handle_t * h)92ec214349SKristof Provost ifconfig_close(ifconfig_handle_t *h)
93ec214349SKristof Provost {
949a2ff315SKristof Provost
95ec214349SKristof Provost for (int i = 0; i <= AF_MAX; i++) {
96ec214349SKristof Provost if (h->sockets[i] != -1) {
97ec214349SKristof Provost (void)close(h->sockets[i]);
98ec214349SKristof Provost }
99ec214349SKristof Provost }
100b1d757bcSAlan Somers freeifaddrs(h->ifap);
101ec214349SKristof Provost free(h);
102ec214349SKristof Provost }
103ec214349SKristof Provost
104ec214349SKristof Provost ifconfig_errtype
ifconfig_err_errtype(ifconfig_handle_t * h)105ec214349SKristof Provost ifconfig_err_errtype(ifconfig_handle_t *h)
106ec214349SKristof Provost {
1079a2ff315SKristof Provost
108ec214349SKristof Provost return (h->error.errtype);
109ec214349SKristof Provost }
110ec214349SKristof Provost
111ec214349SKristof Provost int
ifconfig_err_errno(ifconfig_handle_t * h)112ec214349SKristof Provost ifconfig_err_errno(ifconfig_handle_t *h)
113ec214349SKristof Provost {
1149a2ff315SKristof Provost
115ec214349SKristof Provost return (h->error.errcode);
116ec214349SKristof Provost }
117ec214349SKristof Provost
118ec214349SKristof Provost unsigned long
ifconfig_err_ioctlreq(ifconfig_handle_t * h)119ec214349SKristof Provost ifconfig_err_ioctlreq(ifconfig_handle_t *h)
120ec214349SKristof Provost {
1219a2ff315SKristof Provost
122ec214349SKristof Provost return (h->error.ioctl_request);
123ec214349SKristof Provost }
124ec214349SKristof Provost
125ec214349SKristof Provost int
ifconfig_foreach_iface(ifconfig_handle_t * h,ifconfig_foreach_func_t cb,void * udata)126b1d757bcSAlan Somers ifconfig_foreach_iface(ifconfig_handle_t *h,
127b1d757bcSAlan Somers ifconfig_foreach_func_t cb, void *udata)
128b1d757bcSAlan Somers {
129b1d757bcSAlan Somers int ret;
130b1d757bcSAlan Somers
131b1d757bcSAlan Somers ret = ifconfig_getifaddrs(h);
132b1d757bcSAlan Somers if (ret == 0) {
133b1d757bcSAlan Somers struct ifaddrs *ifa;
134b1d757bcSAlan Somers char *ifname = NULL;
135b1d757bcSAlan Somers
136b1d757bcSAlan Somers for (ifa = h->ifap; ifa; ifa = ifa->ifa_next) {
137b1d757bcSAlan Somers if (ifname != ifa->ifa_name) {
138b1d757bcSAlan Somers ifname = ifa->ifa_name;
139b1d757bcSAlan Somers cb(h, ifa, udata);
140b1d757bcSAlan Somers }
141b1d757bcSAlan Somers }
142b1d757bcSAlan Somers }
143b1d757bcSAlan Somers /* Free ifaddrs so we don't accidentally cache stale data */
144b1d757bcSAlan Somers freeifaddrs(h->ifap);
145b1d757bcSAlan Somers h->ifap = NULL;
146b1d757bcSAlan Somers
147b1d757bcSAlan Somers return (ret);
148b1d757bcSAlan Somers }
149b1d757bcSAlan Somers
150b1d757bcSAlan Somers void
ifconfig_foreach_ifaddr(ifconfig_handle_t * h,struct ifaddrs * ifa,ifconfig_foreach_func_t cb,void * udata)151b1d757bcSAlan Somers ifconfig_foreach_ifaddr(ifconfig_handle_t *h, struct ifaddrs *ifa,
152b1d757bcSAlan Somers ifconfig_foreach_func_t cb, void *udata)
153b1d757bcSAlan Somers {
154b1d757bcSAlan Somers struct ifaddrs *ift;
155b1d757bcSAlan Somers
156b1d757bcSAlan Somers for (ift = ifa;
157b1d757bcSAlan Somers ift != NULL &&
158b1d757bcSAlan Somers ift->ifa_addr != NULL &&
159b1d757bcSAlan Somers strcmp(ift->ifa_name, ifa->ifa_name) == 0;
160b1d757bcSAlan Somers ift = ift->ifa_next) {
161b1d757bcSAlan Somers cb(h, ift, udata);
162b1d757bcSAlan Somers }
163b1d757bcSAlan Somers }
164b1d757bcSAlan Somers
165b1d757bcSAlan Somers int
ifconfig_get_description(ifconfig_handle_t * h,const char * name,char ** description)1669a2ff315SKristof Provost ifconfig_get_description(ifconfig_handle_t *h, const char *name,
1679a2ff315SKristof Provost char **description)
168ec214349SKristof Provost {
169ec214349SKristof Provost struct ifreq ifr;
1709a2ff315SKristof Provost char *descr;
1719a2ff315SKristof Provost size_t descrlen;
172ec214349SKristof Provost
1739a2ff315SKristof Provost descr = NULL;
1749a2ff315SKristof Provost descrlen = 64;
1759a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
176ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1779a2ff315SKristof Provost
178ec214349SKristof Provost for (;;) {
179ec214349SKristof Provost if ((descr = reallocf(descr, descrlen)) == NULL) {
180ec214349SKristof Provost h->error.errtype = OTHER;
181ec214349SKristof Provost h->error.errcode = ENOMEM;
182ec214349SKristof Provost return (-1);
183ec214349SKristof Provost }
184ec214349SKristof Provost
185ec214349SKristof Provost ifr.ifr_buffer.buffer = descr;
186ec214349SKristof Provost ifr.ifr_buffer.length = descrlen;
1879a2ff315SKristof Provost if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDESCR, &ifr) != 0) {
188b1d757bcSAlan Somers free(descr);
189ec214349SKristof Provost return (-1);
190ec214349SKristof Provost }
191ec214349SKristof Provost
192ec214349SKristof Provost if (ifr.ifr_buffer.buffer == descr) {
193ec214349SKristof Provost if (strlen(descr) > 0) {
194ec214349SKristof Provost *description = strdup(descr);
195ec214349SKristof Provost free(descr);
196b1d757bcSAlan Somers
197b1d757bcSAlan Somers if (description == NULL) {
198b1d757bcSAlan Somers h->error.errtype = OTHER;
199b1d757bcSAlan Somers h->error.errcode = ENOMEM;
200b1d757bcSAlan Somers return (-1);
201b1d757bcSAlan Somers }
202b1d757bcSAlan Somers
203ec214349SKristof Provost return (0);
204ec214349SKristof Provost }
205ec214349SKristof Provost } else if (ifr.ifr_buffer.length > descrlen) {
206ec214349SKristof Provost descrlen = ifr.ifr_buffer.length;
207ec214349SKristof Provost continue;
208ec214349SKristof Provost }
209ec214349SKristof Provost break;
210ec214349SKristof Provost }
211ec214349SKristof Provost free(descr);
212ec214349SKristof Provost h->error.errtype = OTHER;
213ec214349SKristof Provost h->error.errcode = 0;
214ec214349SKristof Provost return (-1);
215ec214349SKristof Provost }
216ec214349SKristof Provost
217ec214349SKristof Provost int
ifconfig_set_description(ifconfig_handle_t * h,const char * name,const char * newdescription)218ec214349SKristof Provost ifconfig_set_description(ifconfig_handle_t *h, const char *name,
219ec214349SKristof Provost const char *newdescription)
220ec214349SKristof Provost {
221ec214349SKristof Provost struct ifreq ifr;
222ec214349SKristof Provost int desclen;
223ec214349SKristof Provost
2249a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
225ec214349SKristof Provost desclen = strlen(newdescription);
226ec214349SKristof Provost
227ec214349SKristof Provost /*
228ec214349SKristof Provost * Unset description if the new description is 0 characters long.
229ec214349SKristof Provost * TODO: Decide whether this should be an error condition instead.
230ec214349SKristof Provost */
231ec214349SKristof Provost if (desclen == 0) {
232ec214349SKristof Provost return (ifconfig_unset_description(h, name));
233ec214349SKristof Provost }
234ec214349SKristof Provost
235ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
236ec214349SKristof Provost ifr.ifr_buffer.length = desclen + 1;
237ec214349SKristof Provost ifr.ifr_buffer.buffer = strdup(newdescription);
2389a2ff315SKristof Provost
239ec214349SKristof Provost if (ifr.ifr_buffer.buffer == NULL) {
240ec214349SKristof Provost h->error.errtype = OTHER;
241ec214349SKristof Provost h->error.errcode = ENOMEM;
242ec214349SKristof Provost return (-1);
243ec214349SKristof Provost }
244ec214349SKristof Provost
245b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) != 0) {
246ec214349SKristof Provost free(ifr.ifr_buffer.buffer);
247ec214349SKristof Provost return (-1);
248ec214349SKristof Provost }
2499a2ff315SKristof Provost
250ec214349SKristof Provost free(ifr.ifr_buffer.buffer);
251ec214349SKristof Provost return (0);
252ec214349SKristof Provost }
253ec214349SKristof Provost
2549a2ff315SKristof Provost int
ifconfig_unset_description(ifconfig_handle_t * h,const char * name)2559a2ff315SKristof Provost ifconfig_unset_description(ifconfig_handle_t *h, const char *name)
256ec214349SKristof Provost {
257ec214349SKristof Provost struct ifreq ifr;
258ec214349SKristof Provost
2599a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
260ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
261ec214349SKristof Provost ifr.ifr_buffer.length = 0;
262ec214349SKristof Provost ifr.ifr_buffer.buffer = NULL;
263ec214349SKristof Provost
264b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) < 0) {
265ec214349SKristof Provost return (-1);
266ec214349SKristof Provost }
267ec214349SKristof Provost return (0);
268ec214349SKristof Provost }
269ec214349SKristof Provost
2709a2ff315SKristof Provost int
ifconfig_set_name(ifconfig_handle_t * h,const char * name,const char * newname)2719a2ff315SKristof Provost ifconfig_set_name(ifconfig_handle_t *h, const char *name, const char *newname)
272ec214349SKristof Provost {
273ec214349SKristof Provost struct ifreq ifr;
274ec214349SKristof Provost char *tmpname;
275ec214349SKristof Provost
2769a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
277ec214349SKristof Provost tmpname = strdup(newname);
278ec214349SKristof Provost if (tmpname == NULL) {
279ec214349SKristof Provost h->error.errtype = OTHER;
280ec214349SKristof Provost h->error.errcode = ENOMEM;
281ec214349SKristof Provost return (-1);
282ec214349SKristof Provost }
283ec214349SKristof Provost
284ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
285ec214349SKristof Provost ifr.ifr_data = tmpname;
286b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFNAME, &ifr) != 0) {
287ec214349SKristof Provost free(tmpname);
288ec214349SKristof Provost return (-1);
289ec214349SKristof Provost }
2909a2ff315SKristof Provost
291ec214349SKristof Provost free(tmpname);
292ec214349SKristof Provost return (0);
293ec214349SKristof Provost }
294ec214349SKristof Provost
2959a2ff315SKristof Provost int
ifconfig_get_orig_name(ifconfig_handle_t * h,const char * ifname,char ** orig_name)296c2803f1aSAndriy Voskoboinyk ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname,
297c2803f1aSAndriy Voskoboinyk char **orig_name)
298c2803f1aSAndriy Voskoboinyk {
299c2803f1aSAndriy Voskoboinyk size_t len;
300b1d757bcSAlan Somers unsigned int ifindex;
301c2803f1aSAndriy Voskoboinyk int name[6];
302b1d757bcSAlan Somers
303b1d757bcSAlan Somers ifindex = if_nametoindex(ifname);
304b1d757bcSAlan Somers if (ifindex == 0) {
305b1d757bcSAlan Somers goto fail;
306b1d757bcSAlan Somers }
307c2803f1aSAndriy Voskoboinyk
308c2803f1aSAndriy Voskoboinyk name[0] = CTL_NET;
309c2803f1aSAndriy Voskoboinyk name[1] = PF_LINK;
310c2803f1aSAndriy Voskoboinyk name[2] = NETLINK_GENERIC;
311c2803f1aSAndriy Voskoboinyk name[3] = IFMIB_IFDATA;
312b1d757bcSAlan Somers name[4] = ifindex;
313b1d757bcSAlan Somers name[5] = IFDATA_DRIVERNAME;
314c2803f1aSAndriy Voskoboinyk
315c2803f1aSAndriy Voskoboinyk len = 0;
316b1d757bcSAlan Somers if (sysctl(name, 6, NULL, &len, 0, 0) < 0) {
317c2803f1aSAndriy Voskoboinyk goto fail;
318b1d757bcSAlan Somers }
319c2803f1aSAndriy Voskoboinyk
320c2803f1aSAndriy Voskoboinyk *orig_name = malloc(len);
321b1d757bcSAlan Somers if (*orig_name == NULL) {
322c2803f1aSAndriy Voskoboinyk goto fail;
323b1d757bcSAlan Somers }
324c2803f1aSAndriy Voskoboinyk
325c2803f1aSAndriy Voskoboinyk if (sysctl(name, 6, *orig_name, &len, 0, 0) < 0) {
326c2803f1aSAndriy Voskoboinyk free(*orig_name);
327c2803f1aSAndriy Voskoboinyk *orig_name = NULL;
328c2803f1aSAndriy Voskoboinyk goto fail;
329c2803f1aSAndriy Voskoboinyk }
330c2803f1aSAndriy Voskoboinyk
331c2803f1aSAndriy Voskoboinyk return (0);
332c2803f1aSAndriy Voskoboinyk
333c2803f1aSAndriy Voskoboinyk fail:
334c2803f1aSAndriy Voskoboinyk h->error.errtype = OTHER;
335b1d757bcSAlan Somers h->error.errcode = (errno != 0) ? errno : ENOENT;
336c2803f1aSAndriy Voskoboinyk return (-1);
337c2803f1aSAndriy Voskoboinyk }
338c2803f1aSAndriy Voskoboinyk
339c2803f1aSAndriy Voskoboinyk int
ifconfig_get_fib(ifconfig_handle_t * h,const char * name,int * fib)340b1d757bcSAlan Somers ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib)
341b1d757bcSAlan Somers {
342b1d757bcSAlan Somers struct ifreq ifr;
343b1d757bcSAlan Somers
344b1d757bcSAlan Somers memset(&ifr, 0, sizeof(ifr));
345b1d757bcSAlan Somers (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
346b1d757bcSAlan Somers
347b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFFIB, &ifr) == -1) {
348b1d757bcSAlan Somers return (-1);
349b1d757bcSAlan Somers }
350b1d757bcSAlan Somers
351b1d757bcSAlan Somers *fib = ifr.ifr_fib;
352b1d757bcSAlan Somers return (0);
353b1d757bcSAlan Somers }
354b1d757bcSAlan Somers
355b1d757bcSAlan Somers int
ifconfig_set_mtu(ifconfig_handle_t * h,const char * name,const int mtu)3569a2ff315SKristof Provost ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu)
357ec214349SKristof Provost {
358ec214349SKristof Provost struct ifreq ifr;
359ec214349SKristof Provost
3609a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
361ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
362ec214349SKristof Provost ifr.ifr_mtu = mtu;
3639a2ff315SKristof Provost
364b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMTU, &ifr) < 0) {
365ec214349SKristof Provost return (-1);
366ec214349SKristof Provost }
3679a2ff315SKristof Provost
368ec214349SKristof Provost return (0);
369ec214349SKristof Provost }
370ec214349SKristof Provost
3719a2ff315SKristof Provost int
ifconfig_get_mtu(ifconfig_handle_t * h,const char * name,int * mtu)3729a2ff315SKristof Provost ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu)
373ec214349SKristof Provost {
374ec214349SKristof Provost struct ifreq ifr;
375ec214349SKristof Provost
3769a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
377ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
3789a2ff315SKristof Provost
379b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMTU, &ifr) == -1) {
380ec214349SKristof Provost return (-1);
381ec214349SKristof Provost }
3829a2ff315SKristof Provost
383ec214349SKristof Provost *mtu = ifr.ifr_mtu;
384ec214349SKristof Provost return (0);
385ec214349SKristof Provost }
386ec214349SKristof Provost
3879a2ff315SKristof Provost int
ifconfig_get_nd6(ifconfig_handle_t * h,const char * name,struct in6_ndireq * nd)388b1d757bcSAlan Somers ifconfig_get_nd6(ifconfig_handle_t *h, const char *name,
389b1d757bcSAlan Somers struct in6_ndireq *nd)
390b1d757bcSAlan Somers {
391b1d757bcSAlan Somers memset(nd, 0, sizeof(*nd));
392b1d757bcSAlan Somers strlcpy(nd->ifname, name, sizeof(nd->ifname));
393b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_INET6, SIOCGIFINFO_IN6, nd) == -1) {
394b1d757bcSAlan Somers return (-1);
395b1d757bcSAlan Somers }
396b1d757bcSAlan Somers if (isnd6defif(h, name)) {
397b1d757bcSAlan Somers nd->ndi.flags |= ND6_IFF_DEFAULTIF;
398b1d757bcSAlan Somers } else if (h->error.errtype != OK) {
399b1d757bcSAlan Somers return (-1);
400b1d757bcSAlan Somers }
401b1d757bcSAlan Somers
402b1d757bcSAlan Somers return (0);
403b1d757bcSAlan Somers }
404b1d757bcSAlan Somers
405b1d757bcSAlan Somers int
ifconfig_set_metric(ifconfig_handle_t * h,const char * name,const int metric)406ce0d4434SAlan Somers ifconfig_set_metric(ifconfig_handle_t *h, const char *name, const int metric)
407ec214349SKristof Provost {
408ec214349SKristof Provost struct ifreq ifr;
409ec214349SKristof Provost
4109a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
411ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
412ce0d4434SAlan Somers ifr.ifr_metric = metric;
4139a2ff315SKristof Provost
414b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMETRIC, &ifr) < 0) {
415ec214349SKristof Provost return (-1);
416ec214349SKristof Provost }
4179a2ff315SKristof Provost
418ec214349SKristof Provost return (0);
419ec214349SKristof Provost }
420ec214349SKristof Provost
4219a2ff315SKristof Provost int
ifconfig_get_metric(ifconfig_handle_t * h,const char * name,int * metric)4229a2ff315SKristof Provost ifconfig_get_metric(ifconfig_handle_t *h, const char *name, int *metric)
423ec214349SKristof Provost {
424ec214349SKristof Provost struct ifreq ifr;
425ec214349SKristof Provost
4269a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
427ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
4289a2ff315SKristof Provost
429b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMETRIC, &ifr) == -1) {
430ec214349SKristof Provost return (-1);
431ec214349SKristof Provost }
4329a2ff315SKristof Provost
433ec214349SKristof Provost *metric = ifr.ifr_metric;
434ec214349SKristof Provost return (0);
435ec214349SKristof Provost }
436ec214349SKristof Provost
4379a2ff315SKristof Provost int
ifconfig_set_capability(ifconfig_handle_t * h,const char * name,const int capability)4389a2ff315SKristof Provost ifconfig_set_capability(ifconfig_handle_t *h, const char *name,
439ec214349SKristof Provost const int capability)
440ec214349SKristof Provost {
441ec214349SKristof Provost struct ifreq ifr;
442ec214349SKristof Provost struct ifconfig_capabilities ifcap;
4439a2ff315SKristof Provost int flags, value;
444ec214349SKristof Provost
4459a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
4469a2ff315SKristof Provost
447b1d757bcSAlan Somers if (ifconfig_get_capability(h, name, &ifcap) != 0) {
448ec214349SKristof Provost return (-1);
449ec214349SKristof Provost }
450ec214349SKristof Provost
451ec214349SKristof Provost value = capability;
452ec214349SKristof Provost flags = ifcap.curcap;
453ec214349SKristof Provost if (value < 0) {
454ec214349SKristof Provost value = -value;
455ec214349SKristof Provost flags &= ~value;
456ec214349SKristof Provost } else {
457ec214349SKristof Provost flags |= value;
458ec214349SKristof Provost }
459ec214349SKristof Provost flags &= ifcap.reqcap;
460ec214349SKristof Provost
461ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
462ec214349SKristof Provost
463ec214349SKristof Provost /*
464ec214349SKristof Provost * TODO: Verify that it's safe to not have ifr.ifr_curcap
465ec214349SKristof Provost * set for this request.
466ec214349SKristof Provost */
467ec214349SKristof Provost ifr.ifr_reqcap = flags;
468b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFCAP, &ifr) < 0) {
469ec214349SKristof Provost return (-1);
470ec214349SKristof Provost }
471ec214349SKristof Provost return (0);
472ec214349SKristof Provost }
473ec214349SKristof Provost
4749a2ff315SKristof Provost int
ifconfig_get_capability(ifconfig_handle_t * h,const char * name,struct ifconfig_capabilities * capability)4759a2ff315SKristof Provost ifconfig_get_capability(ifconfig_handle_t *h, const char *name,
476ec214349SKristof Provost struct ifconfig_capabilities *capability)
477ec214349SKristof Provost {
478ec214349SKristof Provost struct ifreq ifr;
479ec214349SKristof Provost
4809a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
481ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
482ec214349SKristof Provost
483b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFCAP, &ifr) < 0) {
484ec214349SKristof Provost return (-1);
485ec214349SKristof Provost }
486ec214349SKristof Provost capability->curcap = ifr.ifr_curcap;
487ec214349SKristof Provost capability->reqcap = ifr.ifr_reqcap;
488ec214349SKristof Provost return (0);
489ec214349SKristof Provost }
490ec214349SKristof Provost
4919a2ff315SKristof Provost int
ifconfig_get_groups(ifconfig_handle_t * h,const char * name,struct ifgroupreq * ifgr)492b1d757bcSAlan Somers ifconfig_get_groups(ifconfig_handle_t *h, const char *name,
493b1d757bcSAlan Somers struct ifgroupreq *ifgr)
494b1d757bcSAlan Somers {
495b1d757bcSAlan Somers int len;
496b1d757bcSAlan Somers
497b1d757bcSAlan Somers memset(ifgr, 0, sizeof(*ifgr));
498b1d757bcSAlan Somers strlcpy(ifgr->ifgr_name, name, IFNAMSIZ);
499b1d757bcSAlan Somers
500b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFGROUP, ifgr) == -1) {
501b1d757bcSAlan Somers if ((h->error.errcode == EINVAL) ||
502b1d757bcSAlan Somers (h->error.errcode == ENOTTY)) {
503b1d757bcSAlan Somers return (0);
504b1d757bcSAlan Somers } else {
505b1d757bcSAlan Somers return (-1);
506b1d757bcSAlan Somers }
507b1d757bcSAlan Somers }
508b1d757bcSAlan Somers
509b1d757bcSAlan Somers len = ifgr->ifgr_len;
510b1d757bcSAlan Somers ifgr->ifgr_groups = (struct ifg_req *)malloc(len);
511b1d757bcSAlan Somers if (ifgr->ifgr_groups == NULL) {
512*1d9ba697SRyan Moeller h->error.errtype = OTHER;
513*1d9ba697SRyan Moeller h->error.errcode = ENOMEM;
514*1d9ba697SRyan Moeller return (-1);
515b1d757bcSAlan Somers }
516b1d757bcSAlan Somers bzero(ifgr->ifgr_groups, len);
517b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFGROUP, ifgr) == -1) {
518b1d757bcSAlan Somers return (-1);
519b1d757bcSAlan Somers }
520b1d757bcSAlan Somers
521b1d757bcSAlan Somers return (0);
522b1d757bcSAlan Somers }
523b1d757bcSAlan Somers
524b1d757bcSAlan Somers int
ifconfig_get_ifstatus(ifconfig_handle_t * h,const char * name,struct ifstat * ifs)525b1d757bcSAlan Somers ifconfig_get_ifstatus(ifconfig_handle_t *h, const char *name,
526b1d757bcSAlan Somers struct ifstat *ifs)
527b1d757bcSAlan Somers {
528b1d757bcSAlan Somers strlcpy(ifs->ifs_name, name, sizeof(ifs->ifs_name));
529b1d757bcSAlan Somers return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFSTATUS, ifs));
530b1d757bcSAlan Somers }
531b1d757bcSAlan Somers
532b1d757bcSAlan Somers int
ifconfig_destroy_interface(ifconfig_handle_t * h,const char * name)5339a2ff315SKristof Provost ifconfig_destroy_interface(ifconfig_handle_t *h, const char *name)
534ec214349SKristof Provost {
535ec214349SKristof Provost struct ifreq ifr;
536ec214349SKristof Provost
5379a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
538ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
539ec214349SKristof Provost
540b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFDESTROY, &ifr) < 0) {
541ec214349SKristof Provost return (-1);
542ec214349SKristof Provost }
543ec214349SKristof Provost return (0);
544ec214349SKristof Provost }
545ec214349SKristof Provost
5469a2ff315SKristof Provost int
ifconfig_create_interface(ifconfig_handle_t * h,const char * name,char ** ifname)5479a2ff315SKristof Provost ifconfig_create_interface(ifconfig_handle_t *h, const char *name, char **ifname)
548ec214349SKristof Provost {
549ec214349SKristof Provost struct ifreq ifr;
550ec214349SKristof Provost
5519a2ff315SKristof Provost memset(&ifr, 0, sizeof(ifr));
552b1d757bcSAlan Somers
553ec214349SKristof Provost (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
554ec214349SKristof Provost
555ec214349SKristof Provost /*
556ec214349SKristof Provost * TODO:
557ec214349SKristof Provost * Insert special snowflake handling here. See GitHub issue #12 for details.
558ec214349SKristof Provost * In the meantime, hard-nosupport interfaces that need special handling.
559ec214349SKristof Provost */
5609a2ff315SKristof Provost if ((strncmp(name, "wlan",
5619a2ff315SKristof Provost strlen("wlan")) == 0) ||
5629a2ff315SKristof Provost (strncmp(name, "vlan",
5639a2ff315SKristof Provost strlen("vlan")) == 0) ||
5649a2ff315SKristof Provost (strncmp(name, "vxlan",
5659a2ff315SKristof Provost strlen("vxlan")) == 0)) {
566ec214349SKristof Provost h->error.errtype = OTHER;
567ec214349SKristof Provost h->error.errcode = ENOSYS;
568ec214349SKristof Provost return (-1);
569ec214349SKristof Provost }
570ec214349SKristof Provost
571ec214349SKristof Provost /* No special handling for this interface type. */
572ec214349SKristof Provost if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFCREATE2, &ifr) < 0) {
573ec214349SKristof Provost return (-1);
574ec214349SKristof Provost }
5759a2ff315SKristof Provost
576ec214349SKristof Provost *ifname = strdup(ifr.ifr_name);
577b1d757bcSAlan Somers if (ifname == NULL) {
578b1d757bcSAlan Somers h->error.errtype = OTHER;
579b1d757bcSAlan Somers h->error.errcode = ENOMEM;
580b1d757bcSAlan Somers return (-1);
581b1d757bcSAlan Somers }
582b1d757bcSAlan Somers
583b1d757bcSAlan Somers return (0);
584b1d757bcSAlan Somers }
585b1d757bcSAlan Somers
586b1d757bcSAlan Somers int
ifconfig_create_interface_vlan(ifconfig_handle_t * h,const char * name,char ** ifname,const char * vlandev,const unsigned short vlantag)587b1d757bcSAlan Somers ifconfig_create_interface_vlan(ifconfig_handle_t *h, const char *name,
588b1d757bcSAlan Somers char **ifname, const char *vlandev, const unsigned short vlantag)
589b1d757bcSAlan Somers {
590b1d757bcSAlan Somers struct ifreq ifr;
591b1d757bcSAlan Somers struct vlanreq params;
592b1d757bcSAlan Somers
593b1d757bcSAlan Somers if ((vlantag == NOTAG) || (vlandev[0] == '\0')) {
594b1d757bcSAlan Somers // TODO: Add proper error tracking here
595b1d757bcSAlan Somers return (-1);
596b1d757bcSAlan Somers }
597b1d757bcSAlan Somers
598b1d757bcSAlan Somers bzero(¶ms, sizeof(params));
599b1d757bcSAlan Somers (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
600b1d757bcSAlan Somers params.vlr_tag = vlantag;
601b1d757bcSAlan Somers (void)strlcpy(params.vlr_parent, vlandev, sizeof(params.vlr_parent));
602b1d757bcSAlan Somers ifr.ifr_data = (caddr_t)¶ms;
603b1d757bcSAlan Somers
604b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFCREATE2, &ifr) < 0) {
605b1d757bcSAlan Somers // TODO: Add proper error tracking here
606b1d757bcSAlan Somers return (-1);
607b1d757bcSAlan Somers }
608b1d757bcSAlan Somers
609b1d757bcSAlan Somers *ifname = strdup(ifr.ifr_name);
610b1d757bcSAlan Somers return (0);
611b1d757bcSAlan Somers }
612b1d757bcSAlan Somers
613b1d757bcSAlan Somers int
ifconfig_set_vlantag(ifconfig_handle_t * h,const char * name,const char * vlandev,const unsigned short vlantag)614b1d757bcSAlan Somers ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name,
615b1d757bcSAlan Somers const char *vlandev, const unsigned short vlantag)
616b1d757bcSAlan Somers {
617b1d757bcSAlan Somers struct ifreq ifr;
618b1d757bcSAlan Somers struct vlanreq params;
619b1d757bcSAlan Somers
620b1d757bcSAlan Somers bzero(¶ms, sizeof(params));
621b1d757bcSAlan Somers params.vlr_tag = vlantag;
622b1d757bcSAlan Somers strlcpy(params.vlr_parent, vlandev, sizeof(params.vlr_parent));
623b1d757bcSAlan Somers
624b1d757bcSAlan Somers ifr.ifr_data = (caddr_t)¶ms;
625b1d757bcSAlan Somers (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
626b1d757bcSAlan Somers if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSETVLAN, &ifr) == -1) {
627b1d757bcSAlan Somers return (-1);
628b1d757bcSAlan Somers }
629ec214349SKristof Provost return (0);
630ec214349SKristof Provost }
6310710ec8cSRyan Moeller
6320710ec8cSRyan Moeller int
ifconfig_list_cloners(ifconfig_handle_t * h,char ** bufp,size_t * lenp)6330710ec8cSRyan Moeller ifconfig_list_cloners(ifconfig_handle_t *h, char **bufp, size_t *lenp)
6340710ec8cSRyan Moeller {
6350710ec8cSRyan Moeller struct if_clonereq ifcr;
6360710ec8cSRyan Moeller char *buf;
6370710ec8cSRyan Moeller
6380710ec8cSRyan Moeller memset(&ifcr, 0, sizeof(ifcr));
6390710ec8cSRyan Moeller *bufp = NULL;
6400710ec8cSRyan Moeller *lenp = 0;
6410710ec8cSRyan Moeller
6420710ec8cSRyan Moeller if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFGCLONERS, &ifcr) < 0)
6430710ec8cSRyan Moeller return (-1);
6440710ec8cSRyan Moeller
6450710ec8cSRyan Moeller buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
6460710ec8cSRyan Moeller if (buf == NULL) {
6470710ec8cSRyan Moeller h->error.errtype = OTHER;
6480710ec8cSRyan Moeller h->error.errcode = ENOMEM;
6490710ec8cSRyan Moeller return (-1);
6500710ec8cSRyan Moeller }
6510710ec8cSRyan Moeller
6520710ec8cSRyan Moeller ifcr.ifcr_count = ifcr.ifcr_total;
6530710ec8cSRyan Moeller ifcr.ifcr_buffer = buf;
6540710ec8cSRyan Moeller if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFGCLONERS, &ifcr) < 0) {
6550710ec8cSRyan Moeller free(buf);
6560710ec8cSRyan Moeller return (-1);
6570710ec8cSRyan Moeller }
6580710ec8cSRyan Moeller
6590710ec8cSRyan Moeller *bufp = buf;
6600710ec8cSRyan Moeller *lenp = ifcr.ifcr_total;
6610710ec8cSRyan Moeller return (0);
6620710ec8cSRyan Moeller }
663