blob: 9cb7605f85f2880960eb2f1b08996f04830328a9 [file] [log] [blame]
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +02001/* GTP Hub Implementation */
2
3/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Neels Hofmeyr
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
24#include <stdint.h>
25#include <sys/socket.h>
26
27#include <osmocom/core/select.h>
28#include <osmocom/core/timer.h>
Neels Hofmeyr1ba50c62015-11-20 01:28:40 +010029#include <osmocom/core/rate_ctr.h>
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020030
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +010031#include <openbsc/gprs_sgsn.h>
32
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020033
34/* support */
35
36/* TODO move to osmocom/core/socket.c ? */
37#include <netdb.h> /* for IPPROTO_* etc */
38struct osmo_sockaddr {
39 struct sockaddr_storage a;
40 socklen_t l;
41};
42
43/* TODO move to osmocom/core/socket.c ? */
44/*! \brief Initialize a sockaddr
45 * \param[out] addr Valid osmo_sockaddr pointer to write result to
46 * \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
47 * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
48 * \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
49 * \param[in] host Remote host name or IP address in string form
50 * \param[in] port Remote port number in host byte order
51 * \returns 0 on success, otherwise an error code (from getaddrinfo()).
52 *
53 * Copy the first result from a getaddrinfo() call with the given parameters to
54 * *addr and *addr_len. On error, do not change *addr and return nonzero.
55 */
56int osmo_sockaddr_init(struct osmo_sockaddr *addr,
57 uint16_t family, uint16_t type, uint8_t proto,
58 const char *host, uint16_t port);
59
60/* Conveniently pass AF_UNSPEC, SOCK_DGRAM and IPPROTO_UDP to
61 * osmo_sockaddr_init(). */
62static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
63 const char *host, uint16_t port)
64{
Neels Hofmeyr9cfe0372015-11-16 14:52:05 +010065 return osmo_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
66 host, port);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020067}
68
69/*! \brief convert sockaddr to human readable string.
70 * \param[out] addr_str Valid pointer to a buffer of length addr_str_len.
71 * \param[in] addr_str_len Size of buffer addr_str points at.
72 * \param[out] port_str Valid pointer to a buffer of length port_str_len.
73 * \param[in] port_str_len Size of buffer port_str points at.
74 * \param[in] addr Binary representation as returned by osmo_sockaddr_init().
75 * \param[in] flags flags as passed to getnameinfo().
76 * \returns 0 on success, an error code on error.
77 *
78 * Return the IPv4 or IPv6 address string and the port (a.k.a. service) string
79 * representations of the given struct osmo_sockaddr in two caller provided
80 * char buffers. Flags of (NI_NUMERICHOST | NI_NUMERICSERV) return numeric
81 * address and port. Either one of addr_str or port_str may be NULL, in which
82 * case nothing is returned there.
83 *
84 * See also osmo_sockaddr_to_str() (less flexible, but much more convenient). */
85int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
86 char *port_str, size_t port_str_len,
87 const struct osmo_sockaddr *addr,
88 int flags);
89
90
Neels Hofmeyr9cfe0372015-11-16 14:52:05 +010091/*! \brief concatenate the parts returned by osmo_sockaddr_to_strs().
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020092 * \param[in] addr Binary representation as returned by osmo_sockaddr_init().
93 * \param[in] buf A buffer to use for string operations.
94 * \param[in] buf_len Length of the buffer.
95 * \returns Address string (in buffer).
96 *
97 * Compose a string of the numeric IP-address and port represented by *addr of
98 * the form "<ip-addr> port <port>". The returned string is valid until the
99 * next invocation of this function.
100 */
101const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
102 char *buf, size_t buf_len);
103
104/*! \brief conveniently return osmo_sockaddr_to_strb() in a static buffer.
105 * \param[in] addr Binary representation as returned by osmo_sockaddr_init().
106 * \returns Address string in static buffer.
107 *
108 * See osmo_sockaddr_to_strb().
109 *
110 * Note: only one osmo_sockaddr_to_str() call will work per print/log
111 * statement. For two or more, use osmo_sockaddr_to_strb() with a separate
112 * buffer each.
113 */
114const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr);
115
116/*! \brief compare two osmo_sockaddr.
117 * \param[in] a The first address to compare.
118 * \param[in] b The other address to compare.
119 * \returns 0 if equal, otherwise -1 or 1.
120 */
Neels Hofmeyr9cfe0372015-11-16 14:52:05 +0100121int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
122 const struct osmo_sockaddr *b);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200123
124/*! \brief Overwrite *dst with *src.
125 * Like memcpy(), but copy only the valid bytes. */
Neels Hofmeyr9cfe0372015-11-16 14:52:05 +0100126void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
127 const struct osmo_sockaddr *src);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200128
129
130/* general */
131
132enum gtphub_plane_idx {
133 GTPH_PLANE_CTRL = 0,
134 GTPH_PLANE_USER = 1,
135 GTPH_PLANE_N
136};
137
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100138enum gtphub_side_idx {
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100139 GTPH_SIDE_SGSN = 0,
140 GTPH_SIDE_GGSN = 1,
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100141 GTPH_SIDE_N
142};
143
Neels Hofmeyrf9773202015-11-27 00:05:56 +0100144#define for_each_side(I) for (I = 0; I < GTPH_SIDE_N; I++)
145#define for_each_plane(I) for (I = 0; I < GTPH_PLANE_N; I++)
146#define for_each_side_and_plane(I,J) for_each_side(I) for_each_plane(J)
147
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100148static inline int other_side_idx(int side_idx)
149{
150 return (side_idx + 1) & 1;
151}
152
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200153extern const char* const gtphub_plane_idx_names[GTPH_PLANE_N];
154extern const uint16_t gtphub_plane_idx_default_port[GTPH_PLANE_N];
155
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100156extern const char* const gtphub_side_idx_names[GTPH_SIDE_N];
157
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200158/* A host address in the form that is expected in the 7.7.32 GSN Address IE.
159 * len is either 4 (IPv4) or 16 (IPv6), any other value is invalid. If no
160 * address is set, len shall be 0. */
161struct gsn_addr {
162 uint16_t len;
163 uint8_t buf[16];
164};
165
166void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src);
167int gsn_addr_from_str(struct gsn_addr *gsna, const char *numeric_addr_str);
168
169/* Return gsna in numeric string form, in a static buffer. */
170const char *gsn_addr_to_str(const struct gsn_addr *gsna);
171
172/* note: strbuf_len doesn't need to be larger than INET6_ADDRSTRLEN + 1. */
173const char *gsn_addr_to_strb(const struct gsn_addr *gsna,
174 char *strbuf, int strbuf_len);
175
176/* Return 1 on match, zero otherwise. */
177int gsn_addr_same(const struct gsn_addr *a, const struct gsn_addr *b);
178
Neels Hofmeyrc2275942015-11-10 22:07:04 +0100179/* Decode sa to gsna. Return 0 on success. If port is non-NULL, the port number
180 * from sa is also returned. */
181int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
182 const struct osmo_sockaddr *sa);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200183
184/* expiry */
185
186struct expiring_item;
187typedef void (*del_cb_t)(struct expiring_item *);
188
189struct expiring_item {
190 struct llist_head entry;
191 time_t expiry;
192 del_cb_t del_cb;
193};
194
195struct expiry {
196 int expiry_in_seconds;
197 struct llist_head items;
198};
199
200/* Initialize an expiry queue. */
201void expiry_init(struct expiry *exq, int expiry_in_seconds);
202
Neels Hofmeyr9cfe0372015-11-16 14:52:05 +0100203/* Add a new mapping, or restart the expiry timeout for an already listed
204 * mapping. */
Neels Hofmeyr231653a2015-11-24 13:23:44 +0100205void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200206
Neels Hofmeyr16c3f572015-11-11 17:27:01 +0100207/* Initialize to all-empty; must be called before using the item in any way. */
208void expiring_item_init(struct expiring_item *item);
209
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200210/* Remove the given item from its expiry queue, and call item->del_cb, if set.
211 * This sets item->del_cb to NULL and is harmless when run a second time on the
212 * same item, so the del_cb may choose to call this function, too, to allow
213 * deleting items from several code paths. */
214void expiring_item_del(struct expiring_item *item);
215
216/* Carry out due expiry of mappings. Must be invoked regularly.
217 * 'now' is the current clock count in seconds and must correspond to the clock
218 * count passed to nr_map_add(). A monotonous clock counter should be used. */
219int expiry_tick(struct expiry *exq, time_t now);
220
Neels Hofmeyr20bd6bf2015-11-20 00:08:28 +0100221/* Expire all items. */
222void expiry_clear(struct expiry *exq);
223
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200224
225/* number map */
226
227/* A number map assigns a "random" mapped number to each user provided number.
228 * If the same number is requested multiple times, the same mapped number is
229 * returned.
230 *
231 * Number maps plug into possibly shared pools and expiry queues, for example:
232 *
233 * mapA -----------+-> pool1 <-+-- mapB
234 * {10->1, 11->5} | {1, 2, 3, ...} | {10->2, 11->3}
235 * | |
236 * | |
237 * /-> \-> expiry1 <-/
238 * | (30 seconds)
239 * |
240 * mapC -------+-----> pool2 <-+-- mapD
241 * {10->1, 11->3} {1, 2, 3, ...} | {10->2, 11->5}
242 * |
243 * expiry2 <-/
244 * (60 seconds)
245 *
246 * A map contains mappings ("10->1"). Each map needs a number pool, which can
247 * be shared with other maps. Each new mapping receives a number from the pool,
248 * which is then unavailable to any other map using the same pool.
249 *
250 * A map may point at an expiry queue, in which case all mappings added to it
251 * are also appended to the expiry queue (using a separate llist entry in the
252 * mapping). Any number of maps may submit to the same expiry queue, if they
253 * desire the same expiry timeout. An expiry queue stores the mappings in
254 * chronological order, so that expiry checking is needed only from the start
255 * of the queue; hence only mappings with identical expiry timeout can be added
256 * to the same expiry queue. Upon expiry, a mapping is dropped from the map it
257 * was submitted at. expiry_tick() needs to be called regularly for each expiry
258 * queue.
259 *
260 * A nr_mapping can be embedded in a larger struct: each mapping can have a
261 * distinct destructor (del_cb), and each del_cb can figure out the container
262 * struct's address and free that upon expiry or manual deletion. So in expiry
263 * queues (and even maps), mappings of different container types can be mixed.
264 * This can help to drastically reduce the amount of unnecessary visits during
265 * expiry checking, for the case that no expiry is pending. An expiry queue
266 * always knows which mappings to expire next, because they are right at the
267 * start of its list.
268 *
269 * Mapping allocation and a del_cb are provided by the caller. If del_cb is
270 * NULL, no deallocation will be done (allowing statically allocated entries).
271 */
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200272
Neels Hofmeyr334af5d2015-11-17 14:24:46 +0100273typedef unsigned int nr_t;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200274
275/* Generator for unused numbers. So far this counts upwards from zero, but the
276 * implementation may change in the future. Treat this like an opaque struct.
277 * If this becomes random, the tests need to be fixed. */
278struct nr_pool {
279 nr_t last_nr;
Neels Hofmeyre2ed8e62015-11-17 14:30:37 +0100280 nr_t nr_min;
281 nr_t nr_max;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200282};
283
284struct nr_mapping {
285 struct llist_head entry;
286 struct expiring_item expiry_entry;
287
288 void *origin;
289 nr_t orig;
290 nr_t repl;
291};
292
293struct nr_map {
294 struct nr_pool *pool; /* multiple nr_maps can share a nr_pool. */
295 struct expiry *add_items_to_expiry;
296 struct llist_head mappings;
297};
298
299
Neels Hofmeyre2ed8e62015-11-17 14:30:37 +0100300void nr_pool_init(struct nr_pool *pool, nr_t nr_min, nr_t nr_max);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200301
302/* Return the next unused number from the nr_pool. */
303nr_t nr_pool_next(struct nr_pool *pool);
304
305/* Initialize the nr_mapping to zero/empty values. */
306void nr_mapping_init(struct nr_mapping *mapping);
307
308/* Remove the given mapping from its parent map and expiry queue, and call
309 * mapping->del_cb, if set. */
310void nr_mapping_del(struct nr_mapping *mapping);
311
312/* Initialize an (already allocated) nr_map, and set the map's number pool.
313 * Multiple nr_map instances may use the same nr_pool. Set the nr_map's expiry
314 * queue to exq, so that all added mappings are automatically expired after the
315 * time configured in exq. exq may be NULL to disable automatic expiry. */
316void nr_map_init(struct nr_map *map, struct nr_pool *pool,
317 struct expiry *exq);
318
319/* Add a new entry to the map. mapping->orig, mapping->origin and
320 * mapping->del_cb must be set before calling this function. The remaining
321 * fields of *mapping will be overwritten. mapping->repl is set to the next
322 * available mapped number from map->pool. 'now' is the current clock count in
323 * seconds; if no map->expiry is used, just pass 0 for 'now'. */
324void nr_map_add(struct nr_map *map, struct nr_mapping *mapping,
325 time_t now);
326
Neels Hofmeyr508514c2015-11-24 13:30:38 +0100327/* Restart the timeout for the given mapping. mapping must be a member of map.
328 */
329void nr_map_refresh(struct nr_map *map, struct nr_mapping *mapping,
330 time_t now);
331
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200332/* Return a known mapping from nr_orig and the given origin. If nr_orig is
333 * unknown, return NULL. */
334struct nr_mapping *nr_map_get(const struct nr_map *map,
335 void *origin, nr_t nr_orig);
336
337/* Return a known mapping to nr_repl. If nr_repl is unknown, return NULL. */
338struct nr_mapping *nr_map_get_inv(const struct nr_map *map, nr_t nr_repl);
339
340/* Remove all mappings from map. */
341void nr_map_clear(struct nr_map *map);
342
343/* Return 1 if map has no entries, 0 otherwise. */
344int nr_map_empty(const struct nr_map *map);
345
346
347/* config */
348
Neels Hofmeyr2c8b5812015-11-25 16:45:59 +0100349static const int GTPH_EXPIRE_QUICKLY_SECS = 30; /* TODO is there a spec for this? */
350static const int GTPH_EXPIRE_SLOWLY_MINUTES = 6 * 60; /* TODO is there a spec for this? */
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200351
352struct gtphub_cfg_addr {
353 const char *addr_str;
354 uint16_t port;
355};
356
357struct gtphub_cfg_bind {
358 struct gtphub_cfg_addr bind;
359};
360
361struct gtphub_cfg {
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100362 struct gtphub_cfg_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N];
363 struct gtphub_cfg_addr proxy[GTPH_SIDE_N][GTPH_PLANE_N];
Neels Hofmeyrca2361c2015-12-03 14:12:44 +0100364 int sgsn_use_sender; /* Use sender, not GSN addr IE with std ports */
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200365};
366
367
368/* state */
369
370struct gtphub_peer {
371 struct llist_head entry;
372
373 struct llist_head addresses; /* Alternatives, not load balancing. */
374 struct nr_pool seq_pool;
375 struct nr_map seq_map;
376};
377
378struct gtphub_peer_addr {
379 struct llist_head entry;
380
381 struct gtphub_peer *peer;
382 struct gsn_addr addr;
383 struct llist_head ports;
384};
385
386struct gtphub_peer_port {
387 struct llist_head entry;
388
389 struct gtphub_peer_addr *peer_addr;
390 uint16_t port;
391 unsigned int ref_count; /* references from other peers' seq_maps */
Neels Hofmeyrbc443302015-12-01 15:20:18 +0100392 struct osmo_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
393 int last_restart_count; /* 0..255 = valid, all else means unknown */
Neels Hofmeyre38fb662015-12-06 16:44:14 +0100394
395 struct rate_ctr_group *counters_io;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200396};
397
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100398struct gtphub_tunnel_endpoint {
399 struct gtphub_peer_port *peer;
400 uint32_t tei_orig; /* from/to peer */
Neels Hofmeyre38fb662015-12-06 16:44:14 +0100401
402 struct rate_ctr_group *counters_io;
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100403};
404
405struct gtphub_tunnel {
406 struct llist_head entry;
407 struct expiring_item expiry_entry;
408
Neels Hofmeyree07e4f2015-12-06 19:11:45 +0100409 uint32_t tei_repl; /* unique TEI to replace peers' TEIs */
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100410 struct gtphub_tunnel_endpoint endpoint[GTPH_SIDE_N][GTPH_PLANE_N];
411};
412
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200413struct gtphub_bind {
414 struct gsn_addr local_addr;
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100415 uint16_t local_port;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200416 struct osmo_fd ofd;
417
418 /* list of struct gtphub_peer */
419 struct llist_head peers;
Neels Hofmeyr390e9102015-11-16 13:45:13 +0100420
421 const char *label; /* For logging */
Neels Hofmeyr1ba50c62015-11-20 01:28:40 +0100422 struct rate_ctr_group *counters_io;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200423};
424
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100425struct gtphub_resolved_ggsn {
426 struct llist_head entry;
427 struct expiring_item expiry_entry;
428
429 /* The APN OI, the Operator Identifier, is the combined address,
430 * including parts of the IMSI and APN NI, and ending with ".gprs". */
431 char apn_oi_str[GSM_APN_LENGTH];
432
433 /* Which address and port we resolved that to. */
434 struct gtphub_peer_port *peer;
435};
436
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200437struct gtphub {
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100438 struct gtphub_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N];
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200439
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100440 /* pointers to an entry of to_gsns[s][p].peers */
441 struct gtphub_peer_port *proxy[GTPH_SIDE_N][GTPH_PLANE_N];
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200442
Neels Hofmeyre2ed8e62015-11-17 14:30:37 +0100443 /* The TEI numbers will simply wrap and be reused, which will work out
444 * in practice. Problems would arise if one given peer maintained the
445 * same TEI for a time long enough for the TEI nr map to wrap an entire
446 * uint32_t; if a new TEI were mapped every second, this would take
447 * more than 100 years (in which a single given TEI must not time out)
448 * to cause a problem. */
Neels Hofmeyrd121ea62015-11-27 01:20:53 +0100449 struct nr_pool tei_pool;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200450
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100451 struct llist_head tunnels; /* struct gtphub_tunnel */
Neels Hofmeyr10fc0242015-12-01 00:23:45 +0100452 struct llist_head pending_deletes; /* opaque (gtphub.c) */
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100453
Neels Hofmeyr4960fab2015-11-18 17:53:00 +0100454 struct llist_head ggsn_lookups; /* opaque (gtphub_ares.c) */
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100455 struct llist_head resolved_ggsns; /* struct gtphub_resolved_ggsn */
456
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200457 struct osmo_timer_list gc_timer;
Neels Hofmeyr2c8b5812015-11-25 16:45:59 +0100458 struct expiry expire_quickly;
459 struct expiry expire_slowly;
Neels Hofmeyrbb3d6782015-11-09 15:12:25 +0100460
Neels Hofmeyrba9e9f62015-11-26 22:19:22 +0100461 uint8_t restart_counter;
Neels Hofmeyrca2361c2015-12-03 14:12:44 +0100462
463 int sgsn_use_sender;
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200464};
465
466struct gtp_packet_desc;
467
468
469/* api */
470
Neels Hofmeyr4b2cbda2015-11-20 03:16:19 +0100471int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200472int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file);
473
474/* Initialize and start gtphub: bind to ports, run expiry timers. */
Neels Hofmeyrba9e9f62015-11-26 22:19:22 +0100475int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg,
476 uint8_t restart_counter);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200477
Neels Hofmeyr20bd6bf2015-11-20 00:08:28 +0100478/* Close all sockets, expire all maps and peers and free all allocations. The
479 * struct is then unusable, unless gtphub_start() is run on it again. */
480void gtphub_stop(struct gtphub *hub);
481
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200482time_t gtphub_now(void);
483
484/* Remove expired items, empty peers, ... */
485void gtphub_gc(struct gtphub *hub, time_t now);
486
487/* Return the string of the first address for this peer. */
488const char *gtphub_peer_str(struct gtphub_peer *peer);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200489
Neels Hofmeyre54cd152015-11-24 13:31:06 +0100490/* Return a human readable description of tun in a static buffer. */
491const char *gtphub_tunnel_str(struct gtphub_tunnel *tun);
492
493/* Return 1 if all of tun's endpoints are fully established, 0 otherwise. */
494int gtphub_tunnel_complete(struct gtphub_tunnel *tun);
495
Neels Hofmeyra9905a52015-11-29 23:49:48 +0100496int gtphub_handle_buf(struct gtphub *hub,
497 unsigned int side_idx,
498 unsigned int port_idx,
499 const struct osmo_sockaddr *from_addr,
500 uint8_t *buf,
501 size_t received,
502 time_t now,
503 uint8_t **reply_buf,
504 struct osmo_fd **to_ofd,
505 struct osmo_sockaddr *to_addr);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200506
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100507struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
508 struct gtphub_bind *bind,
509 const struct gsn_addr *addr,
510 uint16_t port);
511
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200512struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
513 const struct osmo_sockaddr *addr);
Neels Hofmeyr30f7bcb2015-11-08 20:34:47 +0100514
515void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
516 struct gsn_addr *resolved_addr,
517 time_t now);
518
519const char *gtphub_port_str(struct gtphub_peer_port *port);
Neels Hofmeyr996ec1d2015-12-02 15:43:10 +0100520
521int gtphub_write(const struct osmo_fd *to,
522 const struct osmo_sockaddr *to_addr,
523 const uint8_t *buf, size_t buf_len);