Index: lib/libifc/Makefile =================================================================== --- lib/libifc/Makefile +++ lib/libifc/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +PACKAGE= lib${LIB} +LIB= ifc + +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 Index: lib/libifc/libifc.h =================================================================== --- lib/libifc/libifc.h +++ lib/libifc/libifc.h @@ -0,0 +1,109 @@ +/* + * 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. + */ + +#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); Index: lib/libifc/libifc.c =================================================================== --- lib/libifc/libifc.c +++ lib/libifc/libifc.c @@ -0,0 +1,395 @@ +/* + * 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. + */ + +/* + * 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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "libifc.h" +#include "libifc_internal.h" + + +libifc_handle_t * +libifc_open() +{ + 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); +} Index: lib/libifc/libifc_internal.h =================================================================== --- lib/libifc/libifc_internal.h +++ lib/libifc/libifc_internal.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#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 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); Index: lib/libifc/libifc_internal.c =================================================================== --- lib/libifc/libifc_internal.c +++ lib/libifc/libifc_internal.c @@ -0,0 +1,98 @@ +/* + * 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. + */ + + +#include + +#include +#include +#include +#include +#include + + +#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); +} Index: share/examples/libifc/Makefile =================================================================== --- share/examples/libifc/Makefile +++ share/examples/libifc/Makefile @@ -0,0 +1,7 @@ +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_* Index: share/examples/libifc/ifcreate.c =================================================================== --- share/examples/libifc/ifcreate.c +++ share/examples/libifc/ifcreate.c @@ -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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +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); + } +} Index: share/examples/libifc/ifdestroy.c =================================================================== --- share/examples/libifc/ifdestroy.c +++ share/examples/libifc/ifdestroy.c @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +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); + } +} Index: share/examples/libifc/setdescription.c =================================================================== --- share/examples/libifc/setdescription.c +++ share/examples/libifc/setdescription.c @@ -0,0 +1,89 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + + +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); + } + + printf("New description: %s\n\n", ifdescr); + + if (libifc_set_description(lifh, ifname, ifdescr) == 0) { + printf("New description successfully set.\n"); + } else { + switch (libifc_err_errtype(lifh)) { + case SOCKET: + err(libifc_err_errno(lifh), "Socket error"); + break; + case IOCTL: + err(libifc_err_errno( + lifh), "IOCTL(%lu) error", + libifc_err_ioctlreq(lifh)); + break; + case OTHER: + err(libifc_err_errno(lifh), "Other error"); + break; + } + } + + free(ifname); + free(ifdescr); + free(curdescr); + ifname = NULL; + ifdescr = NULL; + curdescr = NULL; + + libifc_close(lifh); + return (0); +} Index: share/examples/libifc/setmtu.c =================================================================== --- share/examples/libifc/setmtu.c +++ share/examples/libifc/setmtu.c @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +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 MTU to set."); + } + + char *ifname, *ptr; + int mtu; + + /* We have a static number of arguments. Therefore we can do it simple. */ + ifname = strdup(argv[1]); + mtu = (int)strtol(argv[2], &ptr, 10); + + printf("Interface name: %s\n", ifname); + printf("New MTU: %d", mtu); + + libifc_handle_t *lifh = libifc_open(); + if (libifc_set_mtu(lifh, ifname, mtu) == 0) { + printf("Successfully changed MTU of %s to %d\n", ifname, mtu); + 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) == SIOCSIFMTU) { + warnx("Failed to set MTU (SIOCSIFMTU)\n"); + } else { + warnx( + "Failed to set MTU due to error in unexpected ioctl() call %lu. Error code: %i.\n", + libifc_err_ioctlreq(lifh), + libifc_err_errno(lifh)); + } + break; + default: + warnx( + "Should basically never end up here in this example.\n"); + break; + } + + libifc_close(lifh); + lifh = NULL; + free(ifname); + return (-1); + } +} Index: share/mk/bsd.libnames.mk =================================================================== --- share/mk/bsd.libnames.mk +++ share/mk/bsd.libnames.mk @@ -82,6 +82,7 @@ LIBIBSDP?= ${DESTDIR}${LIBDIR}/libibsdp.a LIBIBUMAD?= ${DESTDIR}${LIBDIR}/libibumad.a LIBIBVERBS?= ${DESTDIR}${LIBDIR}/libibverbs.a +LIBIFC?= ${DESTDIR}${LIBDIR}/libifc.a LIBIPSEC?= ${DESTDIR}${LIBDIR}/libipsec.a LIBJAIL?= ${DESTDIR}${LIBDIR}/libjail.a LIBKADM5CLNT?= ${DESTDIR}${LIBDIR}/libkadm5clnt.a Index: share/mk/src.libnames.mk =================================================================== --- share/mk/src.libnames.mk +++ share/mk/src.libnames.mk @@ -105,6 +105,7 @@ heimntlm \ heimsqlite \ hx509 \ + ifc \ ipsec \ jail \ kadm5clnt \