Projects
osmocom:latest
osmo-uecups
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
osmo-uecups_0.1.4.dsc -> osmo-uecups_0.2.0.dsc
Changed
@@ -2,18 +2,18 @@ Source: osmo-uecups Binary: osmo-uecups Architecture: any -Version: 0.1.4 +Version: 0.2.0 Maintainer: Harald Welte <laforge@osmocom.org> Homepage: https://osmocom.org/projects/osmo-uecups Standards-Version: 3.9.8 -Vcs-Browser: https://git.osmocom.org/osmo-uecups -Vcs-Git: git://git.osmocom.org/osmo-uecups.git -Build-Depends: debhelper (>= 9), dh-autoreconf, autotools-dev, autoconf, autoconf-archive, automake, libtool, pkg-config, libjansson-dev, libnl-route-3-dev, libosmocore-dev (>= 1.1.0), libosmo-netif-dev, libsctp-dev, osmo-gsm-manuals-dev +Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups +Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups +Build-Depends: debhelper (>= 9), dh-autoreconf, autotools-dev, autoconf, automake, libtool, pkg-config, libjansson-dev, libnl-route-3-dev, libosmocore-dev (>= 1.7.0), libosmo-netif-dev (>= 1.2.0), libsctp-dev, osmo-gsm-manuals-dev (>= 1.3.0) Package-List: osmo-uecups deb net extra arch=any Checksums-Sha1: - c6aeef775fdda61264cdb2ad00a61fe0252315ac 24820 osmo-uecups_0.1.4.tar.xz + 77306a9b01a6aa28b457695a40b0925d1e9bdabd 26876 osmo-uecups_0.2.0.tar.xz Checksums-Sha256: - 1d274267b3b7eff28685378f6c4b7a381ca1e1935e14f63e26404ba7649e881b 24820 osmo-uecups_0.1.4.tar.xz + 3d5d3c6f2a696c6b628e069da41da727d312c896f4c9ba7fdc6c56ba4bc722c3 26876 osmo-uecups_0.2.0.tar.xz Files: - 9bf103bc1e191aa723dd657b367abd5a 24820 osmo-uecups_0.1.4.tar.xz + a577448bb7ef43c46b2fcad209b7e780 26876 osmo-uecups_0.2.0.tar.xz
View file
osmo-uecups_0.1.4.tar.xz/.tarball-version -> osmo-uecups_0.2.0.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -0.1.4 \ No newline at end of file +0.2.0 \ No newline at end of file
View file
osmo-uecups_0.1.4.tar.xz/README.md -> osmo-uecups_0.2.0.tar.xz/README.md
Changed
@@ -30,9 +30,9 @@ You can clone from the official osmo-bts.git repository using - git clone git://git.osmocom.org/osmo-uecups.git + git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups -There is a cgit interface at httsp://git.osmocom.org/osmo-uecups/ +There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups> Documentation ------------- @@ -62,5 +62,5 @@ https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for more details -The current patch queue for osmo-bts can be seen at +The current patch queue for osmo-uecups can be seen at https://gerrit.osmocom.org/#/q/project:osmo-uecups+status:open
View file
osmo-uecups_0.1.4.tar.xz/configure.ac -> osmo-uecups_0.2.0.tar.xz/configure.ac
Changed
@@ -26,9 +26,9 @@ fi PKG_PROG_PKG_CONFIG(0.20) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.1.0) -PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.1.0) -PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.7.0) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.7.0) +PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.7.0) +PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.2.0) PKG_CHECK_MODULES(LIBJANSSON, jansson) PKG_CHECK_MODULES(LIBNLROUTE3, libnl-route-3.0)
View file
osmo-uecups_0.1.4.tar.xz/daemon/Makefile.am -> osmo-uecups_0.2.0.tar.xz/daemon/Makefile.am
Changed
@@ -36,10 +36,12 @@ $(NULL) osmo_uecups_daemon_SOURCES = \ + cups_client.c \ utility.c \ netdev.c \ netns.c \ tun_device.c \ + gtp_daemon.c \ gtp_endpoint.c \ gtp_tunnel.c \ daemon_vty.c \
View file
osmo-uecups_0.2.0.tar.xz/daemon/cups_client.c
Added
@@ -0,0 +1,612 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <errno.h> +#include <pthread.h> + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/exec.h> + +#include "internal.h" + +#include <netinet/sctp.h> + +/*********************************************************************** + * Client (Control/User Plane Separation) Socket + ***********************************************************************/ + +#define CUPS_MSGB_SIZE 1024 + +#define LOGCC(cc, lvl, fmt, args ...) \ + LOGP(DUECUPS, lvl, "%s: " fmt, (cc)->sockname, ## args) + +struct subprocess { + /* member in daemon->cups_clients */ + struct llist_head list; + /* pointer to the client that started us */ + struct cups_client *cups_client; + /* PID of the process */ + pid_t pid; +}; + +static json_t *gen_uecups_term_ind(pid_t pid, int status); + +/* kill the specified subprocess and forget about it */ +static void subprocess_destroy(struct subprocess *p, int signal) +{ + LOGCC(p->cups_client, LOGL_DEBUG, "Kill subprocess pid %llu with signal %u\n", + (unsigned long long)p->pid, signal); + kill(p->pid, signal); + llist_del(&p->list); + talloc_free(p); +} + +static struct subprocess *subprocess_by_pid(struct gtp_daemon *d, pid_t pid) +{ + struct subprocess *sproc; + llist_for_each_entry(sproc, &d->subprocesses, list) { + if (sproc->pid == pid) + return sproc; + } + return NULL; +} + +void child_terminated(struct gtp_daemon *d, int pid, int status) +{ + struct subprocess *sproc; + json_t *jterm_ind; + + LOGP(DUECUPS, LOGL_DEBUG, "SIGCHLD receive from pid %u; status=%d\n", pid, status); + + sproc = subprocess_by_pid(d, pid); + if (!sproc) { + LOGP(DUECUPS, LOGL_NOTICE, "subprocess %u terminated (status=%d) but we don't know it?\n", + pid, status); + return; + } + + /* generate prog_term_ind towards control plane */ + jterm_ind = gen_uecups_term_ind(pid, status); + if (!jterm_ind) + return; + + cups_client_tx_json(sproc->cups_client, jterm_ind); + + llist_del(&sproc->list); + talloc_free(sproc); +} + +/* Send JSON to a given client/connection */ +int cups_client_tx_json(struct cups_client *cc, json_t *jtx) +{ + struct msgb *msg = msgb_alloc(CUPS_MSGB_SIZE, "Tx JSON"); + char *json_str = json_dumps(jtx, JSON_SORT_KEYS); + char *out; + int json_strlen; + + json_decref(jtx); + if (!json_str) { + LOGCC(cc, LOGL_ERROR, "Error encoding JSON\n"); + return 0; + } + json_strlen = strlen(json_str); + + LOGCC(cc, LOGL_DEBUG, "JSON Tx '%s'\n", json_str); + + if (json_strlen > msgb_tailroom(msg)) { + LOGCC(cc, LOGL_ERROR, "Not enough room for JSON in msgb\n"); + free(json_str); + return 0; + } + + out = (char *)msgb_put(msg, json_strlen); + memcpy(out, json_str, json_strlen); + free(json_str); + osmo_stream_srv_send(cc->srv, msg); + + return 0; +} + +json_t *gen_uecups_result(const char *name, const char *res) +{ + json_t *jres = json_object(); + json_t *jret = json_object(); + + json_object_set_new(jres, "result", json_string(res)); + json_object_set_new(jret, name, jres); + + return jret; +} + +static int parse_ep(struct sockaddr_storage *out, json_t *in) +{ + json_t *jaddr_type, *jport, *jip; + const char *addr_type, *ip; + uint8_t buf16; + + /* {"addr_type":"IPV4","ip":"31323334","Port":2152} */ + + if (!json_is_object(in)) + return -EINVAL; + + jaddr_type = json_object_get(in, "addr_type"); + jport = json_object_get(in, "Port"); + jip = json_object_get(in, "ip"); + + if (!jaddr_type || !jport || !jip) + return -EINVAL; + + if (!json_is_string(jaddr_type) || !json_is_integer(jport) || !json_is_string(jip)) + return -EINVAL; + + addr_type = json_string_value(jaddr_type); + ip = json_string_value(jip); + + memset(out, 0, sizeof(*out)); + + if (!strcmp(addr_type, "IPV4")) { + struct sockaddr_in *sin = (struct sockaddr_in *) out; + if (osmo_hexparse(ip, buf, sizeof(buf)) != 4) + return -EINVAL; + memcpy(&sin->sin_addr, buf, 4); + sin->sin_family = AF_INET; + sin->sin_port = htons(json_integer_value(jport)); + } else if (!strcmp(addr_type, "IPV6")) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) out; + if (osmo_hexparse(ip, buf, sizeof(buf)) != 16) + return -EINVAL; + memcpy(&sin6->sin6_addr, buf, 16); + sin6->sin6_family = AF_INET6; + sin6->sin6_port = htons(json_integer_value(jport)); + } else + return -EINVAL; + + return 0; +} + +static int parse_eua(struct sockaddr_storage *out, json_t *jip, json_t *jaddr_type) +{ + const char *addr_type, *ip; + uint8_t buf16; + + if (!json_is_string(jip) || !json_is_string(jaddr_type)) + return -EINVAL; + + addr_type = json_string_value(jaddr_type); + ip = json_string_value(jip); + + memset(out, 0, sizeof(*out)); + + if (!strcmp(addr_type, "IPV4")) { + struct sockaddr_in *sin = (struct sockaddr_in *) out; + if (osmo_hexparse(ip, buf, sizeof(buf)) != 4) + return -EINVAL; + memcpy(&sin->sin_addr, buf, 4); + sin->sin_family = AF_INET; + } else if (!strcmp(addr_type, "IPV6")) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) out; + if (osmo_hexparse(ip, buf, sizeof(buf)) != 16) + return -EINVAL; + memcpy(&sin6->sin6_addr, buf, 16); + sin6->sin6_family = AF_INET6; + } else
View file
osmo-uecups_0.1.4.tar.xz/daemon/daemon_vty.c -> osmo-uecups_0.2.0.tar.xz/daemon/daemon_vty.c
Changed
@@ -99,7 +99,7 @@ vty_out(vty, "Cannot destrory non-existant TUN%s", VTY_NEWLINE); return CMD_WARNING; } - _tun_device_deref_destroy(tun); + _tun_device_deref_release(tun); pthread_rwlock_unlock(&g_daemon->rwlock); return CMD_SUCCESS;
View file
osmo-uecups_0.2.0.tar.xz/daemon/gtp_daemon.c
Added
@@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +#include <pthread.h> + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/logging.h> + +#include "internal.h" + + +/*********************************************************************** + * GTP Daemon + ***********************************************************************/ + +#ifndef OSMO_VTY_PORT_UECUPS +#define OSMO_VTY_PORT_UECUPS 4268 +#endif + +struct gtp_daemon *g_daemon; + +static void gtp_daemon_itq_read_cb(struct osmo_it_q *q, struct llist_head *item) +{ + struct gtp_daemon *d = (struct gtp_daemon *)q->data; + struct gtp_daemon_itq_msg *itq_msg = container_of(item, struct gtp_daemon_itq_msg, list); + + LOGP(DTUN, LOGL_DEBUG, "Rx new itq message from %s\n", + itq_msg->tun_released.tun->devname); + + _tun_device_destroy(itq_msg->tun_released.tun); + if (d->reset_all_state_tun_remaining > 0) { + d->reset_all_state_tun_remaining--; + if (d->reset_all_state_tun_remaining == 0) { + struct cups_client *cc; + llist_for_each_entry(cc, &d->cups_clients, list) { + json_t *jres; + if (!cc->reset_all_state_res_pending) + continue; + cc->reset_all_state_res_pending = false; + jres = gen_uecups_result("reset_all_state_res", "OK"); + cups_client_tx_json(cc, jres); + } + } + } +} + +struct gtp_daemon *gtp_daemon_alloc(void *ctx) +{ + struct gtp_daemon *d = talloc_zero(ctx, struct gtp_daemon); + if (!d) + return NULL; + + INIT_LLIST_HEAD(&d->gtp_endpoints); + INIT_LLIST_HEAD(&d->tun_devices); + INIT_LLIST_HEAD(&d->gtp_tunnels); + INIT_LLIST_HEAD(&d->subprocesses); + pthread_rwlock_init(&d->rwlock, NULL); + d->main_thread = pthread_self(); + + d->itq = osmo_it_q_alloc(d, "itq", 4096, gtp_daemon_itq_read_cb, d); + osmo_fd_register(&d->itq->event_ofd); + + INIT_LLIST_HEAD(&d->cups_clients); + + d->cfg.cups_local_ip = talloc_strdup(d, "localhost"); + d->cfg.cups_local_port = UECUPS_SCTP_PORT; + + return d; +}
View file
osmo-uecups_0.1.4.tar.xz/daemon/internal.h -> osmo-uecups_0.2.0.tar.xz/daemon/internal.h
Changed
@@ -1,13 +1,22 @@ /* SPDX-License-Identifier: GPL-2.0 */ #pragma once +#include "netns.h" + #include <stdint.h> #include <stdbool.h> #include <pthread.h> #include <sys/socket.h> + +#include <jansson.h> + #include <osmocom/core/linuxlist.h> #include <osmocom/core/write_queue.h> +#include <osmocom/core/it_q.h> #include <osmocom/core/utils.h> +#include <osmocom/core/socket.h> + +#include <osmocom/netif/stream.h> struct nl_sock; struct osmo_stream_srv_link; @@ -84,6 +93,13 @@ /*********************************************************************** * TUN Device ***********************************************************************/ +/* Message sent tun thread -> main thread through osmo_itq */ +struct gtp_daemon_itq_msg { + struct llist_head list; + struct { + struct tun_device *tun; + } tun_released; /* tun became stopped and can be freed */ +}; struct tun_device { /* entry in global list */ @@ -110,6 +126,9 @@ /* the thread handling Rx from the tun fd */ pthread_t thread; + + /* Used to store messages to be sent to main thread, since tun thread doesn't allocate through talloc */ + struct gtp_daemon_itq_msg itq_msg; }; struct tun_device * @@ -121,13 +140,33 @@ struct tun_device * _tun_device_find(struct gtp_daemon *d, const char *devname); -void _tun_device_deref_destroy(struct tun_device *tun); +void _tun_device_destroy(struct tun_device *tun); bool _tun_device_release(struct tun_device *tun); +void _tun_device_deref_release(struct tun_device *tun); bool tun_device_release(struct tun_device *tun); +/*********************************************************************** + * Client (Control/User Plane Separation) Socket + ***********************************************************************/ + +struct cups_client { + /* member in daemon->cups_clients */ + struct llist_head list; + /* back-pointer to daemon */ + struct gtp_daemon *d; + /* client socket */ + struct osmo_stream_srv *srv; + char socknameOSMO_SOCK_NAME_MAXLEN; + bool reset_all_state_res_pending; +}; + +struct osmo_stream_srv_link *cups_srv_link_create(struct gtp_daemon *d); +void child_terminated(struct gtp_daemon *d, int pid, int status); +json_t *gen_uecups_result(const char *name, const char *res); +int cups_client_tx_json(struct cups_client *cc, json_t *jtx); /*********************************************************************** * GTP Tunnel @@ -222,6 +261,12 @@ struct osmo_stream_srv_link *cups_link; struct osmo_signalfd *signalfd; + /* inter-thread queue between main thread and workers, pass struct gtp_daemon_itq_msg: */ + struct osmo_it_q *itq; + + /* Number of tunnels in progrress of being released: */ + unsigned int reset_all_state_tun_remaining; + struct { char *cups_local_ip; uint16_t cups_local_port; @@ -229,4 +274,6 @@ }; extern struct gtp_daemon *g_daemon; +struct gtp_daemon *gtp_daemon_alloc(void *ctx); + int gtpud_vty_init(void);
View file
osmo-uecups_0.1.4.tar.xz/daemon/main.c -> osmo-uecups_0.2.0.tar.xz/daemon/main.c
Changed
@@ -1,4 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#define _GNU_SOURCE +#include <getopt.h> #include <unistd.h> #include <stdint.h> #include <stdbool.h> @@ -22,7 +24,6 @@ #include <osmocom/core/stats.h> #include <osmocom/core/rate_ctr.h> #include <osmocom/core/socket.h> -#include <osmocom/core/exec.h> #include <osmocom/vty/telnet_interface.h> #include <osmocom/vty/logging.h> #include <osmocom/vty/stats.h> @@ -31,7 +32,6 @@ #include <osmocom/vty/misc.h> #include <osmocom/netif/stream.h> -#include <netinet/sctp.h> #include <jansson.h> @@ -39,327 +39,13 @@ #include "netns.h" #include "gtp.h" -/*********************************************************************** - * Client (Contol/User Plane Separation) Socket - ***********************************************************************/ +static void *g_tall_ctx; +static char *g_config_file = "osmo-uecups-daemon.cfg"; +static int g_daemonize; +extern struct vty_app_info g_vty_info; #include <pwd.h> -#define CUPS_MSGB_SIZE 1024 - -#define LOGCC(cc, lvl, fmt, args ...) \ - LOGP(DUECUPS, lvl, "%s: " fmt, (cc)->sockname, ## args) - -struct cups_client { - /* member in daemon->cups_clients */ - struct llist_head list; - /* back-pointer to daemon */ - struct gtp_daemon *d; - /* client socket */ - struct osmo_stream_srv *srv; - char socknameOSMO_SOCK_NAME_MAXLEN; -}; - -struct subprocess { - /* member in daemon->cups_clients */ - struct llist_head list; - /* pointer to the client that started us */ - struct cups_client *cups_client; - /* PID of the process */ - pid_t pid; -}; - -/* kill the specified subprocess and forget about it */ -static void subprocess_destroy(struct subprocess *p, int signal) -{ - kill(p->pid, signal); - llist_del(&p->list); - talloc_free(p); -} - -/* Send JSON to a given client/connection */ -static int cups_client_tx_json(struct cups_client *cc, json_t *jtx) -{ - struct msgb *msg = msgb_alloc(CUPS_MSGB_SIZE, "Tx JSON"); - char *json_str = json_dumps(jtx, JSON_SORT_KEYS); - char *out; - int json_strlen; - - json_decref(jtx); - if (!json_str) { - LOGCC(cc, LOGL_ERROR, "Error encoding JSON\n"); - return 0; - } - json_strlen = strlen(json_str); - - LOGCC(cc, LOGL_DEBUG, "JSON Tx '%s'\n", json_str); - - if (json_strlen > msgb_tailroom(msg)) { - LOGCC(cc, LOGL_ERROR, "Not enough room for JSON in msgb\n"); - free(json_str); - return 0; - } - - out = (char *)msgb_put(msg, json_strlen); - memcpy(out, json_str, json_strlen); - free(json_str); - osmo_stream_srv_send(cc->srv, msg); - - return 0; -} - -static json_t *gen_uecups_result(const char *name, const char *res) -{ - json_t *jres = json_object(); - json_t *jret = json_object(); - - json_object_set_new(jres, "result", json_string(res)); - json_object_set_new(jret, name, jres); - - return jret; -} - -static int parse_ep(struct sockaddr_storage *out, json_t *in) -{ - json_t *jaddr_type, *jport, *jip; - const char *addr_type, *ip; - uint8_t buf16; - - /* {"addr_type":"IPV4","ip":"31323334","Port":2152} */ - - if (!json_is_object(in)) - return -EINVAL; - - jaddr_type = json_object_get(in, "addr_type"); - jport = json_object_get(in, "Port"); - jip = json_object_get(in, "ip"); - - if (!jaddr_type || !jport || !jip) - return -EINVAL; - - if (!json_is_string(jaddr_type) || !json_is_integer(jport) || !json_is_string(jip)) - return -EINVAL; - - addr_type = json_string_value(jaddr_type); - ip = json_string_value(jip); - - memset(out, 0, sizeof(*out)); - - if (!strcmp(addr_type, "IPV4")) { - struct sockaddr_in *sin = (struct sockaddr_in *) out; - if (osmo_hexparse(ip, buf, sizeof(buf)) != 4) - return -EINVAL; - memcpy(&sin->sin_addr, buf, 4); - sin->sin_family = AF_INET; - sin->sin_port = htons(json_integer_value(jport)); - } else if (!strcmp(addr_type, "IPV6")) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) out; - if (osmo_hexparse(ip, buf, sizeof(buf)) != 16) - return -EINVAL; - memcpy(&sin6->sin6_addr, buf, 16); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(json_integer_value(jport)); - } else - return -EINVAL; - - return 0; -} - -static int parse_eua(struct sockaddr_storage *out, json_t *jip, json_t *jaddr_type) -{ - const char *addr_type, *ip; - uint8_t buf16; - - if (!json_is_string(jip) || !json_is_string(jaddr_type)) - return -EINVAL; - - addr_type = json_string_value(jaddr_type); - ip = json_string_value(jip); - - memset(out, 0, sizeof(*out)); - - if (!strcmp(addr_type, "IPV4")) { - struct sockaddr_in *sin = (struct sockaddr_in *) out; - if (osmo_hexparse(ip, buf, sizeof(buf)) != 4) - return -EINVAL; - memcpy(&sin->sin_addr, buf, 4); - sin->sin_family = AF_INET; - } else if (!strcmp(addr_type, "IPV6")) { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) out; - if (osmo_hexparse(ip, buf, sizeof(buf)) != 16) - return -EINVAL; - memcpy(&sin6->sin6_addr, buf, 16); - sin6->sin6_family = AF_INET6; - } else - return -EINVAL; - - return 0; -} - - -static int parse_create_tun(struct gtp_tunnel_params *out, json_t *ctun) -{ - json_t *jlocal_gtp_ep, *jremote_gtp_ep; - json_t *jrx_teid, *jtx_teid; - json_t *jtun_dev_name, *jtun_netns_name; - json_t *juser_addr, *juser_addr_type; - int rc; - - /* '{"create_tun":{"tx_teid":1234,"rx_teid":5678,"user_addr_type":"IPV4","user_addr":"21222324","local_gtp_ep":{"addr_type":"IPV4","ip":"31323334","Port":2152},"remote_gtp_ep":{"addr_type":"IPV4","ip":"41424344","Port":2152},"tun_dev_name":"tun23","tun_netns_name":"foo"}}' */ - - if (!json_is_object(ctun))
View file
osmo-uecups_0.1.4.tar.xz/daemon/tun_device.c -> osmo-uecups_0.2.0.tar.xz/daemon/tun_device.c
Changed
@@ -120,6 +120,14 @@ return 0; } +static void tun_device_pthread_cleanup_routine(void *data) +{ + struct tun_device *tun = data; + LOGTUN(tun, LOGL_DEBUG, "pthread_cleanup\n"); + int rc = osmo_it_q_enqueue(tun->d->itq, &tun->itq_msg, list); + OSMO_ASSERT(rc == 0); +} + /* one thread for reading from each TUN device (TUN -> GTP encapsulation) */ static void *tun_device_thread(void *arg) { @@ -131,11 +139,18 @@ uint8_t *buffer = base_buffer + sizeof(struct gtp1_header); struct sockaddr_storage daddr; + int old_cancelst_unused; /* initialize the fixed part of the GTP header */ gtph->flags = 0x30; gtph->type = GTP_TPDU; + pthread_cleanup_push(tun_device_pthread_cleanup_routine, tun); + /* IMPORTANT!: All logging functions in this function block must be called with + * PTHREAD_CANCEL_DISABLE set, otherwise the thread could be cancelled while + * holding the logging mutex, hence causing deadlock with main (or other) + * thread. */ + while (1) { struct gtp_tunnel *t; struct pkt_info pinfo; @@ -144,6 +159,7 @@ /* 1) read from tun */ rc = read(tun->fd, buffer, MAX_UDP_PACKET); if (rc < 0) { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelst_unused); LOGTUN(tun, LOGL_FATAL, "Error readingfrom tun device: %s\n", strerror(errno)); exit(1); } @@ -152,8 +168,10 @@ rc = parse_pkt(&pinfo, buffer, nread); if (rc < 0) { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelst_unused); LOGTUN(tun, LOGL_NOTICE, "Error parsing IP packet: %s\n", osmo_hexdump(buffer, nread)); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelst_unused); continue; } @@ -171,7 +189,9 @@ getnameinfo((const struct sockaddr *)&pinfo.saddr, sizeof(pinfo.saddr), host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelst_unused); LOGTUN(tun, LOGL_NOTICE, "No tunnel found for source address %s:%s\n", host, port); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelst_unused); continue; } outfd = t->gtp_ep->fd; @@ -183,10 +203,12 @@ rc = sendto(outfd, base_buffer, nread+sizeof(*gtph), 0, (struct sockaddr *)&daddr, sizeof(daddr)); if (rc < 0) { + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelst_unused); LOGTUN(tun, LOGL_FATAL, "Error Writing to UDP socket: %s\n", strerror(errno)); exit(1); } } + pthread_cleanup_pop(1); } static int tun_open(int flags, const char *name) @@ -290,13 +312,15 @@ if (tun->netns_name) { rc = netdev_add_defaultroute(tun->nl, tun->ifindex, AF_INET); if (rc < 0) - LOGTUN(tun, LOGL_ERROR, "Cannot add IPv4 default route\n"); + LOGTUN(tun, LOGL_ERROR, "Cannot add IPv4 default route " + "(rc=%d): %s\n", rc, nl_geterror(rc)); else LOGTUN(tun, LOGL_INFO, "Added IPv4 default route\n"); rc = netdev_add_defaultroute(tun->nl, tun->ifindex, AF_INET6); if (rc < 0) - LOGTUN(tun, LOGL_ERROR, "Cannot add IPv6 default route\n"); + LOGTUN(tun, LOGL_ERROR, "Cannot add IPv6 default route " + "(rc=%d): %s\n", rc, nl_geterror(rc)); else LOGTUN(tun, LOGL_INFO, "Added IPv6 default route\n"); } @@ -374,24 +398,24 @@ return tun; } -/* UNLOCKED hard/forced destroy; caller must make sure references are cleaned up */ -static void _tun_device_destroy(struct tun_device *tun) +/* UNLOCKED hard/forced destroy; caller must make sure references are cleaned + * up, and tun thread is stopped beforehand by calling + * _tun_device_{deref_}release */ +void _tun_device_destroy(struct tun_device *tun) { /* talloc is not thread safe, all alloc/free must come from main thread */ ASSERT_MAIN_THREAD(tun->d); + LOGTUN(tun, LOGL_INFO, "Destroying\n"); - pthread_cancel(tun->thread); - llist_del(&tun->list); if (tun->netns_name) close(tun->netns_fd); close(tun->fd); nl_socket_free(tun->nl); - LOGTUN(tun, LOGL_INFO, "Destroying\n"); talloc_free(tun); } -/* UNLOCKED remove all objects referencing this tun and then destroy */ -void _tun_device_deref_destroy(struct tun_device *tun) +/* UNLOCKED remove all objects referencing this tun and then start async tun release procedure */ +void _tun_device_deref_release(struct tun_device *tun) { struct gtp_daemon *d = tun->d; char *devname = talloc_strdup(d, tun->devname); @@ -410,12 +434,12 @@ * check if the tun can still be found in the list */ tun2 = _tun_device_find(d, devname); if (tun2 && tun2 == tun) - _tun_device_destroy(tun2); + _tun_device_release(tun2); talloc_free(devname); } -/* UNLOCKED release a reference; destroy if refcount drops to 0 */ +/* UNLOCKED release a reference; start async tun release procedure if refcount drops to 0 */ bool _tun_device_release(struct tun_device *tun) { bool released = false; @@ -425,10 +449,17 @@ tun->use_count--; if (tun->use_count == 0) { - _tun_device_destroy(tun); + LOGTUN(tun, LOGL_INFO, "Releasing\n"); + llist_del(&tun->list); + tun->itq_msg.tun_released.tun = tun; + tun->d->reset_all_state_tun_remaining++; + /* We cancel the thread: the pthread_cleanup routing will send a message + * back to us (main thread) when finally cancelled. */ + pthread_cancel(tun->thread); released = true; - } else + } else { LOGTUN(tun, LOGL_DEBUG, "Release; new use_count=%lu\n", tun->use_count); + } return released; }
View file
osmo-uecups_0.1.4.tar.xz/debian/changelog -> osmo-uecups_0.2.0.tar.xz/debian/changelog
Changed
@@ -1,3 +1,26 @@ +osmo-uecups (0.2.0) unstable; urgency=medium + + Pau Espin Pedrol + * debian/control: Drop dependency on autoconf-archive + * main.c: Fix typo in comment + * main: Remove duplicate call to child_terminated() + * main.c: Improve logging + * Fix use-after-free by tun thread after tun obj destroyed + * Add optarg support + * Move several objects outside of main.c + * tun_device: Avoid deadlocks logging while thread is cancelled + * .gitignore: Add configure~ + + Vadim Yanitskiy + * daemon: enable multithread logging in main() + * daemon: log more details when netdev_add_defaultroute() fails + + Harald Welte + * update git URLs (git -> https; gitea) + * README.md: Fix copy+paste mistke + + -- Pau Espin Pedrol <pespin@sysmocom.de> Wed, 29 Jun 2022 12:24:31 +0200 + osmo-uecups (0.1.4) unstable; urgency=medium Harald Welte
View file
osmo-uecups_0.1.4.tar.xz/debian/control -> osmo-uecups_0.2.0.tar.xz/debian/control
Changed
@@ -6,19 +6,18 @@ dh-autoreconf, autotools-dev, autoconf, - autoconf-archive, automake, libtool, pkg-config, libjansson-dev, libnl-route-3-dev, - libosmocore-dev (>= 1.1.0), - libosmo-netif-dev, + libosmocore-dev (>= 1.7.0), + libosmo-netif-dev (>= 1.2.0), libsctp-dev, - osmo-gsm-manuals-dev + osmo-gsm-manuals-dev (>= 1.3.0) Standards-Version: 3.9.8 -Vcs-Git: git://git.osmocom.org/osmo-uecups.git -Vcs-Browser: https://git.osmocom.org/osmo-uecups +Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups +Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups Homepage: https://osmocom.org/projects/osmo-uecups Package: osmo-uecups
View file
osmo-uecups_0.1.4.tar.xz/debian/copyright -> osmo-uecups_0.2.0.tar.xz/debian/copyright
Changed
@@ -1,6 +1,6 @@ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: osmo-uecups -Source: git://git.osmocom.org/osmo-uecups +Source: https://gitea.osmocom.org/cellular-infrastructure/osmo-uecups Files: * Copyright: 2019-2020 Harald Welte <laforge@osmocom.org>
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.