Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F1841553
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/libnozzle/libnozzle.c b/libnozzle/libnozzle.c
index 0ea6e0c6..6cd5c634 100644
--- a/libnozzle/libnozzle.c
+++ b/libnozzle/libnozzle.c
@@ -1,1142 +1,1134 @@
/*
* Copyright (C) 2010-2018 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/ethernet.h>
#include <pthread.h>
#include <limits.h>
#include <stdio.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <stdint.h>
#ifdef KNET_LINUX
#include <linux/if_tun.h>
#include <netinet/ether.h>
#endif
#ifdef KNET_BSD
#include <net/if_dl.h>
#endif
#include "libnozzle.h"
#include "internals.h"
/*
* internal functions are all _unlocked_
* locking should be handled at external API functions
*/
static int lib_init = 0;
static struct nozzle_lib_config lib_cfg;
static pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER;
/*
* internal helpers
*/
-static void _close(nozzle_t nozzle)
-{
-#ifdef KNET_BSD
- struct ifreq ifr;
-#endif
-
- if (!nozzle)
- return;
-
- if (nozzle->fd)
- close(nozzle->fd);
-
-#ifdef KNET_BSD
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifname, nozzle->name, IFNAMSIZ);
-
- ioctl(lib_cfg.ioctlfd, SIOCIFDESTROY, &ifr);
-#endif
-
- free(nozzle);
-
- return;
-}
-
-static void _close_cfg(void)
-{
- if (lib_cfg.head == NULL) {
- close(lib_cfg.ioctlfd);
- lib_init = 0;
- }
-}
-
static int _set_ip(nozzle_t nozzle, const char *command,
const char *ipaddr, const char *prefix,
char **error_string, int secondary)
{
char *broadcast = NULL;
char cmdline[4096];
#ifdef KNET_BSD
char proto[6];
int v4 = 1;
snprintf(proto, sizeof(proto), "inet");
#endif
if (!strchr(ipaddr, ':')) {
broadcast = generate_v4_broadcast(ipaddr, prefix);
if (!broadcast) {
errno = EINVAL;
return -1;
}
}
#ifdef KNET_BSD
else {
v4 = 0;
snprintf(proto, sizeof(proto), "inet6");
}
#endif
memset(cmdline, 0, sizeof(cmdline));
#ifdef KNET_LINUX
if (broadcast) {
snprintf(cmdline, sizeof(cmdline)-1,
"ip addr %s %s/%s dev %s broadcast %s",
command, ipaddr, prefix,
nozzle->name, broadcast);
} else {
snprintf(cmdline, sizeof(cmdline)-1,
"ip addr %s %s/%s dev %s",
command, ipaddr, prefix,
nozzle->name);
}
#endif
#ifdef KNET_BSD
if (!strcmp(command, "add")) {
snprintf(cmdline, sizeof(cmdline)-1,
"ifconfig %s %s %s/%s",
nozzle->name, proto, ipaddr, prefix);
if (broadcast) {
snprintf(cmdline + strlen(cmdline),
sizeof(cmdline) - strlen(cmdline) -1,
" broadcast %s", broadcast);
}
if ((secondary) && (v4)) {
snprintf(cmdline + strlen(cmdline),
sizeof(cmdline) - strlen(cmdline) -1,
" alias");
}
} else {
snprintf(cmdline, sizeof(cmdline)-1,
"ifconfig %s %s %s/%s delete",
nozzle->name, proto, ipaddr, prefix);
}
#endif
if (broadcast) {
free(broadcast);
}
return execute_bin_sh_command(cmdline, error_string);
}
/*
* internal helpers below should be completed
*
* keep all ioctl work within this file
*/
+static void lib_fini(void)
+{
+ if (lib_cfg.head == NULL) {
+ close(lib_cfg.ioctlfd);
+ lib_init = 0;
+ }
+}
+
+static void destroy_iface(nozzle_t nozzle)
+{
+#ifdef KNET_BSD
+ struct ifreq ifr;
+#endif
+
+ if (!nozzle)
+ return;
+
+ if (nozzle->fd)
+ close(nozzle->fd);
+
+#ifdef KNET_BSD
+ memset(&ifr, 0, sizeof(struct ifreq));
+ strncpy(ifname, nozzle->name, IFNAMSIZ);
+
+ ioctl(lib_cfg.ioctlfd, SIOCIFDESTROY, &ifr);
+#endif
+
+ free(nozzle);
+
+ lib_fini();
+
+ return;
+}
+
static int is_valid_nozzle(const nozzle_t nozzle)
{
nozzle_t temp;
if (!nozzle) {
return 0;
}
if (!lib_init) {
return 0;
}
temp = lib_cfg.head;
while (temp != NULL) {
if (nozzle == temp)
return 1;
temp = temp->next;
}
return 0;
}
static int get_iface_mtu(const nozzle_t nozzle)
{
int err = 0, savederrno = 0;
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifname, nozzle->name, IFNAMSIZ);
err = ioctl(lib_cfg.ioctlfd, SIOCGIFMTU, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
err = ifr.ifr_mtu;
out_clean:
errno = savederrno;
return err;
}
static int get_iface_mac(const nozzle_t nozzle, char **ether_addr)
{
int err = 0, savederrno = 0;
struct ifreq ifr;
char mac[MACADDR_CHAR_MAX];
#ifdef KNET_BSD
struct ifaddrs *ifap = NULL;
struct ifaddrs *ifa;
int found = 0;
#endif
memset(&mac, 0, MACADDR_CHAR_MAX);
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifname, nozzle->name, IFNAMSIZ);
#ifdef KNET_LINUX
err = ioctl(lib_cfg.ioctlfd, SIOCGIFHWADDR, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
ether_ntoa_r((struct ether_addr *)ifr.ifr_hwaddr.sa_data, mac);
#endif
#ifdef KNET_BSD
/*
* there is no ioctl to get the ether address of an interface on FreeBSD
* (not to be confused with hwaddr). Use workaround described here:
* https://lists.freebsd.org/pipermail/freebsd-hackers/2004-June/007394.html
*/
err = getifaddrs(&ifap);
if (err < 0) {
savederrno = errno;
goto out_clean;
}
ifa = ifap;
while (ifa) {
if (!strncmp(nozzle->name, ifa->ifa_name, IFNAMSIZ)) {
found = 1;
break;
}
ifa=ifa->ifa_next;
}
if (found) {
ether_ntoa_r((struct ether_addr *)LLADDR((struct sockaddr_dl *)ifa->ifa_addr), mac);
} else {
errno = EINVAL;
err = -1;
}
freeifaddrs(ifap);
if (err) {
goto out_clean;
}
#endif
*ether_addr = strdup(mac);
if (!*ether_addr) {
savederrno = errno;
err = -1;
}
out_clean:
errno = savederrno;
return err;
}
static int set_iface_down(nozzle_t nozzle)
{
int err = 0, savederrno = 0;
struct ifreq ifr;
if (!nozzle->up) {
goto out_clean;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifname, nozzle->name, IFNAMSIZ);
err = ioctl(lib_cfg.ioctlfd, SIOCGIFFLAGS, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
ifr.ifr_flags &= ~IFF_UP;
err = ioctl(lib_cfg.ioctlfd, SIOCSIFFLAGS, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
nozzle->up = 0;
out_clean:
errno = savederrno;
return err;
}
/*
* public API
*/
-nozzle_t nozzle_open(char *devname, size_t devname_size, const char *updownpath)
-{
- int savederrno = 0;
- nozzle_t nozzle = NULL;
- char *temp_mac = NULL;
-#ifdef KNET_LINUX
- struct ifreq ifr;
-#endif
-#ifdef KNET_BSD
- uint16_t i;
- long int nozzlenum = 0;
- char curnozzle[IFNAMSIZ];
-#endif
-
- if (devname == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- if (devname_size < IFNAMSIZ) {
- errno = EINVAL;
- return NULL;
- }
-
- if (strlen(devname) > IFNAMSIZ) {
- errno = E2BIG;
- return NULL;
- }
-
-#ifdef KNET_BSD
- /*
- * BSD does not support named devices like Linux
- * but it is possible to force a nozzleX device number
- * where X is 0 to 255.
- */
- if (strlen(devname)) {
- if (strncmp(devname, "tap", 3)) {
- errno = EINVAL;
- return NULL;
- }
- errno = 0;
- nozzlenum = strtol(devname+3, NULL, 10);
- if (errno) {
- errno = EINVAL;
- return NULL;
- }
- if ((nozzlenum < 0) || (nozzlenum > 255)) {
- errno = EINVAL;
- return NULL;
- }
- }
-#endif
-
- if (updownpath) {
- /* only absolute paths */
- if (updownpath[0] != '/') {
- errno = EINVAL;
- return NULL;
- }
- if (strlen(updownpath) >= UPDOWN_PATH_MAX) {
- errno = E2BIG;
- return NULL;
- }
- }
-
- savederrno = pthread_mutex_lock(&config_mutex);
- if (savederrno) {
- errno = savederrno;
- return NULL;
- }
-
- if (!lib_init) {
- lib_cfg.head = NULL;
-#ifdef KNET_LINUX
- lib_cfg.ioctlfd = socket(AF_INET, SOCK_STREAM, 0);
-#endif
-#ifdef KNET_BSD
- lib_cfg.ioctlfd = socket(AF_LOCAL, SOCK_DGRAM, 0);
-#endif
- if (lib_cfg.ioctlfd < 0) {
- savederrno = errno;
- goto out_error;
- }
- lib_init = 1;
- }
-
- nozzle = malloc(sizeof(struct nozzle_iface));
- if (!nozzle) {
- savederrno = ENOMEM;
- goto out_error;
- }
-
- memset(nozzle, 0, sizeof(struct nozzle_iface));
-
-#ifdef KNET_BSD
- if (!strlen(devname)) {
- for (i = 0; i < 256; i++) {
- snprintf(curnozzle, sizeof(curnozzle) - 1, "/dev/tap%u", i);
- nozzle->fd = open(curnozzle, O_RDWR);
- savederrno = errno;
- if (nozzle->fd > 0) {
- break;
- }
- }
- snprintf(curnozzle, sizeof(curnozzle) -1 , "tap%u", i);
- } else {
- snprintf(curnozzle, sizeof(curnozzle) - 1, "/dev/%s", devname);
- nozzle->fd = open(curnozzle, O_RDWR);
- savederrno = errno;
- snprintf(curnozzle, sizeof(curnozzle) - 1, "%s", devname);
- }
- if (nozzle->fd < 0) {
- errno = EBUSY;
- goto out_error;
- }
- strncpy(devname, curnozzle, IFNAMSIZ);
- strncpy(nozzle->name, curnozzle, IFNAMSIZ);
-#endif
-
-#ifdef KNET_LINUX
- if ((nozzle->fd = open("/dev/net/tun", O_RDWR)) < 0) {
- savederrno = errno;
- goto out_error;
- }
-
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifname, devname, IFNAMSIZ);
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
-
- if (ioctl(nozzle->fd, TUNSETIFF, &ifr) < 0) {
- savederrno = errno;
- goto out_error;
- }
-
- if ((strlen(devname) > 0) && (strcmp(devname, ifname) != 0)) {
- errno = EBUSY;
- goto out_error;
- }
-
- strncpy(devname, ifname, IFNAMSIZ);
- strncpy(nozzle->name, ifname, IFNAMSIZ);
-#endif
-
- nozzle->default_mtu = get_iface_mtu(nozzle);
- if (nozzle->default_mtu < 0) {
- savederrno = errno;
- goto out_error;
- }
-
- if (get_iface_mac(nozzle, &temp_mac) < 0) {
- savederrno = errno;
- goto out_error;
- }
-
- strncpy(nozzle->default_mac, temp_mac, 18);
- free(temp_mac);
-
- if (updownpath) {
- int len = strlen(updownpath);
-
- strcpy(nozzle->updownpath, updownpath);
- if (nozzle->updownpath[len-1] != '/') {
- nozzle->updownpath[len] = '/';
- }
- nozzle->hasupdown = 1;
- }
-
- nozzle->next = lib_cfg.head;
- lib_cfg.head = nozzle;
-
- pthread_mutex_unlock(&config_mutex);
- errno = savederrno;
- return nozzle;
-
-out_error:
- _close(nozzle);
- _close_cfg();
- pthread_mutex_unlock(&config_mutex);
- errno = savederrno;
- return NULL;
-}
-
-int nozzle_close(nozzle_t nozzle)
-{
- int err = 0, savederrno = 0;
- nozzle_t temp = lib_cfg.head;
- nozzle_t prev = lib_cfg.head;
- struct nozzle_ip *ip, *ip_next;
- char *error_string = NULL;
-
- savederrno = pthread_mutex_lock(&config_mutex);
- if (savederrno) {
- errno = savederrno;
- return -1;
- }
-
- if (!is_valid_nozzle(nozzle)) {
- savederrno = EINVAL;
- err = -1;
- goto out_clean;
- }
-
- while ((temp) && (temp != nozzle)) {
- prev = temp;
- temp = temp->next;
- }
-
- if (nozzle == prev) {
- lib_cfg.head = nozzle->next;
- } else {
- prev->next = nozzle->next;
- }
-
- set_iface_down(nozzle);
-
- ip = nozzle->ip;
- while (ip) {
- ip_next = ip->next;
- _set_ip(nozzle, "del", ip->ipaddr, ip->prefix, &error_string, 0);
- if (error_string) {
- free(error_string);
- error_string = NULL;
- }
- free(ip);
- ip = ip_next;
- }
-
- _close(nozzle);
- _close_cfg();
-
-out_clean:
- pthread_mutex_unlock(&config_mutex);
- errno = savederrno;
- return err;
-}
-
int nozzle_set_mtu(nozzle_t nozzle, const int mtu, char **error_string)
{
int err = 0, savederrno = 0;
struct nozzle_ip *tmp_ip;
struct ifreq ifr;
if ((!mtu) || (!error_string)) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
err = nozzle->current_mtu = get_iface_mtu(nozzle);
if (err < 0) {
savederrno = errno;
goto out_clean;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifname, nozzle->name, IFNAMSIZ);
ifr.ifr_mtu = mtu;
err = ioctl(lib_cfg.ioctlfd, SIOCSIFMTU, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
if ((nozzle->current_mtu < 1280) && (mtu >= 1280)) {
tmp_ip = nozzle->ip;
while(tmp_ip) {
if (tmp_ip->domain == AF_INET6) {
err = _set_ip(nozzle, "add", tmp_ip->ipaddr, tmp_ip->prefix, error_string, 0);
if (err) {
savederrno = errno;
err = -1;
goto out_clean;
}
}
tmp_ip = tmp_ip->next;
}
}
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_reset_mtu(nozzle_t nozzle, char **error_string)
{
return nozzle_set_mtu(nozzle, nozzle->default_mtu, error_string);
}
int nozzle_add_ip(nozzle_t nozzle, const char *ipaddr, const char *prefix, char **error_string)
{
int err = 0, savederrno = 0;
int found = 0;
struct nozzle_ip *ip = NULL, *ip_prev = NULL, *ip_last = NULL;
int secondary = 0;
if ((!ipaddr) || (!prefix) || (!error_string)) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
found = find_ip(nozzle, ipaddr, prefix, &ip, &ip_prev);
if (found) {
goto out_clean;
}
ip = malloc(sizeof(struct nozzle_ip));
if (!ip) {
savederrno = errno;
err = -1 ;
goto out_clean;
}
memset(ip, 0, sizeof(struct nozzle_ip));
strncpy(ip->ipaddr, ipaddr, IPADDR_CHAR_MAX);
strncpy(ip->prefix, prefix, PREFIX_CHAR_MAX);
if (!strchr(ip->ipaddr, ':')) {
ip->domain = AF_INET;
} else {
ip->domain = AF_INET6;
}
/*
* if user asks for an IPv6 address, but MTU < 1280
* store the IP and bring it up later if and when MTU > 1280
*/
if ((ip->domain == AF_INET6) && (get_iface_mtu(nozzle) < 1280)) {
err = 0;
} else {
if (nozzle->ip) {
secondary = 1;
}
err = _set_ip(nozzle, "add", ipaddr, prefix, error_string, secondary);
savederrno = errno;
}
if (err) {
free(ip);
goto out_clean;
}
if (nozzle->ip) {
ip_last = nozzle->ip;
while (ip_last->next != NULL) {
ip_last = ip_last->next;
}
ip_last->next = ip;
} else {
nozzle->ip = ip;
}
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_del_ip(nozzle_t nozzle, const char *ipaddr, const char *prefix, char **error_string)
{
int err = 0, savederrno = 0;
int found = 0;
struct nozzle_ip *ip = NULL, *ip_prev = NULL;
if ((!ipaddr) || (!prefix) || (!error_string)) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
found = find_ip(nozzle, ipaddr, prefix, &ip, &ip_prev);
if (!found) {
goto out_clean;
}
err = _set_ip(nozzle, "del", ipaddr, prefix, error_string, 0);
savederrno = errno;
if (!err) {
if (ip == ip_prev) {
nozzle->ip = ip->next;
} else {
ip_prev->next = ip->next;
}
free(ip);
}
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_get_ips(const nozzle_t nozzle, char **ipaddr_list, int *entries)
{
int err = 0, savederrno = 0;
int found = 0;
char *ip_list = NULL;
int size = 0, offset = 0, len;
struct nozzle_ip *ip = NULL;
if ((!ipaddr_list) || (!entries)) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
goto out_clean;
}
ip = nozzle->ip;
while (ip) {
found++;
ip = ip->next;
}
if (!found) {
*ipaddr_list = NULL;
*entries = 0;
goto out_clean;
}
size = found * (IPADDR_CHAR_MAX + PREFIX_CHAR_MAX + 2);
ip_list = malloc(size);
if (!ip_list) {
savederrno = errno;
err = -1;
goto out_clean;
}
memset(ip_list, 0, size);
ip = nozzle->ip;
while (ip) {
len = strlen(ip->ipaddr);
memmove(ip_list + offset, ip->ipaddr, len);
offset = offset + len + 1;
len = strlen(ip->prefix);
memmove(ip_list + offset, ip->prefix, len);
offset = offset + len + 1;
ip = ip->next;
}
*ipaddr_list = ip_list;
*entries = found;
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_run_updown(const nozzle_t nozzle, uint8_t action, char **exec_string)
{
int err = 0, savederrno = 0;
char command[PATH_MAX];
const char *action_str = NULL;
struct stat sb;
if (action > NOZZLE_POSTDOWN) {
errno = EINVAL;
return -1;
}
if (!exec_string) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
if (!nozzle->hasupdown) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
switch(action) {
case NOZZLE_PREUP:
action_str = "pre-up.d";
break;
case NOZZLE_UP:
action_str = "up.d";
break;
case NOZZLE_DOWN:
action_str = "down.d";
break;
case NOZZLE_POSTDOWN:
action_str = "post-down.d";
break;
}
memset(command, 0, PATH_MAX);
snprintf(command, PATH_MAX, "%s%s/%s", nozzle->updownpath, action_str, nozzle->name);
err = stat(command, &sb);
if (err) {
savederrno = errno;
goto out_clean;
}
err = execute_bin_sh_command(command, exec_string);
savederrno = errno;
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
/*
* functions below should be completed
*/
+nozzle_t nozzle_open(char *devname, size_t devname_size, const char *updownpath)
+{
+ int savederrno = 0;
+ nozzle_t nozzle = NULL;
+ char *temp_mac = NULL;
+#ifdef KNET_LINUX
+ struct ifreq ifr;
+#endif
+#ifdef KNET_BSD
+ uint16_t i;
+ long int nozzlenum = 0;
+ char curnozzle[IFNAMSIZ];
+#endif
+
+ if (devname == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (devname_size < IFNAMSIZ) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (strlen(devname) > IFNAMSIZ) {
+ errno = E2BIG;
+ return NULL;
+ }
+
+#ifdef KNET_BSD
+ /*
+ * BSD does not support named devices like Linux
+ * but it is possible to force a nozzleX device number
+ * where X is 0 to 255.
+ */
+ if (strlen(devname)) {
+ if (strncmp(devname, "tap", 3)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ errno = 0;
+ nozzlenum = strtol(devname+3, NULL, 10);
+ if (errno) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if ((nozzlenum < 0) || (nozzlenum > 255)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ }
+#endif
+
+ if (updownpath) {
+ /* only absolute paths */
+ if (updownpath[0] != '/') {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (strlen(updownpath) >= UPDOWN_PATH_MAX) {
+ errno = E2BIG;
+ return NULL;
+ }
+ }
+
+ savederrno = pthread_mutex_lock(&config_mutex);
+ if (savederrno) {
+ errno = savederrno;
+ return NULL;
+ }
+
+ if (!lib_init) {
+ lib_cfg.head = NULL;
+#ifdef KNET_LINUX
+ lib_cfg.ioctlfd = socket(AF_INET, SOCK_STREAM, 0);
+#endif
+#ifdef KNET_BSD
+ lib_cfg.ioctlfd = socket(AF_LOCAL, SOCK_DGRAM, 0);
+#endif
+ if (lib_cfg.ioctlfd < 0) {
+ savederrno = errno;
+ goto out_error;
+ }
+ lib_init = 1;
+ }
+
+ nozzle = malloc(sizeof(struct nozzle_iface));
+ if (!nozzle) {
+ savederrno = ENOMEM;
+ goto out_error;
+ }
+
+ memset(nozzle, 0, sizeof(struct nozzle_iface));
+
+#ifdef KNET_BSD
+ if (!strlen(devname)) {
+ for (i = 0; i < 256; i++) {
+ snprintf(curnozzle, sizeof(curnozzle) - 1, "/dev/tap%u", i);
+ nozzle->fd = open(curnozzle, O_RDWR);
+ savederrno = errno;
+ if (nozzle->fd > 0) {
+ break;
+ }
+ }
+ snprintf(curnozzle, sizeof(curnozzle) -1 , "tap%u", i);
+ } else {
+ snprintf(curnozzle, sizeof(curnozzle) - 1, "/dev/%s", devname);
+ nozzle->fd = open(curnozzle, O_RDWR);
+ savederrno = errno;
+ snprintf(curnozzle, sizeof(curnozzle) - 1, "%s", devname);
+ }
+ if (nozzle->fd < 0) {
+ errno = EBUSY;
+ goto out_error;
+ }
+ strncpy(devname, curnozzle, IFNAMSIZ);
+ strncpy(nozzle->name, curnozzle, IFNAMSIZ);
+#endif
+
+#ifdef KNET_LINUX
+ if ((nozzle->fd = open("/dev/net/tun", O_RDWR)) < 0) {
+ savederrno = errno;
+ goto out_error;
+ }
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+ strncpy(ifname, devname, IFNAMSIZ);
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+
+ if (ioctl(nozzle->fd, TUNSETIFF, &ifr) < 0) {
+ savederrno = errno;
+ goto out_error;
+ }
+
+ if ((strlen(devname) > 0) && (strcmp(devname, ifname) != 0)) {
+ errno = EBUSY;
+ goto out_error;
+ }
+
+ strncpy(devname, ifname, IFNAMSIZ);
+ strncpy(nozzle->name, ifname, IFNAMSIZ);
+#endif
+
+ nozzle->default_mtu = get_iface_mtu(nozzle);
+ if (nozzle->default_mtu < 0) {
+ savederrno = errno;
+ goto out_error;
+ }
+
+ if (get_iface_mac(nozzle, &temp_mac) < 0) {
+ savederrno = errno;
+ goto out_error;
+ }
+
+ strncpy(nozzle->default_mac, temp_mac, 18);
+ free(temp_mac);
+
+ if (updownpath) {
+ int len = strlen(updownpath);
+
+ strcpy(nozzle->updownpath, updownpath);
+ if (nozzle->updownpath[len-1] != '/') {
+ nozzle->updownpath[len] = '/';
+ }
+ nozzle->hasupdown = 1;
+ }
+
+ nozzle->next = lib_cfg.head;
+ lib_cfg.head = nozzle;
+
+ pthread_mutex_unlock(&config_mutex);
+ errno = savederrno;
+ return nozzle;
+
+out_error:
+ destroy_iface(nozzle);
+ pthread_mutex_unlock(&config_mutex);
+ errno = savederrno;
+ return NULL;
+}
+
+int nozzle_close(nozzle_t nozzle)
+{
+ int err = 0, savederrno = 0;
+ nozzle_t temp = lib_cfg.head;
+ nozzle_t prev = lib_cfg.head;
+ struct nozzle_ip *ip, *ip_next;
+
+ savederrno = pthread_mutex_lock(&config_mutex);
+ if (savederrno) {
+ errno = savederrno;
+ return -1;
+ }
+
+ if (!is_valid_nozzle(nozzle)) {
+ savederrno = EINVAL;
+ err = -1;
+ goto out_clean;
+ }
+
+ while ((temp) && (temp != nozzle)) {
+ prev = temp;
+ temp = temp->next;
+ }
+
+ if (nozzle == prev) {
+ lib_cfg.head = nozzle->next;
+ } else {
+ prev->next = nozzle->next;
+ }
+
+ ip = nozzle->ip;
+ while (ip) {
+ ip_next = ip->next;
+ free(ip);
+ ip = ip_next;
+ }
+
+ destroy_iface(nozzle);
+
+out_clean:
+ pthread_mutex_unlock(&config_mutex);
+ errno = savederrno;
+ return err;
+}
+
int nozzle_set_up(nozzle_t nozzle)
{
int err = 0, savederrno = 0;
struct ifreq ifr;
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
if (nozzle->up) {
goto out_clean;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifname, nozzle->name, IFNAMSIZ);
err = ioctl(lib_cfg.ioctlfd, SIOCGIFFLAGS, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
err = ioctl(lib_cfg.ioctlfd, SIOCSIFFLAGS, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
nozzle->up = 1;
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_set_down(nozzle_t nozzle)
{
int err = 0, savederrno = 0;
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
err = set_iface_down(nozzle);
savederrno = errno;
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_get_mtu(const nozzle_t nozzle)
{
int err = 0, savederrno = 0;
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
err = get_iface_mtu(nozzle);
savederrno = errno;
out_clean:
pthread_mutex_unlock(&config_mutex);
savederrno = errno;
return err;
}
int nozzle_get_mac(const nozzle_t nozzle, char **ether_addr)
{
int err = 0, savederrno = 0;
if (!ether_addr) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
err = get_iface_mac(nozzle, ether_addr);
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_set_mac(nozzle_t nozzle, const char *ether_addr)
{
int err = 0, savederrno = 0;
struct ifreq ifr;
if (!ether_addr) {
errno = EINVAL;
return -1;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = EINVAL;
err = -1;
goto out_clean;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifname, nozzle->name, IFNAMSIZ);
#ifdef KNET_LINUX
err = ioctl(lib_cfg.ioctlfd, SIOCGIFHWADDR, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
memmove(ifr.ifr_hwaddr.sa_data, ether_aton(ether_addr), ETH_ALEN);
err = ioctl(lib_cfg.ioctlfd, SIOCSIFHWADDR, &ifr);
savederrno = errno;
#endif
#ifdef KNET_BSD
err = ioctl(lib_cfg.ioctlfd, SIOCGIFADDR, &ifr);
if (err) {
savederrno = errno;
goto out_clean;
}
memmove(ifr.ifr_addr.sa_data, ether_aton(ether_addr), ETHER_ADDR_LEN);
ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
err = ioctl(lib_cfg.ioctlfd, SIOCSIFLLADDR, &ifr);
savederrno = errno;
#endif
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return err;
}
int nozzle_reset_mac(nozzle_t nozzle)
{
return nozzle_set_mac(nozzle, nozzle->default_mac);
}
nozzle_t nozzle_get_handle_by_name(const char *devname)
{
int savederrno = 0;
nozzle_t nozzle;
if ((devname == NULL) || (strlen(devname) > IFNAMSIZ)) {
errno = EINVAL;
return NULL;
}
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return NULL;
}
nozzle = lib_cfg.head;
while (nozzle != NULL) {
if (!strcmp(devname, nozzle->name))
break;
nozzle = nozzle->next;
}
if (!nozzle) {
savederrno = ENOENT;
}
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return nozzle;
}
const char *nozzle_get_name_by_handle(const nozzle_t nozzle)
{
int savederrno = 0;
char *name = NULL;
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return NULL;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = ENOENT;
goto out_clean;
}
name = nozzle->name;
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return name;
}
int nozzle_get_fd(const nozzle_t nozzle)
{
int fd = -1, savederrno = 0;
savederrno = pthread_mutex_lock(&config_mutex);
if (savederrno) {
errno = savederrno;
return -1;
}
if (!is_valid_nozzle(nozzle)) {
savederrno = ENOENT;
fd = -1;
goto out_clean;
}
fd = nozzle->fd;
out_clean:
pthread_mutex_unlock(&config_mutex);
errno = savederrno;
return fd;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 5:40 AM (6 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018266
Default Alt Text
(26 KB)
Attached To
Mode
rK kronosnet
Attached
Detach File
Event Timeline
Log In to Comment