blob: 44fd3ccdc32a4436d592edf114c0cec4d15dbc94 [file] [log] [blame]
Harald Weltedda21ed2017-08-12 15:07:02 +02001#pragma once
2
3#include <stdint.h>
4#include <stdbool.h>
5#include <osmocom/core/utils.h>
6#include <osmocom/core/linuxlist.h>
7#include <osmocom/core/select.h>
8#include <osmocom/core/timer.h>
Pau Espin Pedrol9f1f7472022-11-02 19:52:19 +01009#include <osmocom/core/tdef.h>
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +020010#include <osmocom/ctrl/control_if.h>
Keith Whytecea90442023-07-14 02:48:28 +010011#include <osmocom/gsm/protocol/gsm_23_003.h>
Harald Weltedda21ed2017-08-12 15:07:02 +020012
13#include "../lib/tun.h"
14#include "../lib/ippool.h"
15#include "../lib/syserr.h"
16#include "../lib/in46_addr.h"
17#include "../gtp/gtp.h"
18
Pau Espin Pedrolf5fbb412019-08-21 18:49:44 +020019#include "sgsn.h"
20
Harald Weltedda21ed2017-08-12 15:07:02 +020021#define APN_TYPE_IPv4 0x01 /* v4-only */
22#define APN_TYPE_IPv6 0x02 /* v6-only */
23#define APN_TYPE_IPv4v6 0x04 /* v4v6 dual-stack */
24
25struct ggsn_ctx;
26
27struct apn_ctx_ip {
28 struct {
29 struct in46_prefix ifconfig_prefix;
Pau Espin Pedrol37c45e32017-12-14 14:09:13 +010030 struct in46_prefix ll_prefix;
Harald Weltedda21ed2017-08-12 15:07:02 +020031 struct in46_prefix static_prefix;
32 struct in46_prefix dynamic_prefix;
33 /* v4 DNS server names */
34 struct in46_addr dns[2];
35 } cfg;
36
37 /* v4 address pool */
38 struct ippool_t *pool;
Keith Whytecea90442023-07-14 02:48:28 +010039 /* Static IMSI to IPv4 reserved address mappings. */
40 struct llist_head imsi_ip_map;
41
Harald Weltedda21ed2017-08-12 15:07:02 +020042};
43
44struct apn_name {
45 struct llist_head list;
46 char *name;
47};
48
49enum apn_gtpu_mode {
50 APN_GTPU_MODE_TUN = 0, /* default */
51 APN_GTPU_MODE_KERNEL_GTP,
52};
53
Keith Whytecea90442023-07-14 02:48:28 +010054/*
55 * IMSI to static IP map handling
56 */
57struct imsi_map_entry {
58 struct llist_head list;
59 char imsi[OSMO_IMSI_BUF_SIZE];
60 struct in46_addr addr;
61};
62
Harald Weltedda21ed2017-08-12 15:07:02 +020063struct apn_ctx {
64 /* list of APNs inside GGSN */
65 struct llist_head list;
66 /* back-pointer to GGSN */
67 struct ggsn_ctx *ggsn;
68
69 bool started;
70
71 struct {
72 /* Primary name */
73 char *name;
74 /* Description string */
75 char *description;
76 /* List of secondary APN names */
77 struct llist_head name_list;
78 /* types supported address types on this APN */
79 uint32_t apn_type_mask;
80 /* GTP-U via TUN device or in Linux kernel */
81 enum apn_gtpu_mode gtpu_mode;
Pau Espin Pedrol4fac8422023-01-17 14:17:18 +010082 /* administratively shut down (true) or not (false) */
Harald Weltedda21ed2017-08-12 15:07:02 +020083 bool shutdown;
Pau Espin Pedrol4fac8422023-01-17 14:17:18 +010084 /* transmit G-PDU sequence numbers (true) or not (false) */
Harald Welte93fed3b2017-09-24 11:43:17 +080085 bool tx_gpdu_seq;
Harald Weltedda21ed2017-08-12 15:07:02 +020086 } cfg;
87
88 /* corresponding tun device */
89 struct {
90 struct {
91 /* name of the network device */
92 char *dev_name;
93 /* ip-up and ip-down script names/paths */
94 char *ipup_script;
95 char *ipdown_script;
96 } cfg;
97 struct tun_t *tun;
98 struct osmo_fd fd;
99 } tun;
100
Harald Weltef85fe972017-09-24 20:00:34 +0800101 /* ipv6 link-local address */
102 struct in6_addr v6_lladdr;
103
Harald Weltedda21ed2017-08-12 15:07:02 +0200104 struct apn_ctx_ip v4;
105 struct apn_ctx_ip v6;
106};
107
Pau Espin Pedrolf5fbb412019-08-21 18:49:44 +0200108struct pdp_priv_t {
109 struct pdp_t *lib; /* pointer to libgtp associated pdp_t instance */
110 struct sgsn_peer *sgsn;
111 struct apn_ctx *apn;
112 struct llist_head entry; /* to be included into sgsn_peer */
113 /* struct ggsn_ctx can be reached through lib->gsn->priv, or through sgsn->ggsn */
114};
115
Harald Weltedda21ed2017-08-12 15:07:02 +0200116struct ggsn_ctx {
117 /* global list of GGSNs */
118 struct llist_head list;
119
120 /* list of APNs in this GGSN */
121 struct llist_head apn_list;
122
Pau Espin Pedrolf5fbb412019-08-21 18:49:44 +0200123 /* list of SGSN peers (struct sgsn_peer) in this GGSN. TODO: hash table with key <ip+port>? */
124 struct llist_head sgsn_list;
125
Harald Weltedda21ed2017-08-12 15:07:02 +0200126 bool started;
127
128 struct {
129 char *name;
130 /* Description string */
131 char *description;
132 /* an APN that shall be used as default for any non-matching APN */
133 struct apn_ctx *default_apn;
134 /* ADdress to which we listen for GTP */
135 struct in46_addr listen_addr;
Harald Welte98146772017-09-05 17:41:20 +0200136 /* Local GTP-C address advertised in GTP */
137 struct in46_addr gtpc_addr;
138 /* Local GTP-U address advertised in GTP */
139 struct in46_addr gtpu_addr;
Harald Weltedda21ed2017-08-12 15:07:02 +0200140 /* directory for state file */
141 char *state_dir;
Pau Espin Pedrolf5fbb412019-08-21 18:49:44 +0200142 /* Time between Echo requests on each SGSN */
143 unsigned int echo_interval;
Pau Espin Pedrol4fac8422023-01-17 14:17:18 +0100144 /* administratively shut down (true) or not (false) */
Harald Weltedda21ed2017-08-12 15:07:02 +0200145 bool shutdown;
146 } cfg;
147
148 /* The libgtp (G)GSN instance, i.e. what listens to GTP */
149 struct gsn_t *gsn;
150
151 /* osmo-fd for gsn */
152 struct osmo_fd gtp_fd0;
153 struct osmo_fd gtp_fd1c;
154 struct osmo_fd gtp_fd1u;
Harald Weltedda21ed2017-08-12 15:07:02 +0200155};
156
157/* ggsn_vty.c */
158extern struct llist_head g_ggsn_list;
159extern struct vty_app_info g_vty_info;
160extern int ggsn_vty_init(void);
161struct ggsn_ctx *ggsn_find(const char *name);
162struct ggsn_ctx *ggsn_find_or_create(void *ctx, const char *name);
163struct apn_ctx *ggsn_find_apn(struct ggsn_ctx *ggsn, const char *name);
164struct apn_ctx *ggsn_find_or_create_apn(struct ggsn_ctx *ggsn, const char *name);
165
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200166/* ggsn_main.c */
167extern struct ctrl_handle *g_ctrlh;
Harald Weltedda21ed2017-08-12 15:07:02 +0200168extern void *tall_ggsn_ctx;
Pau Espin Pedrol9f1f7472022-11-02 19:52:19 +0100169extern struct osmo_tdef_group ggsn_tdef_group[];
Pau Espin Pedrol421f22e2019-08-20 12:52:13 +0200170
171/* ggsn.c */
Harald Weltedda21ed2017-08-12 15:07:02 +0200172extern int ggsn_start(struct ggsn_ctx *ggsn);
173extern int ggsn_stop(struct ggsn_ctx *ggsn);
174extern int apn_start(struct apn_ctx *apn);
Pau Espin Pedrol72ab4bc2019-05-29 19:08:26 +0200175extern int apn_stop(struct apn_ctx *apn);
Pau Espin Pedrolf5fbb412019-08-21 18:49:44 +0200176void ggsn_close_one_pdp(struct pdp_t *pdp);
Keith Whytecea90442023-07-14 02:48:28 +0100177bool apn_supports_ipv4(const struct apn_ctx *apn);
178int apn_imsi_ip_map_add(const char *imsi, const char *ip, struct apn_ctx_ip *ctx);
179int apn_imsi_ip_map_del(const char *imsi, const char *ip, struct apn_ctx_ip *ctx);
Pau Espin Pedrolf7884e82019-08-20 12:06:13 +0200180
181#define LOGPAPN(level, apn, fmt, args...) \
182 LOGP(DGGSN, level, "APN(%s): " fmt, (apn)->cfg.name, ## args)
183
184#define LOGPGGSN(level, ggsn, fmt, args...) \
185 LOGP(DGGSN, level, "GGSN(%s): " fmt, (ggsn)->cfg.name, ## args)
186
187#define LOGPPDP(level, pdp, fmt, args...) LOGPDPX(DGGSN, level, pdp, fmt, ## args)