Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete FreeBSD support, also fix 'tun' device for it. #2

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion regress/test14.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ main(void) {
return 1;
}

if (tuntap_set_ip(dev, "1.2.3.4", 24) == -1) {
if (tuntap_set_ip(dev, "1.2.3.4", 24, "4.3.2.1") == -1) {
return 1;
}

Expand Down
2 changes: 1 addition & 1 deletion regress/test18.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ main(void) {
return 1;
}

if (tuntap_set_ip(dev, "1.2.3.4", 24) == -1) {
if (tuntap_set_ip(dev, "1.2.3.4", 24, "4.3.2.1") == -1) {
return 1;
}

Expand Down
8 changes: 4 additions & 4 deletions regress/test33.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ else
return 1
fi

# The $TARGET still exists, clean it and return failure
# Everything went fine
if [ $OK -eq 2 ]; then
$IFDEL
return 1
return 0
fi

# Everything went fine
return 0
# The $TARGET still exists, return failure
return 1
4 changes: 2 additions & 2 deletions regress/test34.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fi
# The $TARGET still exists
if [ $OK -eq 2 ]; then
$IFDEL
return 1
return 0
fi

return 0
return 1
100 changes: 75 additions & 25 deletions tuntap-unix-freebsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <[email protected]>
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Expand Down Expand Up @@ -68,15 +79,17 @@ tuntap_sys_start(struct device *dev, int mode, int tun) {
return -1;
}

dev->mode = mode;

/* Try to use the given driver or loop throught the avaible ones */
fd = -1;
if (tun < TUNTAP_ID_MAX) {
(void)snprintf(name, sizeof name, "/dev/%s%i", ifname, tun);
(void)snprintf(name, sizeof(name), "/dev/%s%i", ifname, tun);
fd = open(name, O_RDWR);
} else if (tun == TUNTAP_ID_ANY) {
for (tun = 0; tun < TUNTAP_ID_MAX; ++tun) {
(void)memset(name, '\0', sizeof name);
(void)snprintf(name, sizeof name, "/dev/%s%i",
(void)memset(name, 0, sizeof(name));
(void)snprintf(name, sizeof(name), "/dev/%s%i",
ifname, tun);
if ((fd = open(name, O_RDWR)) > 0)
break;
Expand All @@ -98,10 +111,10 @@ tuntap_sys_start(struct device *dev, int mode, int tun) {
}

/* Set the interface name */
(void)memset(&ifr, '\0', sizeof ifr);
(void)snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "%s%i", ifname, tun);
(void)memset(&ifr, 0, sizeof(ifr));
(void)snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%i", ifname, tun);
/* And save it */
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof dev->if_name);
(void)strlcpy(dev->if_name, ifr.ifr_name, sizeof(dev->if_name));

/* Get the interface default values */
if (ioctl(dev->ctrl_sock, SIOCGIFFLAGS, &ifr) == -1) {
Expand Down Expand Up @@ -156,8 +169,8 @@ int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
struct ifreq ifr;

(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
(void)memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof(ifr.ifr_name));
ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
ifr.ifr_addr.sa_family = AF_LINK;
(void)memcpy(ifr.ifr_addr.sa_data, eth_addr, ETHER_ADDR_LEN);
Expand All @@ -169,40 +182,77 @@ tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr) {
}

int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
struct ifreq ifr;
tuntap_sys_set_ipv4_tap(struct device *dev, t_tun_in_addr *s4, uint32_t bits) {
struct ifaliasreq ifrq;
struct sockaddr_in mask;
struct sockaddr_in addr;

(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
(void)memset(&ifrq, 0, sizeof(ifrq));
(void)strlcpy(ifrq.ifra_name, dev->if_name, sizeof(ifrq.ifra_name));

/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifr);
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifrq);

/* Set the address */
(void)memset(&addr, '\0', sizeof addr);
(void)memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = s4->s_addr;
addr.sin_len = sizeof addr;
(void)memcpy(&ifr.ifr_addr, &addr, sizeof addr);
addr.sin_len = sizeof(addr);
(void)memcpy(&ifrq.ifra_addr, &addr, sizeof(addr));

if (ioctl(dev->ctrl_sock, SIOCSIFADDR, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address");
/* Then set the netmask */
(void)memset(&mask, 0, sizeof(mask));
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof(mask);
(void)memcpy(&ifrq.ifra_mask, &mask, sizeof(ifrq.ifra_mask));

if (ioctl(dev->ctrl_sock, SIOCAIFADDR, &ifrq) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address/netmask");
return -1;
}

return 0;
}

int
tuntap_sys_set_ipv4_tun(struct device *dev, t_tun_in_addr *s4, t_tun_in_addr *s4dest, uint32_t bits) {
struct ifaliasreq ifrq;
struct sockaddr_in mask;
struct sockaddr_in saddr;
struct sockaddr_in daddr;

(void)memset(&ifrq, 0, sizeof(ifrq));
(void)memcpy(ifrq.ifra_name, dev->if_name, sizeof(ifrq.ifra_name));

/* Delete previously assigned address */
(void)ioctl(dev->ctrl_sock, SIOCDIFADDR, &ifrq);

/* Set the address */
(void)memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = s4->s_addr;
saddr.sin_len = sizeof(saddr);
(void)memcpy(&ifrq.ifra_addr, &saddr, sizeof(saddr));

(void)memset(&daddr, 0, sizeof(daddr));
daddr.sin_family = AF_INET;
daddr.sin_addr.s_addr = s4dest->s_addr;
daddr.sin_len = sizeof(daddr);
(void)memcpy(&ifrq.ifra_broadaddr, &daddr, sizeof(daddr));

/* Then set the netmask */
(void)memset(&mask, '\0', sizeof mask);
(void)memset(&mask, 0, sizeof(mask));
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
mask.sin_len = sizeof mask;
(void)memcpy(&ifr.ifr_addr, &mask, sizeof ifr.ifr_addr);
mask.sin_len = sizeof(mask);
(void)memcpy(&ifrq.ifra_mask, &mask, sizeof(ifrq.ifra_mask));

if (ioctl(dev->ctrl_sock, SIOCSIFNETMASK, &ifr) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set netmask");
if (ioctl(dev->ctrl_sock, SIOCAIFADDR, &ifrq) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address");
return -1;
}

return 0;
}

Expand All @@ -212,8 +262,8 @@ tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len) {
struct ifreq ifr;
struct ifreq_buffer ifrbuf;

(void)memset(&ifr, '\0', sizeof ifr);
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof ifr.ifr_name);
(void)memset(&ifr, 0, sizeof(ifr));
(void)strlcpy(ifr.ifr_name, dev->if_name, sizeof(ifr.ifr_name));

ifrbuf.buffer = (void *)descr;
ifrbuf.length = len;
Expand Down
11 changes: 11 additions & 0 deletions tuntap-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <[email protected]>
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Expand Down
110 changes: 107 additions & 3 deletions tuntap.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copyright (c) 2016 Mahdi Mokhtari <[email protected]>
*
* 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.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Expand All @@ -30,6 +41,8 @@
#include <string.h>
#include <ctype.h>

#include <stdarg.h>

#include "tuntap.h"

struct device *
Expand All @@ -39,8 +52,8 @@ tuntap_init(void) {
if ((dev = (struct device *)malloc(sizeof(*dev))) == NULL)
return NULL;

(void)memset(dev->if_name, '\0', sizeof dev->if_name);
(void)memset(dev->hwaddr, '\0', sizeof dev->hwaddr);
(void)memset(dev->if_name, '\0', sizeof(dev->if_name));
(void)memset(dev->hwaddr, '\0', sizeof(dev->hwaddr));
dev->tun_fd = TUNFD_INVALID_VALUE;
dev->ctrl_sock = -1;
dev->flags = 0;
Expand All @@ -65,8 +78,9 @@ tuntap_version(void) {
return TUNTAP_VERSION;
}

#if !defined(FreeBSD)
int
tuntap_set_ip(struct device *dev, const char *addr, int netmask) {
tuntap_set_ip_old(struct device *dev, const char *addr, int netmask) {
t_tun_in_addr baddr4;
t_tun_in6_addr baddr6;
uint32_t mask;
Expand Down Expand Up @@ -117,3 +131,93 @@ tuntap_set_ip(struct device *dev, const char *addr, int netmask) {
/* NOTREACHED */
return -1;
}
#endif

int
tuntap_set_ip(struct device *dev, ...)
{
va_list vl;
char *saddr;
char *daddr;
int netmask;
t_tun_in_addr sbaddr4;
t_tun_in_addr dbaddr4;
t_tun_in6_addr sbaddr6;
t_tun_in6_addr dbaddr6;
uint32_t mask;
int errval;

saddr = daddr = NULL;
netmask = -1;

va_start(vl, dev);
saddr = va_arg(vl, char *);
netmask = va_arg(vl, int);
#if defined(FreeBSD)
if (dev->mode == TUNTAP_MODE_TUNNEL)
daddr = va_arg(vl, char *);
#endif
va_end(vl);

/* Only accept started device */
if (dev->tun_fd == TUNFD_INVALID_VALUE) {
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}

if (saddr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'saddr'");
return -1;
}

if (netmask < 0 || netmask > 128) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'netmask'");
return -1;
}

/* Netmask */
mask = ~0;
mask = ~(mask >> netmask);
mask = htonl(mask);

/*
* Destination address parsing: we try IPv4 first and fall back to
* IPv6 if inet_pton return 0
*/
(void)memset(&sbaddr4, 0, sizeof(sbaddr4));
(void)memset(&sbaddr6, 0, sizeof(sbaddr6));

errval = inet_pton(AF_INET, saddr, &(sbaddr4));
if (errval == 1) {
#if defined(FreeBSD)
#define tuntap_sys_set_ipv4 tuntap_sys_set_ipv4_tap
if (dev->mode == TUNTAP_MODE_TUNNEL) {
if (daddr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'daddr'");
return -1;
}
(void)memset(&dbaddr4, 0, sizeof(dbaddr4));
(void)inet_pton(AF_INET, daddr, &(dbaddr4));
return tuntap_sys_set_ipv4_tun(dev, &sbaddr4, &dbaddr4, mask);
} else
#endif
{
return tuntap_sys_set_ipv4(dev, &sbaddr4, mask);
}
} else if (errval == 0) {
#if !defined(FreeBSD) /* No IPV6 tests YET */
if (inet_pton(AF_INET6, saddr, &(sbaddr6)) == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters");
return -1;
}
return tuntap_sys_set_ipv6(dev, &sbaddr6, mask);
} else if (errval == -1) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters");
return -1;
#endif
}

/* NOTREACHED */
return -1;

}
Loading