svn commit: r329853 - in head: lib/libifconfig share/examples/libifconfig usr.sbin/wlandebug

Alan Somers asomers at FreeBSD.org
Fri Feb 23 03:11:44 UTC 2018


Author: asomers
Date: Fri Feb 23 03:11:43 2018
New Revision: 329853
URL: https://svnweb.freebsd.org/changeset/base/329853

Log:
  libifconfig: multiple feature additions
  
  Added the ability to:
  
  * Create virtual interfaces
  * Create vlan interfaces
  * Get interface fib
  * Get interface groups
  * Get interface status
  * Get nd6 info
  * Get media status
  * Get additional ifaddr info in a convenient struct
  * Get vhids
  * Get carp info
  * Get lagg and laggport status
  * Iterate over all interfaces and ifaddrs
  
  And add more examples, too.
  
  Note that this is a backwards-incompatible change. But that's ok, because it's
  a private library.
  
  MFC after:	3 weeks
  Sponsored by:	Spectra Logic Corp
  Differential Revision:	https://reviews.freebsd.org/D14463

Added:
  head/lib/libifconfig/libifconfig_carp.c   (contents, props changed)
  head/lib/libifconfig/libifconfig_inet.c   (contents, props changed)
  head/lib/libifconfig/libifconfig_inet6.c   (contents, props changed)
  head/lib/libifconfig/libifconfig_lagg.c   (contents, props changed)
  head/lib/libifconfig/libifconfig_media.c   (contents, props changed)
  head/share/examples/libifconfig/ifchangevlan.c   (contents, props changed)
  head/share/examples/libifconfig/ifcreatevlan.c   (contents, props changed)
  head/share/examples/libifconfig/status.c   (contents, props changed)
Modified:
  head/lib/libifconfig/Makefile
  head/lib/libifconfig/libifconfig.c
  head/lib/libifconfig/libifconfig.h
  head/lib/libifconfig/libifconfig_internal.c
  head/lib/libifconfig/libifconfig_internal.h
  head/share/examples/libifconfig/Makefile
  head/share/examples/libifconfig/ifcreate.c
  head/share/examples/libifconfig/ifdestroy.c
  head/share/examples/libifconfig/setdescription.c
  head/share/examples/libifconfig/setmtu.c
  head/usr.sbin/wlandebug/wlandebug.c

Modified: head/lib/libifconfig/Makefile
==============================================================================
--- head/lib/libifconfig/Makefile	Fri Feb 23 02:53:50 2018	(r329852)
+++ head/lib/libifconfig/Makefile	Fri Feb 23 03:11:43 2018	(r329853)
@@ -8,7 +8,9 @@ NO_PIC= 
 
 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 @@ INCS=		libifconfig.h
 #MAN=		libifconfig.3
 
 CFLAGS+= -I${.CURDIR}
-WARNS?=6
+NO_WCAST_ALIGN= yes
 
 .include <bsd.lib.mk>

Modified: head/lib/libifconfig/libifconfig.c
==============================================================================
--- head/lib/libifconfig/libifconfig.c	Fri Feb 23 02:53:50 2018	(r329852)
+++ head/lib/libifconfig/libifconfig.c	Fri Feb 23 03:11:43 2018	(r329853)
@@ -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 @@ ifconfig_close(ifconfig_handle_t *h)
 			(void)close(h->sockets[i]);
 		}
 	}
+	freeifaddrs(h->ifap);
 	free(h);
 }
 
@@ -157,6 +125,46 @@ ifconfig_err_ioctlreq(ifconfig_handle_t *h)
 }
 
 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 @@ ifconfig_get_description(ifconfig_handle_t *h, const c
 		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 @@ ifconfig_get_description(ifconfig_handle_t *h, const c
 			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 @@ ifconfig_set_description(ifconfig_handle_t *h, const c
 		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 @@ ifconfig_unset_description(ifconfig_handle_t *h, const
 	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 @@ ifconfig_set_name(ifconfig_handle_t *h, const char *na
 
 	(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 @@ int
 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 @@ ifconfig_set_mtu(ifconfig_handle_t *h, const char *nam
 	(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 @@ ifconfig_get_mtu(ifconfig_handle_t *h, const char *nam
 	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 @@ ifconfig_get_mtu(ifconfig_handle_t *h, const char *nam
 }
 
 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 @@ ifconfig_set_metric(ifconfig_handle_t *h, const char *
 	(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 @@ ifconfig_get_metric(ifconfig_handle_t *h, const char *
 	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 @@ ifconfig_set_capability(ifconfig_handle_t *h, const ch
 
 	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 @@ ifconfig_set_capability(ifconfig_handle_t *h, const ch
 	 * 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 @@ ifconfig_get_capability(ifconfig_handle_t *h, const ch
 	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 @@ ifconfig_get_capability(ifconfig_handle_t *h, const ch
 }
 
 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 @@ ifconfig_destroy_interface(ifconfig_handle_t *h, const
 	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 @@ ifconfig_create_interface(ifconfig_handle_t *h, const 
 	struct ifreq ifr;
 
 	memset(&ifr, 0, sizeof(ifr));
+
 	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 
 	/*
@@ -512,5 +574,57 @@ ifconfig_create_interface(ifconfig_handle_t *h, const 
 	}
 
 	*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(&params, 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(&params, 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);
 }

Modified: head/lib/libifconfig/libifconfig.h
==============================================================================
--- head/lib/libifconfig/libifconfig.h	Fri Feb 23 02:53:50 2018	(r329852)
+++ head/lib/libifconfig/libifconfig.h	Fri Feb 23 03:11:43 2018	(r329853)
@@ -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 @@ typedef enum {
  * 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 @@ struct ifconfig_capabilities {
 	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 @@ ifconfig_errtype ifconfig_err_errtype(ifconfig_handle_
 /** 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 @@ int ifconfig_set_name(ifconfig_handle_t *h, const char
     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_set_capability(ifconfig_handle_t *h, cons
 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_destroy_interface(ifconfig_handle_t *h, c
  */
 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);

Added: head/lib/libifconfig/libifconfig_carp.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifconfig/libifconfig_carp.c	Fri Feb 23 03:11:43 2018	(r329853)
@@ -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);
+}

Added: head/lib/libifconfig/libifconfig_inet.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifconfig/libifconfig_inet.c	Fri Feb 23 03:11:43 2018	(r329853)
@@ -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);
+}

Added: head/lib/libifconfig/libifconfig_inet6.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifconfig/libifconfig_inet6.c	Fri Feb 23 03:11:43 2018	(r329853)
@@ -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$
+ */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list