[Chilli] Patch to dev_set_address() in tun.c
Sevan / Venture37
venture37 at gmail.com
Sat May 10 23:02:23 UTC 2014
Hi,
Another patch for testing, again it's intended for a specific problem
but it effects everyone.
Attached patch fixes issues with FreeBSD 10 & newer where the tun(4)
interface would not be configured with an address.
This is due to the removal of a macro which has been marked as
deprecated (10+ years apparently) across the BSD's.
The diff separates out the configuration of interface so Linux uses
the traditional method & the BSD's use the new method.
Sevan
-------------- next part --------------
diff --git a/src/net.c b/src/net.c
index c1f8cba..ef6a529 100644
--- a/src/net.c
+++ b/src/net.c
@@ -91,29 +91,28 @@ int dev_get_flags(char const *dev, int *flags) {
int dev_set_address(char const *devname, struct in_addr *address,
struct in_addr *dstaddr, struct in_addr *netmask) {
+#if defined(__linux__)
struct ifreq ifr;
+#elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
+ struct ifaliasreq ifr;
+#endif
int fd;
memset(&ifr, 0, sizeof (ifr));
- ifr.ifr_addr.sa_family = AF_INET;
- ifr.ifr_dstaddr.sa_family = AF_INET;
-
-#if defined(__linux__)
- ifr.ifr_netmask.sa_family = AF_INET;
-
-#elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
- ((struct sockaddr_in *) &ifr.ifr_addr)->sin_len = sizeof (struct sockaddr_in);
- ((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_len = sizeof (struct sockaddr_in);
-#endif
-
- safe_strncpy(ifr.ifr_name, devname, IFNAMSIZ);
-
+
/* Create a channel to the NET kernel. */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
log_err(errno, "socket() failed");
return -1;
}
-
+
+#if defined(__linux__)
+ safe_strncpy(ifr.ifr_name, devname, IFNAMSIZ);
+ ifr.ifr_addr.sa_family = AF_INET;
+ ifr.ifr_dstaddr.sa_family = AF_INET;
+ ifr.ifr_netmask.sa_family = AF_INET;
+ ifr.ifr_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+
if (address) { /* Set the interface address */
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = address->s_addr;
if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
@@ -138,23 +137,46 @@ int dev_set_address(char const *devname, struct in_addr *address,
}
if (netmask) { /* Set the netmask */
-#if defined(__linux__)
((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = netmask->s_addr;
-#elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
- ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = netmask->s_addr;
-#elif defined(__sun__)
- ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = netmask->s_addr;
-#else
-#error "Unknown platform!"
-#endif
-
if (ioctl(fd, SIOCSIFNETMASK, (void *) &ifr) < 0) {
log_err(errno, "ioctl(SIOCSIFNETMASK) failed");
close(fd);
return -1;
}
}
+
+#elif defined(__FreeBSD__) || defined (__APPLE__) || defined (__OpenBSD__) || defined (__NetBSD__)
+ strncpy(ifr.ifra_name, devname, IFNAMSIZ);
+ ifr.ifra_name[IFNAMSIZ-1] = 0; /* Make sure to terminate */
+
+ ((struct sockaddr_in*) &ifr.ifra_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &ifr.ifra_addr)->sin_len = sizeof(ifr.ifra_addr);
+ ((struct sockaddr_in*) &ifr.ifra_addr)->sin_addr.s_addr = address->s_addr;
+
+ ((struct sockaddr_in*) &ifr.ifra_mask)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &ifr.ifra_mask)->sin_len = sizeof(ifr.ifra_mask);
+ ((struct sockaddr_in*) &ifr.ifra_mask)->sin_addr.s_addr = netmask->s_addr;
+
+ /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
+ ((struct sockaddr_in*) &ifr.ifra_broadaddr)->sin_family = AF_INET;
+ ((struct sockaddr_in*) &ifr.ifra_broadaddr)->sin_len = sizeof(ifr.ifra_broadaddr);
+ ((struct sockaddr_in*) &ifr.ifra_broadaddr)->sin_addr.s_addr = dstaddr->s_addr;
+
+ if (ioctl(fd, SIOCAIFADDR, (void *) &ifr) < 0) {
+ if (errno != EEXIST) {
+ log_err(errno, "ioctl(SIOCAIFADDR) failed");
+ }
+ else {
+ log_warn(errno, "ioctl(SIOCAIFADDR): Address already exists");
+ }
+ close(fd);
+ return -1;
+ }
+#else
+#error "Unknown platform!"
+#endif
+
close(fd);
return dev_set_flags(devname, IFF_UP | IFF_RUNNING);
More information about the Chilli
mailing list