[PATCH] osmo-ggsn[master]: lib/tun.c: Generalize tun_{set, add}addr*() functions

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Wed Apr 25 18:46:25 UTC 2018


Review at  https://gerrit.osmocom.org/7922

lib/tun.c: Generalize tun_{set,add}addr*() functions

There's nothing really tun-specific about the adding and removing of
addresses to network devices.  Let's generalize the related code.

Change-Id: I139a950dd81a4b1199953be1608cd109a060f562
---
M lib/tun.c
1 file changed, 97 insertions(+), 51 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/22/7922/1

diff --git a/lib/tun.c b/lib/tun.c
index 14e4a58..88d9ac9 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -102,8 +102,8 @@
 	return 0;
 }
 
-static int tun_setaddr4(struct tun_t *this, struct in_addr *addr,
-			struct in_addr *dstaddr, struct in_addr *netmask)
+static int netdev_setaddr4(const char *devname, struct in_addr *addr,
+			   struct in_addr *dstaddr, struct in_addr *netmask)
 {
 	struct ifreq ifr;
 	int fd;
@@ -122,7 +122,7 @@
 	    sizeof(struct sockaddr_in);
 #endif
 
-	strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
+	strncpy(ifr.ifr_name, devname, IFNAMSIZ);
 	ifr.ifr_name[IFNAMSIZ - 1] = 0;	/* Make sure to terminate */
 
 	/* Create a channel to the NET kernel. */
@@ -132,7 +132,6 @@
 	}
 
 	if (addr) {		/* Set the interface address */
-		this->addr.s_addr = addr->s_addr;
 		memcpy(&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, addr,
 		       sizeof(*addr));
 		if (ioctl(fd, SIOCSIFADDR, (void *)&ifr) < 0) {
@@ -149,7 +148,6 @@
 	}
 
 	if (dstaddr) {		/* Set the destination address */
-		this->dstaddr.s_addr = dstaddr->s_addr;
 		memcpy(&((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr,
 		       dstaddr, sizeof(*dstaddr));
 		if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) & ifr) < 0) {
@@ -161,7 +159,6 @@
 	}
 
 	if (netmask) {		/* Set the netmask */
-		this->netmask.s_addr = netmask->s_addr;
 #if defined(__linux__)
 		memcpy(&((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr,
 		       netmask, sizeof(*netmask));
@@ -180,25 +177,45 @@
 	}
 
 	close(fd);
-	this->addrs++;
 
 	/* On linux the route to the interface is set automatically
 	   on FreeBSD we have to do this manually */
 
 	/* TODO: How does it work on Solaris? */
 
-	netdev_sifflags(this->devname, IFF_UP | IFF_RUNNING);
+	netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
 
 #if defined(__FreeBSD__) || defined (__APPLE__)
-	tun_addroute(this, dstaddr, addr, &this->netmask);
-	this->routes = 1;
+	netdev_addroute(dstaddr, addr, &this->netmask);
 #endif
 
 	return 0;
 }
 
-static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
-			size_t prefixlen)
+static int tun_setaddr4(struct tun_t *this, struct in_addr *addr,
+			struct in_addr *dstaddr, struct in_addr *netmask)
+{
+	int rc;
+	rc = netdev_setaddr4(this->devname, addr, dstaddr, netmask);
+	if (rc < 0)
+		return rc;
+
+	if (addr)
+		this->addr.s_addr = addr->s_addr;
+	if (dstaddr)
+		this->dstaddr.s_addr = dstaddr->s_addr;
+	if (netmask)
+		this->netmask.s_addr = netmask->s_addr;
+	this->addrs++;
+#if defined(__FreeBSD__) || defined (__APPLE__)
+	this->routes = 1;
+#endif
+
+	return rc;
+}
+
+static int netdev_setaddr6(const char *devname, struct in6_addr *addr, struct in6_addr *dstaddr,
+			   size_t prefixlen)
 {
 	struct in6_ifreq ifr;
 	int fd;
@@ -207,13 +224,13 @@
 
 #if defined(__linux__)
 	ifr.ifr6_prefixlen = prefixlen;
-	ifr.ifr6_ifindex = if_nametoindex(this->devname);
+	ifr.ifr6_ifindex = if_nametoindex(devname);
 	if (ifr.ifr6_ifindex == 0) {
-		SYS_ERR(DTUN, LOGL_ERROR, 0, "Error getting ifindex for %s\n", this->devname);
+		SYS_ERR(DTUN, LOGL_ERROR, 0, "Error getting ifindex for %s\n", devname);
 		return -1;
 	}
 #elif defined(__FreeBSD__) || defined (__APPLE__)
-	strncpy(ifr.ifr_name, this->devname, IFNAMSIZ);
+	strncpy(ifr.ifr_name, devname, IFNAMSIZ);
 #endif
 
 	/* Create a channel to the NET kernel */
@@ -239,7 +256,7 @@
 #if 0
 	/* FIXME: looks like this is not possible/necessary for IPv6? */
 	if (dstaddr) {
-		memcpy(&this->dstaddr, dstaddr, sizeof(*dstaddr));
+		memcpy(&dstaddr, dstaddr, sizeof(*dstaddr));
 		memcpy(&ifr.ifr6_addr, dstaddr, sizeof(*dstaddr));
 		if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t *) &ifr) < 0) {
 			SYS_ERR(DTUN, LOGL_ERROR, "ioctl(SIOCSIFDSTADDR) failed");
@@ -263,22 +280,35 @@
 #endif
 
 	close(fd);
-	this->addrs++;
 
 	/* On linux the route to the interface is set automatically
 	   on FreeBSD we have to do this manually */
 
 	/* TODO: How does it work on Solaris? */
 
-	netdev_sifflags(this->devname, IFF_UP | IFF_RUNNING);
+	netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
 
 #if 0	/* FIXME */
 //#if defined(__FreeBSD__) || defined (__APPLE__)
 	netdev_addroute6(dstaddr, addr, prefixlen);
-	this->routes = 1;
 #endif
 
 	return 0;
+}
+
+static int tun_setaddr6(struct tun_t *this, struct in6_addr *addr, struct in6_addr *dstaddr,
+			size_t prefixlen)
+{
+	int rc;
+	rc = netdev_setaddr6(this->devname, addr, dstaddr, prefixlen);
+	if (rc < 0)
+		return rc;
+	this->addrs++;
+#if defined(__FreeBSD__) || defined (__APPLE__)
+	this->routes = 1;
+#endif
+
+	return rc;
 }
 
 int tun_setaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *dstaddr, size_t prefixlen)
@@ -295,9 +325,8 @@
 	}
 }
 
-static int tun_addaddr4(struct tun_t *this,
-		struct in_addr *addr,
-		struct in_addr *dstaddr, struct in_addr *netmask)
+static int netdev_addaddr4(const char *devname, struct in_addr *addr,
+			   struct in_addr *dstaddr, struct in_addr *netmask)
 {
 
 #if defined(__linux__)
@@ -316,9 +345,6 @@
 	struct iovec iov;
 	struct msghdr msg;
 
-	if (!this->addrs)	/* Use ioctl for first addr to make ping work */
-		return tun_setaddr4(this, addr, dstaddr, netmask);
-
 	memset(&req, 0, sizeof(req));
 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
 	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
@@ -327,9 +353,9 @@
 	req.i.ifa_prefixlen = 32;	/* 32 FOR IPv4 */
 	req.i.ifa_flags = 0;
 	req.i.ifa_scope = RT_SCOPE_HOST;	/* TODO or 0 */
-	req.i.ifa_index = if_nametoindex(this->devname);
+	req.i.ifa_index = if_nametoindex(devname);
 	if (!req.i.ifa_index) {
-		SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for %s", this->devname);
+		SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for %s", devname);
 		return -1;
 	}
 
@@ -400,7 +426,7 @@
 		return -1;
 	}
 
-	status = netdev_sifflags(this->devname, IFF_UP | IFF_RUNNING);
+	status = netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
 	if (status == -1) {
 		close(fd);
 		return -1;
@@ -408,7 +434,6 @@
 
 
 	close(fd);
-	this->addrs++;
 	return 0;
 
 #elif defined (__FreeBSD__) || defined (__APPLE__)
@@ -416,14 +441,10 @@
 	int fd;
 	struct ifaliasreq areq;
 
-	/* TODO: Is this needed on FreeBSD? */
-	if (!this->addrs)	/* Use ioctl for first addr to make ping work */
-		return tun_setaddr4(this, addr, dstaddr, netmask);	/* TODO dstaddr */
-
 	memset(&areq, 0, sizeof(areq));
 
 	/* Set up interface name */
-	strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
+	strncpy(areq.ifra_name, devname, IFNAMSIZ);
 	areq.ifra_name[IFNAMSIZ - 1] = 0;	/* Make sure to terminate */
 
 	((struct sockaddr_in *)&areq.ifra_addr)->sin_family = AF_INET;
@@ -458,16 +479,32 @@
 	}
 
 	close(fd);
-	this->addrs++;
 	return 0;
 
 #endif
 
 }
 
-static int tun_addaddr6(struct tun_t *this,
-		struct in6_addr *addr,
-		struct in6_addr *dstaddr, int prefixlen)
+static int tun_addaddr4(struct tun_t *this, struct in_addr *addr,
+			struct in_addr *dstaddr, struct in_addr *netmask)
+{
+	int rc;
+
+	/* TODO: Is this needed on FreeBSD? */
+	if (!this->addrs)	/* Use ioctl for first addr to make ping work */
+		return tun_setaddr4(this, addr, dstaddr, netmask);	/* TODO dstaddr */
+
+	rc = netdev_addaddr4(this->devname, addr, dstaddr, netmask);
+	if (rc < 0)
+		return rc;
+
+	this->addrs++;
+
+	return rc;
+}
+
+static int netdev_addaddr6(const char *devname, struct in6_addr *addr,
+			   struct in6_addr *dstaddr, int prefixlen)
 {
 
 #if defined(__linux__)
@@ -486,9 +523,6 @@
 	struct iovec iov;
 	struct msghdr msg;
 
-	if (!this->addrs)	/* Use ioctl for first addr to make ping work */
-		return tun_setaddr6(this, addr, dstaddr, prefixlen);
-
 	memset(&req, 0, sizeof(req));
 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
 	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
@@ -497,9 +531,9 @@
 	req.i.ifa_prefixlen = 64;	/* 64 FOR IPv6 */
 	req.i.ifa_flags = 0;
 	req.i.ifa_scope = RT_SCOPE_HOST;	/* TODO or 0 */
-	req.i.ifa_index = if_nametoindex(this->devname);
+	req.i.ifa_index = if_nametoindex(devname);
 	if (!req.i.ifa_index) {
-		SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for %s", this->devname);
+		SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for %s", devname);
 		return -1;
 	}
 
@@ -570,7 +604,7 @@
 		return -1;
 	}
 
-	status = netdev_sifflags(this->devname, IFF_UP | IFF_RUNNING);
+	status = netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
 	if (status == -1) {
 		close(fd);
 		return -1;
@@ -578,7 +612,6 @@
 
 
 	close(fd);
-	this->addrs++;
 	return 0;
 
 #elif defined (__FreeBSD__) || defined (__APPLE__)
@@ -586,14 +619,10 @@
 	int fd;
 	struct ifaliasreq areq;
 
-	/* TODO: Is this needed on FreeBSD? */
-	if (!this->addrs)	/* Use ioctl for first addr to make ping work */
-		return tun_setaddr6(this, addr, dstaddr, netmask);	/* TODO dstaddr */
-
 	memset(&areq, 0, sizeof(areq));
 
 	/* Set up interface name */
-	strncpy(areq.ifra_name, this->devname, IFNAMSIZ);
+	strncpy(areq.ifra_name, devname, IFNAMSIZ);
 	areq.ifra_name[IFNAMSIZ - 1] = 0;	/* Make sure to terminate */
 
 	((struct sockaddr_in6 *)&areq.ifra_addr)->sin6_family = AF_INET6;
@@ -623,13 +652,30 @@
 	}
 
 	close(fd);
-	this->addrs++;
 	return 0;
 
 #endif
 
 }
 
+static int tun_addaddr6(struct tun_t *this,
+		struct in6_addr *addr,
+		struct in6_addr *dstaddr, int prefixlen)
+{
+	int rc;
+
+	if (!this->addrs)	/* Use ioctl for first addr to make ping work */
+		return tun_setaddr6(this, addr, dstaddr, prefixlen);
+
+	rc = netdev_addaddr6(this->devname, addr, dstaddr, prefixlen);
+	if (rc < 0)
+		return rc;
+
+	this->addrs++;
+
+	return rc;
+}
+
 int tun_addaddr(struct tun_t *this, struct in46_addr *addr, struct in46_addr *dstaddr, size_t prefixlen)
 {
 	struct in_addr netmask;

-- 
To view, visit https://gerrit.osmocom.org/7922
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I139a950dd81a4b1199953be1608cd109a060f562
Gerrit-PatchSet: 1
Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>



More information about the gerrit-log mailing list