initial check-in of the UECUPS daemon and the related TTCN3 code
Change-Id: I5acf7059722b58e6f57dbf31e18abcc385533970
diff --git a/daemon/internal.h b/daemon/internal.h
new file mode 100644
index 0000000..cbccbfc
--- /dev/null
+++ b/daemon/internal.h
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/utils.h>
+
+struct nl_sock;
+struct osmo_stream_srv_link;
+
+/***********************************************************************
+ * Utility
+ ***********************************************************************/
+/* ensure we are called from main thread context */
+#define ASSERT_MAIN_THREAD(d) OSMO_ASSERT(pthread_self() == (d)->main_thread)
+
+#define MAX_UDP_PACKET 65535
+
+bool sockaddr_equals(const struct sockaddr *a, const struct sockaddr *b);
+
+struct addrinfo *addrinfo_helper(uint16_t family, uint16_t type, uint8_t proto,
+ const char *host, uint16_t port, bool passive);
+enum {
+ DTUN,
+ DEP,
+ DGT,
+ DUECUPS,
+};
+
+/***********************************************************************
+ * netdev / netlink
+ ***********************************************************************/
+
+int netdev_add_addr(struct nl_sock *nlsk, int ifindex, const struct sockaddr_storage *ss);
+int netdev_del_addr(struct nl_sock *nlsk, int ifindex, const struct sockaddr_storage *ss);
+int netdev_set_link(struct nl_sock *nlsk, int ifindex, bool up);
+int netdev_add_defaultroute(struct nl_sock *nlsk, int ifindex, uint8_t family);
+
+
+/***********************************************************************
+ * GTP Endpoint (UDP socket)
+ ***********************************************************************/
+
+struct gtp_daemon;
+
+/* local UDP socket for GTP communication */
+struct gtp_endpoint {
+ /* entry in global list */
+ struct llist_head list;
+ /* back-pointer to daemon */
+ struct gtp_daemon *d;
+ unsigned long use_count;
+
+ /* file descriptor */
+ int fd;
+
+ /* local IP:port */
+ struct sockaddr_storage bind_addr;
+ char *name;
+
+ /* the thread handling Rx from the fd/socket */
+ pthread_t thread;
+};
+
+
+struct gtp_endpoint *
+gtp_endpoint_find_or_create(struct gtp_daemon *d, const struct sockaddr_storage *bind_addr);
+
+struct gtp_endpoint *
+_gtp_endpoint_find(struct gtp_daemon *d, const struct sockaddr_storage *bind_addr);
+
+void _gtp_endpoint_deref_destroy(struct gtp_endpoint *ep);
+
+bool _gtp_endpoint_release(struct gtp_endpoint *ep);
+
+bool gtp_endpoint_release(struct gtp_endpoint *ep);
+
+
+
+/***********************************************************************
+ * TUN Device
+ ***********************************************************************/
+
+struct tun_device {
+ /* entry in global list */
+ struct llist_head list;
+ /* back-pointer to daemon */
+ struct gtp_daemon *d;
+ unsigned long use_count;
+
+ /* which device we refer to */
+ const char *devname;
+ int ifindex;
+
+ /* file descriptor */
+ int fd;
+
+ /* network namespace */
+ const char *netns_name;
+ int netns_fd;
+
+ /* netlink socket in the namespace of the tun device */
+ struct nl_sock *nl;
+
+ /* list of local addresses? or simply only have the kernel know thses? */
+
+ /* the thread handling Rx from the tun fd */
+ pthread_t thread;
+};
+
+struct tun_device *
+tun_device_find_or_create(struct gtp_daemon *d, const char *devname, const char *netns_name);
+
+struct tun_device *
+_tun_device_find(struct gtp_daemon *d, const char *devname);
+
+void _tun_device_deref_destroy(struct tun_device *tun);
+
+bool _tun_device_release(struct tun_device *tun);
+
+bool tun_device_release(struct tun_device *tun);
+
+
+
+/***********************************************************************
+ * GTP Tunnel
+ ***********************************************************************/
+
+/* Every tunnel is identified uniquely by the following tuples:
+ *
+ * a) local endpoint + TEID
+ * this is what happens on incoming GTP messages
+ *
+ * b) tun device + end-user-address (+ filter, if any)
+ * this is what happens when IP arrives on the tun device
+ */
+
+struct gtp_tunnel {
+ /* entry in global list / hash table */
+ struct llist_head list;
+ /* back-pointer to daemon */
+ struct gtp_daemon *d;
+
+ const char *name;
+
+ /* the TUN device associated with this tunnel */
+ struct tun_device *tun_dev;
+ /* the GTP endpoint (UDP socket) associated with this tunnel */
+ struct gtp_endpoint *gtp_ep;
+
+ /* TEID on transmit (host byte order) */
+ uint32_t tx_teid;
+ /* TEID one receive (host byte order) */
+ uint32_t rx_teid;
+
+ /* End user Address (inner IP) */
+ struct sockaddr_storage user_addr;
+
+ /* Remote UDP IP/Port*/
+ struct sockaddr_storage remote_udp;
+
+ /* TODO: Filter */
+};
+
+struct gtp_tunnel *
+_gtp_tunnel_find_r(struct gtp_daemon *d, uint32_t rx_teid, struct gtp_endpoint *ep);
+
+struct gtp_tunnel *
+_gtp_tunnel_find_eua(struct tun_device *tun, const struct sockaddr *sa, uint8_t proto);
+
+struct gtp_tunnel_params {
+ /* TEID in receive and transmit direction */
+ uint32_t rx_teid;
+ uint32_t tx_teid;
+
+ /* end user address */
+ struct sockaddr_storage user_addr;
+
+ /* remote GTP/UDP IP+Port */
+ struct sockaddr_storage remote_udp;
+
+ /* local GTP/UDP IP+Port (used to lookup/create local EP) */
+ struct sockaddr_storage local_udp;
+
+ /* local TUN device name (used to lookup/create local tun) */
+ const char *tun_name;
+ const char *tun_netns_name;
+};
+struct gtp_tunnel *gtp_tunnel_alloc(struct gtp_daemon *d, const struct gtp_tunnel_params *cpars);
+
+void _gtp_tunnel_destroy(struct gtp_tunnel *t);
+bool gtp_tunnel_destroy(struct gtp_daemon *d, const struct sockaddr_storage *bind_addr, uint32_t rx_teid);
+
+
+/***********************************************************************
+ * GTP Daemon
+ ***********************************************************************/
+
+struct gtp_daemon {
+ /* global lists of various objects */
+ struct llist_head gtp_endpoints;
+ struct llist_head tun_devices;
+ struct llist_head gtp_tunnels;
+ /* lock protecting all of the above lists */
+ pthread_rwlock_t rwlock;
+ /* main thread ID */
+ pthread_t main_thread;
+ /* client CUPS interface */
+ struct llist_head cups_clients;
+ struct osmo_stream_srv_link *cups_link;
+
+ struct {
+ char *cups_local_ip;
+ uint16_t cups_local_port;
+ } cfg;
+};
+extern struct gtp_daemon *g_daemon;
+
+int gtpud_vty_init(void);