Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157195280
D14463.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
77 KB
Referenced Files
None
Subscribers
None
D14463.id.diff
View Options
Index: head/lib/libifconfig/Makefile
===================================================================
--- head/lib/libifconfig/Makefile
+++ head/lib/libifconfig/Makefile
@@ -8,7 +8,9 @@
SHLIBDIR?= /lib
SHLIB_MAJOR= 1
-SRCS= libifconfig.c libifconfig_internal.c
+SRCS= libifconfig.c libifconfig_carp.c libifconfig_inet.c
+SRCS+= libifconfig_inet6.c libifconfig_internal.c libifconfig_lagg.c
+SRCS+= libifconfig_media.c
INCSDIR= ${INCLUDEDIR}
INCS= libifconfig.h
@@ -16,6 +18,6 @@
#MAN= libifconfig.3
CFLAGS+= -I${.CURDIR}
-WARNS?=6
+NO_WCAST_ALIGN= yes
.include <bsd.lib.mk>
Index: head/lib/libifconfig/libifconfig.h
===================================================================
--- head/lib/libifconfig/libifconfig.h
+++ head/lib/libifconfig/libifconfig.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -28,8 +28,16 @@
#pragma once
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+
+#define ND6_IFF_DEFAULTIF 0x8000
+
typedef enum {
- OTHER, IOCTL, SOCKET
+ OK = 0,
+ OTHER,
+ IOCTL,
+ SOCKET
} ifconfig_errtype;
/*
@@ -37,8 +45,16 @@
* pointer to it for library use.
*/
struct ifconfig_handle;
-typedef struct ifconfig_handle ifconfig_handle_t;
+typedef struct ifconfig_handle ifconfig_handle_t;
+struct carpreq;
+struct ifaddrs;
+struct in6_ndireq;
+struct lagg_reqall;
+struct lagg_reqflags;
+struct lagg_reqopts;
+struct lagg_reqport;
+
struct ifconfig_capabilities {
/** Current capabilities (ifconfig prints this as 'options')*/
int curcap;
@@ -46,13 +62,44 @@
int reqcap;
};
+/** Stores extra info associated with an inet address */
+struct ifconfig_inet_addr {
+ const struct sockaddr_in *sin;
+ const struct sockaddr_in *netmask;
+ const struct sockaddr_in *dst;
+ const struct sockaddr_in *broadcast;
+ int prefixlen;
+ uint8_t vhid;
+};
+
+/** Stores extra info associated with an inet6 address */
+struct ifconfig_inet6_addr {
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in6 *dstin6;
+ struct in6_addrlifetime lifetime;
+ int prefixlen;
+ uint32_t flags;
+ uint8_t vhid;
+};
+
+/** Stores extra info associated with a lagg(4) interface */
+struct ifconfig_lagg_status {
+ struct lagg_reqall *ra;
+ struct lagg_reqopts *ro;
+ struct lagg_reqflags *rf;
+};
+
/** Retrieves a new state object for use in other API calls.
* Example usage:
*{@code
* // Create state object
- * ifconfig_handle_t *lifh = ifconfig_open();
+ * ifconfig_handle_t *lifh;
+ * lifh = ifconfig_open();
+ * if (lifh == NULL) {
+ * // Handle error
+ * }
*
- * // Do stuff with it
+ * // Do stuff with the handle
*
* // Dispose of the state object
* ifconfig_close(lifh);
@@ -73,6 +120,28 @@
/** Retrieves the errno associated with the error, if any. */
int ifconfig_err_errno(ifconfig_handle_t *h);
+typedef void (*ifconfig_foreach_func_t)(ifconfig_handle_t *h,
+ struct ifaddrs *ifa, void *udata);
+
+/** Iterate over every network interface
+ * @param h An open ifconfig state object
+ * @param cb A callback function to call with a pointer to each interface
+ * @param udata An opaque value that will be passed to the callback.
+ * @return 0 on success, nonzero if the list could not be iterated
+ */
+int ifconfig_foreach_iface(ifconfig_handle_t *h, ifconfig_foreach_func_t cb,
+ void *udata);
+
+/** Iterate over every address on a single network interface
+ * @param h An open ifconfig state object
+ * @param ifa A pointer that was supplied by a previous call to
+ * ifconfig_foreach_iface
+ * @param udata An opaque value that will be passed to the callback.
+ * @param cb A callback function to call with a pointer to each ifaddr
+ */
+void ifconfig_foreach_ifaddr(ifconfig_handle_t *h, struct ifaddrs *ifa,
+ ifconfig_foreach_func_t cb, void *udata);
+
/** If error type was IOCTL, this identifies which request failed. */
unsigned long ifconfig_err_ioctlreq(ifconfig_handle_t *h);
int ifconfig_get_description(ifconfig_handle_t *h, const char *name,
@@ -84,8 +153,12 @@
const char *newname);
int ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname,
char **orig_name);
+int ifconfig_set_fib(ifconfig_handle_t *h, const char *name, int fib);
+int ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib);
int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu);
int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu);
+int ifconfig_get_nd6(ifconfig_handle_t *h, const char *name,
+ struct in6_ndireq *nd);
int ifconfig_set_metric(ifconfig_handle_t *h, const char *name,
const int metric);
int ifconfig_get_metric(ifconfig_handle_t *h, const char *name, int *metric);
@@ -94,6 +167,70 @@
int ifconfig_get_capability(ifconfig_handle_t *h, const char *name,
struct ifconfig_capabilities *capability);
+/** Retrieve the list of groups to which this interface belongs
+ * @param h An open ifconfig state object
+ * @param name The interface name
+ * @param ifgr return argument. The caller is responsible for freeing
+ * ifgr->ifgr_groups
+ * @return 0 on success, nonzero on failure
+ */
+int ifconfig_get_groups(ifconfig_handle_t *h, const char *name,
+ struct ifgroupreq *ifgr);
+int ifconfig_get_ifstatus(ifconfig_handle_t *h, const char *name,
+ struct ifstat *stat);
+
+/** Retrieve the interface media information
+ * @param h An open ifconfig state object
+ * @param name The interface name
+ * @param ifmr Return argument. The caller is responsible for freeing it
+ * @return 0 on success, nonzero on failure
+ */
+int ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name,
+ struct ifmediareq **ifmr);
+const char *ifconfig_media_get_type(int ifmw);
+const char *ifconfig_media_get_subtype(int ifmw);
+const char *ifconfig_media_get_status(const struct ifmediareq *ifmr);
+void ifconfig_media_get_options_string(int ifmw, char *buf, size_t buflen);
+
+int ifconfig_carp_get_info(ifconfig_handle_t *h, const char *name,
+ struct carpreq *carpr, int ncarpr);
+
+/** Retrieve additional information about an inet address
+ * @param h An open ifconfig state object
+ * @param name The interface name
+ * @param ifa Pointer to the the address structure of interest
+ * @param addr Return argument. It will be filled with additional information
+ * about the address.
+ * @return 0 on success, nonzero on failure.
+ */
+int ifconfig_inet_get_addrinfo(ifconfig_handle_t *h,
+ const char *name, struct ifaddrs *ifa, struct ifconfig_inet_addr *addr);
+
+/** Retrieve additional information about an inet6 address
+ * @param h An open ifconfig state object
+ * @param name The interface name
+ * @param ifa Pointer to the the address structure of interest
+ * @param addr Return argument. It will be filled with additional information
+ * about the address.
+ * @return 0 on success, nonzero on failure.
+ */
+int ifconfig_inet6_get_addrinfo(ifconfig_handle_t *h,
+ const char *name, struct ifaddrs *ifa, struct ifconfig_inet6_addr *addr);
+
+/** Retrieve additional information about a lagg(4) interface */
+int ifconfig_lagg_get_lagg_status(ifconfig_handle_t *h,
+ const char *name, struct ifconfig_lagg_status **lagg_status);
+
+/** Retrieve additional information about a member of a lagg(4) interface */
+int ifconfig_lagg_get_laggport_status(ifconfig_handle_t *h,
+ const char *name, struct lagg_reqport *rp);
+
+/** Frees the structure returned by ifconfig_lagg_get_status. Does nothing if
+ * the argument is NULL
+ * @param laggstat Pointer to the structure to free
+ */
+void ifconfig_lagg_free_lagg_status(struct ifconfig_lagg_status *laggstat);
+
/** Destroy a virtual interface
* @param name Interface to destroy
*/
@@ -105,3 +242,15 @@
*/
int ifconfig_create_interface(ifconfig_handle_t *h, const char *name,
char **ifname);
+
+/** Creates a (virtual) interface
+ * @param name Name of interface to create. Example: vlan0 or ix0.50
+ * @param name ifname Is set to actual name of created interface
+ * @param vlandev Name of interface to attach to
+ * @param vlanid VLAN ID/Tag. Must not be 0.
+ */
+int ifconfig_create_interface_vlan(ifconfig_handle_t *h, const char *name,
+ char **ifname, const char *vlandev, const unsigned short vlantag);
+
+int ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name,
+ const char *vlandev, const unsigned short vlantag);
Index: head/lib/libifconfig/libifconfig.c
===================================================================
--- head/lib/libifconfig/libifconfig.c
+++ head/lib/libifconfig/libifconfig.c
@@ -1,38 +1,7 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * thislist of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -61,65 +30,63 @@
* $FreeBSD$
*/
- /*
- * Copyright 1996 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that both the above copyright notice and this
- * permission notice appear in all copies, that both the above
- * copyright notice and this permission notice appear in all
- * supporting documentation, and that the name of M.I.T. not be used
- * in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission. M.I.T. makes
- * no representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied
- * warranty.
- *
- * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
- * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
- * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_mib.h>
+#include <netinet/in.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <ifaddrs.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <net/if_vlan_var.h>
+
#include "libifconfig.h"
#include "libifconfig_internal.h"
+#define NOTAG ((u_short) -1)
+static bool
+isnd6defif(ifconfig_handle_t *h, const char *name)
+{
+ struct in6_ndifreq ndifreq;
+ unsigned int ifindex;
+
+ memset(&ndifreq, 0, sizeof(ndifreq));
+ strlcpy(ndifreq.ifname, name, sizeof(ndifreq.ifname));
+ ifindex = if_nametoindex(ndifreq.ifname);
+ if (ifconfig_ioctlwrap(h, AF_INET6, SIOCGDEFIFACE_IN6, &ndifreq) < 0) {
+ return (false);
+ }
+ h->error.errtype = OK;
+ return (ndifreq.ifindex == ifindex);
+}
+
ifconfig_handle_t *
ifconfig_open(void)
{
- struct ifconfig_handle *h;
+ ifconfig_handle_t *h;
h = calloc(1, sizeof(*h));
+
+ if (h == NULL) {
+ return (NULL);
+ }
for (int i = 0; i <= AF_MAX; i++) {
h->sockets[i] = -1;
}
+
return (h);
}
@@ -132,6 +99,7 @@
(void)close(h->sockets[i]);
}
}
+ freeifaddrs(h->ifap);
free(h);
}
@@ -157,6 +125,46 @@
}
int
+ifconfig_foreach_iface(ifconfig_handle_t *h,
+ ifconfig_foreach_func_t cb, void *udata)
+{
+ int ret;
+
+ ret = ifconfig_getifaddrs(h);
+ if (ret == 0) {
+ struct ifaddrs *ifa;
+ char *ifname = NULL;
+
+ for (ifa = h->ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifname != ifa->ifa_name) {
+ ifname = ifa->ifa_name;
+ cb(h, ifa, udata);
+ }
+ }
+ }
+ /* Free ifaddrs so we don't accidentally cache stale data */
+ freeifaddrs(h->ifap);
+ h->ifap = NULL;
+
+ return (ret);
+}
+
+void
+ifconfig_foreach_ifaddr(ifconfig_handle_t *h, struct ifaddrs *ifa,
+ ifconfig_foreach_func_t cb, void *udata)
+{
+ struct ifaddrs *ift;
+
+ for (ift = ifa;
+ ift != NULL &&
+ ift->ifa_addr != NULL &&
+ strcmp(ift->ifa_name, ifa->ifa_name) == 0;
+ ift = ift->ifa_next) {
+ cb(h, ift, udata);
+ }
+}
+
+int
ifconfig_get_description(ifconfig_handle_t *h, const char *name,
char **description)
{
@@ -179,6 +187,7 @@
ifr.ifr_buffer.buffer = descr;
ifr.ifr_buffer.length = descrlen;
if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFDESCR, &ifr) != 0) {
+ free(descr);
return (-1);
}
@@ -186,6 +195,13 @@
if (strlen(descr) > 0) {
*description = strdup(descr);
free(descr);
+
+ if (description == NULL) {
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOMEM;
+ return (-1);
+ }
+
return (0);
}
} else if (ifr.ifr_buffer.length > descrlen) {
@@ -228,8 +244,7 @@
return (-1);
}
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR,
- &ifr) != 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) != 0) {
free(ifr.ifr_buffer.buffer);
return (-1);
}
@@ -248,8 +263,7 @@
ifr.ifr_buffer.length = 0;
ifr.ifr_buffer.buffer = NULL;
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR,
- &ifr) < 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) < 0) {
return (-1);
}
return (0);
@@ -271,8 +285,7 @@
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_data = tmpname;
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFNAME,
- &ifr) != 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFNAME, &ifr) != 0) {
free(tmpname);
return (-1);
}
@@ -285,61 +298,60 @@
ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname,
char **orig_name)
{
- struct ifmibdata ifmd;
size_t len;
+ unsigned int ifindex;
int name[6];
- int i, maxifno;
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0) {
+ goto fail;
+ }
+
name[0] = CTL_NET;
name[1] = PF_LINK;
name[2] = NETLINK_GENERIC;
- name[3] = IFMIB_SYSTEM;
- name[4] = IFMIB_IFCOUNT;
+ name[3] = IFMIB_IFDATA;
+ name[4] = ifindex;
+ name[5] = IFDATA_DRIVERNAME;
- len = sizeof maxifno;
- if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0) {
- h->error.errtype = OTHER;
- h->error.errcode = errno;
- return (-1);
+ len = 0;
+ if (sysctl(name, 6, NULL, &len, 0, 0) < 0) {
+ goto fail;
}
- name[3] = IFMIB_IFDATA;
- name[5] = IFDATA_GENERAL;
- for (i = 1; i <= maxifno; i++) {
- len = sizeof ifmd;
- name[4] = i;
- if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) {
- if (errno == ENOENT)
- continue;
+ *orig_name = malloc(len);
+ if (*orig_name == NULL) {
+ goto fail;
+ }
- goto fail;
- }
+ if (sysctl(name, 6, *orig_name, &len, 0, 0) < 0) {
+ free(*orig_name);
+ *orig_name = NULL;
+ goto fail;
+ }
- if (strncmp(ifmd.ifmd_name, ifname, IFNAMSIZ) != 0)
- continue;
+ return (0);
- len = 0;
- name[5] = IFDATA_DRIVERNAME;
- if (sysctl(name, 6, NULL, &len, 0, 0) < 0)
- goto fail;
+fail:
+ h->error.errtype = OTHER;
+ h->error.errcode = (errno != 0) ? errno : ENOENT;
+ return (-1);
+}
- *orig_name = malloc(len);
- if (*orig_name == NULL)
- goto fail;
+int
+ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib)
+{
+ struct ifreq ifr;
- if (sysctl(name, 6, *orig_name, &len, 0, 0) < 0) {
- free(*orig_name);
- *orig_name = NULL;
- goto fail;
- }
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- return (0);
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFFIB, &ifr) == -1) {
+ return (-1);
}
-fail:
- h->error.errtype = OTHER;
- h->error.errcode = (i <= maxifno) ? errno : ENOENT;
- return (-1);
+ *fib = ifr.ifr_fib;
+ return (0);
}
int
@@ -351,8 +363,7 @@
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_mtu = mtu;
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMTU,
- &ifr) < 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMTU, &ifr) < 0) {
return (-1);
}
@@ -367,8 +378,7 @@
memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMTU,
- &ifr) == -1) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMTU, &ifr) == -1) {
return (-1);
}
@@ -377,6 +387,24 @@
}
int
+ifconfig_get_nd6(ifconfig_handle_t *h, const char *name,
+ struct in6_ndireq *nd)
+{
+ memset(nd, 0, sizeof(*nd));
+ strlcpy(nd->ifname, name, sizeof(nd->ifname));
+ if (ifconfig_ioctlwrap(h, AF_INET6, SIOCGIFINFO_IN6, nd) == -1) {
+ return (-1);
+ }
+ if (isnd6defif(h, name)) {
+ nd->ndi.flags |= ND6_IFF_DEFAULTIF;
+ } else if (h->error.errtype != OK) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
ifconfig_set_metric(ifconfig_handle_t *h, const char *name, const int metric)
{
struct ifreq ifr;
@@ -385,8 +413,7 @@
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
ifr.ifr_metric = metric;
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMETRIC,
- &ifr) < 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFMETRIC, &ifr) < 0) {
return (-1);
}
@@ -401,8 +428,7 @@
memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMETRIC,
- &ifr) == -1) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFMETRIC, &ifr) == -1) {
return (-1);
}
@@ -420,8 +446,7 @@
memset(&ifr, 0, sizeof(ifr));
- if (ifconfig_get_capability(h, name,
- &ifcap) != 0) {
+ if (ifconfig_get_capability(h, name, &ifcap) != 0) {
return (-1);
}
@@ -442,8 +467,7 @@
* set for this request.
*/
ifr.ifr_reqcap = flags;
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFCAP,
- &ifr) < 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSIFCAP, &ifr) < 0) {
return (-1);
}
return (0);
@@ -458,8 +482,7 @@
memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFCAP,
- &ifr) < 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFCAP, &ifr) < 0) {
return (-1);
}
capability->curcap = ifr.ifr_curcap;
@@ -468,6 +491,45 @@
}
int
+ifconfig_get_groups(ifconfig_handle_t *h, const char *name,
+ struct ifgroupreq *ifgr)
+{
+ int len;
+
+ memset(ifgr, 0, sizeof(*ifgr));
+ strlcpy(ifgr->ifgr_name, name, IFNAMSIZ);
+
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFGROUP, ifgr) == -1) {
+ if ((h->error.errcode == EINVAL) ||
+ (h->error.errcode == ENOTTY)) {
+ return (0);
+ } else {
+ return (-1);
+ }
+ }
+
+ len = ifgr->ifgr_len;
+ ifgr->ifgr_groups = (struct ifg_req *)malloc(len);
+ if (ifgr->ifgr_groups == NULL) {
+ return (1);
+ }
+ bzero(ifgr->ifgr_groups, len);
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFGROUP, ifgr) == -1) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+ifconfig_get_ifstatus(ifconfig_handle_t *h, const char *name,
+ struct ifstat *ifs)
+{
+ strlcpy(ifs->ifs_name, name, sizeof(ifs->ifs_name));
+ return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGIFSTATUS, ifs));
+}
+
+int
ifconfig_destroy_interface(ifconfig_handle_t *h, const char *name)
{
struct ifreq ifr;
@@ -475,8 +537,7 @@
memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFDESTROY,
- &ifr) < 0) {
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFDESTROY, &ifr) < 0) {
return (-1);
}
return (0);
@@ -488,6 +549,7 @@
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
+
(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
/*
@@ -512,5 +574,57 @@
}
*ifname = strdup(ifr.ifr_name);
+ if (ifname == NULL) {
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOMEM;
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+ifconfig_create_interface_vlan(ifconfig_handle_t *h, const char *name,
+ char **ifname, const char *vlandev, const unsigned short vlantag)
+{
+ struct ifreq ifr;
+ struct vlanreq params;
+
+ if ((vlantag == NOTAG) || (vlandev[0] == '\0')) {
+ // TODO: Add proper error tracking here
+ return (-1);
+ }
+
+ bzero(¶ms, sizeof(params));
+ (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ params.vlr_tag = vlantag;
+ (void)strlcpy(params.vlr_parent, vlandev, sizeof(params.vlr_parent));
+ ifr.ifr_data = (caddr_t)¶ms;
+
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCIFCREATE2, &ifr) < 0) {
+ // TODO: Add proper error tracking here
+ return (-1);
+ }
+
+ *ifname = strdup(ifr.ifr_name);
+ return (0);
+}
+
+int
+ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name,
+ const char *vlandev, const unsigned short vlantag)
+{
+ struct ifreq ifr;
+ struct vlanreq params;
+
+ bzero(¶ms, sizeof(params));
+ params.vlr_tag = vlantag;
+ strlcpy(params.vlr_parent, vlandev, sizeof(params.vlr_parent));
+
+ ifr.ifr_data = (caddr_t)¶ms;
+ (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCSETVLAN, &ifr) == -1) {
+ return (-1);
+ }
return (0);
}
Index: head/lib/libifconfig/libifconfig_carp.c
===================================================================
--- head/lib/libifconfig/libifconfig_carp.c
+++ head/lib/libifconfig/libifconfig_carp.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/ip_carp.h>
+
+#include <string.h>
+#include <strings.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+
+int
+ifconfig_carp_get_info(ifconfig_handle_t *h, const char *name,
+ struct carpreq *carpr, int ncarpr)
+{
+ struct ifreq ifr;
+
+ bzero(carpr, sizeof(struct carpreq) * ncarpr);
+ carpr[0].carpr_count = ncarpr;
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)carpr;
+
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGVH, &ifr) != 0) {
+ return (-1);
+ }
+
+ return (0);
+}
Index: head/lib/libifconfig/libifconfig_inet.c
===================================================================
--- head/lib/libifconfig/libifconfig_inet.c
+++ head/lib/libifconfig/libifconfig_inet.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <string.h>
+#include <strings.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+static const struct sockaddr_in NULL_SIN;
+
+static int
+inet_prefixlen(const struct in_addr *addr)
+{
+ int x;
+
+ x = ffs(ntohl(addr->s_addr));
+ return (x == 0 ? 0 : 33 - x);
+}
+
+int
+ifconfig_inet_get_addrinfo(ifconfig_handle_t *h __unused,
+ const char *name __unused, struct ifaddrs *ifa,
+ struct ifconfig_inet_addr *addr)
+{
+ bzero(addr, sizeof(*addr));
+
+ /* Set the address */
+ if (ifa->ifa_addr == NULL) {
+ return (-1);
+ } else {
+ addr->sin = (struct sockaddr_in *)ifa->ifa_addr;
+ }
+
+ /* Set the destination address */
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ if (ifa->ifa_dstaddr) {
+ addr->dst = (struct sockaddr_in *)ifa->ifa_dstaddr;
+ } else {
+ addr->dst = &NULL_SIN;
+ }
+ }
+
+ /* Set the netmask and prefixlen */
+ if (ifa->ifa_netmask) {
+ addr->netmask = (struct sockaddr_in *)ifa->ifa_netmask;
+ } else {
+ addr->netmask = &NULL_SIN;
+ }
+ addr->prefixlen = inet_prefixlen(&addr->netmask->sin_addr);
+
+ /* Set the broadcast */
+ if (ifa->ifa_flags & IFF_BROADCAST) {
+ addr->broadcast = (struct sockaddr_in *)ifa->ifa_broadaddr;
+ }
+
+ /* Set the vhid */
+ if (ifa->ifa_data) {
+ addr->vhid = ((struct if_data *)ifa->ifa_data)->ifi_vhid;
+ }
+
+ return (0);
+}
Index: head/lib/libifconfig/libifconfig_inet6.c
===================================================================
--- head/lib/libifconfig/libifconfig_inet6.c
+++ head/lib/libifconfig/libifconfig_inet6.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <string.h>
+#include <strings.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+
+static int
+inet6_prefixlen(struct in6_addr *addr)
+{
+ int prefixlen = 0;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ int x = ffs(ntohl(addr->__u6_addr.__u6_addr32[i]));
+ prefixlen += x == 0 ? 0 : 33 - x;
+ if (x != 1) {
+ break;
+ }
+ }
+ return (prefixlen);
+}
+
+int
+ifconfig_inet6_get_addrinfo(ifconfig_handle_t *h,
+ const char *name, struct ifaddrs *ifa, struct ifconfig_inet6_addr *addr)
+{
+ struct sockaddr_in6 *netmask;
+ struct in6_ifreq ifr6;
+
+ bzero(addr, sizeof(*addr));
+
+ /* Set the address */
+ addr->sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
+
+ /* Set the destination address */
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ addr->dstin6 = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+ }
+
+ /* Set the prefixlen */
+ netmask = (struct sockaddr_in6 *)ifa->ifa_netmask;
+ addr->prefixlen = inet6_prefixlen(&netmask->sin6_addr);
+
+ /* Set the flags */
+ strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
+ ifr6.ifr_addr = *addr->sin6;
+ if (ifconfig_ioctlwrap(h, AF_INET6, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
+ return (-1);
+ }
+ addr->flags = ifr6.ifr_ifru.ifru_flags6;
+
+ /* Set the lifetimes */
+ memset(&addr->lifetime, 0, sizeof(addr->lifetime));
+ ifr6.ifr_addr = *addr->sin6;
+ if (ifconfig_ioctlwrap(h, AF_INET6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) {
+ return (-1);
+ }
+ addr->lifetime = ifr6.ifr_ifru.ifru_lifetime; /* struct copy */
+
+ /* Set the vhid */
+ if (ifa->ifa_data && ifa->ifa_data) {
+ addr->vhid = ((struct if_data *)ifa->ifa_data)->ifi_vhid;
+ }
+
+ return (0);
+}
Index: head/lib/libifconfig/libifconfig_internal.h
===================================================================
--- head/lib/libifconfig/libifconfig_internal.h
+++ head/lib/libifconfig/libifconfig_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -52,8 +52,13 @@
struct ifconfig_handle {
struct errstate error;
int sockets[AF_MAX + 1];
+ /** Cached output of getifaddrs */
+ struct ifaddrs *ifap;
};
+/* Fetch the list of interface addrs, if it hasn't already been fetched */
+int ifconfig_getifaddrs(ifconfig_handle_t *h);
+
/**
* Retrieves socket for address family <paramref name="addressfamily"> from
* cache, or creates it if it doesn't already exist.
@@ -75,10 +80,6 @@
*/
int ifconfig_socket(ifconfig_handle_t *h, const int addressfamily, int *s);
-/** Function used by other wrapper functions to populate _errstate when appropriate.*/
-int ifconfig_ioctlwrap_ret(ifconfig_handle_t *h, unsigned long request,
- int rcode);
-
/** Function to wrap ioctl() and automatically populate ifconfig_errstate when appropriate.*/
int ifconfig_ioctlwrap(ifconfig_handle_t *h, const int addressfamily,
- unsigned long request, struct ifreq *ifr);
+ unsigned long request, void *data);
Index: head/lib/libifconfig/libifconfig_internal.c
===================================================================
--- head/lib/libifconfig/libifconfig_internal.c
+++ head/lib/libifconfig/libifconfig_internal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -31,6 +31,7 @@
#include <net/if.h>
#include <errno.h>
+#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -38,23 +39,22 @@
#include "libifconfig.h" // Needed for ifconfig_errstate
#include "libifconfig_internal.h"
-
int
-ifconfig_ioctlwrap_ret(ifconfig_handle_t *h, unsigned long request, int rcode)
+ifconfig_getifaddrs(ifconfig_handle_t *h)
{
+ int ret;
- if (rcode != 0) {
- h->error.errtype = IOCTL;
- h->error.ioctl_request = request;
- h->error.errcode = errno;
+ if (h->ifap == NULL) {
+ ret = getifaddrs(&h->ifap);
+ return (ret);
+ } else {
+ return (0);
}
-
- return (rcode);
}
int
ifconfig_ioctlwrap(ifconfig_handle_t *h, const int addressfamily,
- unsigned long request, struct ifreq *ifr)
+ unsigned long request, void *data)
{
int s;
@@ -62,8 +62,14 @@
return (-1);
}
- int rcode = ioctl(s, request, ifr);
- return (ifconfig_ioctlwrap_ret(h, request, rcode));
+ if (ioctl(s, request, data) != 0) {
+ h->error.errtype = IOCTL;
+ h->error.ioctl_request = request;
+ h->error.errcode = errno;
+ return (-1);
+ }
+
+ return (0);
}
/*
Index: head/lib/libifconfig/libifconfig_lagg.c
===================================================================
--- head/lib/libifconfig/libifconfig_lagg.c
+++ head/lib/libifconfig/libifconfig_lagg.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_lagg.h>
+#include <net/ieee8023ad_lacp.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+/* Internal structure used for allocations and frees */
+struct _ifconfig_lagg_status {
+ struct ifconfig_lagg_status l; /* Must be first */
+ struct lagg_reqall ra;
+ struct lagg_reqopts ro;
+ struct lagg_reqflags rf;
+ struct lagg_reqport rpbuf[LAGG_MAX_PORTS];
+};
+
+int
+ifconfig_lagg_get_laggport_status(ifconfig_handle_t *h,
+ const char *name, struct lagg_reqport *rp)
+{
+ strlcpy(rp->rp_ifname, name, sizeof(rp->rp_portname));
+ strlcpy(rp->rp_portname, name, sizeof(rp->rp_portname));
+
+ return (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGLAGGPORT, rp));
+}
+
+int
+ifconfig_lagg_get_lagg_status(ifconfig_handle_t *h,
+ const char *name, struct ifconfig_lagg_status **lagg_status)
+{
+ struct _ifconfig_lagg_status *ls;
+
+ ls = calloc(1, sizeof(struct _ifconfig_lagg_status));
+ if (ls == NULL) {
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOMEM;
+ return (-1);
+ }
+ ls->l.ra = &ls->ra;
+ ls->l.ro = &ls->ro;
+ ls->l.rf = &ls->rf;
+ *lagg_status = &ls->l;
+
+ ls->ra.ra_port = ls->rpbuf;
+ ls->ra.ra_size = sizeof(ls->rpbuf);
+
+ strlcpy(ls->ro.ro_ifname, name, sizeof(ls->ro.ro_ifname));
+ ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGLAGGOPTS, &ls->ro);
+
+ strlcpy(ls->rf.rf_ifname, name, sizeof(ls->rf.rf_ifname));
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGLAGGFLAGS, &ls->rf) != 0) {
+ ls->rf.rf_flags = 0;
+ }
+
+ strlcpy(ls->ra.ra_ifname, name, sizeof(ls->ra.ra_ifname));
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, SIOCGLAGG, &ls->ra) != 0) {
+ free(ls);
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+ifconfig_lagg_free_lagg_status(struct ifconfig_lagg_status *laggstat)
+{
+ free(laggstat);
+}
Index: head/lib/libifconfig/libifconfig_media.c
===================================================================
--- head/lib/libifconfig/libifconfig_media.c
+++ head/lib/libifconfig/libifconfig_media.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/if_media.h>
+#include <net/route.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libifconfig.h"
+#include "libifconfig_internal.h"
+
+
+static struct ifmedia_description *get_toptype_desc(int);
+static struct ifmedia_type_to_subtype *get_toptype_ttos(int);
+static struct ifmedia_description *get_subtype_desc(int,
+ struct ifmedia_type_to_subtype *ttos);
+
+#define IFM_OPMODE(x) \
+ ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
+ IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
+ IFM_IEEE80211_MBSS))
+#define IFM_IEEE80211_STA 0
+
+static struct ifmedia_description ifm_type_descriptions[] =
+ IFM_TYPE_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
+ IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
+ IFM_SUBTYPE_ETHERNET_ALIASES;
+
+static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
+ IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
+ IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
+ IFM_SUBTYPE_TOKENRING_ALIASES;
+
+static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
+ IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
+ IFM_SUBTYPE_FDDI_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_fddi_aliases[] =
+ IFM_SUBTYPE_FDDI_ALIASES;
+
+static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
+ IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
+ IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
+ IFM_SUBTYPE_IEEE80211_ALIASES;
+
+static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
+ IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
+ IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
+ IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
+
+static struct ifmedia_description ifm_subtype_atm_descriptions[] =
+ IFM_SUBTYPE_ATM_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_atm_aliases[] =
+ IFM_SUBTYPE_ATM_ALIASES;
+
+static struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
+ IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_shared_descriptions[] =
+ IFM_SUBTYPE_SHARED_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_shared_aliases[] =
+ IFM_SUBTYPE_SHARED_ALIASES;
+
+static struct ifmedia_description ifm_shared_option_descriptions[] =
+ IFM_SHARED_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_shared_option_aliases[] =
+ IFM_SHARED_OPTION_ALIASES;
+
+struct ifmedia_type_to_subtype {
+ struct {
+ struct ifmedia_description *desc;
+ int alias;
+ }
+ subtypes[5];
+ struct {
+ struct ifmedia_description *desc;
+ int alias;
+ }
+ options[4];
+ struct {
+ struct ifmedia_description *desc;
+ int alias;
+ }
+ modes[3];
+};
+
+/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
+static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] =
+{
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_ethernet_descriptions[0], 0 },
+ { &ifm_subtype_ethernet_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
+ { &ifm_subtype_ethernet_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_tokenring_descriptions[0], 0 },
+ { &ifm_subtype_tokenring_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
+ { &ifm_subtype_tokenring_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_fddi_descriptions[0], 0 },
+ { &ifm_subtype_fddi_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
+ { &ifm_subtype_fddi_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_ieee80211_descriptions[0], 0 },
+ { &ifm_subtype_ieee80211_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
+ { &ifm_subtype_ieee80211_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
+ { &ifm_subtype_ieee80211_mode_aliases[0], 0 },
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_atm_descriptions[0], 0 },
+ { &ifm_subtype_atm_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_shared_option_aliases[0], 1 },
+ { &ifm_subtype_atm_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+};
+
+static struct ifmedia_description *
+get_toptype_desc(int ifmw)
+{
+ struct ifmedia_description *desc;
+
+ for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) {
+ if (IFM_TYPE(ifmw) == desc->ifmt_word) {
+ break;
+ }
+ }
+
+ return (desc);
+}
+
+static struct ifmedia_type_to_subtype *
+get_toptype_ttos(int ifmw)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+
+ for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+ desc->ifmt_string != NULL; desc++, ttos++) {
+ if (IFM_TYPE(ifmw) == desc->ifmt_word) {
+ break;
+ }
+ }
+
+ return (ttos);
+}
+
+static struct ifmedia_description *
+get_subtype_desc(int ifmw,
+ struct ifmedia_type_to_subtype *ttos)
+{
+ int i;
+ struct ifmedia_description *desc;
+
+ for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
+ if (ttos->subtypes[i].alias) {
+ continue;
+ }
+ for (desc = ttos->subtypes[i].desc;
+ desc->ifmt_string != NULL; desc++) {
+ if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) {
+ return (desc);
+ }
+ }
+ }
+
+ return (NULL);
+}
+
+const char *
+ifconfig_media_get_type(int ifmw)
+{
+ struct ifmedia_description *desc;
+
+ /*int seen_option = 0, i;*/
+
+ /* Find the top-level interface type. */
+ desc = get_toptype_desc(ifmw);
+ if (desc->ifmt_string == NULL) {
+ return ("<unknown type>");
+ } else {
+ return (desc->ifmt_string);
+ }
+}
+
+const char *
+ifconfig_media_get_subtype(int ifmw)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+
+ ttos = get_toptype_ttos(ifmw);
+ desc = get_subtype_desc(ifmw, ttos);
+ return (desc->ifmt_string);
+}
+
+/***************************************************************************
+* Above this point, this file is mostly copied from sbin/ifconfig/ifmedia.c
+***************************************************************************/
+
+/* Internal structure used for allocations and frees */
+struct _ifconfig_media_status {
+ struct ifmediareq ifmr;
+ int medialist[0];
+};
+
+int
+ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name,
+ struct ifmediareq **ifmr)
+{
+ struct _ifconfig_media_status *ms, *ms2;
+ unsigned long cmd = SIOCGIFXMEDIA;
+
+ *ifmr = NULL;
+ ms = calloc(1, sizeof(*ms));
+ if (ms == NULL) {
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOMEM;
+ return (-1);
+ }
+ (void)memset(ms, 0, sizeof(*ms));
+ (void)strlcpy(ms->ifmr.ifm_name, name, sizeof(ms->ifmr.ifm_name));
+
+ /*
+ * Check if interface supports extended media types.
+ */
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) {
+ cmd = SIOCGIFMEDIA;
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) {
+ /* Interface doesn't support SIOC{G,S}IFMEDIA. */
+ h->error.errtype = OK;
+ free(ms);
+ return (-1);
+ }
+ }
+ if (ms->ifmr.ifm_count == 0) {
+ *ifmr = &ms->ifmr;
+ return (0); /* Interface has no media types ?*/
+ }
+
+ ms2 = realloc(ms, sizeof(*ms) + sizeof(int) * ms->ifmr.ifm_count);
+ if (ms2 == NULL) {
+ h->error.errtype = OTHER;
+ h->error.errcode = ENOMEM;
+ free(ms);
+ return (-1);
+ }
+ ms2->ifmr.ifm_ulist = &ms2->medialist[0];
+
+ if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms2->ifmr) < 0) {
+ free(ms2);
+ return (-1);
+ }
+
+ *ifmr = &ms2->ifmr;
+ return (0);
+}
+
+const char *
+ifconfig_media_get_status(const struct ifmediareq *ifmr)
+{
+ switch (IFM_TYPE(ifmr->ifm_active)) {
+ case IFM_ETHER:
+ case IFM_ATM:
+ if (ifmr->ifm_status & IFM_ACTIVE) {
+ return ("active");
+ } else {
+ return ("no carrier");
+ }
+ break;
+
+ case IFM_FDDI:
+ case IFM_TOKEN:
+ if (ifmr->ifm_status & IFM_ACTIVE) {
+ return ("inserted");
+ } else {
+ return ("no ring");
+ }
+ break;
+
+ case IFM_IEEE80211:
+ if (ifmr->ifm_status & IFM_ACTIVE) {
+ /* NB: only sta mode associates */
+ if (IFM_OPMODE(ifmr->ifm_active) == IFM_IEEE80211_STA) {
+ return ("associated");
+ } else {
+ return ("running");
+ }
+ } else {
+ return ("no carrier");
+ }
+ break;
+ default:
+ return ("");
+ }
+}
+
+void
+ifconfig_media_get_options_string(int ifmw, char *buf, size_t buflen)
+{
+ struct ifmedia_type_to_subtype *ttos;
+ struct ifmedia_description *desc;
+ int i, seen_option = 0;
+ size_t len;
+
+ assert(buflen > 0);
+ buf[0] = '\0';
+ ttos = get_toptype_ttos(ifmw);
+ for (i = 0; ttos->options[i].desc != NULL; i++) {
+ if (ttos->options[i].alias) {
+ continue;
+ }
+ for (desc = ttos->options[i].desc;
+ desc->ifmt_string != NULL; desc++) {
+ if (ifmw & desc->ifmt_word) {
+ if (seen_option++) {
+ strlcat(buf, ",", buflen);
+ }
+ len = strlcat(buf, desc->ifmt_string, buflen);
+ assert(len < buflen);
+ buf += len;
+ buflen -= len;
+ }
+ }
+ }
+}
Index: head/share/examples/libifconfig/Makefile
===================================================================
--- head/share/examples/libifconfig/Makefile
+++ head/share/examples/libifconfig/Makefile
@@ -4,5 +4,8 @@
$(CC) -Wall -fPIC -lifconfig -g -o example_setmtu setmtu.c
$(CC) -Wall -fPIC -lifconfig -g -o example_ifdestroy ifdestroy.c
$(CC) -Wall -fPIC -lifconfig -g -o example_ifcreate ifcreate.c
+ $(CC) -Wall -fPIC -lifconfig -g -o example_ifcreatevlan ifcreatevlan.c
+ $(CC) -Wall -fPIC -lifconfig -g -o example_ifchanagevlan ifchanagevlan.c
+ $(CC) -Wall -fPIC -lifconfig -g -o example_status status.c
clean:
rm -f example_*
Index: head/share/examples/libifconfig/ifchangevlan.c
===================================================================
--- head/share/examples/libifconfig/ifchangevlan.c
+++ head/share/examples/libifconfig/ifchangevlan.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017, Marie Helene Kvello-Aune
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * thislist of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libifconfig.h>
+
+#include <net/if_vlan_var.h>
+
+int
+main(int argc, char *argv[])
+{
+ char *ifname, *parentif;
+ unsigned short vlantag;
+ const char *errstr;
+ ifconfig_handle_t *lifh;
+
+ if (argc != 4) {
+ errx(EINVAL, "Invalid number of arguments."
+ " Should provide exactly three arguments: "
+ "INTERFACE, PARENT_INTERFACE and VLAN_TAG.");
+ }
+
+ /* We have a static number of arguments. Therefore we can do it simple. */
+ ifname = strdup(argv[1]);
+ parentif = strdup(argv[2]);
+ vlantag = strtonum(argv[3], 0, USHRT_MAX, &errstr);
+
+ if (errstr != NULL) {
+ errx(1, "VLAN_TAG must be between 0 and %i.\n", USHRT_MAX);
+ }
+
+ printf("Interface: %s\nNew VLAN tag: %i\n", ifname, vlantag);
+
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(ENOMEM, "Failed to open libifconfig handle.");
+ return (-1);
+ }
+
+ if (ifconfig_set_vlantag(lifh, ifname, parentif, vlantag) == 0) {
+ printf("Successfully changed vlan tag.\n");
+ ifconfig_close(lifh);
+ lifh = NULL;
+ free(ifname);
+ free(parentif);
+ return (0);
+ }
+
+ switch (ifconfig_err_errtype(lifh)) {
+ case SOCKET:
+ warnx("couldn't create socket. This shouldn't happen.\n");
+ break;
+ case IOCTL:
+ if (ifconfig_err_ioctlreq(lifh) == SIOCGETVLAN) {
+ warnx("Target interface isn't a VLAN interface.\n");
+ }
+ if (ifconfig_err_ioctlreq(lifh) == SIOCSETVLAN) {
+ warnx(
+ "Couldn't change VLAN properties of interface.\n");
+ }
+ break;
+ default:
+ warnx(
+ "This is a thorough example accommodating for temporary"
+ " 'not implemented yet' errors. That's likely what happened"
+ " now. If not, your guess is as good as mine. ;)"
+ " Error code: %d\n", ifconfig_err_errno(
+ lifh));
+ break;
+ }
+
+ ifconfig_close(lifh);
+ lifh = NULL;
+ free(ifname);
+ free(parentif);
+ return (-1);
+}
Index: head/share/examples/libifconfig/ifcreate.c
===================================================================
--- head/share/examples/libifconfig/ifcreate.c
+++ head/share/examples/libifconfig/ifcreate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -40,6 +40,7 @@
main(int argc, char *argv[])
{
char *ifname, *ifactualname;
+ ifconfig_handle_t *lifh;
if (argc != 2) {
errx(EINVAL, "Invalid number of arguments."
@@ -52,7 +53,12 @@
printf("Requested interface name: %s\n", ifname);
- ifconfig_handle_t *lifh = ifconfig_open();
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(ENOMEM, "Failed to open libifconfig handle.");
+ return (-1);
+ }
+
if (ifconfig_create_interface(lifh, ifname, &ifactualname) == 0) {
printf("Successfully created interface '%s'\n", ifactualname);
ifconfig_close(lifh);
Index: head/share/examples/libifconfig/ifcreatevlan.c
===================================================================
--- head/share/examples/libifconfig/ifcreatevlan.c
+++ head/share/examples/libifconfig/ifcreatevlan.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, Marie Helene Kvello-Aune
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * thislist of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libifconfig.h>
+
+
+int
+main(int argc, char *argv[])
+{
+ char *parentif, *ifactualname;
+ unsigned short vlantag;
+ const char *errstr;
+ ifconfig_handle_t *lifh;
+
+ if (argc != 3) {
+ errx(EINVAL, "Invalid number of arguments."
+ " Should provide exactly two arguments: "
+ "PARENT_INTERFACE and VLAN_TAG.");
+ }
+
+ /* We have a static number of arguments. Therefore we can do it simple. */
+ parentif = strdup(argv[1]);
+ vlantag = strtonum(argv[2], 0, USHRT_MAX, &errstr);
+
+ if (errstr != NULL) {
+ errx(1, "VLAN_TAG must be between 0 and %i.\n", USHRT_MAX);
+ }
+
+ printf("Parent interface: %s\nVLAN tag: %i\n", parentif, vlantag);
+
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(ENOMEM, "Failed to open libifconfig handle.");
+ return (-1);
+ }
+
+ if (ifconfig_create_interface_vlan(lifh, "vlan", &ifactualname,
+ parentif, vlantag) == 0) {
+ printf("Successfully created interface '%s'\n", ifactualname);
+ ifconfig_close(lifh);
+ lifh = NULL;
+ free(parentif);
+ free(ifactualname);
+ return (0);
+ }
+
+ switch (ifconfig_err_errtype(lifh)) {
+ case SOCKET:
+ warnx("couldn't create socket. This shouldn't happen.\n");
+ break;
+ case IOCTL:
+ if (ifconfig_err_ioctlreq(lifh) == SIOCIFCREATE2) {
+ warnx(
+ "Failed to create interface (SIOCIFCREATE2)\n");
+ }
+ break;
+ default:
+ warnx(
+ "This is a thorough example accommodating for temporary"
+ " 'not implemented yet' errors. That's likely what happened"
+ " now. If not, your guess is as good as mine. ;)"
+ " Error code: %d\n", ifconfig_err_errno(
+ lifh));
+ break;
+ }
+
+ ifconfig_close(lifh);
+ lifh = NULL;
+ free(parentif);
+ free(ifactualname);
+ return (-1);
+}
Index: head/share/examples/libifconfig/ifdestroy.c
===================================================================
--- head/share/examples/libifconfig/ifdestroy.c
+++ head/share/examples/libifconfig/ifdestroy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -40,6 +40,7 @@
main(int argc, char *argv[])
{
char *ifname;
+ ifconfig_handle_t *lifh;
if (argc != 2) {
errx(EINVAL, "Invalid number of arguments."
@@ -52,7 +53,12 @@
printf("Interface name: %s\n", ifname);
- ifconfig_handle_t *lifh = ifconfig_open();
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(ENOMEM, "Failed to open libifconfig handle.");
+ return (-1);
+ }
+
if (ifconfig_destroy_interface(lifh, ifname) == 0) {
printf("Successfully destroyed interface '%s'.", ifname);
ifconfig_close(lifh);
Index: head/share/examples/libifconfig/setdescription.c
===================================================================
--- head/share/examples/libifconfig/setdescription.c
+++ head/share/examples/libifconfig/setdescription.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -26,6 +26,9 @@
* $FreeBSD$
*/
+#include <arpa/inet.h>
+#include <net/if.h>
+
#include <err.h>
#include <errno.h>
#include <stdio.h>
@@ -38,6 +41,7 @@
main(int argc, char *argv[])
{
char *ifname, *ifdescr, *curdescr;
+ ifconfig_handle_t *lifh;
if (argc != 3) {
errx(EINVAL, "Invalid number of arguments."
@@ -52,7 +56,12 @@
printf("Interface name: %s\n", ifname);
- ifconfig_handle_t *lifh = ifconfig_open();
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(ENOMEM, "Failed to open libifconfig handle.");
+ return (-1);
+ }
+
if (ifconfig_get_description(lifh, ifname, &curdescr) == 0) {
printf("Old description: %s\n", curdescr);
}
@@ -71,7 +80,7 @@
lifh), "IOCTL(%lu) error",
ifconfig_err_ioctlreq(lifh));
break;
- case OTHER:
+ default:
err(ifconfig_err_errno(lifh), "Other error");
break;
}
Index: head/share/examples/libifconfig/setmtu.c
===================================================================
--- head/share/examples/libifconfig/setmtu.c
+++ head/share/examples/libifconfig/setmtu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Marie Helene Kvello-Aune
+ * Copyright (c) 2016-2017, Marie Helene Kvello-Aune
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@@ -42,6 +42,7 @@
{
char *ifname, *ptr;
int mtu;
+ ifconfig_handle_t *lifh;
if (argc != 3) {
errx(EINVAL, "Invalid number of arguments."
@@ -56,7 +57,12 @@
printf("Interface name: %s\n", ifname);
printf("New MTU: %d", mtu);
- ifconfig_handle_t *lifh = ifconfig_open();
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(ENOMEM, "Failed to open libifconfig handle.");
+ return (-1);
+ }
+
if (ifconfig_set_mtu(lifh, ifname, mtu) == 0) {
printf("Successfully changed MTU of %s to %d\n", ifname, mtu);
ifconfig_close(lifh);
Index: head/share/examples/libifconfig/status.c
===================================================================
--- head/share/examples/libifconfig/status.c
+++ head/share/examples/libifconfig/status.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2017, Spectra Logic Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * thislist of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_lagg.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <netinet/in.h>
+#include <netinet/ip_carp.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+#include <err.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libifconfig.h>
+
+static const char *carp_states[] = { CARP_STATES };
+
+static void
+print_carp(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct carpreq carpr[CARP_MAXVHID];
+ int i;
+
+ if (ifconfig_carp_get_info(lifh, ifa->ifa_name, carpr, CARP_MAXVHID)) {
+ return; /* Probably not configured on this interface */
+ }
+ for (i = 0; i < carpr[0].carpr_count; i++) {
+ printf("\tcarp: %s vhid %d advbase %d advskew %d",
+ carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid,
+ carpr[i].carpr_advbase, carpr[i].carpr_advskew);
+ printf("\n");
+ }
+}
+
+static void
+print_inet4_addr(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct ifconfig_inet_addr addr;
+ char addr_buf[NI_MAXHOST];
+
+ if (ifconfig_inet_get_addrinfo(lifh, ifa->ifa_name, ifa, &addr) != 0) {
+ return;
+ }
+
+ inet_ntop(AF_INET, &addr.sin->sin_addr, addr_buf, sizeof(addr_buf));
+ printf("\tinet %s", addr_buf);
+
+ if (addr.dst) {
+ printf(" --> %s", inet_ntoa(addr.dst->sin_addr));
+ }
+
+ printf(" netmask 0x%x ", ntohl(addr.netmask->sin_addr.s_addr));
+
+ if ((addr.broadcast != NULL) &&
+ (addr.broadcast->sin_addr.s_addr != 0)) {
+ printf("broadcast %s ", inet_ntoa(addr.broadcast->sin_addr));
+ }
+
+ if (addr.vhid != 0) {
+ printf("vhid %d ", addr.vhid);
+ }
+ printf("\n");
+}
+
+static void
+print_inet6_addr(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct ifconfig_inet6_addr addr;
+ char addr_buf[NI_MAXHOST];
+ struct timespec now;
+
+ /* Print the address */
+ if (ifconfig_inet6_get_addrinfo(lifh, ifa->ifa_name, ifa, &addr) != 0) {
+ err(1, "ifconfig_inet6_get_addrinfo");
+ }
+ if (0 != getnameinfo((struct sockaddr *)addr.sin6, addr.sin6->sin6_len,
+ addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST)) {
+ inet_ntop(AF_INET6, &addr.sin6->sin6_addr, addr_buf,
+ sizeof(addr_buf));
+ }
+ printf("\tinet6 %s", addr_buf);
+
+ if (addr.dstin6) {
+ inet_ntop(AF_INET6, addr.dstin6, addr_buf, sizeof(addr_buf));
+ printf(" --> %s", addr_buf);
+ }
+
+ /* Print the netmask */
+ printf(" prefixlen %d ", addr.prefixlen);
+
+ /* Print the scopeid*/
+ if (addr.sin6->sin6_scope_id) {
+ printf("scopeid 0x%x ", addr.sin6->sin6_scope_id);
+ }
+
+ /* Print the flags */
+ if ((addr.flags & IN6_IFF_ANYCAST) != 0) {
+ printf("anycast ");
+ }
+ if ((addr.flags & IN6_IFF_TENTATIVE) != 0) {
+ printf("tentative ");
+ }
+ if ((addr.flags & IN6_IFF_DUPLICATED) != 0) {
+ printf("duplicated ");
+ }
+ if ((addr.flags & IN6_IFF_DETACHED) != 0) {
+ printf("detached ");
+ }
+ if ((addr.flags & IN6_IFF_DEPRECATED) != 0) {
+ printf("deprecated ");
+ }
+ if ((addr.flags & IN6_IFF_AUTOCONF) != 0) {
+ printf("autoconf ");
+ }
+ if ((addr.flags & IN6_IFF_TEMPORARY) != 0) {
+ printf("temporary ");
+ }
+ if ((addr.flags & IN6_IFF_PREFER_SOURCE) != 0) {
+ printf("prefer_source ");
+ }
+
+ /* Print the lifetimes */
+ clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+ if (addr.lifetime.ia6t_preferred || addr.lifetime.ia6t_expire) {
+ printf("pltime ");
+ if (addr.lifetime.ia6t_preferred) {
+ printf("%ld ", MAX(0l,
+ addr.lifetime.ia6t_preferred - now.tv_sec));
+ } else {
+ printf("infty ");
+ }
+
+ printf("vltime ");
+ if (addr.lifetime.ia6t_expire) {
+ printf("%ld ", MAX(0l,
+ addr.lifetime.ia6t_expire - now.tv_sec));
+ } else {
+ printf("infty ");
+ }
+ }
+
+ /* Print the vhid */
+ if (addr.vhid != 0) {
+ printf("vhid %d ", addr.vhid);
+ }
+ printf("\n");
+}
+
+static void
+print_link_addr(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ char addr_buf[NI_MAXHOST];
+ struct sockaddr_dl *sdl;
+ int n;
+
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ if ((sdl != NULL) && (sdl->sdl_alen > 0)) {
+ if (((sdl->sdl_type == IFT_ETHER) ||
+ (sdl->sdl_type == IFT_L2VLAN) ||
+ (sdl->sdl_type == IFT_BRIDGE)) &&
+ (sdl->sdl_alen == ETHER_ADDR_LEN)) {
+ ether_ntoa_r((struct ether_addr *)LLADDR(sdl),
+ addr_buf);
+ printf("\tether %s\n", addr_buf);
+ } else {
+ n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
+
+ printf("\tlladdr %s\n", link_ntoa(sdl) + n);
+ }
+ }
+}
+
+static void
+print_ifaddr(ifconfig_handle_t *lifh, struct ifaddrs *ifa, void *udata __unused)
+{
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET:
+ print_inet4_addr(lifh, ifa);
+ break;
+ case AF_INET6:
+
+ /*
+ * printing AF_INET6 status requires calling SIOCGIFAFLAG_IN6
+ * and SIOCGIFALIFETIME_IN6. TODO: figure out the best way to
+ * do that from within libifconfig
+ */
+ print_inet6_addr(lifh, ifa);
+ break;
+ case AF_LINK:
+ print_link_addr(lifh, ifa);
+ break;
+ case AF_LOCAL:
+ case AF_UNSPEC:
+ default:
+ /* TODO */
+ break;
+ }
+}
+
+static void
+print_nd6(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct in6_ndireq nd;
+
+ if (ifconfig_get_nd6(lifh, ifa->ifa_name, &nd) == 0) {
+ printf("\tnd6 options=%x\n", nd.ndi.flags);
+ } else {
+ err(1, "Failed to get nd6 options");
+ }
+}
+
+static void
+print_fib(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ int fib;
+
+ if (ifconfig_get_fib(lifh, ifa->ifa_name, &fib) == 0) {
+ printf("\tfib: %d\n", fib);
+ } else {
+ err(1, "Failed to get interface FIB");
+ }
+}
+
+static void
+print_lagg(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct lagg_protos lpr[] = LAGG_PROTOS;
+ struct ifconfig_lagg_status *ls;
+ struct lacp_opreq *lp;
+ const char *proto = "<unknown>";
+ int i;
+
+ if (ifconfig_lagg_get_lagg_status(lifh, ifa->ifa_name, &ls) < 0) {
+ if (ifconfig_err_errno(lifh) == EINVAL) {
+ return;
+ }
+ err(1, "Failed to get interface lagg status");
+ }
+
+ /* First print the proto */
+ for (i = 0; i < nitems(lpr); i++) {
+ if (ls->ra->ra_proto == lpr[i].lpr_proto) {
+ proto = lpr[i].lpr_name;
+ break;
+ }
+ }
+ printf("\tlaggproto %s", proto);
+
+ /* Now print the lagg hash */
+ if (ls->rf->rf_flags & LAGG_F_HASHMASK) {
+ const char *sep = "";
+
+ printf(" lagghash ");
+ if (ls->rf->rf_flags & LAGG_F_HASHL2) {
+ printf("%sl2", sep);
+ sep = ",";
+ }
+ if (ls->rf->rf_flags & LAGG_F_HASHL3) {
+ printf("%sl3", sep);
+ sep = ",";
+ }
+ if (ls->rf->rf_flags & LAGG_F_HASHL4) {
+ printf("%sl4", sep);
+ sep = ",";
+ }
+ }
+ putchar('\n');
+ printf("\tlagg options:\n");
+ printf("\t\tflags=%x", ls->ro->ro_opts);
+ putchar('\n');
+ printf("\t\tflowid_shift: %d\n", ls->ro->ro_flowid_shift);
+ if (ls->ra->ra_proto == LAGG_PROTO_ROUNDROBIN) {
+ printf("\t\trr_limit: %d\n", ls->ro->ro_bkt);
+ }
+ printf("\tlagg statistics:\n");
+ printf("\t\tactive ports: %d\n", ls->ro->ro_active);
+ printf("\t\tflapping: %u\n", ls->ro->ro_flapping);
+ for (i = 0; i < ls->ra->ra_ports; i++) {
+ lp = (struct lacp_opreq *)&ls->ra->ra_port[i].rp_lacpreq;
+ printf("\tlaggport: %s ", ls->ra->ra_port[i].rp_portname);
+ printf("flags=%x", ls->ra->ra_port[i].rp_flags);
+ if (ls->ra->ra_proto == LAGG_PROTO_LACP) {
+ printf(" state=%x", lp->actor_state);
+ }
+ putchar('\n');
+ }
+
+ printf("\n");
+ ifconfig_lagg_free_lagg_status(ls);
+}
+
+static void
+print_laggport(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct lagg_reqport rp;
+
+ if (ifconfig_lagg_get_laggport_status(lifh, ifa->ifa_name, &rp) < 0) {
+ if ((ifconfig_err_errno(lifh) == EINVAL) ||
+ (ifconfig_err_errno(lifh) == ENOENT)) {
+ return;
+ } else {
+ err(1, "Failed to get lagg port status");
+ }
+ }
+
+ printf("\tlaggdev: %s\n", rp.rp_ifname);
+}
+
+static void
+print_groups(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ struct ifgroupreq ifgr;
+ struct ifg_req *ifg;
+ int len;
+ int cnt = 0;
+
+ if (ifconfig_get_groups(lifh, ifa->ifa_name, &ifgr) != 0) {
+ err(1, "Failed to get groups");
+ }
+
+ ifg = ifgr.ifgr_groups;
+ len = ifgr.ifgr_len;
+ for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
+ len -= sizeof(struct ifg_req);
+ if (strcmp(ifg->ifgrq_group, "all")) {
+ if (cnt == 0) {
+ printf("\tgroups: ");
+ }
+ cnt++;
+ printf("%s ", ifg->ifgrq_group);
+ }
+ }
+ if (cnt) {
+ printf("\n");
+ }
+
+ free(ifgr.ifgr_groups);
+}
+
+static void
+print_media(ifconfig_handle_t *lifh, struct ifaddrs *ifa)
+{
+ int i;
+
+ /* Outline:
+ * 1) Determine whether the iface supports SIOGIFMEDIA or SIOGIFXMEDIA
+ * 2) Get the full media list
+ * 3) Print the current media word
+ * 4) Print the active media word, if different
+ * 5) Print the status
+ * 6) Print the supported media list
+ *
+ * How to print the media word:
+ * 1) Get the top-level interface type and description
+ * 2) Print the subtype
+ * 3) For current word only, print the top type, if it exists
+ * 4) Print options list
+ * 5) Print the instance, if there is one
+ *
+ * How to get the top-level interface type
+ * 1) Shift ifmw right by 0x20 and index into IFM_TYPE_DESCRIPTIONS
+ *
+ * How to get the top-level interface subtype
+ * 1) Shift ifmw right by 0x20, index into ifmedia_types_to_subtypes
+ * 2) Iterate through the resulting table's subtypes table, ignoring
+ * aliases. Iterate through the resulting ifmedia_description
+ * tables, finding an entry with the right media subtype
+ */
+ struct ifmediareq *ifmr;
+ char opts[80];
+
+ if (ifconfig_media_get_mediareq(lifh, ifa->ifa_name, &ifmr) != 0) {
+ if (ifconfig_err_errtype(lifh) != OK) {
+ err(1, "Failed to get media info");
+ } else {
+ return; /* Interface doesn't support media info */
+ }
+ }
+
+ printf("\tmedia: %s %s", ifconfig_media_get_type(ifmr->ifm_current),
+ ifconfig_media_get_subtype(ifmr->ifm_current));
+ if (ifmr->ifm_active != ifmr->ifm_current) {
+ printf(" (%s", ifconfig_media_get_subtype(ifmr->ifm_active));
+ ifconfig_media_get_options_string(ifmr->ifm_active, opts,
+ sizeof(opts));
+ if (opts[0] != '\0') {
+ printf(" <%s>)\n", opts);
+ } else {
+ printf(")\n");
+ }
+ } else {
+ printf("\n");
+ }
+
+ if (ifmr->ifm_status & IFM_AVALID) {
+ printf("\tstatus: %s\n",
+ ifconfig_media_get_status(ifmr));
+ }
+
+ printf("\tsupported media:\n");
+ for (i = 0; i < ifmr->ifm_count; i++) {
+ printf("\t\tmedia %s",
+ ifconfig_media_get_subtype(ifmr->ifm_ulist[i]));
+ ifconfig_media_get_options_string(ifmr->ifm_ulist[i], opts,
+ sizeof(opts));
+ if (opts[0] != '\0') {
+ printf(" mediaopt %s\n", opts);
+ } else {
+ printf("\n");
+ }
+ }
+ free(ifmr);
+}
+
+static void
+print_iface(ifconfig_handle_t *lifh, struct ifaddrs *ifa, void *udata __unused)
+{
+ int metric, mtu;
+ char *description = NULL;
+ struct ifconfig_capabilities caps;
+ struct ifstat ifs;
+
+ printf("%s: flags=%x ", ifa->ifa_name, ifa->ifa_flags);
+
+ if (ifconfig_get_metric(lifh, ifa->ifa_name, &metric) == 0) {
+ printf("metric %d ", metric);
+ } else {
+ err(1, "Failed to get interface metric");
+ }
+
+ if (ifconfig_get_mtu(lifh, ifa->ifa_name, &mtu) == 0) {
+ printf("mtu %d\n", mtu);
+ } else {
+ err(1, "Failed to get interface MTU");
+ }
+
+ if (ifconfig_get_description(lifh, ifa->ifa_name, &description) == 0) {
+ printf("\tdescription: %s\n", description);
+ }
+
+ if (ifconfig_get_capability(lifh, ifa->ifa_name, &caps) == 0) {
+ if (caps.curcap != 0) {
+ printf("\toptions=%x\n", caps.curcap);
+ }
+ if (caps.reqcap != 0) {
+ printf("\tcapabilities=%x\n", caps.reqcap);
+ }
+ } else {
+ err(1, "Failed to get interface capabilities");
+ }
+
+ ifconfig_foreach_ifaddr(lifh, ifa, print_ifaddr, NULL);
+
+ /* This paragraph is equivalent to ifconfig's af_other_status funcs */
+ print_nd6(lifh, ifa);
+ print_media(lifh, ifa);
+ print_groups(lifh, ifa);
+ print_fib(lifh, ifa);
+ print_carp(lifh, ifa);
+ print_lagg(lifh, ifa);
+ print_laggport(lifh, ifa);
+
+ if (ifconfig_get_ifstatus(lifh, ifa->ifa_name, &ifs) == 0) {
+ printf("%s", ifs.ascii);
+ }
+
+ free(description);
+}
+
+int
+main(int argc, char *argv[])
+{
+ ifconfig_handle_t *lifh;
+
+ if (argc != 1) {
+ errx(1, "Usage: example_status");
+ }
+
+ lifh = ifconfig_open();
+ if (lifh == NULL) {
+ errx(1, "Failed to open libifconfig handle.");
+ }
+
+ if (ifconfig_foreach_iface(lifh, print_iface, NULL) != 0) {
+ err(1, "Failed to get interfaces");
+ }
+
+ ifconfig_close(lifh);
+ lifh = NULL;
+ return (-1);
+}
Index: head/usr.sbin/wlandebug/wlandebug.c
===================================================================
--- head/usr.sbin/wlandebug/wlandebug.c
+++ head/usr.sbin/wlandebug/wlandebug.c
@@ -38,6 +38,8 @@
#include <sys/types.h>
#include <sys/sysctl.h>
+#include <net/if.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, May 20, 5:40 AM (2 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33321948
Default Alt Text
D14463.id.diff (77 KB)
Attached To
Mode
D14463: libifconfig: multiple feature additions
Attached
Detach File
Event Timeline
Log In to Comment