blob: b6ae5b46c9dbd212dd4c762e0c5aba1e5168e2c7 [file] [log] [blame]
Alexander Couzens6a161492020-07-12 13:45:50 +02001/*! \file gprs_ns2_vty.c
2 * VTY interface for our GPRS Networks Service (NS) implementation. */
3
Alexander Couzensb3060942021-01-25 16:27:33 +01004/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
Alexander Couzens6a161492020-07-12 13:45:50 +02005 * Author: Alexander Couzens <lynxis@fe80.eu>
6 *
7 * All Rights Reserved
8 *
9 * SPDX-License-Identifier: GPL-2.0+
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26#include <stdlib.h>
27#include <unistd.h>
28#include <errno.h>
29#include <stdint.h>
30
31#include <arpa/inet.h>
Alexander Couzens841817e2020-11-19 00:41:29 +010032#include <net/if.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020033
Alexander Couzens6a161492020-07-12 13:45:50 +020034#include <osmocom/core/byteswap.h>
Daniel Willmanndbab7142020-11-18 14:19:56 +010035#include <osmocom/core/fsm.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020036#include <osmocom/core/linuxlist.h>
Alexander Couzensb3060942021-01-25 16:27:33 +010037#include <osmocom/core/msgb.h>
38#include <osmocom/core/rate_ctr.h>
39#include <osmocom/core/select.h>
40#include <osmocom/core/talloc.h>
41#include <osmocom/core/sockaddr_str.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020042#include <osmocom/core/socket.h>
Alexander Couzens841817e2020-11-19 00:41:29 +010043#include <osmocom/gprs/frame_relay.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020044#include <osmocom/gprs/gprs_ns2.h>
45#include <osmocom/gsm/tlv.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020046#include <osmocom/vty/command.h>
47#include <osmocom/vty/logging.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020048#include <osmocom/vty/misc.h>
Alexander Couzensb3060942021-01-25 16:27:33 +010049#include <osmocom/vty/telnet_interface.h>
50#include <osmocom/vty/vty.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020051
52#include "gprs_ns2_internal.h"
53
Daniel Willmanncb3e9b52020-12-02 15:50:22 +010054#define SHOW_NS_STR "Display information about the NS protocol\n"
Alexander Couzensb3060942021-01-25 16:27:33 +010055#define NSVCI_STR "NS Virtual Connection ID (NS-VCI)\n"
56#define DLCI_STR "Data Link connection identifier\n"
Alexander Couzens6a161492020-07-12 13:45:50 +020057
58static struct gprs_ns2_inst *vty_nsi = NULL;
Alexander Couzens841817e2020-11-19 00:41:29 +010059static struct osmo_fr_network *vty_fr_network = NULL;
Alexander Couzensb3060942021-01-25 16:27:33 +010060static struct llist_head binds;
Alexander Couzens6a161492020-07-12 13:45:50 +020061
Alexander Couzensb3060942021-01-25 16:27:33 +010062struct vty_bind {
63 struct llist_head list;
64 const char *name;
65 enum gprs_ns2_ll ll;
66 int dscp;
67 bool accept_ipaccess;
68 bool accept_sns;
69};
70
71/* TODO: this should into osmo timer */
Alexander Couzens6a161492020-07-12 13:45:50 +020072static const struct value_string gprs_ns_timer_strs[] = {
73 { 0, "tns-block" },
74 { 1, "tns-block-retries" },
75 { 2, "tns-reset" },
76 { 3, "tns-reset-retries" },
77 { 4, "tns-test" },
78 { 5, "tns-alive" },
79 { 6, "tns-alive-retries" },
80 { 7, "tsns-prov" },
Harald Welte33c3c062020-12-16 11:59:19 +010081 { 8, "tsns-size-retries" },
82 { 9, "tsns-config-retries" },
Alexander Couzens6a161492020-07-12 13:45:50 +020083 { 0, NULL }
84};
85
Alexander Couzensb3060942021-01-25 16:27:33 +010086const struct value_string vty_fr_role_names[] = {
87 { FR_ROLE_USER_EQUIPMENT, "fr" },
88 { FR_ROLE_NETWORK_EQUIPMENT, "frnet" },
89 { 0, NULL }
90};
91
92const struct value_string vty_ll_names[] = {
93 { GPRS_NS2_LL_FR, "fr" },
94 { GPRS_NS2_LL_FR_GRE, "frgre" },
95 { GPRS_NS2_LL_UDP, "udp" },
96 { 0, NULL }
97};
98
99static struct vty_bind *vty_bind_by_name(const char *name)
Daniel Willmann751977b2020-12-02 18:59:44 +0100100{
Alexander Couzensb3060942021-01-25 16:27:33 +0100101 struct vty_bind *vbind;
102 llist_for_each_entry(vbind, &binds, list) {
103 if (!strncmp(vbind->name, name, strlen(vbind->name)))
104 return vbind;
Daniel Willmann751977b2020-12-02 18:59:44 +0100105 }
Alexander Couzensb3060942021-01-25 16:27:33 +0100106 return NULL;
Daniel Willmann751977b2020-12-02 18:59:44 +0100107}
108
Alexander Couzensb3060942021-01-25 16:27:33 +0100109static struct vty_bind *vty_bind_alloc(const char *name)
Alexander Couzens6a161492020-07-12 13:45:50 +0200110{
Alexander Couzensb3060942021-01-25 16:27:33 +0100111 struct vty_bind *vbind = talloc_zero(vty_nsi, struct vty_bind);
112 if (!vbind)
113 return NULL;
114
115 vbind->name = talloc_strdup(vty_nsi, name);
116 if (!vbind->name) {
117 talloc_free(vbind);
118 return NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +0200119 }
Alexander Couzensb3060942021-01-25 16:27:33 +0100120
121 llist_add(&vbind->list, &binds);
122 return vbind;
123}
124
125static void vty_bind_free(struct vty_bind *vbind)
126{
127 if (!vbind)
128 return;
129
130 llist_del(&vbind->list);
Alexander Couzens6a161492020-07-12 13:45:50 +0200131}
132
133static struct cmd_node ns_node = {
134 L_NS_NODE,
135 "%s(config-ns)# ",
136 1,
137};
138
Alexander Couzens6a161492020-07-12 13:45:50 +0200139DEFUN(cfg_ns, cfg_ns_cmd,
140 "ns",
141 "Configure the GPRS Network Service")
142{
143 vty->node = L_NS_NODE;
144 return CMD_SUCCESS;
145}
146
Alexander Couzensb3060942021-01-25 16:27:33 +0100147DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
148 "timer " NS_TIMERS " <0-65535>",
149 "Network Service Timer\n"
150 NS_TIMERS_HELP "Timer Value\n")
151{
152 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
153 int val = atoi(argv[1]);
154
155 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
156 return CMD_WARNING;
157
158 vty_nsi->timeout[idx] = val;
159
160 return CMD_SUCCESS;
161}
162
163DEFUN(cfg_ns_nsei, cfg_ns_nsei_cmd,
164 "nse <0-65535>",
165 "Persistent NS Entity\n"
166 "NS Entity ID (NSEI)\n"
167 )
168{
169 struct gprs_ns2_nse *nse;
170 uint16_t nsei = atoi(argv[0]);
171
172 nse = gprs_ns2_nse_by_nsei(vty_nsi, nsei);
173 if (!nse) {
174 nse = gprs_ns2_create_nse(vty_nsi, nsei, GPRS_NS2_LL_UNDEF, GPRS_NS2_DIALECT_UNDEF);
175 if (!nse) {
176 vty_out(vty, "Failed to create NSE!%s", VTY_NEWLINE);
177 return CMD_ERR_INCOMPLETE;
178 }
179 nse->persistent = true;
180 }
181
182 if (!nse->persistent) {
183 /* TODO: should the dynamic NSE removed? */
184 vty_out(vty, "A dynamic NSE with the specified NSEI already exists%s", VTY_NEWLINE);
185 return CMD_ERR_INCOMPLETE;
186 }
187
188 vty->node = L_NS_NSE_NODE;
189 vty->index = nse;
190
191 return CMD_SUCCESS;
192}
193
194DEFUN(cfg_no_ns_nsei, cfg_no_ns_nsei_cmd,
195 "no nse <0-65535>",
196 NO_STR
197 "Delete a Persistent NS Entity\n"
198 "NS Entity ID (NSEI)\n"
199 )
200{
201 struct gprs_ns2_nse *nse;
202 uint16_t nsei = atoi(argv[0]);
203
204 nse = gprs_ns2_nse_by_nsei(vty_nsi, nsei);
205 if (!nse) {
206 vty_out(vty, "Can not find NS Entity %s%s", argv[0], VTY_NEWLINE);
207 return CMD_ERR_NOTHING_TODO;
208 }
209
210 if (!nse->persistent) {
211 vty_out(vty, "Ignoring non-persistent NS Entity%s", VTY_NEWLINE);
212 return CMD_WARNING;
213 }
214
215 vty_out(vty, "Deleting NS Entity %u%s", nse->nsei, VTY_NEWLINE);
216 gprs_ns2_free_nse(nse);
217 return CMD_SUCCESS;
218}
219
220/* TODO: add fr/gre */
221DEFUN(cfg_ns_bind, cfg_ns_bind_cmd,
222 "bind (fr|udp) ID",
223 "Binding\n"
224 "Frame Relay\n" "UDP/IP\n"
225 "a unique identifier for this bind to reference NS-VCs\n"
226 )
227{
228 const char *nstype = argv[0];
229 const char *name = argv[1];
230 struct vty_bind *vbind;
231 enum gprs_ns2_ll ll;
232 int rc;
233
234 rc = get_string_value(vty_ll_names, nstype);
235 if (rc < 0)
236 return CMD_WARNING;
237 ll = (enum gprs_ns2_ll) rc;
238
239 if (!osmo_identifier_valid(name)) {
240 vty_out(vty, "Invalid ID. The ID should be only alphanumeric.%s", VTY_NEWLINE);
241 return CMD_WARNING;
242 }
243
244 vbind = vty_bind_by_name(name);
245 if (vbind) {
246 if (vbind->ll != ll) {
247 vty_out(vty, "A bind with the specified ID already exists with a different type (fr|frgre|udp)!%s",
248 VTY_NEWLINE);
249 return CMD_WARNING;
250 }
251 } else {
252 vbind = vty_bind_alloc(name);
253 if (!vbind) {
254 vty_out(vty, "Can not create bind - out of memory%s", VTY_NEWLINE);
255 return CMD_WARNING;
256 }
257 vbind->ll = ll;
258 }
259
260 vty->index = vbind;
261 vty->node = L_NS_BIND_NODE;
262
263 return CMD_SUCCESS;
264}
265
266DEFUN(cfg_no_ns_bind, cfg_no_ns_bind_cmd,
267 "no bind ID",
268 NO_STR
269 "Delete a binding\n"
270 "a unique identifier for this bind to reference NS-VCs\n"
271 )
272{
273 struct vty_bind *vbind;
274 struct gprs_ns2_vc_bind *bind;
275 const char *name = argv[0];
276
277 vbind = vty_bind_by_name(name);
278 if (!vbind) {
279 vty_out(vty, "bind %s does not exist!%s", name, VTY_NEWLINE);
280 return CMD_WARNING;
281 }
282 vty_bind_free(vbind);
283 bind = gprs_ns2_bind_by_name(vty_nsi, name);
284 if (bind)
285 bind->driver->free_bind(bind);
286 return CMD_SUCCESS;
287}
288
289
290static void config_write_vbind(struct vty *vty, struct vty_bind *vbind)
291{
292 struct gprs_ns2_vc_bind *bind;
293 const struct osmo_sockaddr *addr;
294 struct osmo_sockaddr_str addr_str;
295 const char *netif, *frrole_str, *llstr;
296 enum osmo_fr_role frrole;
297
298 llstr = get_value_string_or_null(vty_ll_names, vbind->ll);
299 if (!llstr)
300 return;
301 vty_out(vty, " bind %s %s%s", llstr, vbind->name, VTY_NEWLINE);
302
303 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
304 switch (vbind->ll) {
305 case GPRS_NS2_LL_FR:
306 if (bind) {
307 netif = gprs_ns2_fr_bind_netif(bind);
308 if (!netif)
309 return;
310 frrole = gprs_ns2_fr_bind_role(bind);
311 if ((int) frrole == -1)
312 return;
313 frrole_str = get_value_string_or_null(vty_fr_role_names, frrole);
314 if (netif && frrole_str)
315 vty_out(vty, " fr %s %s%s", netif, frrole_str, VTY_NEWLINE);
316 }
317 break;
318 case GPRS_NS2_LL_UDP:
319 if (bind) {
320 addr = gprs_ns2_ip_bind_sockaddr(bind);
321 if (!osmo_sockaddr_str_from_sockaddr(&addr_str, &addr->u.sas)) {
322 vty_out(vty, " listen %s %u%s", addr_str.ip, addr_str.port,
323 VTY_NEWLINE);
324 }
325 }
326 if (vbind->accept_ipaccess)
327 vty_out(vty, " accept-ipaccess%s", VTY_NEWLINE);
328 if (vbind->dscp)
329 vty_out(vty, " dscp %u%s", vbind->dscp, VTY_NEWLINE);
330 break;
331 default:
332 return;
333 }
334}
335
336static void config_write_nsvc(struct vty *vty, const struct gprs_ns2_vc *nsvc)
337{
338 const char *netif;
339 uint16_t dlci;
340 const struct osmo_sockaddr *addr;
341 struct osmo_sockaddr_str addr_str;
342
343 switch (nsvc->nse->ll) {
344 case GPRS_NS2_LL_UNDEF:
345 break;
346 case GPRS_NS2_LL_UDP:
347 switch (nsvc->nse->dialect) {
348 case GPRS_NS2_DIALECT_IPACCESS:
349 addr = gprs_ns2_ip_vc_remote(nsvc);
350 if (!addr)
351 break;
352 if (osmo_sockaddr_str_from_sockaddr(&addr_str, &addr->u.sas))
353 break;
354 vty_out(vty, " nsvc ipa %s %s %u nsvci %u%s",
355 nsvc->bind->name, addr_str.ip, addr_str.port,
356 nsvc->nsvci, VTY_NEWLINE);
357 break;
358 case GPRS_NS2_DIALECT_STATIC_ALIVE:
359 addr = gprs_ns2_ip_vc_remote(nsvc);
360 if (!addr)
361 break;
362 if (osmo_sockaddr_str_from_sockaddr(&addr_str, &addr->u.sas))
363 break;
364 vty_out(vty, " nsvc udp %s %s %u%s",
365 nsvc->bind->name, addr_str.ip, addr_str.port, VTY_NEWLINE);
366 break;
367 default:
368 break;
369 }
370 break;
371 case GPRS_NS2_LL_FR:
372 netif = gprs_ns2_fr_bind_netif(nsvc->bind);
373 if (!netif)
374 break;
375 dlci = gprs_ns2_fr_nsvc_dlci(nsvc);
376 if (!dlci)
377 break;
378 OSMO_ASSERT(nsvc->nsvci_is_valid);
379 vty_out(vty, " nsvc fr %s dlci %u nsvci %u%s",
380 netif, dlci, nsvc->nsvci, VTY_NEWLINE);
381 break;
382 case GPRS_NS2_LL_FR_GRE:
383 break;
384 }
385}
386
387static void _config_write_ns_nse(struct vty *vty, struct gprs_ns2_nse *nse)
388{
389 struct gprs_ns2_vc *nsvc;
390
391 vty_out(vty, " nse %u%s", nse->nsei, VTY_NEWLINE);
392 switch (nse->dialect) {
393 case GPRS_NS2_DIALECT_SNS:
394 ns2_sns_write_vty(vty, nse);
395 break;
396 default:
397 llist_for_each_entry(nsvc, &nse->nsvc, list) {
398 config_write_nsvc(vty, nsvc);
399 }
400 break;
401 }
402}
403
404static int config_write_ns(struct vty *vty)
405{
406 unsigned int i;
407
408 vty_out(vty, "ns%s", VTY_NEWLINE);
409
410 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
411 vty_out(vty, " timer %s %u%s",
412 get_value_string(gprs_ns_timer_strs, i),
413 vty_nsi->timeout[i], VTY_NEWLINE);
414
415 return 0;
416}
417
418static int config_write_ns_nse(struct vty *vty)
419{
420 struct gprs_ns2_nse *nse;
421
422 llist_for_each_entry(nse, &vty_nsi->nse, list) {
423 if (!nse->persistent)
424 continue;
425
426 _config_write_ns_nse(vty, nse);
427 }
428
429 return 0;
430}
431
432static int config_write_ns_bind(struct vty *vty)
433{
434 struct vty_bind *vbind;
435
436 llist_for_each_entry(vbind, &binds, list) {
437 config_write_vbind(vty, vbind);
438 }
439
440 return 0;
441}
442
443static struct cmd_node ns_bind_node = {
444 L_NS_BIND_NODE,
445 "%s(config-ns-bind)# ",
446 1,
447};
448
449DEFUN(cfg_ns_bind_listen, cfg_ns_bind_listen_cmd,
450 "listen " VTY_IPV46_CMD " <1-65535>",
451 "Binding\n"
452 "IPv4 Address\n" "IPv6 Address\n"
453 "Port\n"
454 )
455{
456 struct vty_bind *vbind = vty->index;
457 struct gprs_ns2_vc_bind *bind;
458
459 const char *addr_str = argv[0];
460 unsigned int port = atoi(argv[1]);
461 struct osmo_sockaddr_str sockaddr_str;
462 struct osmo_sockaddr sockaddr;
463
464 if (vbind->ll != GPRS_NS2_LL_UDP) {
465 vty_out(vty, "listen can be only used with UDP bind%s",
466 VTY_NEWLINE);
467 return CMD_WARNING;
468 }
469
470 if (osmo_sockaddr_str_from_str(&sockaddr_str, addr_str, port)) {
471 vty_out(vty, "Can not parse the Address %s %s%s", argv[0], argv[1], VTY_NEWLINE);
472 return CMD_WARNING;
473 }
474 osmo_sockaddr_str_to_sockaddr(&sockaddr_str, &sockaddr.u.sas);
475 if (gprs_ns2_ip_bind_by_sockaddr(vty_nsi, &sockaddr)) {
476 vty_out(vty, "A bind with the specified address already exists!%s", VTY_NEWLINE);
477 return CMD_WARNING;
478 }
479
480 if (gprs_ns2_ip_bind(vty_nsi, vbind->name, &sockaddr, vbind->dscp, &bind) != 0) {
481 vty_out(vty, "Failed to create the bind!%s", VTY_NEWLINE);
482 return CMD_WARNING;
483 }
484
485 bind->accept_ipaccess = vbind->accept_ipaccess;
486 bind->accept_sns = vbind->accept_sns;
487
488 return CMD_SUCCESS;
489}
490
491DEFUN(cfg_no_ns_bind_listen, cfg_no_ns_bind_listen_cmd,
492 "no listen",
493 NO_STR
494 "Delete a IP/Port assignment\n"
495 )
496{
497 struct vty_bind *vbind = vty->index;
498 struct gprs_ns2_vc_bind *bind;
499
500 if (vbind->ll != GPRS_NS2_LL_UDP) {
501 vty_out(vty, "no listen can be only used with UDP bind%s", VTY_NEWLINE);
502 return CMD_WARNING;
503 }
504
505 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
506 if (!bind)
507 return CMD_ERR_NOTHING_TODO;
508
509 OSMO_ASSERT(bind->ll != GPRS_NS2_LL_UDP);
510 bind->driver->free_bind(bind);
511 return CMD_SUCCESS;
512}
513
514DEFUN(cfg_ns_bind_dscp, cfg_ns_bind_dscp_cmd,
515 "dscp <0-255>",
516 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
517{
518 struct vty_bind *vbind = vty->index;
519 struct gprs_ns2_vc_bind *bind;
520 uint16_t dscp = atoi(argv[0]);
521
522 if (vbind->ll != GPRS_NS2_LL_UDP) {
523 vty_out(vty, "dscp can be only used with UDP bind%s",
524 VTY_NEWLINE);
525 return CMD_WARNING;
526 }
527
528 vbind->dscp = dscp;
529 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
530 if (bind)
531 gprs_ns2_ip_bind_set_dscp(bind, dscp);
532
533 return CMD_SUCCESS;
534}
535
536DEFUN(cfg_no_ns_bind_dscp, cfg_no_ns_bind_dscp_cmd,
537 "no dscp",
538 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
539{
540 struct vty_bind *vbind = vty->index;
541 struct gprs_ns2_vc_bind *bind;
542 uint16_t dscp = 0;
543
544 if (vbind->ll != GPRS_NS2_LL_UDP) {
545 vty_out(vty, "dscp can be only used with UDP bind%s",
546 VTY_NEWLINE);
547 return CMD_WARNING;
548 }
549
550 vbind->dscp = dscp;
551 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
552 if (bind)
553 gprs_ns2_ip_bind_set_dscp(bind, dscp);
554
555 return CMD_SUCCESS;
556}
557
558DEFUN(cfg_ns_bind_ipaccess, cfg_ns_bind_ipaccess_cmd,
559 "accept-ipaccess",
560 "Allow to create dynamic NS Entity by NS Reset PDU on UDP (ip.access style)\n"
561 )
562{
563 struct vty_bind *vbind = vty->index;
564 struct gprs_ns2_vc_bind *bind;
565
566 if (vbind->ll != GPRS_NS2_LL_UDP) {
567 vty_out(vty, "accept-ipaccess can be only used with UDP bind%s",
568 VTY_NEWLINE);
569 return CMD_WARNING;
570 }
571
572 vbind->accept_ipaccess = true;
573 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
574 if (bind)
575 bind->accept_ipaccess = true;
576
577 return CMD_SUCCESS;
578}
579
580DEFUN(cfg_no_ns_bind_ipaccess, cfg_no_ns_bind_ipaccess_cmd,
581 "no accept-ipaccess",
582 NO_STR
583 "Reject NS Reset PDU on UDP (ip.access style)\n"
584 )
585{
586 struct vty_bind *vbind = vty->index;
587 struct gprs_ns2_vc_bind *bind;
588
589 if (vbind->ll != GPRS_NS2_LL_UDP) {
590 vty_out(vty, "no accept-ipaccess can be only used with UDP bind%s",
591 VTY_NEWLINE);
592 return CMD_WARNING;
593 }
594
595 vbind->accept_ipaccess = false;
596 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
597 if (bind)
598 bind->accept_ipaccess = false;
599
600 return CMD_SUCCESS;
601}
602
603
604DEFUN(cfg_ns_bind_fr, cfg_ns_bind_fr_cmd,
605 "fr NETIF (fr|frnet)",
606 "frame relay\n"
607 IFNAME_STR
608 "fr (user) is used by BSS or SGSN attached to UNI of a FR network\n"
609 "frnet (network) is used by SGSN if BSS is directly attached\n"
610 )
611{
612 struct vty_bind *vbind = vty->index;
613 struct gprs_ns2_vc_bind *bind;
614 const char *netif = argv[0];
615 const char *role = argv[1];
616
617 int rc = 0;
618 enum osmo_fr_role frrole;
619
620 if (vbind->ll != GPRS_NS2_LL_FR) {
621 vty_out(vty, "fr can be only used with frame relay bind%s", VTY_NEWLINE);
622 return CMD_WARNING;
623 }
624
625 if (!strcmp(role, "fr"))
626 frrole = FR_ROLE_USER_EQUIPMENT;
627 else if (!strcmp(role, "frnet"))
628 frrole = FR_ROLE_NETWORK_EQUIPMENT;
629 else
630 return CMD_WARNING;
631
632 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
633 if (bind) {
634 vty_out(vty, "Interface %s already used.%s", netif, VTY_NEWLINE);
635 return CMD_WARNING;
636 }
637
638 rc = gprs_ns2_fr_bind(vty_nsi, vbind->name, netif, vty_fr_network, frrole, &bind);
639 if (rc < 0) {
640 LOGP(DLNS, LOGL_ERROR, "Failed to bind interface %s on fr. Err: %d\n", netif, rc);
641 return CMD_WARNING;
642 }
643
644 return CMD_SUCCESS;
645}
646
647DEFUN(cfg_no_ns_bind_fr, cfg_no_ns_bind_fr_cmd,
648 "no fr NETIF",
649 NO_STR
650 "Delete a frame relay link\n"
651 "Delete a frame relay link\n"
652 IFNAME_STR
653 )
654{
655 struct vty_bind *vbind = vty->index;
656 struct gprs_ns2_vc_bind *bind;
657 const char *netif = argv[0];
658
659 if (vbind->ll != GPRS_NS2_LL_FR) {
660 vty_out(vty, "fr can be only used with frame relay bind%s",
661 VTY_NEWLINE);
662 return CMD_WARNING;
663 }
664
665 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
666 if (!bind) {
667 vty_out(vty, "Interface not found.%s", VTY_NEWLINE);
668 return CMD_WARNING;
669 }
670
671 if (strcmp(bind->name, vbind->name)) {
672 vty_out(vty, "The specified interface is not bound to this bind.%s", VTY_NEWLINE);
673 return CMD_WARNING;
674 }
675
676 bind->driver->free_bind(bind);
677 return CMD_SUCCESS;
678}
679
680
681static struct cmd_node ns_nse_node = {
682 L_NS_NSE_NODE,
683 "%s(config-ns-nse)# ",
684 1,
685};
686
687DEFUN(cfg_ns_nse_nsvc_fr, cfg_ns_nse_nsvc_fr_cmd,
688 "nsvc fr NETIF dlci <16-1007> nsvci <0-65535>",
689 "NS Virtual Connection\n"
690 "frame relay\n"
691 "frame relay interface. Must be registered via fr vty\n"
692 NSVCI_STR
693 NSVCI_STR
694 DLCI_STR
695 DLCI_STR
696 )
697{
698 struct gprs_ns2_vc_bind *bind;
699 struct gprs_ns2_vc *nsvc;
700 struct gprs_ns2_nse *nse = vty->index;
701 const char *netif = argv[0];
702 uint16_t dlci = atoi(argv[1]);
703 uint16_t nsvci = atoi(argv[2]);
704 bool dialect_modified = false;
705 bool ll_modified = false;
706
707 if (nse->ll != GPRS_NS2_LL_FR && nse->ll != GPRS_NS2_LL_UNDEF) {
708 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
709 goto err;
710 }
711
712 if (nse->dialect != GPRS_NS2_DIALECT_STATIC_RESETBLOCK && nse->dialect != GPRS_NS2_DIALECT_UNDEF) {
713 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
714 goto err;
715 }
716
717 if (nse->ll == GPRS_NS2_LL_UNDEF) {
718 nse->ll = GPRS_NS2_LL_FR;
719 ll_modified = true;
720 }
721
722 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
723 nse->dialect = GPRS_NS2_DIALECT_STATIC_RESETBLOCK;
724 dialect_modified = true;
725 }
726
727
728 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
729 if (!bind) {
730 vty_out(vty, "Can not find fr interface \"%s\". Please configure it via fr vty.%s",
731 netif, VTY_NEWLINE);
732 goto err;
733 }
734
735 if (gprs_ns2_fr_nsvc_by_dlci(bind, dlci)) {
736 vty_out(vty, "A NS-VC with the specified DLCI already exist!%s", VTY_NEWLINE);
737 goto err;
738 }
739
740 if (gprs_ns2_nsvc_by_nsvci(vty_nsi, nsvci)) {
741 vty_out(vty, "A NS-VC with the specified NS-VCI already exist!%s", VTY_NEWLINE);
742 goto err;
743 }
744
745 nsvc = gprs_ns2_fr_connect(bind, nse, nsvci, dlci);
746 if (!nsvc) {
747 /* Could not create NS-VC, connect failed */
748 vty_out(vty, "Failed to create the NS-VC%s", VTY_NEWLINE);
749 goto err;
750 }
751 nsvc->persistent = true;
752 return CMD_SUCCESS;
753
754err:
755 if (ll_modified)
756 nse->ll = GPRS_NS2_LL_UNDEF;
757 if (dialect_modified)
758 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
759
760 return CMD_WARNING;
761}
762
763DEFUN(cfg_no_ns_nse_nsvc_fr_dlci, cfg_no_ns_nse_nsvc_fr_dlci_cmd,
764 "no nsvc fr NETIF dlci <16-1007>",
765 NO_STR
766 "Delete frame relay NS-VC\n"
767 "frame relay\n"
768 "frame relay interface. Must be registered via fr vty\n"
769 DLCI_STR
770 DLCI_STR
771 )
772{
773 struct gprs_ns2_vc_bind *bind;
774 struct gprs_ns2_vc *nsvc;
775 struct gprs_ns2_nse *nse = vty->index;
776 const char *netif = argv[0];
777 uint16_t dlci = atoi(argv[1]);
778
779 if (nse->ll != GPRS_NS2_LL_FR) {
780 vty_out(vty, "This NSE doesn't support frame relay.%s", VTY_NEWLINE);
781 return CMD_WARNING;
782 }
783
784 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
785 if (!bind) {
786 vty_out(vty, "Can not find fr interface \"%s\"%s",
787 netif, VTY_NEWLINE);
788 return CMD_ERR_NOTHING_TODO;
789 }
790
791 nsvc = gprs_ns2_fr_nsvc_by_dlci(bind, dlci);
792 if (!nsvc) {
793 vty_out(vty, "Can not find a NS-VC on fr interface %s with dlci %u%s",
794 netif, dlci, VTY_NEWLINE);
795 return CMD_WARNING;
796 }
797
798 if (nse != nsvc->nse) {
799 vty_out(vty, "The specified NS-VC is not a part of the NSE %u!%s"
800 "To remove this NS-VC go to the vty node 'nse %u'%s",
801 nse->nsei, VTY_NEWLINE,
802 nsvc->nse->nsei, VTY_NEWLINE);
803 return CMD_WARNING;
804 }
805
806 gprs_ns2_free_nsvc(nsvc);
807 if (llist_empty(&nse->nsvc)) {
808 nse->ll = GPRS_NS2_LL_UNDEF;
809 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
810 }
811
812 return CMD_SUCCESS;
813}
814
815DEFUN(cfg_no_ns_nse_nsvci, cfg_no_ns_nse_nsvci_cmd,
816 "no nsvc nsvci <0-65535>",
817 NO_STR
818 "Delete NSVC\n"
819 NSVCI_STR
820 NSVCI_STR
821 )
822{
823 struct gprs_ns2_vc *nsvc;
824 struct gprs_ns2_nse *nse = vty->index;
825 uint16_t nsvci = atoi(argv[0]);
826
827 switch (nse->dialect) {
828 case GPRS_NS2_DIALECT_SNS:
829 case GPRS_NS2_DIALECT_STATIC_ALIVE:
830 vty_out(vty, "NSE doesn't support NSVCI.%s", VTY_NEWLINE);
831 return CMD_WARNING;
832 case GPRS_NS2_DIALECT_UNDEF:
833 vty_out(vty, "No NSVCs configured%s", VTY_NEWLINE);
834 return CMD_WARNING;
835 case GPRS_NS2_DIALECT_IPACCESS:
836 case GPRS_NS2_DIALECT_STATIC_RESETBLOCK:
837 break;
838 }
839
840 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, nsvci);
841 if (!nsvc) {
842 vty_out(vty, "Can not find NS-VC with NS-VCI %u%s", nsvci, VTY_NEWLINE);
843 return CMD_WARNING;
844 }
845
846 if (nse != nsvc->nse) {
847 vty_out(vty, "NS-VC with NS-VCI %u is not part of this NSE!%s",
848 nsvci, VTY_NEWLINE);
849 return CMD_WARNING;
850 }
851
852 gprs_ns2_free_nsvc(nsvc);
853 if (llist_empty(&nse->nsvc)) {
854 nse->ll = GPRS_NS2_LL_UNDEF;
855 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
856 }
857
858 return CMD_SUCCESS;
859}
860
861DEFUN(cfg_ns_nse_nsvc_udp, cfg_ns_nse_nsvc_udp_cmd,
862 "nsvc udp BIND " VTY_IPV46_CMD " <1-65535>",
863 "NS Virtual Connection\n"
864 "NS over UDP\n"
865 "A unique bind identifier created by ns bind\n"
866 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
867 "Remote UDP Port\n"
868 )
869{
870 struct gprs_ns2_vc_bind *bind;
871 struct gprs_ns2_vc *nsvc;
872 struct gprs_ns2_nse *nse = vty->index;
873 bool dialect_modified = false;
874 bool ll_modified = false;
875
876 const char *bind_name = argv[0];
877 struct osmo_sockaddr_str remote_str;
878 struct osmo_sockaddr remote;
879 uint16_t port = atoi(argv[2]);
880
881 if (nse->ll == GPRS_NS2_LL_UNDEF) {
882 nse->ll = GPRS_NS2_LL_UDP;
883 ll_modified = true;
884 }
885
886 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
887 nse->dialect = GPRS_NS2_DIALECT_STATIC_ALIVE;
888 dialect_modified = true;
889 }
890
891 if (nse->ll != GPRS_NS2_LL_UDP) {
892 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
893 goto err;
894 }
895
896 if (nse->dialect != GPRS_NS2_DIALECT_STATIC_ALIVE) {
897 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
898 goto err;
899 }
900
901 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
902 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
903 goto err;
904 }
905
906 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
907 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
908 goto err;
909 }
910
911 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
912 if (!bind) {
913 vty_out(vty, "Can not find bind with name %s%s",
914 bind_name, VTY_NEWLINE);
915 goto err;
916 }
917
918 if (bind->ll != GPRS_NS2_LL_UDP) {
919 vty_out(vty, "Bind %s is not an UDP bind.%s",
920 bind_name, VTY_NEWLINE);
921 goto err;
922 }
923
924 nsvc = gprs_ns2_ip_connect(bind, &remote, nse, 0);
925 if (!nsvc) {
926 vty_out(vty, "Can not create NS-VC.%s", VTY_NEWLINE);
927 goto err;
928 }
929 nsvc->persistent = true;
930
931 return CMD_SUCCESS;
932
933err:
934 if (ll_modified)
935 nse->ll = GPRS_NS2_LL_UNDEF;
936 if (dialect_modified)
937 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
938 return CMD_WARNING;
939}
940
941DEFUN(cfg_no_ns_nse_nsvc_udp, cfg_no_ns_nse_nsvc_udp_cmd,
942 "no nsvc udp BIND " VTY_IPV46_CMD " <1-65535>",
943 NO_STR
944 "Delete a NS Virtual Connection\n"
945 "NS over UDP\n"
946 "A unique bind identifier created by ns bind\n"
947 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
948 "Remote UDP Port\n"
949 )
950{
951 struct gprs_ns2_vc_bind *bind;
952 struct gprs_ns2_vc *nsvc;
953 struct gprs_ns2_nse *nse = vty->index;
954 const char *bind_name = argv[0];
955 struct osmo_sockaddr_str remote_str;
956 struct osmo_sockaddr remote;
957 uint16_t port = atoi(argv[2]);
958
959 if (nse->ll != GPRS_NS2_LL_UDP) {
960 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
961 return CMD_WARNING;
962 }
963
964 if (nse->dialect != GPRS_NS2_DIALECT_STATIC_ALIVE) {
965 vty_out(vty, "This NSE doesn't support UDP with dialect static alive.%s", VTY_NEWLINE);
966 return CMD_WARNING;
967 }
968
969 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
970 if (!bind) {
971 vty_out(vty, "Can not find bind with name %s%s",
972 bind_name, VTY_NEWLINE);
973 return CMD_WARNING;
974 }
975
976 if (bind->ll != GPRS_NS2_LL_UDP) {
977 vty_out(vty, "Bind %s is not an UDP bind.%s",
978 bind_name, VTY_NEWLINE);
979 return CMD_WARNING;
980 }
981
982 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
983 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
984 return CMD_WARNING;
985 }
986
987 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
988 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
989 return CMD_WARNING;
990 }
991
992 nsvc = gprs_ns2_nsvc_by_sockaddr_bind(bind, &remote);
993 if (!nsvc) {
994 vty_out(vty, "Can not find NS-VC with remote %s:%u%s",
995 remote_str.ip, remote_str.port, VTY_NEWLINE);
996 return CMD_WARNING;
997 }
998
999 if (!nsvc->persistent) {
1000 vty_out(vty, "NS-VC with remote %s:%u is a dynamic NS-VC. Not configured by vty.%s",
1001 remote_str.ip, remote_str.port, VTY_NEWLINE);
1002 return CMD_WARNING;
1003 }
1004
1005 if (nsvc->nse != nse) {
1006 vty_out(vty, "NS-VC is not part of this NSE!%s", VTY_NEWLINE);
1007 return CMD_WARNING;
1008 }
1009
1010 gprs_ns2_free_nsvc(nsvc);
1011 if (llist_empty(&nse->nsvc)) {
1012 nse->ll = GPRS_NS2_LL_UNDEF;
1013 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
1014 }
1015
1016 return CMD_SUCCESS;
1017}
1018
1019DEFUN(cfg_ns_nse_nsvc_ipa, cfg_ns_nse_nsvc_ipa_cmd,
1020 "nsvc ipa BIND " VTY_IPV46_CMD " <1-65535> nsvci <0-65535>" ,
1021 "NS Virtual Connection\n"
1022 "NS over UDP ip.access style (uses RESET/BLOCK)\n"
1023 "A unique bind identifier created by ns bind\n"
1024 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1025 "Remote UDP Port\n"
1026 NSVCI_STR
1027 NSVCI_STR
1028 )
1029{
1030 struct gprs_ns2_vc_bind *bind;
1031 struct gprs_ns2_vc *nsvc;
1032 struct gprs_ns2_nse *nse = vty->index;
1033 bool dialect_modified = false;
1034 bool ll_modified = false;
1035
1036 const char *bind_name = argv[0];
1037 struct osmo_sockaddr_str remote_str;
1038 struct osmo_sockaddr remote;
1039 uint16_t port = atoi(argv[2]);
1040 uint16_t nsvci = atoi(argv[3]);
1041
1042 if (nse->ll == GPRS_NS2_LL_UNDEF) {
1043 nse->ll = GPRS_NS2_LL_UDP;
1044 ll_modified = true;
1045 }
1046
1047 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
1048 nse->dialect = GPRS_NS2_DIALECT_IPACCESS;
1049 dialect_modified = true;
1050 }
1051
1052 if (nse->ll != GPRS_NS2_LL_UDP) {
1053 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
1054 goto err;
1055 }
1056
1057 if (nse->dialect != GPRS_NS2_DIALECT_IPACCESS) {
1058 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
1059 goto err;
1060 }
1061
1062 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
1063 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1064 goto err;
1065 }
1066
1067 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1068 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1069 goto err;
1070 }
1071
1072 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
1073 if (!bind) {
1074 vty_out(vty, "Can not find bind with name %s%s",
1075 bind_name, VTY_NEWLINE);
1076 goto err;
1077 }
1078
1079 if (bind->ll != GPRS_NS2_LL_UDP) {
1080 vty_out(vty, "Bind %s is not an UDP bind.%s",
1081 bind_name, VTY_NEWLINE);
1082 goto err;
1083 }
1084
1085 nsvc = gprs_ns2_ip_connect(bind, &remote, nse, nsvci);
1086 if (!nsvc) {
1087 vty_out(vty, "Can not create NS-VC.%s", VTY_NEWLINE);
1088 goto err;
1089 }
1090 nsvc->persistent = true;
1091
1092 return CMD_SUCCESS;
1093
1094err:
1095 if (ll_modified)
1096 nse->ll = GPRS_NS2_LL_UNDEF;
1097 if (dialect_modified)
1098 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
1099 return CMD_WARNING;
1100}
1101
1102DEFUN(cfg_no_ns_nse_nsvc_ipa, cfg_no_ns_nse_nsvc_ipa_cmd,
1103 "no nsvc ipa BIND " VTY_IPV46_CMD " <1-65535> nsvci <0-65535>",
1104 NO_STR
1105 "Delete a NS Virtual Connection\n"
1106 "NS over UDP\n"
1107 "A unique bind identifier created by ns bind\n"
1108 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1109 "Remote UDP Port\n"
1110 NSVCI_STR
1111 NSVCI_STR
1112 )
1113{
1114 struct gprs_ns2_vc_bind *bind;
1115 struct gprs_ns2_vc *nsvc;
1116 struct gprs_ns2_nse *nse = vty->index;
1117 const char *bind_name = argv[0];
1118 struct osmo_sockaddr_str remote_str;
1119 struct osmo_sockaddr remote;
1120 uint16_t port = atoi(argv[2]);
1121 uint16_t nsvci = atoi(argv[3]);
1122
1123 if (nse->ll != GPRS_NS2_LL_UDP) {
1124 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
1125 return CMD_WARNING;
1126 }
1127
1128 if (nse->dialect != GPRS_NS2_DIALECT_IPACCESS) {
1129 vty_out(vty, "This NSE doesn't support UDP with dialect ipaccess.%s", VTY_NEWLINE);
1130 return CMD_WARNING;
1131 }
1132
1133 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
1134 if (!bind) {
1135 vty_out(vty, "Can not find bind with name %s%s",
1136 bind_name, VTY_NEWLINE);
1137 return CMD_WARNING;
1138 }
1139
1140 if (bind->ll != GPRS_NS2_LL_UDP) {
1141 vty_out(vty, "Bind %s is not an UDP bind.%s",
1142 bind_name, VTY_NEWLINE);
1143 return CMD_WARNING;
1144 }
1145
1146 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
1147 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1148 return CMD_WARNING;
1149 }
1150
1151 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1152 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1153 return CMD_WARNING;
1154 }
1155
1156 nsvc = gprs_ns2_nsvc_by_sockaddr_bind(bind, &remote);
1157 if (!nsvc) {
1158 vty_out(vty, "Can not find NS-VC with remote %s:%u%s",
1159 remote_str.ip, remote_str.port, VTY_NEWLINE);
1160 return CMD_WARNING;
1161 }
1162
1163 if (!nsvc->persistent) {
1164 vty_out(vty, "NS-VC with remote %s:%u is a dynamic NS-VC. Not configured by vty.%s",
1165 remote_str.ip, remote_str.port, VTY_NEWLINE);
1166 return CMD_WARNING;
1167 }
1168
1169 if (nsvc->nse != nse) {
1170 vty_out(vty, "NS-VC is not part of this NSE!%s", VTY_NEWLINE);
1171 return CMD_WARNING;
1172 }
1173
1174 if (!nsvc->nsvci_is_valid) {
1175 vty_out(vty, "NS-VC doesn't have a nsvci!%s", VTY_NEWLINE);
1176 return CMD_WARNING;
1177 }
1178
1179 if (nsvc->nsvci != nsvci) {
1180 vty_out(vty, "NS-VC has a different nsvci (%u)!%s",
1181 nsvc->nsvci, VTY_NEWLINE);
1182 return CMD_WARNING;
1183 }
1184
1185 gprs_ns2_free_nsvc(nsvc);
1186 if (llist_empty(&nse->nsvc)) {
1187 nse->ll = GPRS_NS2_LL_UNDEF;
1188 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
1189 }
1190
1191 return CMD_SUCCESS;
1192}
1193
1194DEFUN(cfg_ns_nse_ip_sns, cfg_ns_nse_ip_sns_cmd,
1195 "ip-sns " VTY_IPV46_CMD " <1-65535>",
1196 "SNS Initial Endpoint\n"
1197 "SGSN IPv4 Address\n" "SGSN IPv6 Address\n"
1198 "SGSN UDP Port\n"
1199 )
1200{
1201 struct gprs_ns2_nse *nse = vty->index;
1202 bool dialect_modified = false;
1203 bool ll_modified = false;
1204 int rc;
1205
1206 /* argv[0] */
1207 struct osmo_sockaddr_str remote_str;
1208 struct osmo_sockaddr remote;
1209 uint16_t port = atoi(argv[1]);
1210
1211 if (nse->ll == GPRS_NS2_LL_UNDEF) {
1212 nse->ll = GPRS_NS2_LL_UDP;
1213 ll_modified = true;
1214 }
1215
1216 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
1217 char sns[16];
1218 snprintf(sns, sizeof(sns), "NSE%05u-SNS", nse->nsei);
1219 nse->bss_sns_fi = ns2_sns_bss_fsm_alloc(nse, sns);
1220 if (!nse->bss_sns_fi)
1221 goto err;
1222 nse->dialect = GPRS_NS2_DIALECT_SNS;
1223 dialect_modified = true;
1224 }
1225
1226 if (nse->ll != GPRS_NS2_LL_UDP) {
1227 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
1228 goto err;
1229 }
1230
1231 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
1232 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
1233 goto err;
1234 }
1235
1236 if (osmo_sockaddr_str_from_str(&remote_str, argv[0], port)) {
1237 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1238 goto err;
1239 }
1240
1241 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1242 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1243 goto err;
1244 }
1245
1246 rc = gprs_ns2_sns_add_endpoint(nse, &remote);
1247 switch (rc) {
1248 case 0:
1249 return CMD_SUCCESS;
1250 case -EADDRINUSE:
1251 vty_out(vty, "Specified SNS endpoint already part of the NSE.%s", VTY_NEWLINE);
1252 return CMD_WARNING;
1253 default:
1254 vty_out(vty, "Can not add specified SNS endpoint.%s", VTY_NEWLINE);
1255 return CMD_WARNING;
1256 }
1257
1258err:
1259 if (ll_modified)
1260 nse->ll = GPRS_NS2_LL_UNDEF;
1261 if (dialect_modified)
1262 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
1263 return CMD_WARNING;
1264}
1265
1266DEFUN(cfg_no_ns_nse_ip_sns, cfg_no_ns_nse_ip_sns_cmd,
1267 "no ip-sns " VTY_IPV46_CMD " <1-65535>",
1268 NO_STR
1269 "Delete a SNS Initial Endpoint\n"
1270 "SGSN IPv4 Address\n" "SGSN IPv6 Address\n"
1271 "SGSN UDP Port\n"
1272 )
1273{
1274 struct gprs_ns2_nse *nse = vty->index;
1275 struct osmo_sockaddr_str remote_str; /* argv[0] */
1276 struct osmo_sockaddr remote;
1277 uint16_t port = atoi(argv[1]);
1278 int count;
1279
1280 if (nse->ll != GPRS_NS2_LL_UDP) {
1281 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
1282 return CMD_WARNING;
1283 }
1284
1285 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
1286 vty_out(vty, "This NSE doesn't support UDP with dialect ip-sns.%s", VTY_NEWLINE);
1287 return CMD_WARNING;
1288 }
1289
1290 if (osmo_sockaddr_str_from_str(&remote_str, argv[0], port)) {
1291 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1292 return CMD_WARNING;
1293 }
1294
1295 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1296 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1297 return CMD_WARNING;
1298 }
1299
1300 if (gprs_ns2_sns_del_endpoint(nse, &remote)) {
1301 vty_out(vty, "Can not remove specified SNS endpoint.%s", VTY_NEWLINE);
1302 return CMD_WARNING;
1303 }
1304
1305 count = gprs_ns2_sns_count(nse);
1306 if (count > 0) {
1307 /* there are other sns endpoints */
1308 return CMD_SUCCESS;
1309 } else if (count < 0) {
1310 OSMO_ASSERT(0);
1311 } else {
1312 /* clean up nse to allow other nsvc commands */
1313 osmo_fsm_inst_term(nse->bss_sns_fi, OSMO_FSM_TERM_REQUEST, NULL);
1314 nse->bss_sns_fi = NULL;
1315 nse->ll = GPRS_NS2_LL_UNDEF;
1316 nse->dialect = GPRS_NS2_DIALECT_UNDEF;
1317 }
1318
1319 return CMD_SUCCESS;
1320}
1321
1322
1323/* non-config commands */
Alexander Couzens6a161492020-07-12 13:45:50 +02001324static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)
1325{
Harald Weltedc2d0802020-12-01 18:17:28 +01001326 char nsvci_str[32];
1327
1328 if (nsvc->nsvci_is_valid)
1329 snprintf(nsvci_str, sizeof(nsvci_str), "%05u", nsvc->nsvci);
1330 else
1331 snprintf(nsvci_str, sizeof(nsvci_str), "none");
1332
1333 vty_out(vty, " NSVCI %s: %s %s data_weight=%u sig_weight=%u %s%s", nsvci_str,
1334 osmo_fsm_inst_state_name(nsvc->fi),
1335 nsvc->persistent ? "PERSIST" : "DYNAMIC",
1336 nsvc->data_weight, nsvc->sig_weight,
1337 gprs_ns2_ll_str(nsvc), VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +02001338
1339 if (stats) {
Harald Welte7aa60992020-12-01 17:53:17 +01001340 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
1341 vty_out_stat_item_group(vty, " ", nsvc->statg);
Alexander Couzens6a161492020-07-12 13:45:50 +02001342 }
1343}
1344
1345static void dump_nse(struct vty *vty, const struct gprs_ns2_nse *nse, bool stats, bool persistent_only)
1346{
1347 struct gprs_ns2_vc *nsvc;
1348
Harald Welte0ff12ad2020-12-01 17:51:07 +01001349 vty_out(vty, "NSEI %05u: %s, %s%s", nse->nsei, gprs_ns2_lltype_str(nse->ll),
1350 nse->alive ? "ALIVE" : "DEAD", VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +02001351
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001352 ns2_sns_dump_vty(vty, " ", nse, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +02001353 llist_for_each_entry(nsvc, &nse->nsvc, list) {
1354 if (persistent_only) {
1355 if (nsvc->persistent)
1356 dump_nsvc(vty, nsvc, stats);
1357 } else {
1358 dump_nsvc(vty, nsvc, stats);
1359 }
1360 }
1361}
1362
Alexander Couzens22f34712020-10-02 02:34:39 +02001363static void dump_bind(struct vty *vty, const struct gprs_ns2_vc_bind *bind, bool stats)
1364{
1365 if (bind->dump_vty)
1366 bind->dump_vty(bind, vty, stats);
1367}
1368
Harald Welte2fce19a2020-12-01 17:52:55 +01001369static void dump_ns_bind(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats)
Alexander Couzens6a161492020-07-12 13:45:50 +02001370{
Alexander Couzens22f34712020-10-02 02:34:39 +02001371 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6a161492020-07-12 13:45:50 +02001372
Alexander Couzens22f34712020-10-02 02:34:39 +02001373 llist_for_each_entry(bind, &nsi->binding, list) {
1374 dump_bind(vty, bind, stats);
1375 }
Harald Welte2fce19a2020-12-01 17:52:55 +01001376}
1377
1378
1379static void dump_ns_entities(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats, bool persistent_only)
1380{
1381 struct gprs_ns2_nse *nse;
Alexander Couzens22f34712020-10-02 02:34:39 +02001382
Alexander Couzens6a161492020-07-12 13:45:50 +02001383 llist_for_each_entry(nse, &nsi->nse, list) {
1384 dump_nse(vty, nse, stats, persistent_only);
Alexander Couzens6a161492020-07-12 13:45:50 +02001385 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001386}
1387
Harald Welte25ee7552020-12-02 22:14:00 +01001388/* Backwards compatibility, among other things for the TestVTYGbproxy which expects
1389 * 'show ns' to output something about binds */
1390DEFUN_HIDDEN(show_ns, show_ns_cmd, "show ns",
1391 SHOW_STR SHOW_NS_STR)
1392{
1393 dump_ns_entities(vty, vty_nsi, false, false);
1394 dump_ns_bind(vty, vty_nsi, false);
1395 return CMD_SUCCESS;
1396}
1397
1398
Harald Welte2fce19a2020-12-01 17:52:55 +01001399DEFUN(show_ns_binds, show_ns_binds_cmd, "show ns binds [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001400 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +01001401 "Display information about the NS protocol binds\n"
1402 "Include statistic\n")
Alexander Couzens6a161492020-07-12 13:45:50 +02001403{
Harald Welte2fce19a2020-12-01 17:52:55 +01001404 bool stats = false;
1405 if (argc > 0)
1406 stats = true;
1407
1408 dump_ns_bind(vty, vty_nsi, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +02001409 return CMD_SUCCESS;
1410}
1411
Harald Welte2fce19a2020-12-01 17:52:55 +01001412DEFUN(show_ns_entities, show_ns_entities_cmd, "show ns entities [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001413 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +01001414 "Display information about the NS protocol entities (NSEs)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +02001415 "Include statistics\n")
1416{
Harald Welte2fce19a2020-12-01 17:52:55 +01001417 bool stats = false;
1418 if (argc > 0)
1419 stats = true;
1420
1421 dump_ns_entities(vty, vty_nsi, stats, false);
Alexander Couzens6a161492020-07-12 13:45:50 +02001422 return CMD_SUCCESS;
1423}
1424
1425DEFUN(show_ns_pers, show_ns_pers_cmd, "show ns persistent",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001426 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +02001427 "Show only persistent NS\n")
1428{
Harald Welte2fce19a2020-12-01 17:52:55 +01001429 dump_ns_entities(vty, vty_nsi, true, true);
Alexander Couzens6a161492020-07-12 13:45:50 +02001430 return CMD_SUCCESS;
1431}
1432
1433DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001434 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +02001435 "Select one NSE by its NSE Identifier\n"
1436 "Select one NSE by its NS-VC Identifier\n"
1437 "The Identifier of selected type\n"
1438 "Include Statistics\n")
1439{
1440 struct gprs_ns2_inst *nsi = vty_nsi;
1441 struct gprs_ns2_nse *nse;
1442 struct gprs_ns2_vc *nsvc;
1443 uint16_t id = atoi(argv[1]);
1444 bool show_stats = false;
1445
1446 if (argc >= 3)
1447 show_stats = true;
1448
1449 if (!strcmp(argv[0], "nsei")) {
1450 nse = gprs_ns2_nse_by_nsei(nsi, id);
1451 if (!nse) {
1452 return CMD_WARNING;
1453 }
1454
1455 dump_nse(vty, nse, show_stats, false);
1456 } else {
1457 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
1458
1459 if (!nsvc) {
1460 vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
1461 return CMD_WARNING;
1462 }
1463
1464 dump_nsvc(vty, nsvc, show_stats);
1465 }
1466
1467 return CMD_SUCCESS;
1468}
1469
Daniel Willmanndbab7142020-11-18 14:19:56 +01001470static int nsvc_force_unconf_cb(struct gprs_ns2_vc *nsvc, void *ctx)
1471{
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001472 ns2_vc_force_unconfigured(nsvc);
Daniel Willmanndbab7142020-11-18 14:19:56 +01001473 return 0;
1474}
1475
1476DEFUN_HIDDEN(nsvc_force_unconf, nsvc_force_unconf_cmd,
1477 "nsvc nsei <0-65535> force-unconfigured",
1478 "NS Virtual Connection\n"
1479 "The NSEI\n"
1480 "Reset the NSVCs back to initial state\n"
1481 )
1482{
1483 struct gprs_ns2_inst *nsi = vty_nsi;
1484 struct gprs_ns2_nse *nse;
1485
1486 uint16_t id = atoi(argv[0]);
1487
1488 nse = gprs_ns2_nse_by_nsei(nsi, id);
1489 if (!nse) {
1490 vty_out(vty, "Could not find NSE for NSEI %u%s", id, VTY_NEWLINE);
1491 return CMD_WARNING;
1492 }
1493
Alexander Couzensb3060942021-01-25 16:27:33 +01001494 if (!nse->persistent) {
1495 gprs_ns2_free_nse(nse);
1496 } else if (nse->dialect == GPRS_NS2_DIALECT_SNS) {
Alexander Couzens280ed782020-12-21 18:25:41 +01001497 gprs_ns2_free_nsvcs(nse);
1498 } else {
1499 /* Perform the operation for all nsvc */
1500 gprs_ns2_nse_foreach_nsvc(nse, nsvc_force_unconf_cb, NULL);
1501 }
Daniel Willmanndbab7142020-11-18 14:19:56 +01001502
1503 return CMD_SUCCESS;
1504}
1505
Alexander Couzensb3060942021-01-25 16:27:33 +01001506DEFUN(nsvc_block, nsvc_block_cmd,
1507 "nsvc <0-65535> (block|unblock)",
1508 "NS Virtual Connection\n"
1509 NSVCI_STR
1510 "Block a NSVC. As cause code O&M intervention will be used.\n"
1511 "Unblock a NSVC. As cause code O&M intervention will be used.\n")
Alexander Couzens841817e2020-11-19 00:41:29 +01001512{
Alexander Couzensb3060942021-01-25 16:27:33 +01001513 struct gprs_ns2_inst *nsi = vty_nsi;
1514 struct gprs_ns2_vc *nsvc;
Alexander Couzens841817e2020-11-19 00:41:29 +01001515
Alexander Couzensb3060942021-01-25 16:27:33 +01001516 uint16_t id = atoi(argv[0]);
Alexander Couzens841817e2020-11-19 00:41:29 +01001517
Alexander Couzensb3060942021-01-25 16:27:33 +01001518 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
1519 if (!nsvc) {
1520 vty_out(vty, "Could not find NSVCI %05u%s", id, VTY_NEWLINE);
Alexander Couzens841817e2020-11-19 00:41:29 +01001521 return CMD_WARNING;
1522 }
1523
Alexander Couzensb3060942021-01-25 16:27:33 +01001524 if (!strcmp(argv[1], "block")) {
1525 ns2_vc_block(nsvc);
1526 } else {
1527 ns2_vc_unblock(nsvc);
Alexander Couzens6a161492020-07-12 13:45:50 +02001528 }
1529
1530 return CMD_SUCCESS;
1531}
1532
Alexander Couzensb3060942021-01-25 16:27:33 +01001533static void log_set_nse_filter(struct log_target *target,
1534 struct gprs_ns2_nse *nse)
Alexander Couzens6a161492020-07-12 13:45:50 +02001535{
Alexander Couzensb3060942021-01-25 16:27:33 +01001536 if (nse) {
1537 target->filter_map |= (1 << LOG_FLT_GB_NSE);
1538 target->filter_data[LOG_FLT_GB_NSE] = nse;
1539 } else if (target->filter_data[LOG_FLT_GB_NSE]) {
1540 target->filter_map = ~(1 << LOG_FLT_GB_NSE);
1541 target->filter_data[LOG_FLT_GB_NSE] = NULL;
1542 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001543}
1544
Alexander Couzensb3060942021-01-25 16:27:33 +01001545static void log_set_nsvc_filter(struct log_target *target,
1546 struct gprs_ns2_vc *nsvc)
Alexander Couzens6a161492020-07-12 13:45:50 +02001547{
Alexander Couzensb3060942021-01-25 16:27:33 +01001548 if (nsvc) {
1549 target->filter_map |= (1 << LOG_FLT_GB_NSVC);
1550 target->filter_data[LOG_FLT_GB_NSVC] = nsvc;
1551 } else if (target->filter_data[LOG_FLT_GB_NSVC]) {
1552 target->filter_map = ~(1 << LOG_FLT_GB_NSVC);
1553 target->filter_data[LOG_FLT_GB_NSVC] = NULL;
1554 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001555}
1556
Daniel Willmann751977b2020-12-02 18:59:44 +01001557DEFUN(logging_fltr_nse,
1558 logging_fltr_nse_cmd,
1559 "logging filter nse nsei <0-65535>",
1560 LOGGING_STR FILTER_STR
1561 "Filter based on NS Entity\n"
1562 "Identify NSE by NSEI\n"
1563 "Numeric identifier\n")
1564{
1565 struct log_target *tgt;
1566 struct gprs_ns2_nse *nse;
Daniel Willmann89106522020-12-04 01:36:59 +01001567 uint16_t id = atoi(argv[0]);
Daniel Willmann751977b2020-12-02 18:59:44 +01001568
1569 log_tgt_mutex_lock();
1570 tgt = osmo_log_vty2tgt(vty);
1571 if (!tgt) {
1572 log_tgt_mutex_unlock();
1573 return CMD_WARNING;
1574 }
1575
1576 nse = gprs_ns2_nse_by_nsei(vty_nsi, id);
1577 if (!nse) {
1578 vty_out(vty, "No NSE by that identifier%s", VTY_NEWLINE);
1579 log_tgt_mutex_unlock();
1580 return CMD_WARNING;
1581 }
1582
1583 log_set_nse_filter(tgt, nse);
1584 log_tgt_mutex_unlock();
1585 return CMD_SUCCESS;
1586}
1587
Alexander Couzens6a161492020-07-12 13:45:50 +02001588/* TODO: add filter for single connection by description */
1589DEFUN(logging_fltr_nsvc,
1590 logging_fltr_nsvc_cmd,
1591 "logging filter nsvc nsvci <0-65535>",
1592 LOGGING_STR FILTER_STR
1593 "Filter based on NS Virtual Connection\n"
1594 "Identify NS-VC by NSVCI\n"
1595 "Numeric identifier\n")
1596{
1597 struct log_target *tgt;
1598 struct gprs_ns2_vc *nsvc;
Daniel Willmann89106522020-12-04 01:36:59 +01001599 uint16_t id = atoi(argv[0]);
Alexander Couzens6a161492020-07-12 13:45:50 +02001600
1601 log_tgt_mutex_lock();
1602 tgt = osmo_log_vty2tgt(vty);
1603 if (!tgt) {
1604 log_tgt_mutex_unlock();
1605 return CMD_WARNING;
1606 }
1607
1608 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, id);
1609 if (!nsvc) {
1610 vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
1611 log_tgt_mutex_unlock();
1612 return CMD_WARNING;
1613 }
1614
1615 log_set_nsvc_filter(tgt, nsvc);
1616 log_tgt_mutex_unlock();
1617 return CMD_SUCCESS;
1618}
1619
Alexander Couzensb3060942021-01-25 16:27:33 +01001620int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi)
Alexander Couzens6a161492020-07-12 13:45:50 +02001621{
Alexander Couzens6a161492020-07-12 13:45:50 +02001622 vty_nsi = nsi;
Alexander Couzensb3060942021-01-25 16:27:33 +01001623 INIT_LLIST_HEAD(&binds);
Alexander Couzens6a161492020-07-12 13:45:50 +02001624
Alexander Couzensb3060942021-01-25 16:27:33 +01001625 vty_fr_network = osmo_fr_network_alloc(nsi);
1626 if (!vty_fr_network)
1627 return -ENOMEM;
Alexander Couzens6a161492020-07-12 13:45:50 +02001628
Harald Welte25ee7552020-12-02 22:14:00 +01001629 install_lib_element_ve(&show_ns_cmd);
Harald Welte2fce19a2020-12-01 17:52:55 +01001630 install_lib_element_ve(&show_ns_binds_cmd);
1631 install_lib_element_ve(&show_ns_entities_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001632 install_lib_element_ve(&show_ns_pers_cmd);
1633 install_lib_element_ve(&show_nse_cmd);
Daniel Willmann751977b2020-12-02 18:59:44 +01001634 install_lib_element_ve(&logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001635 install_lib_element_ve(&logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02001636
Daniel Willmanndbab7142020-11-18 14:19:56 +01001637 install_lib_element(ENABLE_NODE, &nsvc_force_unconf_cmd);
Alexander Couzensb3060942021-01-25 16:27:33 +01001638 install_lib_element(ENABLE_NODE, &nsvc_block_cmd);
Daniel Willmanndbab7142020-11-18 14:19:56 +01001639
Daniel Willmann751977b2020-12-02 18:59:44 +01001640 install_lib_element(CFG_LOG_NODE, &logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001641 install_lib_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02001642
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001643 install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
Alexander Couzensb3060942021-01-25 16:27:33 +01001644
Alexander Couzens6a161492020-07-12 13:45:50 +02001645 install_node(&ns_node, config_write_ns);
Alexander Couzensb3060942021-01-25 16:27:33 +01001646 /* TODO: convert into osmo timer */
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07001647 install_lib_element(L_NS_NODE, &cfg_ns_timer_cmd);
Alexander Couzensb3060942021-01-25 16:27:33 +01001648 install_lib_element(L_NS_NODE, &cfg_ns_nsei_cmd);
1649 install_lib_element(L_NS_NODE, &cfg_no_ns_nsei_cmd);
1650 install_lib_element(L_NS_NODE, &cfg_ns_bind_cmd);
1651 install_lib_element(L_NS_NODE, &cfg_no_ns_bind_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02001652
Alexander Couzensb3060942021-01-25 16:27:33 +01001653 install_node(&ns_bind_node, config_write_ns_bind);
1654 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_listen_cmd);
1655 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_listen_cmd);
1656 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_dscp_cmd);
1657 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_dscp_cmd);
1658 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_ipaccess_cmd);
1659 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_ipaccess_cmd);
1660 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_fr_cmd);
1661 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_fr_cmd);
1662 /* TODO: accept-ip-sns when SGSN SNS has been implemented */
Alexander Couzens6a161492020-07-12 13:45:50 +02001663
Alexander Couzensb3060942021-01-25 16:27:33 +01001664 install_node(&ns_nse_node, config_write_ns_nse);
1665 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_fr_cmd);
1666 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvci_cmd);
1667 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_fr_dlci_cmd);
1668 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_udp_cmd);
1669 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_udp_cmd);
1670 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_ipa_cmd);
1671 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_ipa_cmd);
1672 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_ip_sns_cmd);
1673 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_ip_sns_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02001674
1675 return 0;
1676}