svn commit: r304815 - in head: lib lib/libifc share/examples/libifc share/mk

Kristof Provost kp at FreeBSD.org
Thu Aug 25 19:40:27 UTC 2016


Author: kp
Date: Thu Aug 25 19:40:25 2016
New Revision: 304815
URL: https://svnweb.freebsd.org/changeset/base/304815

Log:
  Add libifc, a library implementing core functionality that exists in ifconfig(8) today.
  
  libifc (pronounced lib-ifconfig) aims to be a light abstraction layer between
  programs and the kernel APIs for managing the network configuration.
  This should hopefully make programs easier to maintain, and reduce code
  duplication.
  
  Work will begin on making ifconfig(8) use this library in the near future.
  
  This code is still evolving. The interface should not be considered stable until
  it is announced as such.
  
  Submitted By: Marie Helene Kvello-Aune <marieheleneka at gmail.com>
  Reviewed By: kp
  Differential Revision: https://reviews.freebsd.org/D7529

Added:
  head/lib/libifc/
  head/lib/libifc/Makefile   (contents, props changed)
  head/lib/libifc/libifc.c   (contents, props changed)
  head/lib/libifc/libifc.h   (contents, props changed)
  head/lib/libifc/libifc_internal.c   (contents, props changed)
  head/lib/libifc/libifc_internal.h   (contents, props changed)
  head/share/examples/libifc/
  head/share/examples/libifc/Makefile   (contents, props changed)
  head/share/examples/libifc/ifcreate.c   (contents, props changed)
  head/share/examples/libifc/ifdestroy.c   (contents, props changed)
  head/share/examples/libifc/setdescription.c   (contents, props changed)
  head/share/examples/libifc/setmtu.c   (contents, props changed)
Modified:
  head/lib/Makefile
  head/share/mk/bsd.libnames.mk
  head/share/mk/src.libnames.mk

Modified: head/lib/Makefile
==============================================================================
--- head/lib/Makefile	Thu Aug 25 19:36:58 2016	(r304814)
+++ head/lib/Makefile	Thu Aug 25 19:40:25 2016	(r304815)
@@ -60,6 +60,7 @@ SUBDIR=	${SUBDIR_BOOTSTRAP} \
 	${_libgssapi} \
 	${_librpcsec_gss} \
 	${_libiconv_modules} \
+	libifc \
 	libipsec \
 	libjail \
 	libkiconv \

Added: head/lib/libifc/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifc/Makefile	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+PACKAGE=	lib${LIB}
+LIB=		ifc
+# Don't build shared library, for now.
+NO_PIC= 
+
+SHLIBDIR?=	/lib
+SHLIB_MAJOR=	1
+SRCS=		libifc.c libifc_internal.c
+
+INCSDIR=	${INCLUDEDIR}
+INCS=		libifc.h
+
+#MAN=		libifco.3
+
+CFLAGS+= -I${.CURDIR}
+WARNS?=6
+
+.include <bsd.lib.mk>

Added: head/lib/libifc/libifc.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifc/libifc.c	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,397 @@
+/*
+ * 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.
+ *
+ * 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.
+ * 4. 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.
+ */
+
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libifc.h"
+#include "libifc_internal.h"
+
+
+libifc_handle_t *
+libifc_open(void)
+{
+	struct libifc_handle *h;
+
+	h = calloc(1, sizeof(struct libifc_handle));
+
+	for (int i = 0; i <= AF_MAX; i++) {
+		h->sockets[i] = -1;
+	}
+
+	return (h);
+}
+
+
+void
+libifc_close(libifc_handle_t *h)
+{
+	for (int i = 0; i <= AF_MAX; i++) {
+		if (h->sockets[i] != -1) {
+			(void)close(h->sockets[i]);
+		}
+	}
+	free(h);
+}
+
+
+libifc_errtype
+libifc_err_errtype(libifc_handle_t *h)
+{
+	return (h->error.errtype);
+}
+
+
+int
+libifc_err_errno(libifc_handle_t *h)
+{
+	return (h->error.errcode);
+}
+
+
+unsigned long
+libifc_err_ioctlreq(libifc_handle_t *h)
+{
+	return (h->error.ioctl_request);
+}
+
+
+int
+libifc_get_description(libifc_handle_t *h, const char *name, char **description)
+{
+	struct ifreq ifr;
+	char *descr = NULL;
+	size_t descrlen = 64;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	for (;;) {
+		if ((descr = reallocf(descr, descrlen)) == NULL) {
+			h->error.errtype = OTHER;
+			h->error.errcode = ENOMEM;
+			return (-1);
+		}
+
+		ifr.ifr_buffer.buffer = descr;
+		ifr.ifr_buffer.length = descrlen;
+		if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFDESCR,
+		    &ifr) != 0) {
+			return (-1);
+		}
+
+		if (ifr.ifr_buffer.buffer == descr) {
+			if (strlen(descr) > 0) {
+				*description = strdup(descr);
+				free(descr);
+				return (0);
+			}
+		} else if (ifr.ifr_buffer.length > descrlen) {
+			descrlen = ifr.ifr_buffer.length;
+			continue;
+		}
+		break;
+	}
+	free(descr);
+	h->error.errtype = OTHER;
+	h->error.errcode = 0;
+	return (-1);
+}
+
+
+int
+libifc_set_description(libifc_handle_t *h, const char *name,
+    const char *newdescription)
+{
+	struct ifreq ifr;
+	int desclen;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	desclen = strlen(newdescription);
+
+	/*
+	 * Unset description if the new description is 0 characters long.
+	 * TODO: Decide whether this should be an error condition instead.
+	 */
+	if (desclen == 0) {
+		return (libifc_unset_description(h, name));
+	}
+
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+	ifr.ifr_buffer.length = desclen + 1;
+	ifr.ifr_buffer.buffer = strdup(newdescription);
+	if (ifr.ifr_buffer.buffer == NULL) {
+		h->error.errtype = OTHER;
+		h->error.errcode = ENOMEM;
+		return (-1);
+	}
+
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) != 0) {
+		free(ifr.ifr_buffer.buffer);
+		return (-1);
+	}
+	free(ifr.ifr_buffer.buffer);
+	return (0);
+}
+
+
+int libifc_unset_description(libifc_handle_t *h, const char *name)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	ifr.ifr_buffer.length = 0;
+	ifr.ifr_buffer.buffer = NULL;
+
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFDESCR, &ifr) < 0) {
+		return (-1);
+	}
+	return (0);
+}
+
+
+int libifc_set_name(libifc_handle_t *h, const char *name, const char *newname)
+{
+	struct ifreq ifr;
+	char *tmpname;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	tmpname = strdup(newname);
+	if (tmpname == NULL) {
+		h->error.errtype = OTHER;
+		h->error.errcode = ENOMEM;
+		return (-1);
+	}
+
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	ifr.ifr_data = tmpname;
+
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFNAME, &ifr) != 0) {
+		free(tmpname);
+		return (-1);
+	}
+	free(tmpname);
+	return (0);
+}
+
+
+int libifc_set_mtu(libifc_handle_t *h, const char *name, const int mtu)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	ifr.ifr_mtu = mtu;
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFMTU, &ifr) < 0) {
+		return (-1);
+	}
+	return (0);
+}
+
+
+int libifc_get_mtu(libifc_handle_t *h, const char *name, int *mtu)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFMTU, &ifr) == -1) {
+		return (-1);
+	}
+	*mtu = ifr.ifr_mtu;
+	return (0);
+}
+
+
+int libifc_set_metric(libifc_handle_t *h, const char *name, const int mtu)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	ifr.ifr_mtu = mtu;
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFMETRIC, &ifr) < 0) {
+		return (-1);
+	}
+	return (0);
+}
+
+
+int libifc_get_metric(libifc_handle_t *h, const char *name, int *metric)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFMETRIC, &ifr) == -1) {
+		return (-1);
+	}
+	*metric = ifr.ifr_metric;
+	return (0);
+}
+
+
+int libifc_set_capability(libifc_handle_t *h, const char *name,
+    const int capability)
+{
+	struct ifreq ifr;
+	struct libifc_capabilities ifcap;
+	int flags;
+	int value;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	if (libifc_get_capability(h, name, &ifcap) != 0) {
+		return (-1);
+	}
+
+	value = capability;
+	flags = ifcap.curcap;
+	if (value < 0) {
+		value = -value;
+		flags &= ~value;
+	} else {
+		flags |= value;
+	}
+	flags &= ifcap.reqcap;
+
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+	/*
+	 * TODO: Verify that it's safe to not have ifr.ifr_curcap
+	 * set for this request.
+	 */
+	ifr.ifr_reqcap = flags;
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCSIFCAP, &ifr) < 0) {
+		return (-1);
+	}
+	return (0);
+}
+
+
+int libifc_get_capability(libifc_handle_t *h, const char *name,
+    struct libifc_capabilities *capability)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCGIFCAP, &ifr) < 0) {
+		return (-1);
+	}
+	capability->curcap = ifr.ifr_curcap;
+	capability->reqcap = ifr.ifr_reqcap;
+	return (0);
+}
+
+
+int libifc_destroy_interface(libifc_handle_t *h, const char *name)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCIFDESTROY, &ifr) < 0) {
+		return (-1);
+	}
+	return (0);
+}
+
+
+int libifc_create_interface(libifc_handle_t *h, const char *name, char **ifname)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(struct ifreq));
+	(void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+	/*
+	 * TODO:
+	 * Insert special snowflake handling here. See GitHub issue #12 for details.
+	 * In the meantime, hard-nosupport interfaces that need special handling.
+	 */
+	if ((strncmp(name, "wlan", strlen("wlan")) == 0) ||
+	    (strncmp(name, "vlan", strlen("vlan")) == 0) ||
+	    (strncmp(name, "vxlan", strlen("vxlan")) == 0)) {
+		h->error.errtype = OTHER;
+		h->error.errcode = ENOSYS;
+		return (-1);
+	}
+
+	/* No special handling for this interface type. */
+
+	if (libifc_ioctlwrap(h, AF_LOCAL, SIOCIFCREATE2, &ifr) < 0) {
+		return (-1);
+	}
+	*ifname = strdup(ifr.ifr_name);
+	return (0);
+}

Added: head/lib/libifc/libifc.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifc/libifc.h	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,111 @@
+/*
+ * 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$
+ */
+
+#pragma once
+
+typedef enum {
+	OTHER, IOCTL, SOCKET
+} libifc_errtype;
+
+/*
+ * Opaque definition so calling application can just pass a
+ * pointer to it for library use.
+ */
+struct libifc_handle;
+typedef struct libifc_handle   libifc_handle_t;
+
+struct libifc_capabilities {
+	/** Current capabilities (ifconfig prints this as 'options')*/
+	int curcap;
+	/** Requested capabilities (ifconfig prints this as 'capabilities')*/
+	int reqcap;
+};
+
+
+/** Retrieves a new state object for use in other API calls.
+ * Example usage:
+ *{@code
+ * // Create state object
+ * libifc_handle_t *lifh = libifc_open();
+ *
+ * // Do stuff with it
+ *
+ * // Dispose of the state object
+ * libifc_close(lifh);
+ * lifh = NULL;
+ *}
+ */
+libifc_handle_t *libifc_open(void);
+
+/** Frees resources held in the provided state object.
+ * @param h The state object to close.
+ * @see #libifc_open(void)
+ */
+void libifc_close(libifc_handle_t *h);
+
+/** Identifies what kind of error occured. */
+libifc_errtype libifc_err_errtype(libifc_handle_t *h);
+
+/** Retrieves the errno associated with the error, if any. */
+int libifc_err_errno(libifc_handle_t *h);
+
+/** If error type was IOCTL, this identifies which request failed. */
+unsigned long libifc_err_ioctlreq(libifc_handle_t *h);
+
+int libifc_get_description(libifc_handle_t *h, const char *name,
+    char **description);
+int libifc_set_description(libifc_handle_t *h, const char *name,
+    const char *newdescription);
+int libifc_unset_description(libifc_handle_t *h, const char *name);
+int libifc_set_name(libifc_handle_t *h, const char *name, const char *newname);
+int libifc_set_mtu(libifc_handle_t *h, const char *name, const int mtu);
+int libifc_get_mtu(libifc_handle_t *h, const char *name, int *mtu);
+
+int libifc_set_metric(libifc_handle_t *h, const char *name, const int metric);
+int libifc_get_metric(libifc_handle_t *h, const char *name, int *metric);
+
+int libifc_set_capability(libifc_handle_t *h, const char *name,
+    const int capability);
+int libifc_get_capability(libifc_handle_t *h, const char *name,
+    struct libifc_capabilities *capability);
+
+/** Destroy a virtual interface
+ * @param name Interface to destroy
+ */
+int libifc_destroy_interface(libifc_handle_t *h, const char *name);
+
+/** Creates a (virtual) interface
+ * @param name Name of interface to create. Example: bridge or bridge42
+ * @param name ifname Is set to actual name of created interface
+ */
+int libifc_create_interface(libifc_handle_t *h, const char *name,
+    char **ifname);

Added: head/lib/libifc/libifc_internal.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifc/libifc_internal.c	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,100 @@
+/*
+ * 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$
+ */
+
+
+#include <net/if.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+
+#include "libifc.h" // Needed for libifc_errstate
+#include "libifc_internal.h"
+
+int
+libifc_ioctlwrap_ret(libifc_handle_t *h, unsigned long request, int rcode)
+{
+	if (rcode != 0) {
+		h->error.errtype = IOCTL;
+		h->error.ioctl_request = request;
+		h->error.errcode = errno;
+	}
+	return (rcode);
+}
+
+
+int
+libifc_ioctlwrap(libifc_handle_t *h, const int addressfamily,
+    unsigned long request, struct ifreq *ifr)
+{
+	int s;
+
+	if (libifc_socket(h, addressfamily, &s) != 0) {
+		return (-1);
+	}
+
+	int rcode = ioctl(s, request, ifr);
+	return (libifc_ioctlwrap_ret(h, request, rcode));
+}
+
+
+/*
+ * Function to get socket for the specified address family.
+ * If the socket doesn't already exist, attempt to create it.
+ */
+int libifc_socket(libifc_handle_t *h, const int addressfamily, int *s)
+{
+	if (addressfamily > AF_MAX) {
+		h->error.errtype = SOCKET;
+		h->error.errcode = EINVAL;
+		return (-1);
+	}
+
+	if (h->sockets[addressfamily] != -1) {
+		*s = h->sockets[addressfamily];
+		return (0);
+	}
+
+	/* We don't have a socket of that type available. Create one. */
+	h->sockets[addressfamily] = socket(addressfamily, SOCK_DGRAM, 0);
+	if (h->sockets[addressfamily] == -1) {
+		h->error.errtype = SOCKET;
+		h->error.errcode = errno;
+		return (-1);
+	}
+
+	*s = h->sockets[addressfamily];
+	return (0);
+}

Added: head/lib/libifc/libifc_internal.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libifc/libifc_internal.h	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,87 @@
+/*
+ * 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$
+ */
+
+#pragma once
+
+#include "libifc.h"
+
+
+struct errstate {
+	/**
+	 * Type of error.
+	 */
+	libifc_errtype errtype;
+
+	/**
+	 * The error occured in this ioctl() request.
+	 * Populated if errtype = IOCTL
+	 */
+	unsigned long ioctl_request;
+
+	/**
+	 * The value of the global errno variable when the error occured.
+	 */
+	int errcode;
+};
+
+struct libifc_handle {
+	struct errstate error;
+	int sockets[AF_MAX + 1];
+};
+
+/**
+ * Retrieves socket for address family <paramref name="addressfamily"> from
+ * cache, or creates it if it doesn't already exist.
+ * @param addressfamily The address family of the socket to retrieve
+ * @param s The retrieved socket.
+ * @return 0 on success, -1 on failure.
+ * {@example
+ * This example shows how to retrieve a socket from the cache.
+ * {@code
+ * static void myfunc() \{
+ *    int s;
+ *    if (libifc_socket(AF_LOCAL, &s) != 0) \{
+ *        // Handle error state here
+ *    \}
+ *    // user code here
+ * \}
+ * }
+ * }
+ */
+int libifc_socket(libifc_handle_t *h, const int addressfamily, int *s);
+
+/** Function used by other wrapper functions to populate _errstate when appropriate.*/
+int libifc_ioctlwrap_ret(libifc_handle_t *h, unsigned long request, int rcode);
+
+/** Function to wrap ioctl() and automatically populate libifc_errstate when appropriate.*/
+int libifc_ioctlwrap(libifc_handle_t *h, const int addressfamily,
+    unsigned long request, struct ifreq *ifr);

Added: head/share/examples/libifc/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/examples/libifc/Makefile	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+default:
+	$(CC) -Wall -fPIC -lifc -g -o example_setdescription setdescription.c
+	$(CC) -Wall -fPIC -lifc -g -o example_setmtu setmtu.c
+	$(CC) -Wall -fPIC -lifc -g -o example_ifdestroy ifdestroy.c
+	$(CC) -Wall -fPIC -lifc -g -o example_ifcreate ifcreate.c
+clean:
+	rm -f example_*

Added: head/share/examples/libifc/ifcreate.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/examples/libifc/ifcreate.c	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,93 @@
+/*
+ * 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$
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libifc.h>
+
+
+int main(int argc, char *argv[])
+{
+	if (argc != 2) {
+		errx(EINVAL, "Invalid number of arguments."
+		    " Only one argument is accepted, and it should be the name"
+		    " of the interface to be created.");
+	}
+
+	char *ifname, *ifactualname;
+
+	/* We have a static number of arguments. Therefore we can do it simple. */
+	ifname = strdup(argv[1]);
+
+	printf("Requested interface name: %s\n", ifname);
+
+	libifc_handle_t *lifh = libifc_open();
+	if (libifc_create_interface(lifh, ifname, &ifactualname) == 0) {
+		printf("Successfully created interface '%s'\n", ifactualname);
+		libifc_close(lifh);
+		lifh = NULL;
+		free(ifname);
+		free(ifactualname);
+		return (0);
+	} else {
+		switch (libifc_err_errtype(lifh)) {
+		case SOCKET:
+			warnx("couldn't create socket. This shouldn't happen.\n");
+			break;
+		case IOCTL:
+			if (libifc_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", libifc_err_errno(
+					lifh));
+			break;
+		}
+
+		libifc_close(lifh);
+		lifh = NULL;
+		free(ifname);
+		free(ifactualname);
+		return (-1);
+	}
+}

Added: head/share/examples/libifc/ifdestroy.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/examples/libifc/ifdestroy.c	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,87 @@
+/*
+ * 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$
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libifc.h>
+
+
+int main(int argc, char *argv[])
+{
+	if (argc != 2) {
+		errx(EINVAL, "Invalid number of arguments."
+		    " Only one argument is accepted, and it should be the name"
+		    " of the interface to be destroyed.");
+	}
+
+	char *ifname;
+
+	/* We have a static number of arguments. Therefore we can do it simple. */
+	ifname = strdup(argv[1]);
+
+	printf("Interface name: %s\n", ifname);
+
+	libifc_handle_t *lifh = libifc_open();
+	if (libifc_destroy_interface(lifh, ifname) == 0) {
+		printf("Successfully destroyed interface '%s'.", ifname);
+		libifc_close(lifh);
+		lifh = NULL;
+		free(ifname);
+		return (0);
+	} else {
+		switch (libifc_err_errtype(lifh)) {
+		case SOCKET:
+			warnx("couldn't create socket. This shouldn't happen.\n");
+			break;
+		case IOCTL:
+			if (libifc_err_ioctlreq(lifh) == SIOCIFDESTROY) {
+				warnx(
+					"Failed to destroy interface (SIOCIFDESTROY)\n");
+			}
+			break;
+		default:
+			warnx(
+				"Should basically never end up here in this example.\n");
+			break;
+		}
+
+		libifc_close(lifh);
+		lifh = NULL;
+		free(ifname);
+		return (-1);
+	}
+}

Added: head/share/examples/libifc/setdescription.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/examples/libifc/setdescription.c	Thu Aug 25 19:40:25 2016	(r304815)
@@ -0,0 +1,91 @@
+/*
+ * 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$
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libifc.h>
+
+
+int main(int argc, char *argv[])
+{
+	if (argc != 3) {
+		errx(EINVAL, "Invalid number of arguments."
+		    " First argument should be interface name, second argument"
+		    " should be the description to set.");
+	}
+
+	char *ifname, *ifdescr, *curdescr;
+	/* We have a static number of arguments. Therefore we can do it simple. */
+	ifname = strdup(argv[1]);
+	ifdescr = strdup(argv[2]);
+	curdescr = NULL;
+
+	printf("Interface name: %s\n", ifname);
+
+	libifc_handle_t *lifh = libifc_open();
+	if (libifc_get_description(lifh, ifname, &curdescr) == 0) {
+		printf("Old description: %s\n", curdescr);

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


More information about the svn-src-all mailing list