pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-ggsn/+/38483?usp=email )


Change subject: ggsn: Use osmo_netdev_addaddr() libosmocore API
......................................................................

ggsn: Use osmo_netdev_addaddr() libosmocore API

This allows dropping a lot of duplicated code.
While at it, drop references to non-linux systems, which are not
maintained anymore.
Param "dstaddr" was not used anywhere in the old APIs, so it can also be
dropped.
Param "tun->routes" was also used in BSD code, so it can also be
dropped.

Change-Id: I1fccfd658542481cd61536fbd3c7a3a32a1c253b
---
M ggsn/ggsn.c
M lib/netdev.c
M lib/netdev.h
M lib/tun.c
M lib/tun.h
M sgsnemu/sgsnemu.c
6 files changed, 39 insertions(+), 620 deletions(-)



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

diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 7967f42..1908958 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -264,7 +264,7 @@
        if (apn->v4.cfg.ifconfig_prefix.addr.len) {
                LOGPAPN(LOGL_INFO, apn, "Setting tun IP address %s\n",
                        in46p_ntoa(&apn->v4.cfg.ifconfig_prefix));
-               if (tun_addaddr(apn->tun.tun, 
&apn->v4.cfg.ifconfig_prefix.addr, NULL,
+               if (tun_addaddr(apn->tun.tun, &apn->v4.cfg.ifconfig_prefix.addr,
                                apn->v4.cfg.ifconfig_prefix.prefixlen)) {
                        LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv4 
address %s: %s\n",
                                in46p_ntoa(&apn->v4.cfg.ifconfig_prefix), 
strerror(errno));
@@ -276,7 +276,7 @@
        if (apn->v6.cfg.ifconfig_prefix.addr.len) {
                LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 address %s\n",
                        in46p_ntoa(&apn->v6.cfg.ifconfig_prefix));
-               if (tun_addaddr(apn->tun.tun, 
&apn->v6.cfg.ifconfig_prefix.addr, NULL,
+               if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ifconfig_prefix.addr,
                                apn->v6.cfg.ifconfig_prefix.prefixlen)) {
                        LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv6 
address %s: %s. "
                                "Ensure you have ipv6 support and not used the 
disable_ipv6 sysctl?\n",
@@ -289,7 +289,7 @@
        if (apn->v6.cfg.ll_prefix.addr.len) {
                LOGPAPN(LOGL_INFO, apn, "Setting tun IPv6 link-local address 
%s\n",
                        in46p_ntoa(&apn->v6.cfg.ll_prefix));
-               if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ll_prefix.addr, NULL,
+               if (tun_addaddr(apn->tun.tun, &apn->v6.cfg.ll_prefix.addr,
                                apn->v6.cfg.ll_prefix.prefixlen)) {
                        LOGPAPN(LOGL_ERROR, apn, "Failed to set tun IPv6 
link-local address %s: %s. "
                                "Ensure you have ipv6 support and not used the 
disable_ipv6 sysctl?\n",
@@ -300,6 +300,15 @@
                apn->v6_lladdr = apn->v6.cfg.ll_prefix.addr.v6;
        }

+       rc = osmo_netdev_ifupdown(apn->tun.tun->netdev, true);
+       if (rc < 0) {
+               LOGPAPN(LOGL_ERROR, apn, "Failed to set tun interface UP: %s. "
+                       "Ensure you have ipv6 support and not used the 
disable_ipv6 sysctl?\n",
+                       strerror(errno));
+               apn_stop(apn);
+               return -1;
+       }
+
        if (apn->tun.cfg.ipup_script) {
                LOGPAPN(LOGL_INFO, apn, "Running ip-up script %s\n",
                        apn->tun.cfg.ipup_script);
diff --git a/lib/netdev.c b/lib/netdev.c
index fd3caff..fb18d60 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -37,522 +37,14 @@
 #include <net/route.h>
 #include <net/if.h>

-#if defined(__linux__)
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>

-#elif defined (__FreeBSD__)
-#include <net/if_var.h>
-#include <netinet/in_var.h>
-
-#elif defined (__APPLE__)
-#include <net/if.h>
-
-#else
-#error  "Unknown platform!"
-#endif
-
 #include "netdev.h"
 #include "syserr.h"

-#if defined(__linux__)
-
 #include <linux/ipv6.h>

-static int netdev_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int 
dlen)
-{
-       int len = RTA_LENGTH(dlen);
-       int alen = NLMSG_ALIGN(n->nlmsg_len);
-       struct rtattr *rta = (struct rtattr *)(((void *)n) + alen);
-       if (alen + len > nsize)
-               return -1;
-       rta->rta_len = len;
-       rta->rta_type = type;
-       memcpy(RTA_DATA(rta), d, dlen);
-       n->nlmsg_len = alen + len;
-       return 0;
-}
-#endif
-
-static int netdev_sifflags(const char *devname, int flags)
-{
-       struct ifreq ifr;
-       int fd;
-
-       memset(&ifr, '\0', sizeof(ifr));
-       ifr.ifr_flags = flags;
-       strncpy(ifr.ifr_name, devname, IFNAMSIZ);
-       ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
-       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
-               return -1;
-       }
-       if (ioctl(fd, SIOCSIFFLAGS, &ifr)) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno,
-                       "ioctl(SIOCSIFFLAGS) failed");
-               close(fd);
-               return -1;
-       }
-       close(fd);
-       return 0;
-}
-
-int netdev_setaddr4(const char *devname, struct in_addr *addr,
-                   struct in_addr *dstaddr, struct in_addr *netmask)
-{
-       struct ifreq ifr;
-       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__)
-       ((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
-
-       strncpy(ifr.ifr_name, devname, IFNAMSIZ);
-       ifr.ifr_name[IFNAMSIZ - 1] = 0; /* Make sure to terminate */
-
-       /* Create a channel to the NET kernel. */
-       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
-               return -1;
-       }
-
-       if (addr) {             /* Set the interface address */
-               memcpy(&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, addr,
-                      sizeof(*addr));
-               if (ioctl(fd, SIOCSIFADDR, (void *)&ifr) < 0) {
-                       if (errno != EEXIST) {
-                               SYS_ERR(DTUN, LOGL_ERROR, errno,
-                                       "ioctl(SIOCSIFADDR) failed");
-                       } else {
-                               SYS_ERR(DTUN, LOGL_NOTICE, errno,
-                                       "ioctl(SIOCSIFADDR): Address already 
exists");
-                       }
-                       close(fd);
-                       return -1;
-               }
-       }
-
-       if (dstaddr) {          /* Set the destination address */
-               memcpy(&((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr,
-                      dstaddr, sizeof(*dstaddr));
-               if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t) & ifr) < 0) {
-                       SYS_ERR(DTUN, LOGL_ERROR, errno,
-                               "ioctl(SIOCSIFDSTADDR) failed");
-                       close(fd);
-                       return -1;
-               }
-       }
-
-       if (netmask) {          /* Set the netmask */
-#if defined(__linux__)
-               memcpy(&((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr,
-                      netmask, sizeof(*netmask));
-#elif defined(__FreeBSD__) || defined (__APPLE__)
-               ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr =
-                   netmask->s_addr;
-#endif
-
-               if (ioctl(fd, SIOCSIFNETMASK, (void *)&ifr) < 0) {
-                       SYS_ERR(DTUN, LOGL_ERROR, errno,
-                               "ioctl(SIOCSIFNETMASK) failed");
-                       close(fd);
-                       return -1;
-               }
-       }
-
-       close(fd);
-
-       netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
-
-       /* On linux the route to the interface is set automatically
-          on FreeBSD we have to do this manually */
-#if defined(__FreeBSD__) || defined (__APPLE__)
-       netdev_addroute4(dstaddr, addr, &this->netmask);
-#endif
-
-       return 0;
-}
-
-int netdev_setaddr6(const char *devname, struct in6_addr *addr, struct 
in6_addr *dstaddr,
-                   size_t prefixlen)
-{
-       struct in6_ifreq ifr;
-       int fd;
-
-       memset(&ifr, 0, sizeof(ifr));
-
-#if defined(__linux__)
-       ifr.ifr6_prefixlen = prefixlen;
-       ifr.ifr6_ifindex = if_nametoindex(devname);
-       if (ifr.ifr6_ifindex == 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0, "Error getting ifindex for %s\n", 
devname);
-               return -1;
-       }
-#elif defined(__FreeBSD__) || defined (__APPLE__)
-       strncpy(ifr.ifr_name, devname, IFNAMSIZ);
-#endif
-
-       /* Create a channel to the NET kernel */
-       if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0, "socket() failed");
-               return -1;
-       }
-
-#if defined(__linux__)
-       if (addr) {
-               memcpy(&ifr.ifr6_addr, addr, sizeof(*addr));
-               if (ioctl(fd, SIOCSIFADDR, (void *) &ifr) < 0) {
-                       if (errno != EEXIST) {
-                               SYS_ERR(DTUN, LOGL_ERROR, 0, 
"ioctl(SIOCSIFADDR) failed");
-                       } else {
-                               SYS_ERR(DTUN, LOGL_NOTICE, 0, 
"ioctl(SIOCSIFADDR): Address already exists");
-                       }
-                       close(fd);
-                       return -1;
-               }
-       }
-
-#if 0
-       /* FIXME: looks like this is not possible/necessary for IPv6? */
-       if (dstaddr) {
-               memcpy(&ifr.ifr6_addr, dstaddr, sizeof(*dstaddr));
-               if (ioctl(fd, SIOCSIFDSTADDR, (caddr_t *) &ifr) < 0) {
-                       SYS_ERR(DTUN, LOGL_ERROR, "ioctl(SIOCSIFDSTADDR) 
failed");
-                       close(fd);
-                       return -1;
-               }
-       }
-#endif
-
-#elif defined(__FreeBSD__) || defined (__APPLE__)
-       if (addr)
-               memcpy(&ifr.ifr_ifru.ifru_addr, addr, 
sizeof(ifr.ifr_ifru.ifru_addr));
-       if (dstaddr)
-               memcpy(&ifr.ifr_ifru.ifru_dstaddr, dstaddr, 
sizeof(ifr.ifr_ifru.ifru_dstaddr));
-
-       if (ioctl(fd, SIOCSIFADDR_IN6, (struct ifreq *)&ifr) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0, "ioctl(SIOCSIFADDR_IN6) failed");
-               close(fd);
-               return -1;
-       }
-#endif
-
-       close(fd);
-
-       netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
-
-       /* On linux the route to the interface is set automatically
-          on FreeBSD we have to do this manually */
-#if 0  /* FIXME */
-//#if defined(__FreeBSD__) || defined (__APPLE__)
-       netdev_addroute6(dstaddr, addr, prefixlen);
-#endif
-
-       return 0;
-}
-
-int netdev_addaddr4(const char *devname, struct in_addr *addr,
-                   struct in_addr *dstaddr, struct in_addr *netmask)
-{
-       int fd;
-#if defined(__linux__)
-       struct {
-               struct nlmsghdr n;
-               struct ifaddrmsg i;
-               char buf[TUN_NLBUFSIZE];
-       } req;
-
-       struct sockaddr_nl local;
-       socklen_t addr_len;
-       int status;
-
-       struct sockaddr_nl nladdr;
-       struct iovec iov;
-       struct msghdr msg;
-
-       memset(&req, 0, sizeof(req));
-       req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-       req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
-       req.n.nlmsg_type = RTM_NEWADDR;
-       req.i.ifa_family = AF_INET;
-       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(devname);
-       if (!req.i.ifa_index) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for 
%s", devname);
-               return -1;
-       }
-
-       netdev_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(*addr));
-       if (dstaddr)
-               netdev_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, 
sizeof(*dstaddr));
-
-       if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
-               return -1;
-       }
-
-       memset(&local, 0, sizeof(local));
-       local.nl_family = AF_NETLINK;
-       local.nl_groups = 0;
-
-       if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "bind() failed");
-               close(fd);
-               return -1;
-       }
-
-       addr_len = sizeof(local);
-       if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno,
-                       "getsockname() failed");
-               close(fd);
-               return -1;
-       }
-
-       if (addr_len != sizeof(local)) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0,
-                       "Wrong address length %d", addr_len);
-               close(fd);
-               return -1;
-       }
-
-       if (local.nl_family != AF_NETLINK) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0,
-                       "Wrong address family %d", local.nl_family);
-               close(fd);
-               return -1;
-       }
-
-       iov.iov_base = (void *)&req.n;
-       iov.iov_len = req.n.nlmsg_len;
-
-       msg.msg_name = (void *)&nladdr;
-       msg.msg_namelen = sizeof(nladdr);
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = 0;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = 0;
-       nladdr.nl_groups = 0;
-
-       req.n.nlmsg_seq = 0;
-       req.n.nlmsg_flags |= NLM_F_ACK;
-
-       status = sendmsg(fd, &msg, 0);
-       if (status != req.n.nlmsg_len) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "sendmsg() failed, returned 
%d", status);
-               close(fd);
-               return -1;
-       }
-
-       status = netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
-       if (status == -1) {
-               close(fd);
-               return -1;
-       }
-#elif defined (__FreeBSD__) || defined (__APPLE__)
-       struct ifaliasreq areq;
-
-       memset(&areq, 0, sizeof(areq));
-
-       /* Set up interface name */
-       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;
-       ((struct sockaddr_in *)&areq.ifra_addr)->sin_len =
-           sizeof(areq.ifra_addr);
-       ((struct sockaddr_in *)&areq.ifra_addr)->sin_addr.s_addr = addr->s_addr;
-
-       ((struct sockaddr_in *)&areq.ifra_mask)->sin_family = AF_INET;
-       ((struct sockaddr_in *)&areq.ifra_mask)->sin_len =
-           sizeof(areq.ifra_mask);
-       ((struct sockaddr_in *)&areq.ifra_mask)->sin_addr.s_addr =
-           netmask->s_addr;
-
-       /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
-       ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_family = AF_INET;
-       ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_len =
-           sizeof(areq.ifra_broadaddr);
-       ((struct sockaddr_in *)&areq.ifra_broadaddr)->sin_addr.s_addr =
-           dstaddr->s_addr;
-
-       /* Create a channel to the NET kernel. */
-       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
-               return -1;
-       }
-
-       if (ioctl(fd, SIOCAIFADDR, (void *)&areq) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno,
-                       "ioctl(SIOCAIFADDR) failed");
-               close(fd);
-               return -1;
-       }
-#endif
-       close(fd);
-       return 0;
-}
-
-int netdev_addaddr6(const char *devname, struct in6_addr *addr,
-                   struct in6_addr *dstaddr, int prefixlen)
-{
-       int fd;
-#if defined(__linux__)
-       struct {
-               struct nlmsghdr n;
-               struct ifaddrmsg i;
-               char buf[TUN_NLBUFSIZE];
-       } req;
-
-       struct sockaddr_nl local;
-       socklen_t addr_len;
-       int status;
-
-       struct sockaddr_nl nladdr;
-       struct iovec iov;
-       struct msghdr msg;
-
-       memset(&req, 0, sizeof(req));
-       req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
-       req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
-       req.n.nlmsg_type = RTM_NEWADDR;
-       req.i.ifa_family = AF_INET6;
-       req.i.ifa_prefixlen = prefixlen;        /* 64 FOR IPv6 */
-       req.i.ifa_flags = 0;
-       req.i.ifa_scope = RT_SCOPE_HOST;        /* TODO or 0 */
-       req.i.ifa_index = if_nametoindex(devname);
-       if (!req.i.ifa_index) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "Unable to get ifindex for 
%s", devname);
-               return -1;
-       }
-
-       netdev_nlattr(&req.n, sizeof(req), IFA_ADDRESS, addr, sizeof(*addr));
-       if (dstaddr)
-               netdev_nlattr(&req.n, sizeof(req), IFA_LOCAL, dstaddr, 
sizeof(*dstaddr));
-
-       if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
-               return -1;
-       }
-
-       memset(&local, 0, sizeof(local));
-       local.nl_family = AF_NETLINK;
-       local.nl_groups = 0;
-
-       if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "bind() failed");
-               close(fd);
-               return -1;
-       }
-
-       addr_len = sizeof(local);
-       if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno,
-                       "getsockname() failed");
-               close(fd);
-               return -1;
-       }
-
-       if (addr_len != sizeof(local)) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0,
-                       "Wrong address length %d", addr_len);
-               close(fd);
-               return -1;
-       }
-
-       if (local.nl_family != AF_NETLINK) {
-               SYS_ERR(DTUN, LOGL_ERROR, 0,
-                       "Wrong address family %d", local.nl_family);
-               close(fd);
-               return -1;
-       }
-
-       iov.iov_base = (void *)&req.n;
-       iov.iov_len = req.n.nlmsg_len;
-
-       msg.msg_name = (void *)&nladdr;
-       msg.msg_namelen = sizeof(nladdr);
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-       msg.msg_control = NULL;
-       msg.msg_controllen = 0;
-       msg.msg_flags = 0;
-
-       memset(&nladdr, 0, sizeof(nladdr));
-       nladdr.nl_family = AF_NETLINK;
-       nladdr.nl_pid = 0;
-       nladdr.nl_groups = 0;
-
-       req.n.nlmsg_seq = 0;
-       req.n.nlmsg_flags |= NLM_F_ACK;
-
-       status = sendmsg(fd, &msg, 0);
-       if (status != req.n.nlmsg_len) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "sendmsg() failed, returned 
%d", status);
-               close(fd);
-               return -1;
-       }
-
-       status = netdev_sifflags(devname, IFF_UP | IFF_RUNNING);
-       if (status == -1) {
-               close(fd);
-               return -1;
-       }
-#elif defined (__FreeBSD__) || defined (__APPLE__)
-       struct ifaliasreq areq;
-
-       memset(&areq, 0, sizeof(areq));
-
-       /* Set up interface name */
-       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;
-       ((struct sockaddr_in6 *)&areq.ifra_addr)->sin6_len = 
sizeof(areq.ifra_addr);
-       ((struct sockaddr_in6 *)&areq.ifra_addr)->sin6_addr.s6_addr = 
addr->s6_addr;
-
-       ((struct sockaddr_in6 *)&areq.ifra_mask)->sin6_family = AF_INET6;
-       ((struct sockaddr_in6 *)&areq.ifra_mask)->sin6_len = 
sizeof(areq.ifra_mask);
-       ((struct sockaddr_in6 *)&areq.ifra_mask)->sin6_addr.s6_addr = 
netmask->s6_addr;
-
-       /* For some reason FreeBSD uses ifra_broadcast for specifying dstaddr */
-       ((struct sockaddr_in6 *)&areq.ifra_broadaddr)->sin6_family = AF_INET6;
-       ((struct sockaddr_in6 *)&areq.ifra_broadaddr)->sin6_len = 
sizeof(areq.ifra_broadaddr);
-       ((struct sockaddr_in6 *)&areq.ifra_broadaddr)->sin6_addr.s6_addr = 
dstaddr->s6_addr;
-
-       /* Create a channel to the NET kernel. */
-       if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno, "socket() failed");
-               return -1;
-       }
-
-       if (ioctl(fd, SIOCAIFADDR, (void *)&areq) < 0) {
-               SYS_ERR(DTUN, LOGL_ERROR, errno,
-                       "ioctl(SIOCAIFADDR) failed");
-               close(fd);
-               return -1;
-       }
-#endif
-       close(fd);
-       return 0;
-}
-
 static int netdev_route4(struct in_addr *dst, struct in_addr *gateway, struct 
in_addr *mask, int delete)
 {
        int fd;
diff --git a/lib/netdev.h b/lib/netdev.h
index 1bce814..2e8e77b 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -53,18 +53,6 @@
   };
 #endif /* !HAVE_IPHDR */

-extern int netdev_setaddr4(const char *devname, struct in_addr *addr,
-                          struct in_addr *dstaddr, struct in_addr *netmask);
-
-extern int netdev_setaddr6(const char *devname, struct in6_addr *addr, struct 
in6_addr *dstaddr,
-                          size_t prefixlen);
-
-extern int netdev_addaddr4(const char *devname, struct in_addr *addr,
-                          struct in_addr *dstaddr, struct in_addr *netmask);
-
-extern int netdev_addaddr6(const char *devname, struct in6_addr *addr,
-                          struct in6_addr *dstaddr, int prefixlen);
-
 extern int netdev_addroute4(struct in_addr *dst, struct in_addr *gateway, 
struct in_addr *mask);
 extern int netdev_delroute4(struct in_addr *dst, struct in_addr *gateway, 
struct in_addr *mask);
 extern int netdev_addroute6(struct in6_addr *dst, struct in6_addr *gateway, 
int prefixlen, const char *gw_iface);
diff --git a/lib/tun.c b/lib/tun.c
index acc3927..055c4fc 100644
--- a/lib/tun.c
+++ b/lib/tun.c
@@ -49,99 +49,38 @@
 #include "syserr.h"
 #include "gtp-kernel.h"

-static int tun_setaddr4(struct tun_t *this, struct in_addr *addr,
-                       struct in_addr *dstaddr, struct in_addr *netmask)
+int tun_addaddr(struct tun_t *this, struct in46_addr *addr, size_t prefixlen)
 {
+       struct osmo_sockaddr osa = {0};
        int rc;
-       rc = netdev_setaddr4(this->devname, addr, dstaddr, netmask);
-       if (rc < 0)
-               return rc;
+       OSMO_ASSERT(this->netdev);
+       OSMO_ASSERT(addr);

-       if (addr) {
-               this->addr.len = sizeof(struct in_addr);
-               this->addr.v4.s_addr = addr->s_addr;
-       }
-       if (dstaddr) {
-               this->dstaddr.len = sizeof(struct in_addr);
-               this->dstaddr.v4.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 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;
-       if (dstaddr) {
-               this->dstaddr.len = sizeof(*dstaddr);
-               memcpy(&this->dstaddr.v6, dstaddr, sizeof(*dstaddr));
-       }
-       this->addrs++;
-#if defined(__FreeBSD__) || defined (__APPLE__)
-       this->routes = 1;
-#endif
-
-       return rc;
-}
-
-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 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;
        switch (addr->len) {
        case 4:
-               netmask.s_addr = htonl(0xffffffff << (32 - prefixlen));
-               return tun_addaddr4(this, &addr->v4, dstaddr ? &dstaddr->v4 : 
NULL, &netmask);
+               osa.u.sin.sin_family = AF_INET;
+               memcpy(&osa.u.sin.sin_addr, &addr->v4, sizeof(struct in_addr));
+               /* Store first IPv4 IP address to be used in ipup script: */
+               if (this->addrs == 0) {
+                       this->addr.len = sizeof(struct in_addr);
+                       this->addr.v4.s_addr = addr->v4.s_addr;
+                       this->netmask.s_addr = htonl(0xffffffff << (32 - 
prefixlen));
+               }
+               break;
        case 16:
-               return tun_addaddr6(this, &addr->v6, dstaddr ? &dstaddr->v6 : 
NULL, prefixlen);
+               osa.u.sin.sin_family = AF_INET6;
+               memcpy(&osa.u.sin6.sin6_addr, &addr->v6, sizeof(struct 
in6_addr));
+               break;
        default:
                return -1;
        }
+
+       rc = osmo_netdev_add_addr(this->netdev, &osa, prefixlen);
+       if (rc < 0)
+               return rc;
+
+       this->addrs++;
+       return rc;
 }

 static int tun_tundev_data_ind_cb(struct osmo_tundev *tundev, struct msgb *msg)
@@ -168,7 +107,6 @@

        t->cb_ind = NULL;
        t->addrs = 0;
-       t->routes = 0;
        t->fd = -1;

        if (!use_kernel) {
@@ -235,11 +173,6 @@

 int tun_free(struct tun_t *tun)
 {
-
-       if (tun->routes) {
-               netdev_delroute4(&tun->dstaddr.v4, &tun->addr.v4, 
&tun->netmask);
-       }
-
        if (tun->tundev) {
                if (osmo_tundev_close(tun->tundev) < 0) {
                        SYS_ERR(DTUN, LOGL_ERROR, errno, "close() failed");
diff --git a/lib/tun.h b/lib/tun.h
index 8a3a2d4..544e56a 100644
--- a/lib/tun.h
+++ b/lib/tun.h
@@ -37,10 +37,8 @@
        struct osmo_netdev *netdev;
        int fd;                 /* File descriptor to tun interface */
        struct in46_addr addr;
-       struct in46_addr dstaddr;
        struct in_addr netmask;
        int addrs;              /* Number of allocated IP addresses */
-       int routes;             /* One if we allocated an automatic route */
        char devname[IFNAMSIZ]; /* Name of the tun device */
        int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len);
        /* to be used by libgtp callers/users (to attach their own private 
state) */
@@ -52,8 +50,7 @@
 extern int tun_decaps(struct tun_t *this);
 extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);

-extern int tun_addaddr(struct tun_t *this, struct in46_addr *addr,
-                      struct in46_addr *dstaddr, size_t prefixlen);
+extern int tun_addaddr(struct tun_t *this, struct in46_addr *addr, size_t 
prefixlen);

 extern int tun_set_cb_ind(struct tun_t *this,
                          int (*cb_ind) (struct tun_t * tun, void *pack,
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index d6d87b7..9ab0f25 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -1649,7 +1649,7 @@
                        if (addr[i].len == 16)
                                prefixlen = 64;
                        /* printf("Setting up interface and routing\n"); */
-                       tun_addaddr(tun, &addr[i], NULL, prefixlen);
+                       tun_addaddr(tun, &addr[i], prefixlen);
                        if (options.defaultroute) {
                                if (in46a_is_v4(&addr[i])) {
                                        struct in_addr rm;
@@ -1786,7 +1786,7 @@
                                        }
                                }
 #endif
-                               rc = tun_addaddr(tun, &addr, NULL, 
opt_prefix->prefix_len);
+                               rc = tun_addaddr(tun, &addr, 
opt_prefix->prefix_len);
                                if (rc < 0) {
                                        SYS_ERR(DSGSN, LOGL_ERROR, 0, "Failed 
to add addr %s to tun %s",
                                                in46a_ntoa(&addr), 
tun->devname);
@@ -1936,7 +1936,7 @@
        }

        if ((options.createif) && (options.netaddr.len)) {
-               tun_addaddr(tun, &options.netaddr, NULL, options.prefixlen);
+               tun_addaddr(tun, &options.netaddr, options.prefixlen);
                if (options.defaultroute) {
                        if (in46a_is_v4(&options.netaddr)) {
                                struct in_addr rm;

--
To view, visit https://gerrit.osmocom.org/c/osmo-ggsn/+/38483?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: I1fccfd658542481cd61536fbd3c7a3a32a1c253b
Gerrit-Change-Number: 38483
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>

Reply via email to