Introduce a VTY, factually turning OpenGGSN into an Osmocom program
Change-Id: I9613ca3436e77ea132c47f0096df7c5050d7e826
This commit is contained in:
parent
4d72643ede
commit
c9f4f37dd4
111
doc/ggsn.8
111
doc/ggsn.8
|
@ -31,33 +31,13 @@ ggsn \- Gateway GPRS Support Node.
|
|||
|
||||
.B ggsn
|
||||
[
|
||||
.BI \-\-fg
|
||||
.BI \-\-help
|
||||
] [
|
||||
.BI \-\-debug
|
||||
.BI \-\-daemonize
|
||||
] [
|
||||
.BI \-\-conf " file"
|
||||
.BI \-\-config-file " file"
|
||||
] [
|
||||
.BI \-\-pidfile " file"
|
||||
] [
|
||||
.BI \-\-statedir " file"
|
||||
] [
|
||||
.BI \-\-listen " host"
|
||||
] [
|
||||
.BI \-\-net " net"
|
||||
] [
|
||||
.BI \-\-ipup " script"
|
||||
] [
|
||||
.BI \-\-ipdown " script"
|
||||
] [
|
||||
.BI \-\-dynip " net"
|
||||
] [
|
||||
.BI \-\-statip " net"
|
||||
] [
|
||||
.BI \-\-pcodns1 " host"
|
||||
] [
|
||||
.BI \-\-pcodns2 " host"
|
||||
] [
|
||||
.BI \-\-timelimit " seconds"
|
||||
.BI \-\-version
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B ggsn
|
||||
|
@ -115,86 +95,17 @@ Print help and exit.
|
|||
Print version and exit.
|
||||
|
||||
.TP
|
||||
.BI --fg
|
||||
Run in foreground (default = off)
|
||||
.BI --daemonize
|
||||
Run in background as a daemon (default = off)
|
||||
|
||||
.TP
|
||||
.BI --debug
|
||||
Run in debug mode (default = off)
|
||||
|
||||
.TP
|
||||
.BI --conf " file"
|
||||
.BI --config-file " file"
|
||||
Read configuration
|
||||
.I file
|
||||
(default = /etc/ggsn.conf) where each line corresponds to one command
|
||||
line option, but with the leading '--' removed. Command line options
|
||||
override the options given in the configuration file.
|
||||
|
||||
.TP
|
||||
.BI --pidfile " file"
|
||||
Filename of process id
|
||||
.I file
|
||||
(default = /var/run/ggsn.pid)
|
||||
|
||||
.TP
|
||||
.BI --statedir " path"
|
||||
.I path
|
||||
to directory of nonvolatile data (default = /var/lib/ggsn/)
|
||||
|
||||
.TP
|
||||
.BI --listen " host"
|
||||
Local interface IP address to use for the Gn/Gp interface. This option
|
||||
must be specified. For security issues it is not possible to use
|
||||
INADDR_ANY.
|
||||
|
||||
.TP
|
||||
.BI --net " net"
|
||||
Network address of the Gi interface (default = 192.168.0.0/24). The
|
||||
network address is set during initialisation when
|
||||
.B ggsn
|
||||
establishes a tun device for the Gi interface.
|
||||
|
||||
.TP
|
||||
.BI --ipup " script"
|
||||
Script executed after the Gi tun network interface has been brought
|
||||
up. Executed with the following parameters: <devicename> <ip address>
|
||||
|
||||
.TP
|
||||
.BI --ipdown " script"
|
||||
Script executed after the Gi tun network interface has been taken
|
||||
down. Executed with the following parameters: <devicename> <ip
|
||||
address>
|
||||
|
||||
.TP
|
||||
.BI --dynip " net"
|
||||
Dynamic IP address pool. Specifies a pool of dynamic IP addresses. If
|
||||
this option is omitted the network address specified by the
|
||||
.BI --net
|
||||
option is used for dynamic IP address allocation.
|
||||
|
||||
.TP
|
||||
.BI --pcodns1 " host"
|
||||
PCO DNS Server 1 (default = 0.0.0.0). PCO stands for Protocol
|
||||
Configuration options, and is part of the GPRS protocols. It is used
|
||||
to inform the mobile station about the DNS address to use for host
|
||||
name resolution.
|
||||
|
||||
.TP
|
||||
.BI --pcodns2 " host"
|
||||
PCO DNS Server 2 (default = 0.0.0.0). PCO stands for Protocol
|
||||
Configuration options, and is part of the GPRS protocols. It is used
|
||||
to inform the mobile station about the DNS address to use for host
|
||||
name resolution.
|
||||
|
||||
.TP
|
||||
.BI --timelimit " seconds"
|
||||
Exit
|
||||
.B ggsn
|
||||
after \fIseconds\fP. Used for debugging.
|
||||
|
||||
(default = ./openggsn.cfg)
|
||||
|
||||
.SH FILES
|
||||
.I /etc/ggsn.conf
|
||||
.I ./openggsn.cfg
|
||||
.RS
|
||||
The configuration file for
|
||||
.B ggsn.
|
||||
|
@ -210,7 +121,7 @@ Directory holding nonvolatile data.
|
|||
|
||||
.SH BUGS
|
||||
Report all bugs to the OpenGGSN bug tracking list at
|
||||
.I http://sourceforge.net/projects/ggsn/
|
||||
.I https://osmocom.org/projects/openggsn
|
||||
|
||||
.B ggsn
|
||||
has very limited management support. Currently both SNMP as well as
|
||||
|
@ -250,6 +161,7 @@ can be found at
|
|||
.SH COPYRIGHT
|
||||
|
||||
Copyright (C) 2002, 2003 by Mondru AB.
|
||||
Copyright (C) 2017 Harald Welte
|
||||
|
||||
The contents of this file may be used under the terms of the GNU
|
||||
General Public License Version 2, provided that the above copyright
|
||||
|
@ -258,3 +170,4 @@ substantial portions of the software.
|
|||
|
||||
.SH AUTHORS
|
||||
Jens Jakobsen <jj@openggsn.org>
|
||||
Harald Welte <laforge@gnumonks.org>
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
##############################################################################
|
||||
#
|
||||
# Sample ggsn configuration file
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# TAG: fg
|
||||
# Include this flag if process is to run in the foreground
|
||||
#
|
||||
#fg
|
||||
|
||||
# TAG: debug
|
||||
# Include this flag to include debug information.
|
||||
#debug
|
||||
|
||||
|
||||
# TAG: conf
|
||||
# Configuration file to use. This file is the configuration file,
|
||||
# so changing this parameter in the configuration file does not make
|
||||
# sense. Use it on the command line instead.
|
||||
|
||||
# TAG: pidfile
|
||||
# File to store information about the process id of the program.
|
||||
# The program must have write access to this file/directory.
|
||||
#pidfile /var/run/ggsn.pid
|
||||
|
||||
# TAG: statedir
|
||||
# Directory to use for nonvolatile storage.
|
||||
# The program must have write access to this directory.
|
||||
#statedir /var/lib/ggsn/
|
||||
|
||||
|
||||
# TAG: listen
|
||||
# Specifies the local IP address to listen to
|
||||
#listen 10.0.0.240
|
||||
|
||||
# TAG: net
|
||||
# IP network address of external packet data network
|
||||
# Used to set up network interface.
|
||||
#net 192.168.0.0/24
|
||||
|
||||
# TAG: ipup
|
||||
# Script executed after network interface has been brought up.
|
||||
# Executed with the following parameters: <devicename> <ip address>
|
||||
#ipup /etc/ggsn/ip-up
|
||||
|
||||
# TAG: ipdown
|
||||
# Script executed after network interface has been taken down.
|
||||
# Executed with the following parameters: <devicename> <ip address>
|
||||
#ipdown /etc/ggsn/ip-down
|
||||
|
||||
# TAG: dynip
|
||||
# Dynamic IP address pool.
|
||||
# Used for allocation of dynamic IP address when address is not given
|
||||
# by HLR.
|
||||
# If this option is not given then the net option is used as a substitute.
|
||||
#dynip 192.168.0.0/24
|
||||
|
||||
# TAG: statip
|
||||
# Use of this tag is currently UNSUPPORTED
|
||||
# Static IP address pool.
|
||||
# Used for allocation of static IP address by means of HLR.
|
||||
#statip 192.168.1.0/24
|
||||
|
||||
# TAG: pcodns1
|
||||
# Protocol configuration option domain name system server 1.
|
||||
#pcodns1 0.0.0.0
|
||||
|
||||
# TAG: pcodns2
|
||||
# Protocol configuration option domain name system server 2.
|
||||
#pcodns2 0.0.0.0
|
||||
|
||||
# TAG: timelimit
|
||||
# Exit after timelimit seconds.
|
||||
# Setting timelimit to zero will cause the program not to exit.
|
||||
#timelimit 0
|
||||
|
||||
# TAG: apn
|
||||
# Use of this tag is EXPERIMENTAL
|
||||
# Access point name to connect to when run in client mode.
|
||||
#apn internet
|
||||
|
||||
# TAG: qos
|
||||
# Use of this tag is EXPERIMENTAL
|
||||
# Requested Quality of Service used when run in client mode.
|
||||
# 3 bytes corresponding to ????
|
||||
#qos 0x0b921f
|
||||
|
||||
# TAG: qos
|
||||
# Enable GTP datapath through Linux kernel driver gtp.ko (since 4.7).
|
||||
#gtp-linux
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
!
|
||||
! OpenGGSN (0.94.1-adac) configuration saved from vty
|
||||
!!
|
||||
!
|
||||
log stderr
|
||||
logging filter all 1
|
||||
logging color 1
|
||||
logging print category 0
|
||||
logging timestamp 0
|
||||
logging level ip info
|
||||
logging level tun info
|
||||
logging level ggsn info
|
||||
logging level sgsn notice
|
||||
logging level icmp6 notice
|
||||
logging level lglobal notice
|
||||
logging level llapd notice
|
||||
logging level linp notice
|
||||
logging level lmux notice
|
||||
logging level lmi notice
|
||||
logging level lmib notice
|
||||
logging level lsms notice
|
||||
logging level lctrl notice
|
||||
logging level lgtp info
|
||||
logging level lstats notice
|
||||
logging level lgsup notice
|
||||
logging level loap notice
|
||||
logging level lss7 notice
|
||||
logging level lsccp notice
|
||||
logging level lsua notice
|
||||
logging level lm3ua notice
|
||||
logging level lmgcp notice
|
||||
!
|
||||
stats interval 5
|
||||
!
|
||||
line vty
|
||||
no login
|
||||
!
|
||||
ggsn ggsn0
|
||||
gtp state-dir /tmp
|
||||
gtp bind-ip 127.0.0.6
|
||||
apn internet
|
||||
gtpu-mode tun
|
||||
tun-device tun4
|
||||
type-support v4
|
||||
ip prefix dynamic 176.16.222.0/24
|
||||
ip dns 0 192.168.100.1
|
||||
ip dns 1 8.8.8.8
|
||||
ip ifconfig 176.16.222.0/24
|
||||
no shutdown
|
||||
apn inet6
|
||||
gtpu-mode tun
|
||||
tun-device tun6
|
||||
type-support v6
|
||||
ipv6 prefix dynamic 2001:780:44:2000:0:0:0:0/56
|
||||
ipv6 dns 0 2001:4860:4860::8888
|
||||
ipv6 ifconfig 2001:780:44:2000:0:0:0:0/56
|
||||
no shutdown
|
||||
apn inet46
|
||||
gtpu-mode tun
|
||||
tun-device tun46
|
||||
type-support v4v6
|
||||
ip prefix dynamic 176.16.46.0/24
|
||||
ip dns 0 192.168.100.1
|
||||
ip dns 1 8.8.8.8
|
||||
ip ifconfig 176.16.46.0/24
|
||||
ipv6 prefix dynamic 2001:780:44:2100:0:0:0:0/56
|
||||
ipv6 dns 0 2001:4860:4860::8888
|
||||
ipv6 ifconfig 2001:780:44:2100:0:0:0:0/56
|
||||
no shutdown
|
||||
default-apn internet
|
||||
no shutdown ggsn
|
|
@ -2,17 +2,17 @@ bin_PROGRAMS = ggsn
|
|||
|
||||
AM_LDFLAGS = @EXEC_LDFLAGS@
|
||||
|
||||
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS)
|
||||
AM_CFLAGS = -O2 -D_GNU_SOURCE -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCTRL_CFLAGS) $(LIBOSMOVTY_CFLAGS)
|
||||
|
||||
ggsn_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBOSMOVTY_LIBS)
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
AM_CFLAGS += -DGTP_KERNEL
|
||||
ggsn_LDADD = @EXEC_LDADD@ -lgtp -lgtpnl -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS)
|
||||
else
|
||||
ggsn_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS)
|
||||
ggsn_LDADD += -lgtpnl
|
||||
endif
|
||||
|
||||
ggsn_DEPENDENCIES = ../gtp/libgtp.la ../lib/libmisc.a
|
||||
ggsn_SOURCES = ggsn.c cmdline.c cmdline.h gtp-kernel.h icmpv6.c icmpv6.h checksum.c checksum.h
|
||||
ggsn_SOURCES = ggsn_vty.c ggsn.c ggsn.h gtp-kernel.h icmpv6.c icmpv6.h checksum.c checksum.h
|
||||
|
||||
if ENABLE_GTP_KERNEL
|
||||
ggsn_SOURCES += gtp-kernel.c
|
||||
|
|
1162
ggsn/cmdline.c
1162
ggsn/cmdline.c
File diff suppressed because it is too large
Load Diff
|
@ -1,38 +0,0 @@
|
|||
# OpenGGSN - Gateway GPRS Support Node
|
||||
# Copyright (C) 2002, 2003, 2004 Mondru AB.
|
||||
#
|
||||
# The contents of this file may be used under the terms of the GNU
|
||||
# General Public License Version 2, provided that the above copyright
|
||||
# notice and this permission notice is included in all copies or
|
||||
# substantial portions of the software.
|
||||
#
|
||||
# Use "gengetopt --conf-parser < cmdline.ggo"
|
||||
# to generate cmdline.c and cmdline.h
|
||||
|
||||
option "fg" f "Run in foreground" flag off
|
||||
option "debug" d "Run in debug mode" flag off
|
||||
|
||||
option "conf" c "Read configuration file" string default="/etc/ggsn.conf" no
|
||||
option "pidfile" - "Filename of process id file" string default="/var/run/ggsn.pid" no
|
||||
option "statedir" - "Directory of nonvolatile data" string default="/var/lib/ggsn/" no
|
||||
|
||||
option "listen" l "Local interface" string no
|
||||
option "net" n "Network" string default="192.168.0.0/24" no
|
||||
option "ipup" - "Script to run after link-up" string no
|
||||
option "ipdown" - "Script to run after link-down" string no
|
||||
|
||||
option "dynip" - "Dynamic IP address pool" string no
|
||||
option "statip" - "Static IP address pool" string no
|
||||
|
||||
option "pcodns1" - "PCO DNS Server 1" string default="0.0.0.0" no
|
||||
option "pcodns2" - "PCO DNS Server 2" string default="0.0.0.0" no
|
||||
|
||||
option "timelimit" - "Exit after timelimit seconds" int default="0" no
|
||||
|
||||
option "apn" a "Access point name" string default="internet" no
|
||||
option "qos" q "Requested quality of service" int default="0x0b921f" no
|
||||
option "logfile" - "Logfile for errors" string no
|
||||
option "loglevel" - "Global log ldevel" string default="error" no
|
||||
|
||||
option "gtp-linux" g "GTP linux kernel support" flag off
|
||||
|
275
ggsn/cmdline.h
275
ggsn/cmdline.h
|
@ -1,275 +0,0 @@
|
|||
/** @file cmdline.h
|
||||
* @brief The header file for the command line option parser
|
||||
* generated by GNU Gengetopt version 2.22.6
|
||||
* http://www.gnu.org/software/gengetopt.
|
||||
* DO NOT modify this file, since it can be overwritten
|
||||
* @author GNU Gengetopt by Lorenzo Bettini */
|
||||
|
||||
#ifndef CMDLINE_H
|
||||
#define CMDLINE_H
|
||||
|
||||
/* If we use autoconf. */
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE
|
||||
/** @brief the program name (used for printing errors) */
|
||||
#define CMDLINE_PARSER_PACKAGE PACKAGE
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_PACKAGE_NAME
|
||||
/** @brief the complete program name (used for help and version) */
|
||||
#ifdef PACKAGE_NAME
|
||||
#define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME
|
||||
#else
|
||||
#define CMDLINE_PARSER_PACKAGE_NAME PACKAGE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CMDLINE_PARSER_VERSION
|
||||
/** @brief the program version */
|
||||
#define CMDLINE_PARSER_VERSION VERSION
|
||||
#endif
|
||||
|
||||
/** @brief Where the command line options are stored */
|
||||
struct gengetopt_args_info
|
||||
{
|
||||
const char *help_help; /**< @brief Print help and exit help description. */
|
||||
const char *version_help; /**< @brief Print version and exit help description. */
|
||||
int fg_flag; /**< @brief Run in foreground (default=off). */
|
||||
const char *fg_help; /**< @brief Run in foreground help description. */
|
||||
int debug_flag; /**< @brief Run in debug mode (default=off). */
|
||||
const char *debug_help; /**< @brief Run in debug mode help description. */
|
||||
char * conf_arg; /**< @brief Read configuration file (default='/etc/ggsn.conf'). */
|
||||
char * conf_orig; /**< @brief Read configuration file original value given at command line. */
|
||||
const char *conf_help; /**< @brief Read configuration file help description. */
|
||||
char * pidfile_arg; /**< @brief Filename of process id file (default='/var/run/ggsn.pid'). */
|
||||
char * pidfile_orig; /**< @brief Filename of process id file original value given at command line. */
|
||||
const char *pidfile_help; /**< @brief Filename of process id file help description. */
|
||||
char * statedir_arg; /**< @brief Directory of nonvolatile data (default='/var/lib/ggsn/'). */
|
||||
char * statedir_orig; /**< @brief Directory of nonvolatile data original value given at command line. */
|
||||
const char *statedir_help; /**< @brief Directory of nonvolatile data help description. */
|
||||
char * listen_arg; /**< @brief Local interface. */
|
||||
char * listen_orig; /**< @brief Local interface original value given at command line. */
|
||||
const char *listen_help; /**< @brief Local interface help description. */
|
||||
char * net_arg; /**< @brief Network (default='192.168.0.0/24'). */
|
||||
char * net_orig; /**< @brief Network original value given at command line. */
|
||||
const char *net_help; /**< @brief Network help description. */
|
||||
char * ipup_arg; /**< @brief Script to run after link-up. */
|
||||
char * ipup_orig; /**< @brief Script to run after link-up original value given at command line. */
|
||||
const char *ipup_help; /**< @brief Script to run after link-up help description. */
|
||||
char * ipdown_arg; /**< @brief Script to run after link-down. */
|
||||
char * ipdown_orig; /**< @brief Script to run after link-down original value given at command line. */
|
||||
const char *ipdown_help; /**< @brief Script to run after link-down help description. */
|
||||
char * dynip_arg; /**< @brief Dynamic IP address pool. */
|
||||
char * dynip_orig; /**< @brief Dynamic IP address pool original value given at command line. */
|
||||
const char *dynip_help; /**< @brief Dynamic IP address pool help description. */
|
||||
char * statip_arg; /**< @brief Static IP address pool. */
|
||||
char * statip_orig; /**< @brief Static IP address pool original value given at command line. */
|
||||
const char *statip_help; /**< @brief Static IP address pool help description. */
|
||||
char * pcodns1_arg; /**< @brief PCO DNS Server 1 (default='0.0.0.0'). */
|
||||
char * pcodns1_orig; /**< @brief PCO DNS Server 1 original value given at command line. */
|
||||
const char *pcodns1_help; /**< @brief PCO DNS Server 1 help description. */
|
||||
char * pcodns2_arg; /**< @brief PCO DNS Server 2 (default='0.0.0.0'). */
|
||||
char * pcodns2_orig; /**< @brief PCO DNS Server 2 original value given at command line. */
|
||||
const char *pcodns2_help; /**< @brief PCO DNS Server 2 help description. */
|
||||
int timelimit_arg; /**< @brief Exit after timelimit seconds (default='0'). */
|
||||
char * timelimit_orig; /**< @brief Exit after timelimit seconds original value given at command line. */
|
||||
const char *timelimit_help; /**< @brief Exit after timelimit seconds help description. */
|
||||
char * apn_arg; /**< @brief Access point name (default='internet'). */
|
||||
char * apn_orig; /**< @brief Access point name original value given at command line. */
|
||||
const char *apn_help; /**< @brief Access point name help description. */
|
||||
int qos_arg; /**< @brief Requested quality of service (default='0x0b921f'). */
|
||||
char * qos_orig; /**< @brief Requested quality of service original value given at command line. */
|
||||
const char *qos_help; /**< @brief Requested quality of service help description. */
|
||||
char * logfile_arg; /**< @brief Logfile for errors. */
|
||||
char * logfile_orig; /**< @brief Logfile for errors original value given at command line. */
|
||||
const char *logfile_help; /**< @brief Logfile for errors help description. */
|
||||
char * loglevel_arg; /**< @brief Global log ldevel (default='error'). */
|
||||
char * loglevel_orig; /**< @brief Global log ldevel original value given at command line. */
|
||||
const char *loglevel_help; /**< @brief Global log ldevel help description. */
|
||||
int gtp_linux_flag; /**< @brief GTP linux kernel support (default=off). */
|
||||
const char *gtp_linux_help; /**< @brief GTP linux kernel support help description. */
|
||||
|
||||
unsigned int help_given ; /**< @brief Whether help was given. */
|
||||
unsigned int version_given ; /**< @brief Whether version was given. */
|
||||
unsigned int fg_given ; /**< @brief Whether fg was given. */
|
||||
unsigned int debug_given ; /**< @brief Whether debug was given. */
|
||||
unsigned int conf_given ; /**< @brief Whether conf was given. */
|
||||
unsigned int pidfile_given ; /**< @brief Whether pidfile was given. */
|
||||
unsigned int statedir_given ; /**< @brief Whether statedir was given. */
|
||||
unsigned int listen_given ; /**< @brief Whether listen was given. */
|
||||
unsigned int net_given ; /**< @brief Whether net was given. */
|
||||
unsigned int ipup_given ; /**< @brief Whether ipup was given. */
|
||||
unsigned int ipdown_given ; /**< @brief Whether ipdown was given. */
|
||||
unsigned int dynip_given ; /**< @brief Whether dynip was given. */
|
||||
unsigned int statip_given ; /**< @brief Whether statip was given. */
|
||||
unsigned int pcodns1_given ; /**< @brief Whether pcodns1 was given. */
|
||||
unsigned int pcodns2_given ; /**< @brief Whether pcodns2 was given. */
|
||||
unsigned int timelimit_given ; /**< @brief Whether timelimit was given. */
|
||||
unsigned int apn_given ; /**< @brief Whether apn was given. */
|
||||
unsigned int qos_given ; /**< @brief Whether qos was given. */
|
||||
unsigned int logfile_given ; /**< @brief Whether logfile was given. */
|
||||
unsigned int loglevel_given ; /**< @brief Whether loglevel was given. */
|
||||
unsigned int gtp_linux_given ; /**< @brief Whether gtp-linux was given. */
|
||||
|
||||
} ;
|
||||
|
||||
/** @brief The additional parameters to pass to parser functions */
|
||||
struct cmdline_parser_params
|
||||
{
|
||||
int override; /**< @brief whether to override possibly already present options (default 0) */
|
||||
int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
|
||||
int check_required; /**< @brief whether to check that all required options were provided (default 1) */
|
||||
int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
|
||||
int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
|
||||
} ;
|
||||
|
||||
/** @brief the purpose string of the program */
|
||||
extern const char *gengetopt_args_info_purpose;
|
||||
/** @brief the usage string of the program */
|
||||
extern const char *gengetopt_args_info_usage;
|
||||
/** @brief the description string of the program */
|
||||
extern const char *gengetopt_args_info_description;
|
||||
/** @brief all the lines making the help output */
|
||||
extern const char *gengetopt_args_info_help[];
|
||||
|
||||
/**
|
||||
* The command line parser
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters - deprecated)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param override whether to override possibly already present options
|
||||
* @param initialize whether to initialize the option structure my_args_info
|
||||
* @param check_required whether to check that all required options were provided
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
* @deprecated use cmdline_parser_ext() instead
|
||||
*/
|
||||
int cmdline_parser2 (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
int override, int initialize, int check_required);
|
||||
|
||||
/**
|
||||
* The command line parser (version with additional parameters)
|
||||
* @param argc the number of command line options
|
||||
* @param argv the command line options
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param params additional parameters for the parser
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_ext (int argc, char **argv,
|
||||
struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into an already open FILE stream.
|
||||
* @param outfile the stream where to dump options
|
||||
* @param args_info the option struct to dump
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_dump(FILE *outfile,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Save the contents of the option struct into a (text) file.
|
||||
* This file can be read by the config file parser (if generated by gengetopt)
|
||||
* @param filename the file where to save
|
||||
* @param args_info the option struct to save
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_file_save(const char *filename,
|
||||
struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* Print the help
|
||||
*/
|
||||
void cmdline_parser_print_help(void);
|
||||
/**
|
||||
* Print the version
|
||||
*/
|
||||
void cmdline_parser_print_version(void);
|
||||
|
||||
/**
|
||||
* Initializes all the fields a cmdline_parser_params structure
|
||||
* to their default values
|
||||
* @param params the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_params_init(struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Allocates dynamically a cmdline_parser_params structure and initializes
|
||||
* all its fields to their default values
|
||||
* @return the created and initialized cmdline_parser_params structure
|
||||
*/
|
||||
struct cmdline_parser_params *cmdline_parser_params_create(void);
|
||||
|
||||
/**
|
||||
* Initializes the passed gengetopt_args_info structure's fields
|
||||
* (also set default values for options that have a default)
|
||||
* @param args_info the structure to initialize
|
||||
*/
|
||||
void cmdline_parser_init (struct gengetopt_args_info *args_info);
|
||||
/**
|
||||
* Deallocates the string fields of the gengetopt_args_info structure
|
||||
* (but does not deallocate the structure itself)
|
||||
* @param args_info the structure to deallocate
|
||||
*/
|
||||
void cmdline_parser_free (struct gengetopt_args_info *args_info);
|
||||
|
||||
/**
|
||||
* The config file parser (deprecated version)
|
||||
* @param filename the name of the config file
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param override whether to override possibly already present options
|
||||
* @param initialize whether to initialize the option structure my_args_info
|
||||
* @param check_required whether to check that all required options were provided
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
* @deprecated use cmdline_parser_config_file() instead
|
||||
*/
|
||||
int cmdline_parser_configfile (const char *filename,
|
||||
struct gengetopt_args_info *args_info,
|
||||
int override, int initialize, int check_required);
|
||||
|
||||
/**
|
||||
* The config file parser
|
||||
* @param filename the name of the config file
|
||||
* @param args_info the structure where option information will be stored
|
||||
* @param params additional parameters for the parser
|
||||
* @return 0 if everything went fine, NON 0 if an error took place
|
||||
*/
|
||||
int cmdline_parser_config_file (const char *filename,
|
||||
struct gengetopt_args_info *args_info,
|
||||
struct cmdline_parser_params *params);
|
||||
|
||||
/**
|
||||
* Checks that all the required options were specified
|
||||
* @param args_info the structure to check
|
||||
* @param prog_name the name of the program that will be used to print
|
||||
* possible errors
|
||||
* @return
|
||||
*/
|
||||
int cmdline_parser_required (struct gengetopt_args_info *args_info,
|
||||
const char *prog_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* CMDLINE_H */
|
1060
ggsn/ggsn.c
1060
ggsn/ggsn.c
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,133 @@
|
|||
#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 "../lib/tun.h"
|
||||
#include "../lib/ippool.h"
|
||||
#include "../lib/syserr.h"
|
||||
#include "../lib/in46_addr.h"
|
||||
#include "../gtp/gtp.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 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;
|
||||
} 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;
|
||||
|
||||
struct apn_ctx_ip v4;
|
||||
struct apn_ctx_ip v6;
|
||||
};
|
||||
|
||||
struct ggsn_ctx {
|
||||
/* global list of GGSNs */
|
||||
struct llist_head list;
|
||||
|
||||
/* list of APNs in this GGSN */
|
||||
struct llist_head apn_list;
|
||||
|
||||
bool started;
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
/* Description string */
|
||||
char *description;
|
||||
/* an APN that shall be used as default for any non-matching APN */
|
||||
struct apn_ctx *default_apn;
|
||||
/* ADdress to which we listen for GTP */
|
||||
struct in46_addr listen_addr;
|
||||
/* directory for state file */
|
||||
char *state_dir;
|
||||
/* 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;
|
||||
|
||||
struct osmo_timer_list gtp_timer;
|
||||
};
|
||||
|
||||
/* 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.c */
|
||||
extern void *tall_ggsn_ctx;
|
||||
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, bool force);
|
|
@ -0,0 +1,890 @@
|
|||
/*
|
||||
* (C) 2017 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
||||
|
||||
#include <osmocom/vty/command.h>
|
||||
#include <osmocom/vty/vty.h>
|
||||
#include <osmocom/vty/misc.h>
|
||||
|
||||
#include "../gtp/gtp.h"
|
||||
#include "../gtp/pdp.h"
|
||||
|
||||
#include "ggsn.h"
|
||||
|
||||
#define PREFIX_STR "Prefix (Network/Netmask)\n"
|
||||
#define IFCONFIG_STR "GGSN-based interface configuration\n"
|
||||
#define GGSN_STR "Gateway GPRS Support NODE (GGSN)\n"
|
||||
|
||||
LLIST_HEAD(g_ggsn_list);
|
||||
|
||||
enum ggsn_vty_node {
|
||||
GGSN_NODE = _LAST_OSMOVTY_NODE + 1,
|
||||
APN_NODE,
|
||||
};
|
||||
|
||||
struct ggsn_ctx *ggsn_find(const char *name)
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
|
||||
llist_for_each_entry(ggsn, &g_ggsn_list, list) {
|
||||
if (!strcmp(ggsn->cfg.name, name))
|
||||
return ggsn;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ggsn_ctx *ggsn_find_or_create(void *ctx, const char *name)
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
|
||||
ggsn = ggsn_find(name);
|
||||
if (ggsn)
|
||||
return ggsn;
|
||||
|
||||
ggsn = talloc_zero(ctx, struct ggsn_ctx);
|
||||
if (!ggsn)
|
||||
return NULL;
|
||||
|
||||
ggsn->cfg.name = talloc_strdup(ggsn, name);
|
||||
ggsn->cfg.state_dir = talloc_strdup(ggsn, "/tmp");
|
||||
ggsn->cfg.shutdown = true;
|
||||
INIT_LLIST_HEAD(&ggsn->apn_list);
|
||||
|
||||
llist_add_tail(&ggsn->list, &g_ggsn_list);
|
||||
return ggsn;
|
||||
}
|
||||
|
||||
struct apn_ctx *ggsn_find_apn(struct ggsn_ctx *ggsn, const char *name)
|
||||
{
|
||||
struct apn_ctx *apn;
|
||||
|
||||
llist_for_each_entry(apn, &ggsn->apn_list, list) {
|
||||
if (!strcmp(apn->cfg.name, name))
|
||||
return apn;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct apn_ctx *ggsn_find_or_create_apn(struct ggsn_ctx *ggsn, const char *name)
|
||||
{
|
||||
struct apn_ctx *apn = ggsn_find_apn(ggsn, name);
|
||||
if (apn)
|
||||
return apn;
|
||||
|
||||
apn = talloc_zero(ggsn, struct apn_ctx);
|
||||
if (!apn)
|
||||
return NULL;
|
||||
apn->ggsn = ggsn;
|
||||
apn->cfg.name = talloc_strdup(apn, name);
|
||||
apn->cfg.shutdown = true;
|
||||
INIT_LLIST_HEAD(&apn->cfg.name_list);
|
||||
|
||||
llist_add_tail(&apn->list, &ggsn->apn_list);
|
||||
return apn;
|
||||
}
|
||||
|
||||
/* GGSN Node */
|
||||
|
||||
static struct cmd_node ggsn_node = {
|
||||
GGSN_NODE,
|
||||
"%s(config-ggsn)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
DEFUN(cfg_ggsn, cfg_ggsn_cmd,
|
||||
"ggsn NAME",
|
||||
"Configure the Gateway GPRS Support Node\n" "GGSN Name (has only local significance)\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
|
||||
ggsn = ggsn_find_or_create(tall_ggsn_ctx, argv[0]);
|
||||
if (!ggsn)
|
||||
return CMD_WARNING;
|
||||
|
||||
vty->node = GGSN_NODE;
|
||||
vty->index = ggsn;
|
||||
vty->index_sub = &ggsn->cfg.description;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_ggsn, cfg_no_ggsn_cmd,
|
||||
"no ggsn NAME",
|
||||
NO_STR "Remove the named Gateway GPRS Support Node\n"
|
||||
"GGSN Name (has only local significance)\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
|
||||
ggsn = ggsn_find(argv[0]);
|
||||
if (!ggsn) {
|
||||
vty_out(vty, "%% No such GGSN '%s'%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!ggsn->cfg.shutdown) {
|
||||
vty_out(vty, "%% GGSN %s is still active, please shutdown first%s",
|
||||
ggsn->cfg.name, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!llist_empty(&ggsn->apn_list)) {
|
||||
vty_out(vty, "%% GGSN %s still has APNs configured, please remove first%s",
|
||||
ggsn->cfg.name, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
llist_del(&ggsn->list);
|
||||
talloc_free(ggsn);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_local_ip, cfg_ggsn_local_ip_cmd,
|
||||
"gtp local-ip A.B.C.D",
|
||||
"GTP Parameters\n"
|
||||
"Set the IP address for the local GTP bind\n"
|
||||
"IPv4 Address\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
size_t t;
|
||||
|
||||
ippool_aton(&ggsn->cfg.listen_addr, &t, argv[0], 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_state_dir, cfg_ggsn_state_dir_cmd,
|
||||
"gtp state-dir PATH",
|
||||
"GTP Parameters\n"
|
||||
"Set the directory for the GTP State file\n"
|
||||
"Local Directory\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
|
||||
osmo_talloc_replace_string(ggsn, &ggsn->cfg.state_dir, argv[0]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_apn, cfg_ggsn_apn_cmd,
|
||||
"apn NAME", "APN Configuration\n" "APN Name\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
struct apn_ctx *apn;
|
||||
|
||||
apn = ggsn_find_or_create_apn(ggsn, argv[0]);
|
||||
if (!apn)
|
||||
return CMD_WARNING;
|
||||
|
||||
vty->node = APN_NODE;
|
||||
vty->index = apn;
|
||||
vty->index_sub = &ggsn->cfg.description;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_no_apn, cfg_ggsn_no_apn_cmd,
|
||||
"no apn NAME",
|
||||
NO_STR "Remove APN Configuration\n" "APN Name\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
struct apn_ctx *apn;
|
||||
|
||||
apn = ggsn_find_apn(ggsn, argv[0]);
|
||||
if (!apn) {
|
||||
vty_out(vty, "%% No such APN '%s'%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
if (!apn->cfg.shutdown) {
|
||||
vty_out(vty, "%% APN %s still active, please shutdown first%s",
|
||||
apn->cfg.name, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
llist_del(&apn->list);
|
||||
talloc_free(apn);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_default_apn, cfg_ggsn_default_apn_cmd,
|
||||
"default-apn NAME",
|
||||
"Set a default-APN to be used if no other APN matches\n"
|
||||
"APN Name\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
struct apn_ctx *apn;
|
||||
|
||||
apn = ggsn_find_apn(ggsn, argv[0]);
|
||||
if (!apn) {
|
||||
vty_out(vty, "%% No APN of name '%s' found%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
ggsn->cfg.default_apn = apn;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_no_default_apn, cfg_ggsn_no_default_apn_cmd,
|
||||
"no default-apn",
|
||||
NO_STR "Remove default-APN to be used if no other APN matches\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
ggsn->cfg.default_apn = NULL;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_shutdown, cfg_ggsn_shutdown_cmd,
|
||||
"shutdown ggsn",
|
||||
"Put the GGSN in administrative shut-down\n" GGSN_STR)
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
|
||||
if (!ggsn->cfg.shutdown) {
|
||||
if (ggsn_stop(ggsn)) {
|
||||
vty_out(vty, "%% Failed to shutdown GGSN%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
ggsn->cfg.shutdown = true;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_ggsn_no_shutdown, cfg_ggsn_no_shutdown_cmd,
|
||||
"no shutdown ggsn",
|
||||
NO_STR GGSN_STR "Remove the GGSN from administrative shut-down\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn = (struct ggsn_ctx *) vty->index;
|
||||
|
||||
if (ggsn->cfg.shutdown) {
|
||||
if (ggsn_start(ggsn) < 0) {
|
||||
vty_out(vty, "%% Failed to start GGSN, check log for details%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
ggsn->cfg.shutdown = false;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* APN Node */
|
||||
|
||||
static struct cmd_node apn_node = {
|
||||
APN_NODE,
|
||||
"%s(config-ggsn-apn)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
static const struct value_string pdp_type_names[] = {
|
||||
{ APN_TYPE_IPv4, "v4" },
|
||||
{ APN_TYPE_IPv6, "v6" },
|
||||
{ APN_TYPE_IPv4v6, "v4v6" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const struct value_string apn_gtpu_mode_names[] = {
|
||||
{ APN_GTPU_MODE_TUN, "tun" },
|
||||
{ APN_GTPU_MODE_KERNEL_GTP, "kernel-gtp" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
#define V4V6V46_STRING "IPv4(-only) PDP Type\n" \
|
||||
"IPv6(-only) PDP Type\n" \
|
||||
"IPv4v6 (dual-stack) PDP Type\n"
|
||||
|
||||
DEFUN(cfg_apn_type_support, cfg_apn_type_support_cmd,
|
||||
"type-support (v4|v6|v4v6)",
|
||||
"Enable support for PDP Type\n"
|
||||
V4V6V46_STRING)
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
uint32_t type = get_string_value(pdp_type_names, argv[0]);
|
||||
|
||||
apn->cfg.apn_type_mask |= type;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_type_support, cfg_apn_no_type_support_cmd,
|
||||
"no type-support (v4|v6|v4v6)",
|
||||
NO_STR "Disable support for PDP Type\n"
|
||||
V4V6V46_STRING)
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
uint32_t type = get_string_value(pdp_type_names, argv[0]);
|
||||
|
||||
apn->cfg.apn_type_mask &= ~type;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_gtpu_mode, cfg_apn_gtpu_mode_cmd,
|
||||
"gtpu-mode (tun|kernel-gtp)",
|
||||
"Set the Mode for this APN (tun or Linux Kernel GTP)\n"
|
||||
"GTP-U in userspace using TUN device\n"
|
||||
"GTP-U in kernel using Linux Kernel GTP\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
|
||||
apn->cfg.gtpu_mode = get_string_value(apn_gtpu_mode_names, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_tun_dev_name, cfg_apn_tun_dev_name_cmd,
|
||||
"tun-device NAME",
|
||||
"Configure tun device name\n"
|
||||
"TUN device name")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
osmo_talloc_replace_string(apn, &apn->tun.cfg.dev_name, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ipup_script, cfg_apn_ipup_script_cmd,
|
||||
"ipup-script PATH",
|
||||
"Configure name/path of ip-up script\n"
|
||||
"File/Path name of ip-up script\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
osmo_talloc_replace_string(apn, &apn->tun.cfg.ipup_script, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_ipup_script, cfg_apn_no_ipup_script_cmd,
|
||||
"no ipup-script",
|
||||
NO_STR "Disable ip-up script\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
talloc_free(apn->tun.cfg.ipup_script);
|
||||
apn->tun.cfg.ipup_script = NULL;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ipdown_script, cfg_apn_ipdown_script_cmd,
|
||||
"ipdown-script PATH",
|
||||
"Configure name/path of ip-down script\n"
|
||||
"File/Path name of ip-down script\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
osmo_talloc_replace_string(apn, &apn->tun.cfg.ipdown_script, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* convert prefix from "A.B.C.D/M" notation to in46_prefix */
|
||||
static void str2prefix(struct in46_prefix *pfx, const char *in)
|
||||
{
|
||||
size_t t;
|
||||
|
||||
ippool_aton(&pfx->addr, &t, in, 0);
|
||||
pfx->prefixlen = t;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_ipdown_script, cfg_apn_no_ipdown_script_cmd,
|
||||
"no ipdown-script",
|
||||
NO_STR "Disable ip-down script\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
talloc_free(apn->tun.cfg.ipdown_script);
|
||||
apn->tun.cfg.ipdown_script = NULL;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ip_prefix, cfg_apn_ip_prefix_cmd,
|
||||
"ip prefix (static|dynamic) A.B.C.D/M",
|
||||
IP_STR PREFIX_STR "IPv4 Adress/Prefix-Length\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
struct in46_prefix *pfx;
|
||||
|
||||
/* first update our parsed prefix */
|
||||
if (!strcmp(argv[0], "static"))
|
||||
pfx = &apn->v4.cfg.static_prefix;
|
||||
else
|
||||
pfx = &apn->v4.cfg.dynamic_prefix;
|
||||
str2prefix(pfx, argv[1]);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ip_ifconfig, cfg_apn_ip_ifconfig_cmd,
|
||||
"ip ifconfig A.B.C.D/M",
|
||||
IP_STR IFCONFIG_STR "IPv4 Adress/Prefix-Length\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
str2prefix(&apn->v4.cfg.ifconfig_prefix, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_ip_ifconfig, cfg_apn_no_ip_ifconfig_cmd,
|
||||
"no ip ifconfig",
|
||||
NO_STR IP_STR IFCONFIG_STR)
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
memset(&apn->v4.cfg.ifconfig_prefix, 0, sizeof(apn->v4.cfg.ifconfig_prefix));
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ipv6_prefix, cfg_apn_ipv6_prefix_cmd,
|
||||
"ipv6 prefix (static|dynamic) X:X::X:X/M",
|
||||
IP6_STR PREFIX_STR "IPv6 Address/Prefix-Length\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
struct in46_prefix *pfx;
|
||||
|
||||
if (!strcmp(argv[0], "static"))
|
||||
pfx = &apn->v6.cfg.static_prefix;
|
||||
else
|
||||
pfx = &apn->v6.cfg.dynamic_prefix;
|
||||
str2prefix(pfx, argv[1]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ipv6_ifconfig, cfg_apn_ipv6_ifconfig_cmd,
|
||||
"ipv6 ifconfig X:X::X:X/M",
|
||||
IP6_STR IFCONFIG_STR "IPv6 Adress/Prefix-Length\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
str2prefix(&apn->v6.cfg.ifconfig_prefix, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_ipv6_ifconfig, cfg_apn_no_ipv6_ifconfig_cmd,
|
||||
"no ipv6 ifconfig",
|
||||
NO_STR IP6_STR IFCONFIG_STR)
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
memset(&apn->v6.cfg.ifconfig_prefix, 0, sizeof(apn->v6.cfg.ifconfig_prefix));
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define DNS_STRINGS "Configure DNS Server\n" "primary/secondary DNS\n" "IP address of DNS Sever\n"
|
||||
|
||||
DEFUN(cfg_apn_ip_dns, cfg_apn_ip_dns_cmd,
|
||||
"ip dns <0-1> A.B.C.D",
|
||||
IP_STR DNS_STRINGS)
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
int idx = atoi(argv[0]);
|
||||
size_t dummy;
|
||||
|
||||
ippool_aton(&apn->v4.cfg.dns[idx], &dummy, argv[1], 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_ipv6_dns, cfg_apn_ipv6_dns_cmd,
|
||||
"ipv6 dns <0-1> X:X::X:X",
|
||||
IP6_STR DNS_STRINGS)
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
int idx = atoi(argv[0]);
|
||||
size_t dummy;
|
||||
|
||||
ippool_aton(&apn->v6.cfg.dns[idx], &dummy, argv[1], 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_dns, cfg_apn_no_dns_cmd,
|
||||
"no (ip|ipv6) dns <0-1>",
|
||||
NO_STR IP_STR IP6_STR "Disable DNS Server\n" "primary/secondary DNS\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
struct in46_addr *a;
|
||||
int idx = atoi(argv[1]);
|
||||
|
||||
if (!strcmp(argv[0], "ip"))
|
||||
a = &apn->v4.cfg.dns[idx];
|
||||
else
|
||||
a = &apn->v6.cfg.dns[idx];
|
||||
|
||||
memset(a, 0, sizeof(*a));
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_shutdown, cfg_apn_shutdown_cmd,
|
||||
"shutdown",
|
||||
"Put the APN in administrative shut-down\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
|
||||
if (!apn->cfg.shutdown) {
|
||||
if (apn_stop(apn, false)) {
|
||||
vty_out(vty, "%% Failed to Stop APN%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
apn->cfg.shutdown = true;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_apn_no_shutdown, cfg_apn_no_shutdown_cmd,
|
||||
"no shutdown",
|
||||
NO_STR "Remove the APN from administrative shut-down\n")
|
||||
{
|
||||
struct apn_ctx *apn = (struct apn_ctx *) vty->index;
|
||||
|
||||
if (apn->cfg.shutdown) {
|
||||
if (apn_start(apn) < 0) {
|
||||
vty_out(vty, "%% Failed to start APN, check log for details%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
apn->cfg.shutdown = false;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void vty_dump_prefix(struct vty *vty, const char *pre, const struct in46_prefix *pfx)
|
||||
{
|
||||
vty_out(vty, "%s %s%s", pre, in46p_ntoa(pfx), VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static void config_write_apn(struct vty *vty, struct apn_ctx *apn)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
vty_out(vty, " apn %s%s", apn->cfg.name, VTY_NEWLINE);
|
||||
if (apn->cfg.description)
|
||||
vty_out(vty, " description %s%s", apn->cfg.description, VTY_NEWLINE);
|
||||
vty_out(vty, " gtpu-mode %s%s", get_value_string(apn_gtpu_mode_names, apn->cfg.gtpu_mode),
|
||||
VTY_NEWLINE);
|
||||
if (apn->tun.cfg.dev_name)
|
||||
vty_out(vty, " tun-device %s%s", apn->tun.cfg.dev_name, VTY_NEWLINE);
|
||||
if (apn->tun.cfg.ipup_script)
|
||||
vty_out(vty, " ipup-script %s%s", apn->tun.cfg.ipup_script, VTY_NEWLINE);
|
||||
if (apn->tun.cfg.ipdown_script)
|
||||
vty_out(vty, " ipdown-script %s%s", apn->tun.cfg.ipdown_script, VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (!(apn->cfg.apn_type_mask & (1 << i)))
|
||||
continue;
|
||||
vty_out(vty, " type-support %s%s", get_value_string(pdp_type_names, (1 << i)),
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
/* IPv4 prefixes + DNS */
|
||||
if (apn->v4.cfg.static_prefix.addr.len)
|
||||
vty_dump_prefix(vty, " ip prefix static", &apn->v4.cfg.static_prefix);
|
||||
if (apn->v4.cfg.dynamic_prefix.addr.len)
|
||||
vty_dump_prefix(vty, " ip prefix dynamic", &apn->v4.cfg.dynamic_prefix);
|
||||
for (i = 0; i < ARRAY_SIZE(apn->v4.cfg.dns); i++) {
|
||||
if (!apn->v4.cfg.dns[i].len)
|
||||
continue;
|
||||
vty_out(vty, " ip dns %u %s%s", i, in46a_ntoa(&apn->v4.cfg.dns[i]), VTY_NEWLINE);
|
||||
}
|
||||
if (apn->v4.cfg.ifconfig_prefix.addr.len)
|
||||
vty_dump_prefix(vty, " ip ifconfig ", &apn->v4.cfg.ifconfig_prefix);
|
||||
|
||||
/* IPv6 prefixes + DNS */
|
||||
if (apn->v6.cfg.static_prefix.addr.len)
|
||||
vty_dump_prefix(vty, " ipv6 prefix static", &apn->v6.cfg.static_prefix);
|
||||
if (apn->v6.cfg.dynamic_prefix.addr.len)
|
||||
vty_dump_prefix(vty, " ipv6 prefix dynamic", &apn->v6.cfg.dynamic_prefix);
|
||||
for (i = 0; i < ARRAY_SIZE(apn->v6.cfg.dns); i++) {
|
||||
if (!apn->v6.cfg.dns[i].len)
|
||||
continue;
|
||||
vty_out(vty, " ip dns %u %s%s", i, in46a_ntoa(&apn->v6.cfg.dns[i]), VTY_NEWLINE);
|
||||
}
|
||||
if (apn->v6.cfg.ifconfig_prefix.addr.len)
|
||||
vty_dump_prefix(vty, " ipv6 ifconfig ", &apn->v6.cfg.ifconfig_prefix);
|
||||
|
||||
/* must be last */
|
||||
vty_out(vty, " %sshutdown%s", apn->cfg.shutdown ? "" : "no ", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
static int config_write_ggsn(struct vty *vty)
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
|
||||
llist_for_each_entry(ggsn, &g_ggsn_list, list) {
|
||||
struct apn_ctx *apn;
|
||||
vty_out(vty, "ggsn %s%s", ggsn->cfg.name, VTY_NEWLINE);
|
||||
if (ggsn->cfg.description)
|
||||
vty_out(vty, " description %s%s", ggsn->cfg.description, VTY_NEWLINE);
|
||||
vty_out(vty, " gtp state-dir %s%s", ggsn->cfg.state_dir, VTY_NEWLINE);
|
||||
vty_out(vty, " gtp local-ip %s%s", in46a_ntoa(&ggsn->cfg.listen_addr), VTY_NEWLINE);
|
||||
llist_for_each_entry(apn, &ggsn->apn_list, list)
|
||||
config_write_apn(vty, apn);
|
||||
if (ggsn->cfg.default_apn)
|
||||
vty_out(vty, " default-apn %s%s", ggsn->cfg.default_apn->cfg.name, VTY_NEWLINE);
|
||||
/* must be last */
|
||||
vty_out(vty, " %sshutdown ggsn%s", ggsn->cfg.shutdown ? "" : "no ", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *print_gsnaddr(const struct ul16_t *in)
|
||||
{
|
||||
struct in46_addr in46;
|
||||
|
||||
in46.len = in->l;
|
||||
OSMO_ASSERT(in->l <= sizeof(in46.v6));
|
||||
memcpy(&in46.v6, in->v, in->l);
|
||||
|
||||
return in46a_ntoa(&in46);
|
||||
}
|
||||
|
||||
static void show_one_pdp(struct vty *vty, struct pdp_t *pdp)
|
||||
{
|
||||
struct in46_addr eua46;
|
||||
|
||||
vty_out(vty, "IMSI: %s, NSAPI: %u, MSISDN: %s%s", imsi_gtp2str(&pdp->imsi), pdp->nsapi,
|
||||
osmo_hexdump_nospc(pdp->msisdn.v, pdp->msisdn.l), VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " Control: %s:%08x ", print_gsnaddr(&pdp->gsnlc), pdp->teic_own);
|
||||
vty_out(vty, "<-> %s:%08x%s", print_gsnaddr(&pdp->gsnrc), pdp->teic_gn, VTY_NEWLINE);
|
||||
|
||||
vty_out(vty, " Data: %s:%08x ", print_gsnaddr(&pdp->gsnlu), pdp->teid_own);
|
||||
vty_out(vty, "<-> %s:%08x%s", print_gsnaddr(&pdp->gsnru), pdp->teid_gn, VTY_NEWLINE);
|
||||
|
||||
in46a_from_eua(&pdp->eua, &eua46);
|
||||
vty_out(vty, " End-User Address: %s%s", in46a_ntoa(&eua46), VTY_NEWLINE);
|
||||
}
|
||||
|
||||
DEFUN(show_pdpctx_imsi, show_pdpctx_imsi_cmd,
|
||||
"show pdp-context imsi IMSI [<0-15>]",
|
||||
SHOW_STR "Display information on PDP Context\n"
|
||||
"PDP contexts for given IMSI\n"
|
||||
"PDP context for given NSAPI\n")
|
||||
{
|
||||
uint64_t imsi = strtoull(argv[0], NULL, 10);
|
||||
unsigned int nsapi;
|
||||
struct pdp_t *pdp;
|
||||
int num_found = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
nsapi = atoi(argv[1]);
|
||||
if (pdp_getimsi(&pdp, imsi, nsapi)) {
|
||||
show_one_pdp(vty, pdp);
|
||||
num_found++;
|
||||
}
|
||||
} else {
|
||||
for (nsapi = 0; nsapi < PDP_MAXNSAPI; nsapi++) {
|
||||
if (pdp_getimsi(&pdp, imsi, nsapi))
|
||||
continue;
|
||||
show_one_pdp(vty, pdp);
|
||||
num_found++;
|
||||
}
|
||||
}
|
||||
if (num_found == 0) {
|
||||
vty_out(vty, "%% No such PDP context found%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
} else
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* show all (active) PDP contexts within a pool */
|
||||
static void ippool_show_pdp_contexts(struct vty *vty, struct ippool_t *pool)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
for (i = 0; i < pool->listsize; i++) {
|
||||
struct ippoolm_t *member = &pool->member[i];
|
||||
if (member->inuse == 0)
|
||||
continue;
|
||||
show_one_pdp(vty, member->peer);
|
||||
}
|
||||
}
|
||||
|
||||
/* show all (active) PDP contexts within an APN */
|
||||
static void apn_show_pdp_contexts(struct vty *vty, struct apn_ctx *apn)
|
||||
{
|
||||
ippool_show_pdp_contexts(vty, apn->v4.pool);
|
||||
ippool_show_pdp_contexts(vty, apn->v6.pool);
|
||||
}
|
||||
|
||||
DEFUN(show_pdpctx, show_pdpctx_cmd,
|
||||
"show pdp-context ggsn NAME [apn APN]",
|
||||
SHOW_STR "Show PDP Context Information\n"
|
||||
GGSN_STR "GGSN Name\n") // FIXME
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
struct apn_ctx *apn;
|
||||
|
||||
ggsn = ggsn_find(argv[0]);
|
||||
if (!ggsn) {
|
||||
vty_out(vty, "%% No such GGSN '%s'%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (argc < 2) {
|
||||
llist_for_each_entry(apn, &ggsn->apn_list, list)
|
||||
apn_show_pdp_contexts(vty, apn);
|
||||
} else {
|
||||
apn = ggsn_find_apn(ggsn, argv[1]);
|
||||
if (!apn) {
|
||||
vty_out(vty, "%% No such APN '%s'%s", argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
apn_show_pdp_contexts(vty, apn);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void show_apn(struct vty *vty, struct apn_ctx *apn)
|
||||
{
|
||||
vty_out(vty, " APN: %s%s", apn->cfg.name, VTY_NEWLINE);
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
static void show_one_ggsn(struct vty *vty, struct ggsn_ctx *ggsn)
|
||||
{
|
||||
struct apn_ctx *apn;
|
||||
vty_out(vty, "GGSN %s: Bound to %s%s", ggsn->cfg.name, in46a_ntoa(&ggsn->cfg.listen_addr),
|
||||
VTY_NEWLINE);
|
||||
/* FIXME */
|
||||
|
||||
llist_for_each_entry(apn, &ggsn->apn_list, list)
|
||||
show_apn(vty, apn);
|
||||
}
|
||||
|
||||
DEFUN(show_ggsn, show_ggsn_cmd,
|
||||
"show ggsn [NAME]",
|
||||
SHOW_STR "Display information on the GGSN\n")
|
||||
{
|
||||
struct ggsn_ctx *ggsn;
|
||||
|
||||
if (argc == 0) {
|
||||
llist_for_each_entry(ggsn, &g_ggsn_list, list)
|
||||
show_one_ggsn(vty, ggsn);
|
||||
} else {
|
||||
ggsn = ggsn_find(argv[0]);
|
||||
if (!ggsn)
|
||||
return CMD_WARNING;
|
||||
show_one_ggsn(vty, ggsn);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int ggsn_vty_init(void)
|
||||
{
|
||||
install_element_ve(&show_pdpctx_cmd);
|
||||
install_element_ve(&show_pdpctx_imsi_cmd);
|
||||
install_element_ve(&show_ggsn_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_ggsn_cmd);
|
||||
install_element(CONFIG_NODE, &cfg_no_ggsn_cmd);
|
||||
install_node(&ggsn_node, config_write_ggsn);
|
||||
vty_install_default(GGSN_NODE);
|
||||
install_element(GGSN_NODE, &cfg_description_cmd);
|
||||
install_element(GGSN_NODE, &cfg_no_description_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_shutdown_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_no_shutdown_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_local_ip_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_state_dir_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_apn_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_no_apn_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_default_apn_cmd);
|
||||
install_element(GGSN_NODE, &cfg_ggsn_no_default_apn_cmd);
|
||||
|
||||
install_node(&apn_node, NULL);
|
||||
vty_install_default(APN_NODE);
|
||||
install_element(APN_NODE, &cfg_description_cmd);
|
||||
install_element(APN_NODE, &cfg_no_description_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_shutdown_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_shutdown_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_gtpu_mode_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_type_support_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_type_support_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_tun_dev_name_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ipup_script_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_ipup_script_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ipdown_script_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_ipdown_script_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ip_prefix_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ipv6_prefix_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ip_dns_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ipv6_dns_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_dns_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ip_ifconfig_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_ip_ifconfig_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_ipv6_ifconfig_cmd);
|
||||
install_element(APN_NODE, &cfg_apn_no_ipv6_ifconfig_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ggsn_vty_is_config_node(struct vty *vty, int node)
|
||||
{
|
||||
switch (node) {
|
||||
case GGSN_NODE:
|
||||
case APN_NODE:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int ggsn_vty_go_parent(struct vty *vty)
|
||||
{
|
||||
switch (vty->node) {
|
||||
case GGSN_NODE:
|
||||
vty->node = CONFIG_NODE;
|
||||
vty->index = NULL;
|
||||
vty->index_sub = NULL;
|
||||
break;
|
||||
case APN_NODE:
|
||||
vty->node = GGSN_NODE;
|
||||
{
|
||||
struct apn_ctx *apn = vty->index;
|
||||
vty->index = apn->ggsn;
|
||||
vty->index_sub = &apn->ggsn->cfg.description;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return vty->node;
|
||||
}
|
||||
|
||||
static const char ggsn_copyright[] =
|
||||
"Copyright (C) 2011-2017 Harald Welte <laforge@gnumonks.org>\r\n"
|
||||
"Copyright (C) 2012-2017 Holger Hans Peter Freyther <holger@moiji-mobile.com>\r\n"
|
||||
"Copyright (C) 2012-2017 sysmocom - s.f.m.c. GmbH\r\n"
|
||||
"Copyright (C) 2002-2005 Mondru AB\r\n"
|
||||
"License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl-2.0.html>\r\n"
|
||||
"This is free software: you are free to change and redistribute it.\r\n"
|
||||
"There is NO WARRANTY, to the extent permitted by law.\r\n";
|
||||
|
||||
struct vty_app_info g_vty_info = {
|
||||
.name = "OpenGGSN",
|
||||
.version = PACKAGE_VERSION,
|
||||
.copyright = ggsn_copyright,
|
||||
.go_parent_cb = ggsn_vty_go_parent,
|
||||
.is_config_node = ggsn_vty_is_config_node,
|
||||
};
|
|
@ -583,7 +583,7 @@ int tun_delroute(struct tun_t *this,
|
|||
return tun_route(this, dst, gateway, mask, 1);
|
||||
}
|
||||
|
||||
int tun_new(struct tun_t **tun)
|
||||
int tun_new(struct tun_t **tun, const char *dev_name)
|
||||
{
|
||||
|
||||
#if defined(__linux__)
|
||||
|
@ -615,6 +615,8 @@ int tun_new(struct tun_t **tun)
|
|||
/* Set device flags. For some weird reason this is also the method
|
||||
used to obtain the network interface name */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
if (dev_name)
|
||||
strcpy(ifr.ifr_name, dev_name);
|
||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI; /* Tun device, no packet info */
|
||||
if (ioctl((*tun)->fd, TUNSETIFF, (void *)&ifr) < 0) {
|
||||
SYS_ERR(DTUN, LOGL_ERROR, errno, "ioctl() failed");
|
||||
|
|
|
@ -65,7 +65,7 @@ struct tun_t {
|
|||
void *priv;
|
||||
};
|
||||
|
||||
extern int tun_new(struct tun_t **tun);
|
||||
extern int tun_new(struct tun_t **tun, const char *dev_name);
|
||||
extern int tun_free(struct tun_t *tun);
|
||||
extern int tun_decaps(struct tun_t *this);
|
||||
extern int tun_encaps(struct tun_t *tun, void *pack, unsigned len);
|
||||
|
|
|
@ -1461,7 +1461,7 @@ int main(int argc, char **argv)
|
|||
if (options.createif) {
|
||||
printf("Setting up interface\n");
|
||||
/* Create a tunnel interface */
|
||||
if (tun_new((struct tun_t **)&tun)) {
|
||||
if (tun_new((struct tun_t **)&tun, NULL)) {
|
||||
SYS_ERR(DSGSN, LOGL_ERROR, 0,
|
||||
"Failed to create tun");
|
||||
exit(1);
|
||||
|
|
Reference in New Issue