aboutsummaryrefslogtreecommitdiffstats
path: root/daemon/internal.h
blob: cbccbfc6800877a90f18b7dd300401472f7f15b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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);