blob: 29a73160086bddb32c62947d9a939b84cabdbd2e [file] [log] [blame]
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +02001/* (C) 2015 by sysmocom s.f.m.c. GmbH
2 * All Rights Reserved
3 *
4 * Author: Neels Hofmeyr
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <string.h>
22
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +010023#include <ares.h>
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020028#include <osmocom/core/talloc.h>
29#include <osmocom/vty/command.h>
30
31#include <openbsc/vty.h>
32#include <openbsc/gtphub.h>
33
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +010034/* TODO split GRX ares from sgsn into a separate struct and allow use without
35 * globals. */
36#include <openbsc/sgsn.h>
37extern struct sgsn_instance *sgsn;
38
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020039static struct gtphub_cfg *g_cfg = 0;
40
41static struct cmd_node gtphub_node = {
42 GTPHUB_NODE,
43 "%s(config-gtphub)# ",
44 1,
45};
46
47#define GTPH_DEFAULT_CONTROL_PORT 2123
48#define GTPH_DEFAULT_USER_PORT 2152
49
50static void write_addrs(struct vty *vty, const char *name,
51 struct gtphub_cfg_addr *c, struct gtphub_cfg_addr *u)
52{
53 if ((c->port == GTPH_DEFAULT_CONTROL_PORT)
54 && (u->port == GTPH_DEFAULT_USER_PORT)
55 && (strcmp(c->addr_str, u->addr_str) == 0)) {
56 /* Default port numbers and same IP address: write "short"
57 * variant. */
58 vty_out(vty, " %s %s%s",
59 name,
60 c->addr_str,
61 VTY_NEWLINE);
62 return;
63 }
64
65 vty_out(vty, " %s ctrl %s %d user %s %d%s",
66 name,
67 c->addr_str, (int)c->port,
68 u->addr_str, (int)u->port,
69 VTY_NEWLINE);
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +010070
71 struct ares_addr_node *server;
72 for (server = sgsn->ares_servers; server; server = server->next)
73 vty_out(vty, " grx-dns-add %s%s", inet_ntoa(server->addr.addr4), VTY_NEWLINE);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +020074}
75
76static int config_write_gtphub(struct vty *vty)
77{
78 vty_out(vty, "gtphub%s", VTY_NEWLINE);
79
80 write_addrs(vty, "bind-to-sgsns",
81 &g_cfg->to_sgsns[GTPH_PLANE_CTRL].bind,
82 &g_cfg->to_sgsns[GTPH_PLANE_USER].bind);
83
84 write_addrs(vty, "bind-to-ggsns",
85 &g_cfg->to_ggsns[GTPH_PLANE_CTRL].bind,
86 &g_cfg->to_ggsns[GTPH_PLANE_USER].bind);
87
88 if (g_cfg->ggsn_proxy[GTPH_PLANE_CTRL].addr_str) {
89 write_addrs(vty, "ggsn-proxy",
90 &g_cfg->ggsn_proxy[GTPH_PLANE_CTRL],
91 &g_cfg->ggsn_proxy[GTPH_PLANE_USER]);
92 }
93
94 return CMD_SUCCESS;
95}
96
97DEFUN(cfg_gtphub, cfg_gtphub_cmd,
98 "gtphub",
99 "Configure the GTP hub")
100{
101 vty->node = GTPHUB_NODE;
102 return CMD_SUCCESS;
103}
104
105#define BIND_ARGS "ctrl ADDR <0-65535> user ADDR <0-65535>"
106#define BIND_DOCS \
107 "Set GTP-C bind\n" \
108 "GTP-C local IP address (v4 or v6)\n" \
109 "GTP-C local port\n" \
110 "Set GTP-U bind\n" \
111 "GTP-U local IP address (v4 or v6)\n" \
112 "GTP-U local port\n"
113
114
115DEFUN(cfg_gtphub_bind_to_sgsns_short, cfg_gtphub_bind_to_sgsns_short_cmd,
116 "bind-to-sgsns ADDR",
117 "GTP Hub Parameters\n"
118 "Set the local bind address to listen for SGSNs, for both GTP-C and GTP-U\n"
119 "Local IP address (v4 or v6)\n"
120 )
121{
122 int i;
123 for (i = 0; i < GTPH_PLANE_N; i++)
124 g_cfg->to_sgsns[i].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
125 g_cfg->to_sgsns[GTPH_PLANE_CTRL].bind.port = GTPH_DEFAULT_CONTROL_PORT;
126 g_cfg->to_sgsns[GTPH_PLANE_USER].bind.port = GTPH_DEFAULT_USER_PORT;
127 return CMD_SUCCESS;
128}
129
130DEFUN(cfg_gtphub_bind_to_ggsns_short, cfg_gtphub_bind_to_ggsns_short_cmd,
131 "bind-to-ggsns ADDR",
132 "GTP Hub Parameters\n"
133 "Set the local bind address to listen for GGSNs, for both GTP-C and GTP-U\n"
134 "Local IP address (v4 or v6)\n"
135 )
136{
137 int i;
138 for (i = 0; i < GTPH_PLANE_N; i++)
139 g_cfg->to_ggsns[i].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
140 g_cfg->to_ggsns[GTPH_PLANE_CTRL].bind.port = GTPH_DEFAULT_CONTROL_PORT;
141 g_cfg->to_ggsns[GTPH_PLANE_USER].bind.port = GTPH_DEFAULT_USER_PORT;
142 return CMD_SUCCESS;
143}
144
145
146static int handle_binds(struct gtphub_cfg_bind *b, const char **argv)
147{
148 b[GTPH_PLANE_CTRL].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
149 b[GTPH_PLANE_CTRL].bind.port = atoi(argv[1]);
150 b[GTPH_PLANE_USER].bind.addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
151 b[GTPH_PLANE_USER].bind.port = atoi(argv[3]);
152 return CMD_SUCCESS;
153}
154
155DEFUN(cfg_gtphub_bind_to_sgsns, cfg_gtphub_bind_to_sgsns_cmd,
156 "bind-to-sgsns " BIND_ARGS,
157 "GTP Hub Parameters\n"
158 "Set the local bind addresses and ports to listen for SGSNs\n"
159 BIND_DOCS
160 )
161{
162 return handle_binds(g_cfg->to_sgsns, argv);
163}
164
165DEFUN(cfg_gtphub_bind_to_ggsns, cfg_gtphub_bind_to_ggsns_cmd,
166 "bind-to-ggsns " BIND_ARGS,
167 "GTP Hub Parameters\n"
168 "Set the local bind addresses and ports to listen for GGSNs\n"
169 BIND_DOCS
170 )
171{
172 return handle_binds(g_cfg->to_ggsns, argv);
173}
174
175DEFUN(cfg_gtphub_ggsn_proxy_short, cfg_gtphub_ggsn_proxy_short_cmd,
176 "ggsn-proxy ADDR",
177 "GTP Hub Parameters\n"
178 "Redirect all GGSN bound traffic to default ports on this address (another gtphub)\n"
179 "Remote IP address (v4 or v6)\n"
180 )
181{
182 g_cfg->ggsn_proxy[GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
183 g_cfg->ggsn_proxy[GTPH_PLANE_CTRL].port = GTPH_DEFAULT_CONTROL_PORT;
184 g_cfg->ggsn_proxy[GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
185 g_cfg->ggsn_proxy[GTPH_PLANE_USER].port = GTPH_DEFAULT_USER_PORT;
186 return CMD_SUCCESS;
187}
188
189DEFUN(cfg_gtphub_ggsn_proxy, cfg_gtphub_ggsn_proxy_cmd,
190 "ggsn-proxy " BIND_ARGS,
191 "GTP Hub Parameters\n"
192 "Redirect all GGSN bound traffic to these addresses and ports (another gtphub)\n"
193 BIND_DOCS
194 )
195{
196 g_cfg->ggsn_proxy[GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
197 g_cfg->ggsn_proxy[GTPH_PLANE_CTRL].port = atoi(argv[1]);
198 g_cfg->ggsn_proxy[GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
199 g_cfg->ggsn_proxy[GTPH_PLANE_USER].port = atoi(argv[3]);
200 return CMD_SUCCESS;
201}
202
203DEFUN(cfg_gtphub_sgsn_proxy_short, cfg_gtphub_sgsn_proxy_short_cmd,
204 "sgsn-proxy ADDR",
205 "GTP Hub Parameters\n"
206 "Redirect all SGSN bound traffic to default ports on this address (another gtphub)\n"
207 "Remote IP address (v4 or v6)\n"
208 )
209{
210 g_cfg->sgsn_proxy[GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
211 g_cfg->sgsn_proxy[GTPH_PLANE_CTRL].port = GTPH_DEFAULT_CONTROL_PORT;
212 g_cfg->sgsn_proxy[GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
213 g_cfg->sgsn_proxy[GTPH_PLANE_USER].port = GTPH_DEFAULT_USER_PORT;
214 return CMD_SUCCESS;
215}
216
217DEFUN(cfg_gtphub_sgsn_proxy, cfg_gtphub_sgsn_proxy_cmd,
218 "sgsn-proxy " BIND_ARGS,
219 "GTP Hub Parameters\n"
220 "Redirect all SGSN bound traffic to these addresses and ports (another gtphub)\n"
221 BIND_DOCS
222 )
223{
224 g_cfg->sgsn_proxy[GTPH_PLANE_CTRL].addr_str = talloc_strdup(tall_vty_ctx, argv[0]);
225 g_cfg->sgsn_proxy[GTPH_PLANE_CTRL].port = atoi(argv[1]);
226 g_cfg->sgsn_proxy[GTPH_PLANE_USER].addr_str = talloc_strdup(tall_vty_ctx, argv[2]);
227 g_cfg->sgsn_proxy[GTPH_PLANE_USER].port = atoi(argv[3]);
228 return CMD_SUCCESS;
229}
230
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +0100231
232/* Copied from sgsn_vty.h */
233DEFUN(cfg_grx_ggsn, cfg_grx_ggsn_cmd,
234 "grx-dns-add A.B.C.D",
235 "Add DNS server\nIPv4 address\n")
236{
237 struct ares_addr_node *node = talloc_zero(tall_bsc_ctx, struct ares_addr_node);
238 node->family = AF_INET;
239 inet_aton(argv[0], &node->addr.addr4);
240
241 node->next = sgsn->ares_servers;
242 sgsn->ares_servers = node;
243 return CMD_SUCCESS;
244}
245
246
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200247DEFUN(show_gtphub, show_gtphub_cmd, "show gtphub",
248 SHOW_STR "Display information about the GTP hub")
249{
250 vty_out(vty, "gtphub has nothing to say yet%s", VTY_NEWLINE);
251 return CMD_SUCCESS;
252}
253
254
255int gtphub_vty_init(void)
256{
257 install_element_ve(&show_gtphub_cmd);
258
259 install_element(CONFIG_NODE, &cfg_gtphub_cmd);
260 install_node(&gtphub_node, config_write_gtphub);
261 vty_install_default(GTPHUB_NODE);
262
263 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_sgsns_short_cmd);
264 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_sgsns_cmd);
265 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_ggsns_short_cmd);
266 install_element(GTPHUB_NODE, &cfg_gtphub_bind_to_ggsns_cmd);
267 install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_short_cmd);
268 install_element(GTPHUB_NODE, &cfg_gtphub_ggsn_proxy_cmd);
269 install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_short_cmd);
270 install_element(GTPHUB_NODE, &cfg_gtphub_sgsn_proxy_cmd);
Neels Hofmeyrb6c2db52015-11-18 18:11:32 +0100271 install_element(GTPHUB_NODE, &cfg_grx_ggsn_cmd);
Neels Hofmeyrc8a614d2015-09-24 17:32:30 +0200272
273 return 0;
274}
275
276int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file)
277{
278 int rc;
279
280 g_cfg = cfg;
281
282 rc = vty_read_config_file(config_file, NULL);
283 if (rc < 0) {
284 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
285 return rc;
286 }
287
288 return 0;
289}