aboutsummaryrefslogtreecommitdiffstats
path: root/ggsn/ggsn.h
blob: 51f4ec1c66b2efd1e58416a26143132c5889ee54 (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
#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/select.h>
#include <osmocom/core/timer.h>
#include <osmocom/ctrl/control_if.h>

#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
#include "../lib/in46_addr.h"
#include "../gtp/gtp.h"

#include "sgsn.h"

#define APN_TYPE_IPv4	0x01	/* v4-only */
#define APN_TYPE_IPv6	0x02	/* v6-only */
#define APN_TYPE_IPv4v6	0x04	/* v4v6 dual-stack */

struct ggsn_ctx;

struct apn_ctx_ip {
	struct {
		struct in46_prefix ifconfig_prefix;
		struct in46_prefix ll_prefix;
		struct in46_prefix static_prefix;
		struct in46_prefix dynamic_prefix;
		/* v4 DNS server names */
		struct in46_addr dns[2];
	} cfg;

	/* v4 address pool */
	struct ippool_t *pool;
};

struct apn_name {
	struct llist_head list;
	char *name;
};

enum apn_gtpu_mode {
	APN_GTPU_MODE_TUN = 0,		/* default */
	APN_GTPU_MODE_KERNEL_GTP,
};

struct apn_ctx {
	/* list of APNs inside GGSN */
	struct llist_head list;
	/* back-pointer to GGSN */
	struct ggsn_ctx *ggsn;

	bool started;

	struct {
		/* Primary name */
		char *name;
		/* Description string */
		char *description;
		/* List of secondary APN names */
		struct llist_head name_list;
		/* types supported address types on this APN */
		uint32_t apn_type_mask;
		/* GTP-U via TUN device or in Linux kernel */
		enum apn_gtpu_mode gtpu_mode;
		/* administratively shut-down (true) or not (false) */
		bool shutdown;
		/* transmit G-PDU sequeence numbers (true) or not (false) */
		bool tx_gpdu_seq;
	} cfg;

	/* corresponding tun device */
	struct {
		struct {
			/* name of the network device */
			char *dev_name;
			/* ip-up and ip-down script names/paths */
			char *ipup_script;
			char *ipdown_script;
		} cfg;
		struct tun_t *tun;
		struct osmo_fd fd;
	} tun;

	/* ipv6 link-local address */
	struct in6_addr v6_lladdr;

	struct apn_ctx_ip v4;
	struct apn_ctx_ip v6;
};

struct pdp_priv_t {
	struct pdp_t *lib; /* pointer to libgtp associated pdp_t instance */
	struct sgsn_peer *sgsn;
	struct apn_ctx *apn;
	struct llist_head entry; /* to be included into sgsn_peer */
	/* struct ggsn_ctx can be reached through lib->gsn->priv, or through sgsn->ggsn */
};

struct ggsn_ctx {
	/* global list of GGSNs */
	struct llist_head list;

	/* list of APNs in this GGSN */
	struct llist_head apn_list;

	/* list of SGSN peers (struct sgsn_peer) in this GGSN. TODO: hash table with key <ip+port>? */
	struct llist_head sgsn_list;

	bool started;

	struct {
		char *name;
		/* Description string */
		char *description;
		/* APNs that shall be used as default for any non-matching APN */
		struct apn_ctx *default_apn_v4;
		struct apn_ctx *default_apn_v6;
		struct apn_ctx *default_apn_v4v6;
		/* ADdress to which we listen for GTP */
		struct in46_addr listen_addr;
		/* Local GTP-C address advertised in GTP */
		struct in46_addr gtpc_addr;
		/* Local GTP-U address advertised in GTP */
		struct in46_addr gtpu_addr;
		/* directory for state file */
		char *state_dir;
		/* Time between Echo requests on each SGSN */
		unsigned int echo_interval;
		/* administratively shut-down (true) or not (false) */
		bool shutdown;
	} cfg;

	/* The libgtp (G)GSN instance, i.e. what listens to GTP */
	struct gsn_t *gsn;

	/* osmo-fd for gsn */
	struct osmo_fd gtp_fd0;
	struct osmo_fd gtp_fd1c;
	struct osmo_fd gtp_fd1u;
};

/* ggsn_vty.c */
extern struct llist_head g_ggsn_list;
extern struct vty_app_info g_vty_info;
extern int ggsn_vty_init(void);
struct ggsn_ctx *ggsn_find(const char *name);
struct ggsn_ctx *ggsn_find_or_create(void *ctx, const char *name);
struct apn_ctx *ggsn_find_apn(struct ggsn_ctx *ggsn, const char *name);
struct apn_ctx *ggsn_find_or_create_apn(struct ggsn_ctx *ggsn, const char *name);

/* ggsn_main.c */
extern struct ctrl_handle *g_ctrlh;
extern void *tall_ggsn_ctx;

/* ggsn.c */
extern int ggsn_start(struct ggsn_ctx *ggsn);
extern int ggsn_stop(struct ggsn_ctx *ggsn);
extern int apn_start(struct apn_ctx *apn);
extern int apn_stop(struct apn_ctx *apn);
void ggsn_close_one_pdp(struct pdp_t *pdp);

#define LOGPAPN(level, apn, fmt, args...)			\
	LOGP(DGGSN, level, "APN(%s): " fmt, (apn)->cfg.name, ## args)

#define LOGPGGSN(level, ggsn, fmt, args...)			\
	LOGP(DGGSN, level, "GGSN(%s): " fmt, (ggsn)->cfg.name, ## args)

#define LOGPPDP(level, pdp, fmt, args...) LOGPDPX(DGGSN, level, pdp, fmt, ## args)

#define LOGTUN(level, tun, fmt, args...) \
	LOGP(DTUN, level, "TUN(%s): " fmt, (tun)->devname, ## args)