pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmocom-bb/+/30994 )


Change subject: layer23: Introduce tun.{c,h}
......................................................................

layer23: Introduce tun.{c,h}

This module provides several operations on tun devices (interfaces).
These functionalitites will be used by the "modem" app to set up tunnels for 
each APN in a
follow-up patch.

The code is basically an import from osmo-ggsn.git
97f60e3dca581797007524e0006ca9fafad59713 src/lib/tun.{c,h}, with
small modifications to make use of osmo_sockaddr instead of
osmo-ggsn.git specific in46_addr.

Related: OS#5503
Change-Id: Id8611b720ada17a3c602872fe095bb91eeb17bcd
---
M src/host/layer23/include/osmocom/bb/common/Makefile.am
M src/host/layer23/include/osmocom/bb/common/apn.h
A src/host/layer23/include/osmocom/bb/common/tun.h
M src/host/layer23/src/common/Makefile.am
M src/host/layer23/src/common/apn.c
A src/host/layer23/src/common/tun.c
6 files changed, 555 insertions(+), 2 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/94/30994/1

diff --git a/src/host/layer23/include/osmocom/bb/common/Makefile.am 
b/src/host/layer23/include/osmocom/bb/common/Makefile.am
index 12be730..67dc21c 100644
--- a/src/host/layer23/include/osmocom/bb/common/Makefile.am
+++ b/src/host/layer23/include/osmocom/bb/common/Makefile.am
@@ -18,5 +18,6 @@
        sim.h \
        subscriber.h \
        support.h \
+       tun.h \
        vty.h \
        $(NULL)
diff --git a/src/host/layer23/include/osmocom/bb/common/apn.h 
b/src/host/layer23/include/osmocom/bb/common/apn.h
index 18dc16f..7a6215b 100644
--- a/src/host/layer23/include/osmocom/bb/common/apn.h
+++ b/src/host/layer23/include/osmocom/bb/common/apn.h
@@ -21,6 +21,7 @@
 #include <osmocom/core/select.h>

 struct osmocom_ms;
+struct tun_t;

 #define APN_TYPE_IPv4  0x01    /* v4-only */
 #define APN_TYPE_IPv6  0x02    /* v6-only */
@@ -54,7 +55,7 @@

        /* corresponding tun device */
        struct {
-               //struct tun_t *tun;
+               struct tun_t *tun;
                struct osmo_fd fd;
        } tun;

@@ -66,3 +67,6 @@
 void apn_free(struct osmobb_apn *apn);
 int apn_start(struct osmobb_apn *apn);
 int apn_stop(struct osmobb_apn *apn);
+
+#define LOGPAPN(level, apn, fmt, args...)                      \
+       LOGP(DTUN, level, "APN(%s): " fmt, (apn)->cfg.name, ## args)
diff --git a/src/host/layer23/include/osmocom/bb/common/tun.h 
b/src/host/layer23/include/osmocom/bb/common/tun.h
new file mode 100644
index 0000000..703d1bd
--- /dev/null
+++ b/src/host/layer23/include/osmocom/bb/common/tun.h
@@ -0,0 +1,64 @@
+/*
+ * TUN interface functions.
+ * Copyright (C) 2002, 2003 Mondru AB.
+ * Copyright (C) 2017-2018 by Harald Welte <lafo...@gnumonks.org>
+ * Copyright (C) 2023 by sysmocom - s.m.f.c. GmbH <i...@sysmocom.de>
+ *
+ * The contents of this file may be used under the terms of the GNU
+ * General Public License Version 2, provided that the above copyright
+ * notice and this permission notice is included in all copies or
+ * substantial portions of the software.
+ *
+ */
+
+#ifndef _TUN_H
+#define _TUN_H
+
+#include <stdbool.h>
+#include <net/if.h>
+
+#include <osmocom/core/socket.h>
+#include <osmocom/bb/common/netdev.h>
+
+#define PACKET_MAX      8196   /* Maximum packet size we receive */
+#define TUN_SCRIPTSIZE   256
+#define TUN_ADDRSIZE     128
+
+/* ***********************************************************
+ * Information storage for each tun instance
+ *************************************************************/
+
+struct tun_t {
+       int fd;                 /* File descriptor to tun interface */
+       struct osmo_sockaddr addr;
+       struct osmo_sockaddr 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 callers/users (to attach their own private state) */
+       void *priv;
+};
+
+extern int tun_new(struct tun_t **tun, const char *dev_name, bool use_kernel, 
int fd0, int fd1u);
+extern int tun_free(struct tun_t *tun);
+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 osmo_sockaddr *addr,
+                      struct osmo_sockaddr *dstaddr, size_t prefixlen);
+
+extern int tun_set_cb_ind(struct tun_t *this,
+                         int (*cb_ind) (struct tun_t * tun, void *pack,
+                                        unsigned len));
+
+extern int tun_runscript(struct tun_t *tun, char *script);
+
+int tun_ip_local_get(const struct tun_t *tun, struct in46_prefix *prefix_list,
+                    size_t prefix_size, int flags);
+
+#define LOGTUN(level, tun, fmt, args...) \
+       LOGP(DTUN, level, "TUN(%s): " fmt, (tun)->devname, ## args)
+
+#endif /* !_TUN_H */
diff --git a/src/host/layer23/src/common/Makefile.am 
b/src/host/layer23/src/common/Makefile.am
index 3a6ba37..cc6f3f5 100644
--- a/src/host/layer23/src/common/Makefile.am
+++ b/src/host/layer23/src/common/Makefile.am
@@ -30,6 +30,7 @@
        subscriber.c \
        support.c \
        sysinfo.c \
+       tun.c \
        utils.c \
        vty.c \
        $(NULL)
diff --git a/src/host/layer23/src/common/apn.c 
b/src/host/layer23/src/common/apn.c
index bd0eb25..f21892e 100644
--- a/src/host/layer23/src/common/apn.c
+++ b/src/host/layer23/src/common/apn.c
@@ -18,12 +18,14 @@
 #include <stdint.h>
 #include <errno.h>
 #include <string.h>
-#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>

 #include <talloc.h>

 #include <osmocom/bb/common/logging.h>
 #include <osmocom/bb/common/apn.h>
+#include <osmocom/bb/common/tun.h>
 #include <osmocom/bb/common/ms.h>

 struct osmobb_apn *apn_alloc(struct osmocom_ms *ms, const char *name)
@@ -49,12 +51,98 @@
        talloc_free(apn);
 }

+/* Local network-originated IP packet, needs to be sent via SNDCP/LLC (GPRS) 
towards GSM network */
+static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
+{
+       struct osmobb_apn *apn = tun->priv;
+       struct osmo_sockaddr dst;
+       struct iphdr *iph = (struct iphdr *)pack;
+       struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+       uint8_t pref_offset;
+
+       switch (iph->version) {
+       case 4:
+               if (len < sizeof(*iph) || len < 4*iph->ihl)
+                       return -1;
+               dst.u.sin.sin_family = AF_INET;
+               dst.u.sin.sin_addr.s_addr = iph->daddr;
+               break;
+       case 6:
+               /* Due to the fact that 3GPP requires an allocation of a
+                * /64 prefix to each MS, we must instruct
+                * ippool_getip() below to match only the leading /64
+                * prefix, i.e. the first 8 bytes of the address. If the ll addr
+                * is used, then the match should be done on the trailing 64
+                * bits. */
+               pref_offset = IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_dst) ? 8 : 0;
+               memcpy(&dst.u.sin6.sin6_addr, ((uint8_t*)&ip6h->ip6_dst) + 
pref_offset, 8);
+               break;
+       default:
+               LOGTUN(LOGL_NOTICE, tun, "non-IPv%u packet received\n", 
iph->version);
+               return -1;
+       }
+
+       LOGPAPN(LOGL_DEBUG, apn, "system wants to transmit IPv%u pkt to %s (%u 
bytes)\n",
+              iph->version == 4 ? '4' : '6', osmo_sockaddr_to_str(&dst), len);
+
+       /* TODO: prepare & transmit SNDCP UNITDATA.req */
+
+       return 0;
+}
+
+/* callback for tun device osmocom select loop integration */
+static int apn_tun_fd_cb(struct osmo_fd *fd, unsigned int what)
+{
+       struct osmobb_apn *apn = fd->data;
+
+       OSMO_ASSERT(what & OSMO_FD_READ);
+
+       return tun_decaps(apn->tun.tun);
+}
+
 int apn_start(struct osmobb_apn *apn)
 {
+       if (apn->started)
+               return 0;
+
+       LOGPAPN(LOGL_INFO, apn, "Opening TUN device %s\n", apn->cfg.dev_name);
+       if (tun_new(&apn->tun.tun, apn->cfg.dev_name, false, -1, -1)) {
+               LOGPAPN(LOGL_ERROR, apn, "Failed to configure tun device\n");
+               return -1;
+       }
+       LOGPAPN(LOGL_INFO, apn, "Opened TUN device %s\n", 
apn->tun.tun->devname);
+
+       /* Register with libosmcoore */
+       osmo_fd_setup(&apn->tun.fd, apn->tun.tun->fd, OSMO_FD_READ, 
apn_tun_fd_cb, apn, 0);
+       osmo_fd_register(&apn->tun.fd);
+
+       /* Set TUN library callback */
+       tun_set_cb_ind(apn->tun.tun, cb_tun_ind);
+
+       /* set back-pointer from TUN device to APN */
+       apn->tun.tun->priv = apn;
+
+       /* TODO: set IP addresses on the tun device once we receive them from 
GGSN. See
+          osmo-ggsn.git's apn_start() */
+
+       LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n");
+       apn->started = true;
        return 0;
 }

 int apn_stop(struct osmobb_apn *apn)
 {
+       LOGPAPN(LOGL_NOTICE, apn, "Stopping\n");
+
+       /* shutdown whatever old state might be left */
+       if (apn->tun.tun) {
+               /* release tun device */
+               LOGPAPN(LOGL_INFO, apn, "Closing TUN device %s\n", 
apn->tun.tun->devname);
+               osmo_fd_unregister(&apn->tun.fd);
+               tun_free(apn->tun.tun);
+               apn->tun.tun = NULL;
+       }
+
+       apn->started = false;
        return 0;
 }
\ No newline at end of file
diff --git a/src/host/layer23/src/common/tun.c 
b/src/host/layer23/src/common/tun.c
new file mode 100644
index 0000000..98d1927
--- /dev/null
+++ b/src/host/layer23/src/common/tun.c
@@ -0,0 +1,395 @@
+/*
+ * TUN interface functions.
+ * Copyright (C) 2002, 2003, 2004 Mondru AB.
+ * Copyright (C) 2017-2018 by Harald Welte <lafo...@gnumonks.org>
+ * Copyright (C) 2023 by sysmocom - s.m.f.c. GmbH <i...@sysmocom.de>
+ *
+ * The contents of this file may be used under the terms of the GNU
+ * General Public License Version 2, provided that the above copyright
+ * notice and this permission notice is included in all copies or
+ * substantial portions of the software.
+ *
+ */
+
+/*
+ * tun.c: Contains all TUN functionality. Is able to handle multiple
+ * tunnels in the same program. Each tunnel is identified by the struct,
+ * which is passed to functions.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <net/route.h>
+#include <net/if.h>
+
+#if defined(__linux__)
+#include <linux/if_tun.h>
+
+#elif defined (__FreeBSD__)
+#include <net/if_tun.h>
+#include <net/if_var.h>
+#include <netinet/in_var.h>
+
+#elif defined (__APPLE__)
+#include <net/if.h>
+
+#else
+#error  "Unknown platform!"
+#endif
+
+#include <osmocom/core/logging.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/bb/common/logging.h>
+#include <osmocom/bb/common/tun.h>
+
+#define SYS_ERR(sub, pri, en, fmt, args...)                            \
+       if (en) {                                                       \
+               logp2(sub, pri, __FILE__, __LINE__, 0,                  \
+                       "errno=%d/%s " fmt "\n", en, strerror(en),      \
+                       ##args);                                        \
+       } else {                                                        \
+               logp2(sub, pri, __FILE__, __LINE__, 0,                  \
+                       fmt "\n", ##args);                              \
+       }
+
+/* FIXME: import gtp-kernel.{c,h} from osmo-ggsn.git. */
+static int gtp_kernel_create(int dest_ns, const char *devname, int fd0, int 
fd1u)
+{
+       return -ENOTSUP;
+}
+static void gtp_kernel_stop(const char *devname)
+{
+       (void)devname;
+}
+
+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.u.sin.sin_family = AF_INET;
+               this->addr.u.sin.sin_addr.s_addr = addr->s_addr;
+       }
+       if (dstaddr) {
+               this->dstaddr.u.sin.sin_family = AF_INET;
+               this->dstaddr.u.sin.sin_addr.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.u.sin6.sin6_family = AF_INET6;
+               memcpy(&this->dstaddr.u.sin6.sin6_addr, 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 osmo_sockaddr *addr, struct 
osmo_sockaddr *dstaddr, size_t prefixlen)
+{
+       struct in_addr netmask;
+       switch (addr->u.sa.sa_family) {
+       case AF_INET:
+               netmask.s_addr = htonl(0xffffffff << (32 - prefixlen));
+               return tun_addaddr4(this, &addr->u.sin.sin_addr, dstaddr ? 
&dstaddr->u.sin.sin_addr : NULL, &netmask);
+       case AF_INET6:
+               return tun_addaddr6(this, &addr->u.sin6.sin6_addr, dstaddr ? 
&dstaddr->u.sin6.sin6_addr : NULL, prefixlen);
+       default:
+               return -1;
+       }
+}
+
+int tun_new(struct tun_t **tun, const char *dev_name, bool use_kernel, int 
fd0, int fd1u)
+{
+
+#if defined(__linux__)
+       struct ifreq ifr;
+
+#elif defined(__FreeBSD__) || defined (__APPLE__)
+       char devname[IFNAMSIZ + 5];     /* "/dev/" + ifname */
+       int devnum;
+       struct ifaliasreq areq;
+       int fd;
+#endif
+
+       if (!(*tun = calloc(1, sizeof(struct tun_t)))) {
+               SYS_ERR(DTUN, LOGL_ERROR, errno, "calloc() failed");
+               return EOF;
+       }
+
+       (*tun)->cb_ind = NULL;
+       (*tun)->addrs = 0;
+       (*tun)->routes = 0;
+
+#if defined(__linux__)
+       if (!use_kernel) {
+               /* Open the actual tun device */
+               if (((*tun)->fd = open("/dev/net/tun", O_RDWR)) < 0) {
+                       SYS_ERR(DTUN, LOGL_ERROR, errno, "open() failed");
+                       goto err_free;
+               }
+
+               /* Set device flags. For some weird reason this is also the 
method
+                  used to obtain the network interface name */
+               memset(&ifr, 0, sizeof(ifr));
+               if (dev_name)
+                       strcpy(ifr.ifr_name, dev_name);
+               ifr.ifr_flags = IFF_TUN | IFF_NO_PI;    /* Tun device, no 
packet info */
+               if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) {
+                       SYS_ERR(DTUN, LOGL_ERROR, errno, "ioctl() failed");
+                       goto err_close;
+               }
+
+               strncpy((*tun)->devname, ifr.ifr_name, IFNAMSIZ);
+               (*tun)->devname[IFNAMSIZ - 1] = 0;
+
+               /* Disable checksums */
+               if (ioctl((*tun)->fd, TUNSETNOCSUM, 1) < 0) {
+                       SYS_ERR(DTUN, LOGL_NOTICE, errno, "could not disable 
checksum on %s", (*tun)->devname);
+               }
+               return 0;
+       } else {
+               strncpy((*tun)->devname, dev_name, IFNAMSIZ);
+               (*tun)->devname[IFNAMSIZ - 1] = 0;
+               (*tun)->fd = -1;
+
+               if (gtp_kernel_create(-1, dev_name, fd0, fd1u) < 0) {
+                       LOGP(DTUN, LOGL_ERROR, "cannot create GTP tunnel 
device: %s\n",
+                               strerror(errno));
+                       return -1;
+               }
+               LOGP(DTUN, LOGL_NOTICE, "GTP kernel configured\n");
+               return 0;
+       }
+
+#elif defined(__FreeBSD__) || defined (__APPLE__)
+
+       if (use_kernel) {
+               LOGP(DTUN, LOGL_ERROR, "No kernel GTP-U support in FreeBSD!\n");
+               return -1;
+       }
+
+       /* Find suitable device */
+       for (devnum = 0; devnum < 255; devnum++) {      /* TODO 255 */
+               snprintf(devname, sizeof(devname), "/dev/tun%d", devnum);
+               if (((*tun)->fd = open(devname, O_RDWR)) >= 0)
+                       break;
+               if (errno != EBUSY)
+                       break;
+       }
+       if ((*tun)->fd < 0) {
+               SYS_ERR(DTUN, LOGL_ERROR, errno,
+                       "Can't find tunnel device");
+               goto err_free;
+       }
+
+       snprintf((*tun)->devname, sizeof((*tun)->devname), "tun%d", devnum);
+       (*tun)->devname[sizeof((*tun)->devname)-1] = 0;
+
+       /* The tun device we found might have "old" IP addresses allocated */
+       /* We need to delete those. This problem is not present on Linux */
+
+       memset(&areq, 0, sizeof(areq));
+
+       /* Set up interface name */
+       strncpy(areq.ifra_name, (*tun)->devname, IFNAMSIZ);
+       areq.ifra_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");
+               goto err_close;
+       }
+
+       /* Delete any IP addresses until SIOCDIFADDR fails */
+       while (ioctl(fd, SIOCDIFADDR, (void *)&areq) != -1) ;
+
+       close(fd);
+       return 0;
+#endif
+
+err_close:
+       close((*tun)->fd);
+err_free:
+       free(*tun);
+       *tun = NULL;
+       return -1;
+}
+
+int tun_free(struct tun_t *tun)
+{
+
+       if (tun->routes) {
+               netdev_delroute4(&tun->dstaddr.u.sin.sin_addr, 
&tun->addr.u.sin.sin_addr, &tun->netmask);
+       }
+
+       if (tun->fd >= 0) {
+               if (close(tun->fd)) {
+                       SYS_ERR(DTUN, LOGL_ERROR, errno, "close() failed");
+               }
+       }
+
+       gtp_kernel_stop(tun->devname);
+
+       /* TODO: For solaris we need to unlink streams */
+
+       free(tun);
+       return 0;
+}
+
+int tun_set_cb_ind(struct tun_t *this,
+                  int (*cb_ind) (struct tun_t * tun, void *pack, unsigned len))
+{
+       this->cb_ind = cb_ind;
+       return 0;
+}
+
+int tun_decaps(struct tun_t *this)
+{
+       unsigned char buffer[PACKET_MAX];
+       int status;
+
+       if ((status = read(this->fd, buffer, sizeof(buffer))) <= 0) {
+               SYS_ERR(DTUN, LOGL_ERROR, errno, "read() failed");
+               return -1;
+       }
+
+       if (this->cb_ind)
+               return this->cb_ind(this, buffer, status);
+
+       return 0;
+}
+
+int tun_encaps(struct tun_t *tun, void *pack, unsigned len)
+{
+       int rc;
+       rc = write(tun->fd, pack, len);
+       if (rc < 0) {
+               SYS_ERR(DTUN, LOGL_ERROR, errno, "TUN(%s): write() failed", 
tun->devname);
+       } else if (rc < len) {
+               LOGTUN(LOGL_ERROR, tun, "short write() %d < %u\n", rc, len);
+       }
+       return rc;
+}
+
+int tun_runscript(struct tun_t *tun, char *script)
+{
+
+       char buf[TUN_SCRIPTSIZE];
+       char snet[TUN_ADDRSIZE];
+       char smask[TUN_ADDRSIZE];
+       int rc;
+
+       snet[0] = '\0';
+       smask[0] = '\0';
+
+       /* system("ipup /dev/tun0 192.168.0.10 255.255.255.0"); */
+       snprintf(buf, sizeof(buf), "%s %s %s %s",
+                script, tun->devname,
+                osmo_sockaddr_ntop(&tun->addr.u.sa, snet),
+                inet_ntop(AF_INET, &tun->netmask, smask, sizeof(smask)));
+       buf[sizeof(buf) - 1] = 0;
+       rc = system(buf);
+       if (rc == -1) {
+               SYS_ERR(DTUN, LOGL_ERROR, errno,
+                       "Error executing command %s", buf);
+               return -1;
+       }
+       return 0;
+}
+
+/*! Obtain the local address of the tun device.
+ *  \param[in] tun Target device owning the IP
+ *  \param[out] prefix_list List of prefix structures to fill with each IPv4/6 
and prefix length found.
+ *  \param[in] prefix_size Amount of elements allowed to be fill in the 
prefix_list array.
+ *  \param[in] flags Specify which kind of IP to look for: IP_TYPE_IPv4, 
IP_TYPE_IPv6_LINK, IP_TYPE_IPv6_NONLINK
+ *  \returns The number of ips found following the criteria specified by 
flags, -1 on error.
+ *
+ * This function will fill prefix_list with up to prefix_size IPs following the
+ * criteria specified by flags parameter. It returns the number of IPs matching
+ * the criteria. As a result, the number returned can be bigger than
+ * prefix_size. It can be used with prefix_size=0 to get an estimate of the 
size
+ * needed for prefix_list.
+ */
+int tun_ip_local_get(const struct tun_t *tun, struct in46_prefix *prefix_list, 
size_t prefix_size, int flags)
+{
+       return netdev_ip_local_get(tun->devname, prefix_list, prefix_size, 
flags);
+}

--
To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/30994
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Change-Id: Id8611b720ada17a3c602872fe095bb91eeb17bcd
Gerrit-Change-Number: 30994
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to