blob: f6553caa9d42fecaa4f0190f99852904b0ce88dd [file] [log] [blame]
Harald Weltef7365592020-04-15 21:48:45 +02001/* SPDX-License-Identifier: GPL-2.0 */
2#include <unistd.h>
3#include <stdint.h>
4#include <stdbool.h>
5#include <stdlib.h>
6#include <string.h>
7#include <stdio.h>
8#include <errno.h>
9#include <sys/types.h>
10#include <sys/socket.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <signal.h>
14#include <netdb.h>
15
16#include <netinet/ip.h>
17#include <netinet/ip6.h>
18
19#include <pthread.h>
20
21#include <linux/if.h>
22#include <linux/if_tun.h>
23#include <sys/ioctl.h>
24
25#include <netlink/socket.h>
26#include <netlink/route/link.h>
27
28#include <osmocom/core/linuxlist.h>
29#include <osmocom/core/talloc.h>
30#include <osmocom/core/logging.h>
31#include <osmocom/core/utils.h>
32
33#include "gtp.h"
34#include "internal.h"
35#include "netns.h"
36
37/***********************************************************************
38 * TUN Device
39 ***********************************************************************/
40
41#define LOGTUN(tun, lvl, fmt, args ...) \
42 LOGP(DTUN, lvl, "%s: " fmt, (tun)->devname, ## args)
43
44/* extracted information from a packet */
45struct pkt_info {
46 struct sockaddr_storage saddr;
47 struct sockaddr_storage daddr;
48 uint8_t proto;
49};
50
51static int parse_pkt(struct pkt_info *out, const uint8_t *in, unsigned int in_len)
52{
53 const struct iphdr *ip4 = (struct iphdr *) in;
54 const uint16_t *l4h = NULL;
55
56 memset(out, 0, sizeof(*out));
57
58 if (ip4->version == 4) {
59 struct sockaddr_in *saddr4 = (struct sockaddr_in *) &out->saddr;
60 struct sockaddr_in *daddr4 = (struct sockaddr_in *) &out->daddr;
61
62 if (in_len < sizeof(*ip4) || in_len < 4*ip4->ihl)
63 return -1;
64
65 saddr4->sin_family = AF_INET;
66 saddr4->sin_addr.s_addr = ip4->saddr;
67
68 daddr4->sin_family = AF_INET;
69 daddr4->sin_addr.s_addr = ip4->daddr;
70
71 out->proto = ip4->protocol;
72 l4h = (const uint16_t *) (in + sizeof(*ip4));
73
74 switch (out->proto) {
75 case IPPROTO_TCP:
76 case IPPROTO_UDP:
77 case IPPROTO_DCCP:
78 case IPPROTO_SCTP:
79 case IPPROTO_UDPLITE:
80 saddr4->sin_port = ntohs(l4h[0]);
81 daddr4->sin_port = ntohs(l4h[1]);
82 break;
83 default:
84 break;
85 }
86 } else if (ip4->version == 6) {
87 const struct ip6_hdr *ip6 = (struct ip6_hdr *) in;
88 struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) &out->saddr;
89 struct sockaddr_in6 *daddr6 = (struct sockaddr_in6 *) &out->daddr;
90
91 if (in_len < sizeof(*ip6))
92 return -1;
93
94 saddr6->sin6_family = AF_INET6;
95 saddr6->sin6_addr = ip6->ip6_src;
96
97 daddr6->sin6_family = AF_INET6;
98 daddr6->sin6_addr = ip6->ip6_dst;
99
100 /* FIXME: ext hdr */
101 out->proto = ip6->ip6_nxt;
102 l4h = (const uint16_t *) (in + sizeof(*ip6));
103
104 switch (out->proto) {
105 case IPPROTO_TCP:
106 case IPPROTO_UDP:
107 case IPPROTO_DCCP:
108 case IPPROTO_SCTP:
109 case IPPROTO_UDPLITE:
110 saddr6->sin6_port = ntohs(l4h[0]);
111 daddr6->sin6_port = ntohs(l4h[1]);
112 break;
113 default:
114 break;
115 }
116 } else
117 return -1;
118
119 return 0;
120}
121
122/* one thread for reading from each TUN device (TUN -> GTP encapsulation) */
123static void *tun_device_thread(void *arg)
124{
125 struct tun_device *tun = (struct tun_device *)arg;
126 struct gtp_daemon *d = tun->d;
127
128 uint8_t base_buffer[MAX_UDP_PACKET+sizeof(struct gtp1_header)];
129 struct gtp1_header *gtph = (struct gtp1_header *)base_buffer;
130 uint8_t *buffer = base_buffer + sizeof(struct gtp1_header);
131
132 struct sockaddr_storage daddr;
133
134 /* initialize the fixed part of the GTP header */
135 gtph->flags = 0x30;
136 gtph->type = GTP_TPDU;
137
138 while (1) {
139 struct gtp_tunnel *t;
140 struct pkt_info pinfo;
141 int rc, nread, outfd;
142
143 /* 1) read from tun */
144 rc = read(tun->fd, buffer, MAX_UDP_PACKET);
145 if (rc < 0) {
146 LOGTUN(tun, LOGL_FATAL, "Error readingfrom tun device: %s\n", strerror(errno));
147 exit(1);
148 }
149 nread = rc;
150 gtph->length = htons(nread);
151
152 rc = parse_pkt(&pinfo, buffer, nread);
153 if (rc < 0) {
154 LOGTUN(tun, LOGL_NOTICE, "Error parsing IP packet: %s\n",
155 osmo_hexdump(buffer, nread));
156 continue;
157 }
158
159 if (pinfo.saddr.ss_family == AF_INET6 && pinfo.proto == IPPROTO_ICMPV6) {
160 /* 2) TODO: magic voodoo for IPv6 neighbor discovery */
161 }
162
163 /* 3) look-up tunnel based on source IP address (+ filter) */
164 pthread_rwlock_rdlock(&d->rwlock);
165 t = _gtp_tunnel_find_eua(tun, (struct sockaddr *) &pinfo.saddr, pinfo.proto);
166 if (!t) {
167 char host[128];
168 char port[8];
169 pthread_rwlock_unlock(&d->rwlock);
170 getnameinfo((const struct sockaddr *)&pinfo.saddr,
171 sizeof(pinfo.saddr), host, sizeof(host), port, sizeof(port),
172 NI_NUMERICHOST | NI_NUMERICSERV);
173 LOGTUN(tun, LOGL_NOTICE, "No tunnel found for source address %s:%s\n", host, port);
174 continue;
175 }
176 outfd = t->gtp_ep->fd;
177 memcpy(&daddr, &t->remote_udp, sizeof(daddr));
178 gtph->tid = htonl(t->tx_teid);
179 pthread_rwlock_unlock(&d->rwlock);
180
181 /* 4) write to GTP/UDP socket */
182 rc = sendto(outfd, base_buffer, nread+sizeof(*gtph), 0,
183 (struct sockaddr *)&daddr, sizeof(daddr));
184 if (rc < 0) {
185 LOGTUN(tun, LOGL_FATAL, "Error Writing to UDP socket: %s\n", strerror(errno));
186 exit(1);
187 }
188 }
189}
190
191static int tun_open(int flags, const char *name)
192{
193 struct ifreq ifr;
194 int fd, rc;
195
196 fd = open("/dev/net/tun", O_RDWR);
197 if (fd < 0) {
198 LOGP(DTUN, LOGL_ERROR, "Cannot open /dev/net/tun: %s\n", strerror(errno));
199 return fd;
200 }
201
202 memset(&ifr, 0, sizeof(ifr));
203 ifr.ifr_flags = IFF_TUN | IFF_NO_PI | flags;
204 if (name) {
205 /* if a TUN interface name was specified, put it in the structure; otherwise,
206 the kernel will try to allocate the "next" device of the specified type */
207 strncpy(ifr.ifr_name, name, IFNAMSIZ);
208 }
209
210 /* try to create the device */
211 rc = ioctl(fd, TUNSETIFF, (void *) &ifr);
212 if (rc < 0) {
213 close(fd);
214 return rc;
215 }
216
217 /* FIXME: read name back from device? */
218 /* FIXME: SIOCSIFTXQLEN / SIOCSIFFLAGS */
219
220 return fd;
221}
222
223static struct tun_device *
224_tun_device_create(struct gtp_daemon *d, const char *devname, const char *netns_name)
225{
226 struct rtnl_link *link;
227 struct tun_device *tun;
228 sigset_t oldmask;
229 int rc;
230
231 tun = talloc_zero(d, struct tun_device);
232 if (!tun)
233 return NULL;
234
235 tun->d = d;
236 tun->use_count = 1;
237 tun->devname = talloc_strdup(tun, devname);
238
239 if (netns_name) {
240 tun->netns_name = talloc_strdup(tun, netns_name);
241 tun->netns_fd = get_nsfd(tun->netns_name);
242 if (tun->netns_fd < 0) {
243 LOGTUN(tun, LOGL_ERROR, "Cannot obtain netns file descriptor: %s\n",
244 strerror(errno));
245 goto err_free;
246 }
247 }
248
249 /* temporarily switch to specified namespace to create tun device */
250 if (tun->netns_name) {
251 rc = switch_ns(tun->netns_fd, &oldmask);
252 if (rc < 0) {
253 LOGTUN(tun, LOGL_ERROR, "Cannot switch to netns '%s': %s\n",
254 tun->netns_name, strerror(errno));
255 goto err_close_ns;
256 }
257 }
258
259 tun->fd = tun_open(0, tun->devname);
260 if (tun->fd < 0) {
261 LOGTUN(tun, LOGL_ERROR, "Cannot open TUN device: %s\n", strerror(errno));
262 goto err_restore_ns;
263 }
264
265 tun->nl = nl_socket_alloc();
266 if (!tun->nl || nl_connect(tun->nl, NETLINK_ROUTE) < 0) {
267 LOGTUN(tun, LOGL_ERROR, "Cannot create netlink socket in namespace '%s'\n",
268 tun->netns_name);
269 goto err_close;
270 }
271
272 rc = rtnl_link_get_kernel(tun->nl, 0, tun->devname, &link);
273 if (rc < 0) {
274 LOGTUN(tun, LOGL_ERROR, "Cannot get ifindex for netif after create?!?\n");
275 goto err_free_nl;
276 }
277 tun->ifindex = rtnl_link_get_ifindex(link);
278 rtnl_link_put(link);
279
280 /* switch back to default namespace before creating new thread */
281 if (tun->netns_name)
282 OSMO_ASSERT(restore_ns(&oldmask) == 0);
283
284 /* bring the network device up */
285 rc = netdev_set_link(tun->nl, tun->ifindex, true);
286 if (rc < 0)
287 LOGTUN(tun, LOGL_ERROR, "Cannot set interface to 'up'\n");
288
289 if (tun->netns_name) {
290 rc = netdev_add_defaultroute(tun->nl, tun->ifindex, AF_INET);
291 if (rc < 0)
292 LOGTUN(tun, LOGL_ERROR, "Cannot add IPv4 default route\n");
293 else
294 LOGTUN(tun, LOGL_INFO, "Added IPv4 default route\n");
295
296 rc = netdev_add_defaultroute(tun->nl, tun->ifindex, AF_INET6);
297 if (rc < 0)
298 LOGTUN(tun, LOGL_ERROR, "Cannot add IPv6 default route\n");
299 else
300 LOGTUN(tun, LOGL_INFO, "Added IPv6 default route\n");
301 }
302
303 if (pthread_create(&tun->thread, NULL, tun_device_thread, tun)) {
304 LOGTUN(tun, LOGL_ERROR, "Cannot create TUN thread: %s\n", strerror(errno));
305 goto err_free_nl;
306 }
307
308 LOGTUN(tun, LOGL_INFO, "Created (in netns '%s')\n", tun->netns_name);
309 llist_add_tail(&tun->list, &d->tun_devices);
310
311 return tun;
312
313err_free_nl:
314 nl_socket_free(tun->nl);
315err_close:
316 close(tun->fd);
317err_restore_ns:
318 if (tun->netns_name)
319 OSMO_ASSERT(restore_ns(&oldmask) == 0);
320err_close_ns:
321 if (tun->netns_name)
322 close(tun->netns_fd);
323err_free:
324 talloc_free(tun);
325 return NULL;
326}
327
328struct tun_device *
329_tun_device_find(struct gtp_daemon *d, const char *devname)
330{
331 struct tun_device *tun;
332
333 llist_for_each_entry(tun, &d->tun_devices, list) {
334 if (!strcmp(tun->devname, devname))
335 return tun;
336 }
337 return NULL;
338}
339
340struct tun_device *
341tun_device_find_or_create(struct gtp_daemon *d, const char *devname, const char *netns_name)
342{
343 struct tun_device *tun;
344
345 /* talloc is not thread safe, all alloc/free must come from main thread */
346 ASSERT_MAIN_THREAD(d);
347
348 pthread_rwlock_wrlock(&d->rwlock);
349 tun = _tun_device_find(d, devname);
350 if (tun)
351 tun->use_count++;
352 else
353 tun = _tun_device_create(d, devname, netns_name);
354 pthread_rwlock_unlock(&d->rwlock);
355
356 return tun;
357}
358
359/* UNLOCKED hard/forced destroy; caller must make sure references are cleaned up */
360static void _tun_device_destroy(struct tun_device *tun)
361{
362 /* talloc is not thread safe, all alloc/free must come from main thread */
363 ASSERT_MAIN_THREAD(tun->d);
364
365 pthread_cancel(tun->thread);
366 llist_del(&tun->list);
367 if (tun->netns_name)
368 close(tun->netns_fd);
369 close(tun->fd);
370 nl_socket_free(tun->nl);
371 LOGTUN(tun, LOGL_INFO, "Destroying\n");
372 talloc_free(tun);
373}
374
375/* UNLOCKED remove all objects referencing this tun and then destroy */
376void _tun_device_deref_destroy(struct tun_device *tun)
377{
378 struct gtp_daemon *d = tun->d;
379 char *devname = talloc_strdup(d, tun->devname);
380 struct gtp_tunnel *t, *t2;
381 struct tun_device *tun2;
382
383 /* talloc is not thread safe, all alloc/free must come from main thread */
384 ASSERT_MAIN_THREAD(tun->d);
385
386 llist_for_each_entry_safe(t, t2, &g_daemon->gtp_tunnels, list) {
387 if (t->tun_dev == tun)
388 _gtp_tunnel_destroy(t);
389 }
390 /* _tun_device_destroy may already have been called via
391 * _gtp_tunnel_destroy -> _tun_device_release, so we have to
392 * check if the tun can still be found in the list */
393 tun2 = _tun_device_find(d, devname);
394 if (tun2 && tun2 == tun)
395 _tun_device_destroy(tun2);
396
397 talloc_free(devname);
398}
399
400/* UNLOCKED release a reference; destroy if refcount drops to 0 */
401bool _tun_device_release(struct tun_device *tun)
402{
403 bool released = false;
404
405 /* talloc is not thread safe, all alloc/free must come from main thread */
406 ASSERT_MAIN_THREAD(tun->d);
407
408 tun->use_count--;
409 if (tun->use_count == 0) {
410 _tun_device_destroy(tun);
411 released = true;
412 } else
413 LOGTUN(tun, LOGL_DEBUG, "Release; new use_count=%lu\n", tun->use_count);
414
415 return released;
416}
417
418/* release a reference; destroy if refcount drops to 0 */
419bool tun_device_release(struct tun_device *tun)
420{
421 struct gtp_daemon *d = tun->d;
422 bool released;
423
424 /* talloc is not thread safe, all alloc/free must come from main thread */
425 ASSERT_MAIN_THREAD(tun->d);
426
427 pthread_rwlock_wrlock(&d->rwlock);
428 released = _tun_device_release(tun);
429 pthread_rwlock_unlock(&d->rwlock);
430
431 return released;
432}