aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2017-07-04 23:08:44 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2017-08-27 03:52:43 +0200
commit218e4b4aa0fc6de842ff820dec8e97d1f083268a (patch)
tree268a6e509270b1c80a36dd1a526da41a9b01a8e0 /include
parent5ea6bfce56d6ae7be6d85e05b5e4eaebc94d1005 (diff)
move openbsc/* to repos root
This is the first step in creating this repository from the legacy openbsc.git. Like all other Osmocom repositories, keep the autoconf and automake files in the repository root. openbsc.git has been the sole exception, which ends now. Change-Id: I9c6f2a448d9cb1cc088cf1cf6918b69d7e69b4e7
Diffstat (limited to 'include')
-rw-r--r--include/Makefile.am8
-rw-r--r--include/compat_af_isdn.h39
-rw-r--r--include/mISDNif.h387
-rw-r--r--include/openbsc/Makefile.am100
-rw-r--r--include/openbsc/abis_nm.h180
-rw-r--r--include/openbsc/abis_om2000.h129
-rw-r--r--include/openbsc/abis_rsl.h118
-rw-r--r--include/openbsc/arfcn_range_encode.h26
-rw-r--r--include/openbsc/auth.h26
-rw-r--r--include/openbsc/bsc_api.h55
-rw-r--r--include/openbsc/bsc_msc.h65
-rw-r--r--include/openbsc/bsc_msc_data.h142
-rw-r--r--include/openbsc/bsc_msg_filter.h107
-rw-r--r--include/openbsc/bsc_nat.h462
-rw-r--r--include/openbsc/bsc_nat_callstats.h55
-rw-r--r--include/openbsc/bsc_nat_sccp.h105
-rw-r--r--include/openbsc/bsc_rll.h19
-rw-r--r--include/openbsc/bsc_subscriber.h43
-rw-r--r--include/openbsc/bss.h20
-rw-r--r--include/openbsc/bts_ipaccess_nanobts_omlattr.h32
-rw-r--r--include/openbsc/chan_alloc.h54
-rw-r--r--include/openbsc/common_bsc.h9
-rw-r--r--include/openbsc/common_cs.h27
-rw-r--r--include/openbsc/crc24.h10
-rw-r--r--include/openbsc/ctrl.h4
-rw-r--r--include/openbsc/db.h86
-rw-r--r--include/openbsc/debug.h49
-rw-r--r--include/openbsc/e1_config.h11
-rw-r--r--include/openbsc/gb_proxy.h288
-rw-r--r--include/openbsc/gprs_gb_parse.h59
-rw-r--r--include/openbsc/gprs_gmm.h35
-rw-r--r--include/openbsc/gprs_llc.h284
-rw-r--r--include/openbsc/gprs_llc_xid.h57
-rw-r--r--include/openbsc/gprs_sgsn.h473
-rw-r--r--include/openbsc/gprs_sndcp.h79
-rw-r--r--include/openbsc/gprs_sndcp_comp.h82
-rw-r--r--include/openbsc/gprs_sndcp_dcomp.h53
-rw-r--r--include/openbsc/gprs_sndcp_pcomp.h46
-rw-r--r--include/openbsc/gprs_sndcp_xid.h218
-rw-r--r--include/openbsc/gprs_subscriber.h31
-rw-r--r--include/openbsc/gprs_utils.h45
-rw-r--r--include/openbsc/gsm_04_08.h85
-rw-r--r--include/openbsc/gsm_04_11.h47
-rw-r--r--include/openbsc/gsm_04_80.h25
-rw-r--r--include/openbsc/gsm_data.h596
-rw-r--r--include/openbsc/gsm_data_shared.h994
-rw-r--r--include/openbsc/gsm_subscriber.h130
-rw-r--r--include/openbsc/gsup_client.h60
-rw-r--r--include/openbsc/gtphub.h523
-rw-r--r--include/openbsc/handover.h14
-rw-r--r--include/openbsc/handover_decision.h7
-rw-r--r--include/openbsc/ipaccess.h52
-rw-r--r--include/openbsc/iu.h62
-rw-r--r--include/openbsc/meas_feed.h41
-rw-r--r--include/openbsc/meas_rep.h67
-rw-r--r--include/openbsc/mgcp.h285
-rw-r--r--include/openbsc/mgcp_internal.h342
-rw-r--r--include/openbsc/mgcp_transcode.h90
-rw-r--r--include/openbsc/misdn.h27
-rw-r--r--include/openbsc/mncc.h219
-rw-r--r--include/openbsc/mncc_int.h14
-rw-r--r--include/openbsc/nat_rewrite_trie.h47
-rw-r--r--include/openbsc/network_listen.h16
-rw-r--r--include/openbsc/oap_client.h82
-rw-r--r--include/openbsc/openbscdefines.h34
-rw-r--r--include/openbsc/osmo_bsc.h71
-rw-r--r--include/openbsc/osmo_bsc_grace.h35
-rw-r--r--include/openbsc/osmo_bsc_rf.h66
-rw-r--r--include/openbsc/osmo_msc.h11
-rw-r--r--include/openbsc/osmux.h42
-rw-r--r--include/openbsc/paging.h77
-rw-r--r--include/openbsc/pcu_if.h35
-rw-r--r--include/openbsc/pcuif_proto.h176
-rw-r--r--include/openbsc/rest_octets.h139
-rw-r--r--include/openbsc/rrlp.h7
-rw-r--r--include/openbsc/rs232.h9
-rw-r--r--include/openbsc/rtp_proxy.h95
-rw-r--r--include/openbsc/sgsn.h186
-rw-r--r--include/openbsc/signal.h262
-rw-r--r--include/openbsc/silent_call.h15
-rw-r--r--include/openbsc/slhc.h187
-rw-r--r--include/openbsc/smpp.h4
-rw-r--r--include/openbsc/sms_queue.h17
-rw-r--r--include/openbsc/socket.h14
-rw-r--r--include/openbsc/system_information.h22
-rw-r--r--include/openbsc/token_auth.h7
-rw-r--r--include/openbsc/transaction.h79
-rw-r--r--include/openbsc/trau_mux.h70
-rw-r--r--include/openbsc/trau_upqueue.h7
-rw-r--r--include/openbsc/ussd.h10
-rw-r--r--include/openbsc/v42bis.h147
-rw-r--r--include/openbsc/v42bis_private.h126
-rw-r--r--include/openbsc/vty.h51
93 files changed, 9944 insertions, 0 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 000000000..3234e6265
--- /dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,8 @@
+SUBDIRS = \
+ openbsc \
+ $(NULL)
+
+noinst_HEADERS = \
+ mISDNif.h \
+ compat_af_isdn.h \
+ $(NULL)
diff --git a/include/compat_af_isdn.h b/include/compat_af_isdn.h
new file mode 100644
index 000000000..56cbfb3f2
--- /dev/null
+++ b/include/compat_af_isdn.h
@@ -0,0 +1,39 @@
+#ifdef MISDN_OLD_AF_COMPATIBILITY
+#undef AF_ISDN
+#undef PF_ISDN
+
+extern int AF_ISDN;
+#define PF_ISDN AF_ISDN
+
+int AF_ISDN;
+
+#endif
+
+extern void init_af_isdn(void);
+
+#ifdef AF_COMPATIBILITY_FUNC
+#ifdef MISDN_OLD_AF_COMPATIBILITY
+void init_af_isdn(void)
+{
+ int s;
+
+ /* test for new value */
+ AF_ISDN = 34;
+ s = socket(AF_ISDN, SOCK_RAW, ISDN_P_BASE);
+ if (s >= 0) {
+ close(s);
+ return;
+ }
+ AF_ISDN = 27;
+ s = socket(AF_ISDN, SOCK_RAW, ISDN_P_BASE);
+ if (s >= 0) {
+ close(s);
+ return;
+ }
+}
+#else
+void init_af_isdn(void)
+{
+}
+#endif
+#endif
diff --git a/include/mISDNif.h b/include/mISDNif.h
new file mode 100644
index 000000000..8e065d24b
--- /dev/null
+++ b/include/mISDNif.h
@@ -0,0 +1,387 @@
+/*
+ *
+ * Author Karsten Keil <kkeil@novell.com>
+ *
+ * Copyright 2008 by Karsten Keil <kkeil@novell.com>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
+ *
+ */
+
+#ifndef mISDNIF_H
+#define mISDNIF_H
+
+#include <stdarg.h>
+#ifdef linux
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/socket.h>
+#else
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#endif
+
+/*
+ * ABI Version 32 bit
+ *
+ * <8 bit> Major version
+ * - changed if any interface become backwards incompatible
+ *
+ * <8 bit> Minor version
+ * - changed if any interface is extended but backwards compatible
+ *
+ * <16 bit> Release number
+ * - should be incremented on every checkin
+ */
+#define MISDN_MAJOR_VERSION 1
+#define MISDN_MINOR_VERSION 1
+#define MISDN_RELEASE 20
+
+/* primitives for information exchange
+ * generell format
+ * <16 bit 0 >
+ * <8 bit command>
+ * BIT 8 = 1 LAYER private
+ * BIT 7 = 1 answer
+ * BIT 6 = 1 DATA
+ * <8 bit target layer mask>
+ *
+ * Layer = 00 is reserved for general commands
+ Layer = 01 L2 -> HW
+ Layer = 02 HW -> L2
+ Layer = 04 L3 -> L2
+ Layer = 08 L2 -> L3
+ * Layer = FF is reserved for broadcast commands
+ */
+
+#define MISDN_CMDMASK 0xff00
+#define MISDN_LAYERMASK 0x00ff
+
+/* generell commands */
+#define OPEN_CHANNEL 0x0100
+#define CLOSE_CHANNEL 0x0200
+#define CONTROL_CHANNEL 0x0300
+#define CHECK_DATA 0x0400
+
+/* layer 2 -> layer 1 */
+#define PH_ACTIVATE_REQ 0x0101
+#define PH_DEACTIVATE_REQ 0x0201
+#define PH_DATA_REQ 0x2001
+#define MPH_ACTIVATE_REQ 0x0501
+#define MPH_DEACTIVATE_REQ 0x0601
+#define MPH_INFORMATION_REQ 0x0701
+#define PH_CONTROL_REQ 0x0801
+
+/* layer 1 -> layer 2 */
+#define PH_ACTIVATE_IND 0x0102
+#define PH_ACTIVATE_CNF 0x4102
+#define PH_DEACTIVATE_IND 0x0202
+#define PH_DEACTIVATE_CNF 0x4202
+#define PH_DATA_IND 0x2002
+#define PH_DATA_E_IND 0x3002
+#define MPH_ACTIVATE_IND 0x0502
+#define MPH_DEACTIVATE_IND 0x0602
+#define MPH_INFORMATION_IND 0x0702
+#define PH_DATA_CNF 0x6002
+#define PH_CONTROL_IND 0x0802
+#define PH_CONTROL_CNF 0x4802
+
+/* layer 3 -> layer 2 */
+#define DL_ESTABLISH_REQ 0x1004
+#define DL_RELEASE_REQ 0x1104
+#define DL_DATA_REQ 0x3004
+#define DL_UNITDATA_REQ 0x3104
+#define DL_INFORMATION_REQ 0x0004
+
+/* layer 2 -> layer 3 */
+#define DL_ESTABLISH_IND 0x1008
+#define DL_ESTABLISH_CNF 0x5008
+#define DL_RELEASE_IND 0x1108
+#define DL_RELEASE_CNF 0x5108
+#define DL_DATA_IND 0x3008
+#define DL_UNITDATA_IND 0x3108
+#define DL_INFORMATION_IND 0x0008
+
+/* intern layer 2 managment */
+#define MDL_ASSIGN_REQ 0x1804
+#define MDL_ASSIGN_IND 0x1904
+#define MDL_REMOVE_REQ 0x1A04
+#define MDL_REMOVE_IND 0x1B04
+#define MDL_STATUS_UP_IND 0x1C04
+#define MDL_STATUS_DOWN_IND 0x1D04
+#define MDL_STATUS_UI_IND 0x1E04
+#define MDL_ERROR_IND 0x1F04
+#define MDL_ERROR_RSP 0x5F04
+
+/* DL_INFORMATION_IND types */
+#define DL_INFO_L2_CONNECT 0x0001
+#define DL_INFO_L2_REMOVED 0x0002
+
+/* PH_CONTROL types */
+/* TOUCH TONE IS 0x20XX XX "0"..."9", "A","B","C","D","*","#" */
+#define DTMF_TONE_VAL 0x2000
+#define DTMF_TONE_MASK 0x007F
+#define DTMF_TONE_START 0x2100
+#define DTMF_TONE_STOP 0x2200
+#define DTMF_HFC_COEF 0x4000
+#define DSP_CONF_JOIN 0x2403
+#define DSP_CONF_SPLIT 0x2404
+#define DSP_RECEIVE_OFF 0x2405
+#define DSP_RECEIVE_ON 0x2406
+#define DSP_ECHO_ON 0x2407
+#define DSP_ECHO_OFF 0x2408
+#define DSP_MIX_ON 0x2409
+#define DSP_MIX_OFF 0x240a
+#define DSP_DELAY 0x240b
+#define DSP_JITTER 0x240c
+#define DSP_TXDATA_ON 0x240d
+#define DSP_TXDATA_OFF 0x240e
+#define DSP_TX_DEJITTER 0x240f
+#define DSP_TX_DEJ_OFF 0x2410
+#define DSP_TONE_PATT_ON 0x2411
+#define DSP_TONE_PATT_OFF 0x2412
+#define DSP_VOL_CHANGE_TX 0x2413
+#define DSP_VOL_CHANGE_RX 0x2414
+#define DSP_BF_ENABLE_KEY 0x2415
+#define DSP_BF_DISABLE 0x2416
+#define DSP_BF_ACCEPT 0x2416
+#define DSP_BF_REJECT 0x2417
+#define DSP_PIPELINE_CFG 0x2418
+#define HFC_VOL_CHANGE_TX 0x2601
+#define HFC_VOL_CHANGE_RX 0x2602
+#define HFC_SPL_LOOP_ON 0x2603
+#define HFC_SPL_LOOP_OFF 0x2604
+
+/* DSP_TONE_PATT_ON parameter */
+#define TONE_OFF 0x0000
+#define TONE_GERMAN_DIALTONE 0x0001
+#define TONE_GERMAN_OLDDIALTONE 0x0002
+#define TONE_AMERICAN_DIALTONE 0x0003
+#define TONE_GERMAN_DIALPBX 0x0004
+#define TONE_GERMAN_OLDDIALPBX 0x0005
+#define TONE_AMERICAN_DIALPBX 0x0006
+#define TONE_GERMAN_RINGING 0x0007
+#define TONE_GERMAN_OLDRINGING 0x0008
+#define TONE_AMERICAN_RINGPBX 0x000b
+#define TONE_GERMAN_RINGPBX 0x000c
+#define TONE_GERMAN_OLDRINGPBX 0x000d
+#define TONE_AMERICAN_RINGING 0x000e
+#define TONE_GERMAN_BUSY 0x000f
+#define TONE_GERMAN_OLDBUSY 0x0010
+#define TONE_AMERICAN_BUSY 0x0011
+#define TONE_GERMAN_HANGUP 0x0012
+#define TONE_GERMAN_OLDHANGUP 0x0013
+#define TONE_AMERICAN_HANGUP 0x0014
+#define TONE_SPECIAL_INFO 0x0015
+#define TONE_GERMAN_GASSENBESETZT 0x0016
+#define TONE_GERMAN_AUFSCHALTTON 0x0016
+
+/* MPH_INFORMATION_IND */
+#define L1_SIGNAL_LOS_OFF 0x0010
+#define L1_SIGNAL_LOS_ON 0x0011
+#define L1_SIGNAL_AIS_OFF 0x0012
+#define L1_SIGNAL_AIS_ON 0x0013
+#define L1_SIGNAL_RDI_OFF 0x0014
+#define L1_SIGNAL_RDI_ON 0x0015
+#define L1_SIGNAL_SLIP_RX 0x0020
+#define L1_SIGNAL_SLIP_TX 0x0021
+
+/*
+ * protocol ids
+ * D channel 1-31
+ * B channel 33 - 63
+ */
+
+#define ISDN_P_NONE 0
+#define ISDN_P_BASE 0
+#define ISDN_P_TE_S0 0x01
+#define ISDN_P_NT_S0 0x02
+#define ISDN_P_TE_E1 0x03
+#define ISDN_P_NT_E1 0x04
+#define ISDN_P_TE_UP0 0x05
+#define ISDN_P_NT_UP0 0x06
+
+#define IS_ISDN_P_TE(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_TE_E1) || \
+ (p == ISDN_P_TE_UP0) || (p == ISDN_P_LAPD_TE))
+#define IS_ISDN_P_NT(p) ((p == ISDN_P_NT_S0) || (p == ISDN_P_NT_E1) || \
+ (p == ISDN_P_NT_UP0) || (p == ISDN_P_LAPD_NT))
+#define IS_ISDN_P_S0(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_NT_S0))
+#define IS_ISDN_P_E1(p) ((p == ISDN_P_TE_E1) || (p == ISDN_P_NT_E1))
+#define IS_ISDN_P_UP0(p) ((p == ISDN_P_TE_UP0) || (p == ISDN_P_NT_UP0))
+
+
+#define ISDN_P_LAPD_TE 0x10
+#define ISDN_P_LAPD_NT 0x11
+
+#define ISDN_P_B_MASK 0x1f
+#define ISDN_P_B_START 0x20
+
+#define ISDN_P_B_RAW 0x21
+#define ISDN_P_B_HDLC 0x22
+#define ISDN_P_B_X75SLP 0x23
+#define ISDN_P_B_L2DTMF 0x24
+#define ISDN_P_B_L2DSP 0x25
+#define ISDN_P_B_L2DSPHDLC 0x26
+
+#define OPTION_L2_PMX 1
+#define OPTION_L2_PTP 2
+#define OPTION_L2_FIXEDTEI 3
+#define OPTION_L2_CLEANUP 4
+
+/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
+#define MISDN_MAX_IDLEN 20
+
+struct mISDNhead {
+ unsigned int prim;
+ unsigned int id;
+} __attribute__((packed));
+
+#define MISDN_HEADER_LEN sizeof(struct mISDNhead)
+#define MAX_DATA_SIZE 2048
+#define MAX_DATA_MEM (MAX_DATA_SIZE + MISDN_HEADER_LEN)
+#define MAX_DFRAME_LEN 260
+
+#define MISDN_ID_ADDR_MASK 0xFFFF
+#define MISDN_ID_TEI_MASK 0xFF00
+#define MISDN_ID_SAPI_MASK 0x00FF
+#define MISDN_ID_TEI_ANY 0x7F00
+
+#define MISDN_ID_ANY 0xFFFF
+#define MISDN_ID_NONE 0xFFFE
+
+#define GROUP_TEI 127
+#define TEI_SAPI 63
+#define CTRL_SAPI 0
+
+#define MISDN_MAX_CHANNEL 127
+#define MISDN_CHMAP_SIZE ((MISDN_MAX_CHANNEL + 1) >> 3)
+
+#define SOL_MISDN 0
+
+struct sockaddr_mISDN {
+ sa_family_t family;
+ unsigned char dev;
+ unsigned char channel;
+ unsigned char sapi;
+ unsigned char tei;
+};
+
+struct mISDNversion {
+ unsigned char major;
+ unsigned char minor;
+ unsigned short release;
+};
+
+#define MAX_DEVICE_ID 63
+
+struct mISDN_devinfo {
+ u_int id;
+ u_int Dprotocols;
+ u_int Bprotocols;
+ u_int protocol;
+ u_char channelmap[MISDN_CHMAP_SIZE];
+ u_int nrbchan;
+ char name[MISDN_MAX_IDLEN];
+};
+
+struct mISDN_devrename {
+ u_int id;
+ char name[MISDN_MAX_IDLEN];
+};
+
+struct ph_info_ch {
+ int32_t protocol;
+ int64_t Flags;
+};
+
+struct ph_info_dch {
+ struct ph_info_ch ch;
+ int16_t state;
+ int16_t num_bch;
+};
+
+struct ph_info {
+ struct ph_info_dch dch;
+ struct ph_info_ch bch[];
+};
+
+/* timer device ioctl */
+#define IMADDTIMER _IOR('I', 64, int)
+#define IMDELTIMER _IOR('I', 65, int)
+/* socket ioctls */
+#define IMGETVERSION _IOR('I', 66, int)
+#define IMGETCOUNT _IOR('I', 67, int)
+#define IMGETDEVINFO _IOR('I', 68, int)
+#define IMCTRLREQ _IOR('I', 69, int)
+#define IMCLEAR_L2 _IOR('I', 70, int)
+#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename)
+
+static inline int
+test_channelmap(u_int nr, u_char *map)
+{
+ if (nr <= MISDN_MAX_CHANNEL)
+ return map[nr >> 3] & (1 << (nr & 7));
+ else
+ return 0;
+}
+
+static inline void
+set_channelmap(u_int nr, u_char *map)
+{
+ map[nr >> 3] |= (1 << (nr & 7));
+}
+
+static inline void
+clear_channelmap(u_int nr, u_char *map)
+{
+ map[nr >> 3] &= ~(1 << (nr & 7));
+}
+
+/* CONTROL_CHANNEL parameters */
+#define MISDN_CTRL_GETOP 0x0000
+#define MISDN_CTRL_LOOP 0x0001
+#define MISDN_CTRL_CONNECT 0x0002
+#define MISDN_CTRL_DISCONNECT 0x0004
+#define MISDN_CTRL_PCMCONNECT 0x0010
+#define MISDN_CTRL_PCMDISCONNECT 0x0020
+#define MISDN_CTRL_SETPEER 0x0040
+#define MISDN_CTRL_UNSETPEER 0x0080
+#define MISDN_CTRL_RX_OFF 0x0100
+#define MISDN_CTRL_FILL_EMPTY 0x0200
+#define MISDN_CTRL_GETPEER 0x0400
+#define MISDN_CTRL_HW_FEATURES_OP 0x2000
+#define MISDN_CTRL_HW_FEATURES 0x2001
+#define MISDN_CTRL_HFC_OP 0x4000
+#define MISDN_CTRL_HFC_PCM_CONN 0x4001
+#define MISDN_CTRL_HFC_PCM_DISC 0x4002
+#define MISDN_CTRL_HFC_CONF_JOIN 0x4003
+#define MISDN_CTRL_HFC_CONF_SPLIT 0x4004
+#define MISDN_CTRL_HFC_RECEIVE_OFF 0x4005
+#define MISDN_CTRL_HFC_RECEIVE_ON 0x4006
+#define MISDN_CTRL_HFC_ECHOCAN_ON 0x4007
+#define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008
+
+
+/* socket options */
+#define MISDN_TIME_STAMP 0x0001
+
+struct mISDN_ctrl_req {
+ int op;
+ int channel;
+ int p1;
+ int p2;
+};
+
+/* muxer options */
+#define MISDN_OPT_ALL 1
+#define MISDN_OPT_TEIMGR 2
+
+#endif /* mISDNIF_H */
diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am
new file mode 100644
index 000000000..2740a5d07
--- /dev/null
+++ b/include/openbsc/Makefile.am
@@ -0,0 +1,100 @@
+noinst_HEADERS = \
+ abis_nm.h \
+ abis_om2000.h \
+ abis_rsl.h \
+ arfcn_range_encode.h \
+ auth.h \
+ bsc_msc.h \
+ bsc_msg_filter.h \
+ bsc_nat.h \
+ bsc_nat_callstats.h \
+ bsc_nat_sccp.h \
+ bsc_rll.h \
+ bsc_subscriber.h \
+ bss.h \
+ bts_ipaccess_nanobts_omlattr.h \
+ chan_alloc.h \
+ common_bsc.h \
+ common_cs.h \
+ crc24.h \
+ ctrl.h \
+ db.h \
+ debug.h \
+ e1_config.h \
+ gb_proxy.h \
+ gprs_gb_parse.h \
+ gprs_gmm.h \
+ gprs_llc.h \
+ gprs_llc_xid.h \
+ gprs_sgsn.h \
+ gprs_sndcp.h \
+ gprs_sndcp_comp.h \
+ gprs_sndcp_dcomp.h \
+ gprs_sndcp_pcomp.h \
+ gprs_sndcp_xid.h \
+ gprs_subscriber.h \
+ gprs_utils.h \
+ gsm_04_08.h \
+ gsm_04_11.h \
+ gsm_04_80.h \
+ gsm_data.h \
+ gsm_data_shared.h \
+ gsm_subscriber.h \
+ gsup_client.h \
+ gtphub.h \
+ handover.h \
+ handover_decision.h \
+ ipaccess.h \
+ iu.h \
+ meas_feed.h \
+ meas_rep.h \
+ mgcp.h \
+ mgcp_internal.h \
+ mgcp_transcode.h \
+ misdn.h \
+ mncc.h \
+ mncc_int.h \
+ nat_rewrite_trie.h \
+ network_listen.h \
+ oap_client.h \
+ openbscdefines.h \
+ osmo_bsc.h \
+ osmo_bsc_grace.h \
+ osmo_bsc_rf.h \
+ osmo_msc.h \
+ bsc_msc_data.h \
+ osmux.h \
+ paging.h \
+ pcu_if.h \
+ pcuif_proto.h \
+ rest_octets.h \
+ rrlp.h \
+ rs232.h \
+ rtp_proxy.h \
+ sgsn.h \
+ signal.h \
+ silent_call.h \
+ slhc.h \
+ smpp.h \
+ sms_queue.h \
+ socket.h \
+ system_information.h \
+ token_auth.h \
+ transaction.h \
+ trau_mux.h \
+ trau_upqueue.h \
+ ussd.h \
+ vty.h \
+ v42bis.h \
+ v42bis_private.h \
+ $(NULL)
+
+openbsc_HEADERS = \
+ bsc_api.h \
+ gsm_04_08.h \
+ meas_rep.h \
+ $(NULL)
+
+# DO NOT add a newline and '$(NULL)' to this line. That would add a trailing
+# space to the directory installed: $prefix/include/'openbsc '
+openbscdir = $(includedir)/openbsc
diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h
new file mode 100644
index 000000000..db2a659e4
--- /dev/null
+++ b/include/openbsc/abis_nm.h
@@ -0,0 +1,180 @@
+/* GSM Network Management messages on the A-bis interface
+ * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
+
+/* (C) 2008-2009 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 Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _NM_H
+#define _NM_H
+
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/abis_nm.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
+
+#include <openbsc/gsm_data.h>
+
+/* max number of attributes represented as 3GPP TS 52.021 §9.4.62 SW Description array */
+#define MAX_BTS_ATTR 5
+
+struct cell_global_id {
+ uint16_t mcc;
+ uint16_t mnc;
+ uint16_t lac;
+ uint16_t ci;
+};
+
+/* The BCCH info from an ip.access test, in host byte order
+ * and already parsed... */
+struct ipac_bcch_info {
+ struct llist_head list;
+
+ uint16_t info_type;
+ uint8_t freq_qual;
+ uint16_t arfcn;
+ uint8_t rx_lev;
+ uint8_t rx_qual;
+ int16_t freq_err;
+ uint16_t frame_offset;
+ uint32_t frame_nr_offset;
+ uint8_t bsic;
+ struct cell_global_id cgi;
+ uint8_t ba_list_si2[16];
+ uint8_t ba_list_si2bis[16];
+ uint8_t ba_list_si2ter[16];
+ uint8_t ca_list_si1[16];
+};
+
+/* PUBLIC */
+
+struct msgb;
+
+struct abis_nm_cfg {
+ /* callback for unidirectional reports */
+ int (*report_cb)(struct msgb *,
+ struct abis_om_fom_hdr *);
+ /* callback for software activate requests from BTS */
+ int (*sw_act_req)(struct msgb *);
+};
+
+extern int abis_nm_rcvmsg(struct msgb *msg);
+
+int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len);
+int abis_nm_rx(struct msgb *msg);
+int abis_nm_opstart(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1, uint8_t i2);
+int abis_nm_chg_adm_state(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0,
+ uint8_t i1, uint8_t i2, enum abis_nm_adm_state adm_state);
+int abis_nm_establish_tei(struct gsm_bts *bts, uint8_t trx_nr,
+ uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot,
+ uint8_t tei);
+int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
+ uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot);
+int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
+ uint8_t e1_port, uint8_t e1_timeslot,
+ uint8_t e1_subslot);
+int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class,
+ uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
+ const uint8_t *attr, uint8_t attr_len);
+int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len);
+int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len);
+int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb);
+int abis_nm_sw_act_req_ack(struct gsm_bts *bts, uint8_t obj_class, uint8_t i1,
+ uint8_t i2, uint8_t i3, int nack, uint8_t *attr, int att_len);
+int abis_nm_raw_msg(struct gsm_bts *bts, int len, uint8_t *msg);
+int abis_nm_event_reports(struct gsm_bts *bts, int on);
+int abis_nm_reset_resource(struct gsm_bts *bts);
+int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
+ uint8_t win_size, int forced,
+ gsm_cbfn *cbfn, void *cb_data);
+int abis_nm_software_load_status(struct gsm_bts *bts);
+int abis_nm_software_activate(struct gsm_bts *bts, const char *fname,
+ gsm_cbfn *cbfn, void *cb_data);
+
+int abis_nm_conn_mdrop_link(struct gsm_bts *bts, uint8_t e1_port0, uint8_t ts0,
+ uint8_t e1_port1, uint8_t ts1);
+
+int abis_nm_perform_test(struct gsm_bts *bts, uint8_t obj_class,
+ uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
+ uint8_t test_nr, uint8_t auton_report, struct msgb *msg);
+
+/* Siemens / BS-11 specific */
+int abis_nm_bs11_reset_resource(struct gsm_bts *bts);
+int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin);
+int abis_nm_bs11_create_object(struct gsm_bts *bts, enum abis_bs11_objtype type,
+ uint8_t idx, uint8_t attr_len, const uint8_t *attr);
+int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, uint8_t idx);
+int abis_nm_bs11_create_bport(struct gsm_bts *bts, uint8_t idx);
+int abis_nm_bs11_delete_object(struct gsm_bts *bts,
+ enum abis_bs11_objtype type, uint8_t idx);
+int abis_nm_bs11_delete_bport(struct gsm_bts *bts, uint8_t idx);
+int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, uint8_t e1_port,
+ uint8_t e1_timeslot, uint8_t e1_subslot, uint8_t tei);
+int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts);
+int abis_nm_bs11_get_serno(struct gsm_bts *bts);
+int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, uint8_t level);
+int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx);
+int abis_nm_bs11_logon(struct gsm_bts *bts, uint8_t level, const char *name, int on);
+int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on);
+int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on);
+int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password);
+int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked);
+int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts);
+int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value);
+int abis_nm_bs11_get_cclk(struct gsm_bts *bts);
+int abis_nm_bs11_get_state(struct gsm_bts *bts);
+int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
+ uint8_t win_size, int forced, gsm_cbfn *cbfn);
+int abis_nm_bs11_set_ext_time(struct gsm_bts *bts);
+int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, uint8_t bport);
+int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, uint8_t bport, enum abis_bs11_line_cfg line_cfg);
+int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect);
+int abis_nm_bs11_restart(struct gsm_bts *bts);
+
+/* ip.access nanoBTS specific commands */
+int abis_nm_ipaccess_msg(struct gsm_bts *bts, uint8_t msg_type,
+ uint8_t obj_class, uint8_t bts_nr,
+ uint8_t trx_nr, uint8_t ts_nr,
+ uint8_t *attr, int attr_len);
+int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
+ int attr_len);
+int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx);
+int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class,
+ uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
+ uint8_t *attr, uint8_t attr_len);
+int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
+ uint32_t ip, uint16_t port, uint8_t stream);
+void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts);
+int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf);
+const char *ipacc_testres_name(uint8_t res);
+
+/* Functions calling into other code parts */
+int nm_is_running(struct gsm_nm_state *s);
+
+int abis_nm_vty_init(void);
+
+void abis_nm_clear_queue(struct gsm_bts *bts);
+
+int _abis_nm_sendmsg(struct msgb *msg);
+
+void abis_nm_queue_send_next(struct gsm_bts *bts); /* for bs11_config. */
+
+int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw, const size_t len);
+
+/* Helper functions for updating attributes */
+int abis_nm_update_max_power_red(struct gsm_bts_trx *trx);
+
+#endif /* _NM_H */
diff --git a/include/openbsc/abis_om2000.h b/include/openbsc/abis_om2000.h
new file mode 100644
index 000000000..b093a0350
--- /dev/null
+++ b/include/openbsc/abis_om2000.h
@@ -0,0 +1,129 @@
+#ifndef OPENBSC_ABIS_OM2K_H
+#define OPENBSC_ABIS_OM2K_H
+/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
+ * implemented based on protocol trace analysis, no formal documentation */
+
+/* (C) 2010-2011 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 Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+enum abis_om2k_mo_cls {
+ OM2K_MO_CLS_TRXC = 0x01,
+ OM2K_MO_CLS_TS = 0x03,
+ OM2K_MO_CLS_TF = 0x04,
+ OM2K_MO_CLS_IS = 0x05,
+ OM2K_MO_CLS_CON = 0x06,
+ OM2K_MO_CLS_DP = 0x07,
+ OM2K_MO_CLS_CF = 0x0a,
+ OM2K_MO_CLS_TX = 0x0b,
+ OM2K_MO_CLS_RX = 0x0c,
+};
+
+enum om2k_mo_state {
+ OM2K_MO_S_RESET = 0,
+ OM2K_MO_S_STARTED,
+ OM2K_MO_S_ENABLED,
+ OM2K_MO_S_DISABLED,
+};
+
+/* on-wire format for IS conn group */
+struct om2k_is_conn_grp {
+ uint16_t icp1;
+ uint16_t icp2;
+ uint8_t cont_idx;
+} __attribute__ ((packed));
+
+/* internal data formant for IS conn group */
+struct is_conn_group {
+ struct llist_head list;
+ uint16_t icp1;
+ uint16_t icp2;
+ uint8_t ci;
+};
+
+/* on-wire format for CON Path */
+struct om2k_con_path {
+ uint16_t ccp;
+ uint8_t ci;
+ uint8_t tag;
+ uint8_t tei;
+} __attribute__ ((packed));
+
+/* internal data format for CON group */
+struct con_group {
+ /* links list of CON groups in BTS */
+ struct llist_head list;
+ struct gsm_bts *bts;
+ /* CON Group ID */
+ uint8_t cg;
+ /* list of CON paths in this group */
+ struct llist_head paths;
+};
+
+/* internal data format for CON path */
+struct con_path {
+ /* links with con_group.paths */
+ struct llist_head list;
+ /* CON Connection Point */
+ uint16_t ccp;
+ /* Contiguity Index */
+ uint8_t ci;
+ /* Tag */
+ uint8_t tag;
+ /* TEI */
+ uint8_t tei;
+};
+
+extern const struct abis_om2k_mo om2k_mo_cf;
+extern const struct abis_om2k_mo om2k_mo_is;
+extern const struct abis_om2k_mo om2k_mo_con;
+extern const struct abis_om2k_mo om2k_mo_tf;
+
+extern const struct value_string om2k_mo_class_short_vals[];
+
+int abis_om2k_rcvmsg(struct msgb *msg);
+
+extern const struct abis_om2k_mo om2k_mo_cf;
+
+int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
+ uint8_t operational);
+int abis_om2k_tx_cap_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
+int abis_om2k_tx_is_conf_req(struct gsm_bts *bts);
+int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts);
+int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx);
+int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx);
+int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts);
+
+struct osmo_fsm_inst *om2k_bts_fsm_start(struct gsm_bts *bts);
+void abis_om2k_bts_init(struct gsm_bts *bts);
+void abis_om2k_trx_init(struct gsm_bts_trx *trx);
+
+int abis_om2k_vty_init(void);
+
+struct vty;
+void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts);
+
+#endif /* OPENBCS_ABIS_OM2K_H */
diff --git a/include/openbsc/abis_rsl.h b/include/openbsc/abis_rsl.h
new file mode 100644
index 000000000..400e09f67
--- /dev/null
+++ b/include/openbsc/abis_rsl.h
@@ -0,0 +1,118 @@
+/* GSM Radio Signalling Link messages on the A-bis interface
+ * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
+
+/* (C) 2008 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 Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _RSL_H
+#define _RSL_H
+
+#include <stdbool.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/sysinfo.h>
+#include <osmocom/core/msgb.h>
+
+struct gsm_bts;
+struct gsm_lchan;
+struct gsm_subscriber;
+struct gsm_bts_trx_ts;
+
+#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
+
+int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len);
+int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
+ const uint8_t *data, int len);
+int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
+ uint8_t act_type,
+ struct rsl_ie_chan_mode *chan_mode,
+ struct rsl_ie_chan_ident *chan_ident,
+ uint8_t bs_power, uint8_t ms_power,
+ uint8_t ta);
+int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
+ uint8_t ho_ref);
+int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
+int rsl_encryption_cmd(struct msgb *msg);
+int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
+ uint8_t *ms_ident, uint8_t chan_needed, bool is_gprs);
+int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val);
+
+int rsl_data_request(struct msgb *msg, uint8_t link_id);
+int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id);
+int rsl_relase_request(struct gsm_lchan *lchan, uint8_t link_id);
+
+/* Ericcson vendor specific RSL extensions */
+int rsl_ericsson_imm_assign_cmd(struct gsm_bts *bts, uint32_t tlli, uint8_t len, uint8_t *val);
+
+/* Siemens vendor-specific RSL extensions */
+int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci);
+
+/* ip.access specfic RSL extensions */
+int rsl_ipacc_crcx(struct gsm_lchan *lchan);
+int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip,
+ uint16_t port, uint8_t rtp_payload2);
+int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan);
+int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act);
+
+int abis_rsl_rcvmsg(struct msgb *msg);
+
+uint64_t str_to_imsi(const char *imsi_str);
+int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
+ enum rsl_rel_mode release_mode);
+
+int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
+int rsl_lchan_mark_broken(struct gsm_lchan *lchan, const char *broken);
+
+/* to be provided by external code */
+int rsl_deact_sacch(struct gsm_lchan *lchan);
+
+/* BCCH related code */
+int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
+int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf);
+
+int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
+ const uint8_t *data, int len);
+
+int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
+int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
+
+/* SMSCB functionality */
+int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
+ struct rsl_ie_cb_cmd_type cb_command,
+ const uint8_t *data, int len);
+
+/* some Nokia specific stuff */
+int rsl_nokia_si_begin(struct gsm_bts_trx *trx);
+int rsl_nokia_si_end(struct gsm_bts_trx *trx);
+
+/* required for Nokia BTS power control */
+int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction);
+
+
+int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
+ enum rsl_rel_mode release_mode);
+int rsl_start_t3109(struct gsm_lchan *lchan);
+
+int rsl_direct_rf_release(struct gsm_lchan *lchan);
+
+void dyn_ts_init(struct gsm_bts_trx_ts *ts);
+int dyn_ts_switchover_start(struct gsm_bts_trx_ts *ts,
+ enum gsm_phys_chan_config to_pchan);
+
+#endif /* RSL_MT_H */
+
diff --git a/include/openbsc/arfcn_range_encode.h b/include/openbsc/arfcn_range_encode.h
new file mode 100644
index 000000000..7ec710c33
--- /dev/null
+++ b/include/openbsc/arfcn_range_encode.h
@@ -0,0 +1,26 @@
+#ifndef ARFCN_RANGE_ENCODE_H
+#define ARFCN_RANGE_ENCODE_H
+
+#include <stdint.h>
+
+enum gsm48_range {
+ ARFCN_RANGE_INVALID = -1,
+ ARFCN_RANGE_128 = 127,
+ ARFCN_RANGE_256 = 255,
+ ARFCN_RANGE_512 = 511,
+ ARFCN_RANGE_1024 = 1023,
+};
+
+#define RANGE_ENC_MAX_ARFCNS 29
+
+int range_enc_determine_range(const int *arfcns, int size, int *f0_out);
+int range_enc_arfcns(enum gsm48_range rng, const int *arfcns, int sze, int *out, int idx);
+int range_enc_find_index(enum gsm48_range rng, const int *arfcns, int size);
+int range_enc_filter_arfcns(int *arfcns, const int sze, const int f0, int *f0_included);
+
+int range_enc_range128(uint8_t *chan_list, int f0, int *w);
+int range_enc_range256(uint8_t *chan_list, int f0, int *w);
+int range_enc_range512(uint8_t *chan_list, int f0, int *w);
+int range_enc_range1024(uint8_t *chan_list, int f0, int f0_incl, int *w);
+
+#endif
diff --git a/include/openbsc/auth.h b/include/openbsc/auth.h
new file mode 100644
index 000000000..61811316b
--- /dev/null
+++ b/include/openbsc/auth.h
@@ -0,0 +1,26 @@
+#ifndef _AUTH_H
+#define _AUTH_H
+
+#include <osmocom/core/utils.h>
+
+struct gsm_auth_tuple;
+struct gsm_subscriber;
+
+enum auth_action {
+ AUTH_ERROR = -1, /* Internal error */
+ AUTH_NOT_AVAIL = 0, /* No auth tuple available */
+ AUTH_DO_AUTH_THEN_CIPH = 1, /* Firsth authenticate, then cipher */
+ AUTH_DO_CIPH = 2, /* Only ciphering */
+ AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */
+};
+
+extern const struct value_string auth_action_names[];
+static inline const char *auth_action_str(enum auth_action a)
+{
+ return get_value_string(auth_action_names, a);
+}
+
+int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr, int key_seq);
+
+#endif /* _AUTH_H */
diff --git a/include/openbsc/bsc_api.h b/include/openbsc/bsc_api.h
new file mode 100644
index 000000000..3a9311991
--- /dev/null
+++ b/include/openbsc/bsc_api.h
@@ -0,0 +1,55 @@
+/* GSM 08.08 like API for OpenBSC */
+
+#ifndef OPENBSC_BSC_API_H
+#define OPENBSC_BSC_API_H
+
+#include "gsm_data.h"
+
+#define BSC_API_CONN_POL_ACCEPT 0
+#define BSC_API_CONN_POL_REJECT 1
+
+struct bsc_api {
+ /*! \brief BTS->MSC: tell MSC a SAPI was not established */
+ void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci);
+ /*! \brief MS->MSC: Tell MSC that ciphering has been enabled */
+ void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, uint8_t chosen_encr);
+ /*! \brief MS->MSC: New MM context with L3 payload */
+ int (*compl_l3)(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, uint16_t chosen_channel);
+ /*! \brief MS->BSC/MSC: Um L3 message */
+ void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id,
+ struct msgb *msg);
+ /*! \brief BSC->MSC: Assignment of lchan successful */
+ void (*assign_compl)(struct gsm_subscriber_connection *conn,
+ uint8_t rr_cause, uint8_t chosen_channel,
+ uint8_t encr_alg_id, uint8_t speech_mode);
+ /*! \brief BSC->MSC: Assignment of lchan failed */
+ void (*assign_fail)(struct gsm_subscriber_connection *conn,
+ uint8_t cause, uint8_t *rr_cause);
+ /*! \brief BSC->MSC: RR conn has been cleared */
+ int (*clear_request)(struct gsm_subscriber_connection *conn,
+ uint32_t cause);
+ /*! \brief BSC->MSC: Classmark Update */
+ void (*classmark_chg)(struct gsm_subscriber_connection *conn,
+ const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len);
+
+ /**
+ * Configure the multirate setting on this channel. If it is
+ * not implemented AMR5.9 will be used.
+ */
+ void (*mr_config)(struct gsm_subscriber_connection *conn,
+ struct gsm_lchan *lchan, int full_rate);
+};
+
+int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
+int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sacch);
+int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate);
+int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
+ const uint8_t *key, int len, int include_imeisv);
+int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
+ unsigned int mi_len, uint8_t *mi, int chan_type);
+int gsm0808_clear(struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/bsc_msc.h b/include/openbsc/bsc_msc.h
new file mode 100644
index 000000000..39258d364
--- /dev/null
+++ b/include/openbsc/bsc_msc.h
@@ -0,0 +1,65 @@
+/* Routines to talk to the MSC using the IPA Protocol */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_MSC_H
+#define BSC_MSC_H
+
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
+
+#include <netinet/in.h>
+
+struct bsc_msc_dest {
+ struct llist_head list;
+
+ char *ip;
+ int port;
+ int dscp;
+};
+
+
+struct bsc_msc_connection {
+ struct osmo_wqueue write_queue;
+ int is_connected;
+ int is_authenticated;
+ int first_contact;
+
+ struct llist_head *dests;
+
+ const char *name;
+
+ void (*connection_loss) (struct bsc_msc_connection *);
+ void (*connected) (struct bsc_msc_connection *);
+ struct osmo_timer_list reconnect_timer;
+ struct osmo_timer_list timeout_timer;
+
+ struct msgb *pending_msg;
+};
+
+struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dest);
+int bsc_msc_connect(struct bsc_msc_connection *);
+void bsc_msc_schedule_connect(struct bsc_msc_connection *);
+
+void bsc_msc_lost(struct bsc_msc_connection *);
+
+struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len);
+
+#endif
diff --git a/include/openbsc/bsc_msc_data.h b/include/openbsc/bsc_msc_data.h
new file mode 100644
index 000000000..38e87cfb9
--- /dev/null
+++ b/include/openbsc/bsc_msc_data.h
@@ -0,0 +1,142 @@
+/*
+ * Data for the true BSC
+ *
+ * (C) 2010-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2015 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * NOTE: This is about a *remote* MSC for OsmoBSC and is not part of libmsc.
+ */
+
+#ifndef _OSMO_MSC_DATA_H
+#define _OSMO_MSC_DATA_H
+
+#include "bsc_msc.h"
+
+#include <osmocom/core/timer.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include <regex.h>
+
+struct osmo_bsc_rf;
+struct gsm_network;
+
+struct gsm_audio_support {
+ uint8_t hr : 1,
+ ver : 7;
+};
+
+enum {
+ MSC_CON_TYPE_NORMAL,
+ MSC_CON_TYPE_LOCAL,
+};
+
+/*! /brief Information on a remote MSC for libbsc.
+ */
+struct bsc_msc_data {
+ struct llist_head entry;
+
+ /* Back pointer */
+ struct gsm_network *network;
+
+ int allow_emerg;
+ int type;
+
+ /* local call routing */
+ char *local_pref;
+ regex_t local_pref_reg;
+
+
+ /* Connection data */
+ char *bsc_token;
+ uint8_t bsc_key[16];
+ uint8_t bsc_key_present;
+
+ int ping_timeout;
+ int pong_timeout;
+ struct osmo_timer_list ping_timer;
+ struct osmo_timer_list pong_timer;
+ int advanced_ping;
+ struct bsc_msc_connection *msc_con;
+ int core_mnc;
+ int core_mcc;
+ int core_lac;
+ int core_ci;
+ int rtp_base;
+
+ /* audio codecs */
+ struct gsm48_multi_rate_conf amr_conf;
+ struct gsm_audio_support **audio_support;
+ int audio_length;
+
+ /* destinations */
+ struct llist_head dests;
+
+ /* ussd welcome text */
+ char *ussd_welcome_txt;
+
+ /* mgcp agent */
+ struct osmo_wqueue mgcp_agent;
+
+ int nr;
+
+ /* ussd msc connection lost text */
+ char *ussd_msc_lost_txt;
+
+ /* ussd text when MSC has entered the grace period */
+ char *ussd_grace_txt;
+
+ char *acc_lst_name;
+};
+
+/*
+ * Per BSC data.
+ */
+struct osmo_bsc_data {
+ struct gsm_network *network;
+
+ /* msc configuration */
+ struct llist_head mscs;
+
+ /* rf ctl related bits */
+ char *mid_call_txt;
+ int mid_call_timeout;
+ char *rf_ctrl_name;
+ struct osmo_bsc_rf *rf_ctrl;
+ int auto_off_timeout;
+
+ /* ussd text when there is no MSC available */
+ char *ussd_no_msc_txt;
+
+ char *acc_lst_name;
+};
+
+
+int osmo_bsc_msc_init(struct bsc_msc_data *msc);
+int osmo_bsc_sccp_init(struct gsm_network *gsmnet);
+int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto);
+int msc_queue_write_with_ping(struct bsc_msc_connection *, struct msgb *msg, int proto);
+
+int osmo_bsc_audio_init(struct gsm_network *network);
+
+struct bsc_msc_data *osmo_msc_data_find(struct gsm_network *, int);
+struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *, int);
+
+
+#endif
diff --git a/include/openbsc/bsc_msg_filter.h b/include/openbsc/bsc_msg_filter.h
new file mode 100644
index 000000000..a9dedf43c
--- /dev/null
+++ b/include/openbsc/bsc_msg_filter.h
@@ -0,0 +1,107 @@
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/msgfile.h>
+#include <osmocom/core/linuxrbtree.h>
+#include <osmocom/core/linuxlist.h>
+
+#include <regex.h>
+
+struct vty;
+struct gsm48_hdr;
+
+struct bsc_filter_reject_cause {
+ int lu_reject_cause;
+ int cm_reject_cause;
+};
+
+struct bsc_filter_barr_entry {
+ struct rb_node node;
+
+ char *imsi;
+ int cm_reject_cause;
+ int lu_reject_cause;
+};
+
+enum bsc_filter_acc_ctr {
+ ACC_LIST_LOCAL_FILTER,
+ ACC_LIST_GLOBAL_FILTER,
+};
+
+struct bsc_msg_acc_lst {
+ struct llist_head list;
+
+ /* counter */
+ struct rate_ctr_group *stats;
+
+ /* the name of the list */
+ const char *name;
+ struct llist_head fltr_list;
+};
+
+struct bsc_msg_acc_lst_entry {
+ struct llist_head list;
+
+ /* the filter */
+ char *imsi_allow;
+ regex_t imsi_allow_re;
+ char *imsi_deny;
+ regex_t imsi_deny_re;
+
+ /* reject reasons for the access lists */
+ int cm_reject_cause;
+ int lu_reject_cause;
+};
+
+enum {
+ FLT_CON_TYPE_NONE,
+ FLT_CON_TYPE_LU,
+ FLT_CON_TYPE_CM_SERV_REQ,
+ FLT_CON_TYPE_PAG_RESP,
+ FLT_CON_TYPE_SSA,
+ FLT_CON_TYPE_LOCAL_REJECT,
+ FLT_CON_TYPE_OTHER,
+};
+
+
+struct bsc_filter_state {
+ char *imsi;
+ int imsi_checked;
+ int con_type;
+};
+
+struct bsc_filter_request {
+ void *ctx;
+ struct rb_root *black_list;
+ struct llist_head *access_lists;
+ const char *local_lst_name;
+ const char *global_lst_name;
+ int bsc_nr;
+};
+
+
+int bsc_filter_barr_adapt(void *ctx, struct rb_root *rbtree, const struct osmo_config_list *);
+int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu);
+
+/**
+ * Content filtering.
+ */
+int bsc_msg_filter_initial(struct gsm48_hdr *hdr, size_t size,
+ struct bsc_filter_request *req,
+ int *con_type, char **imsi,
+ struct bsc_filter_reject_cause *cause);
+int bsc_msg_filter_data(struct gsm48_hdr *hdr, size_t size,
+ struct bsc_filter_request *req,
+ struct bsc_filter_state *state,
+ struct bsc_filter_reject_cause *cause);
+
+/* IMSI allow/deny handling */
+struct bsc_msg_acc_lst *bsc_msg_acc_lst_find(struct llist_head *lst, const char *name);
+struct bsc_msg_acc_lst *bsc_msg_acc_lst_get(void *ctx, struct llist_head *lst, const char *name);
+void bsc_msg_acc_lst_delete(struct bsc_msg_acc_lst *lst);
+
+struct bsc_msg_acc_lst_entry *bsc_msg_acc_lst_entry_create(struct bsc_msg_acc_lst *);
+int bsc_msg_acc_lst_check_allow(struct bsc_msg_acc_lst *lst, const char *imsi);
+
+void bsc_msg_lst_vty_init(void *ctx, struct llist_head *lst, int node);
+void bsc_msg_acc_lst_write(struct vty *vty, struct bsc_msg_acc_lst *lst);
diff --git a/include/openbsc/bsc_nat.h b/include/openbsc/bsc_nat.h
new file mode 100644
index 000000000..94ab0e5ff
--- /dev/null
+++ b/include/openbsc/bsc_nat.h
@@ -0,0 +1,462 @@
+/*
+ * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2012 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_NAT_H
+#define BSC_NAT_H
+
+#include "mgcp.h"
+#include "bsc_msg_filter.h"
+
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/msgfile.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/rate_ctr.h>
+#include <osmocom/core/statistics.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include <regex.h>
+#include <stdbool.h>
+
+#define DIR_BSC 1
+#define DIR_MSC 2
+
+#define PAGIN_GROUP_UNASSIGNED -1
+
+struct sccp_source_reference;
+struct nat_sccp_connection;
+struct bsc_nat_parsed;
+struct bsc_nat;
+struct bsc_nat_ussd_con;
+struct nat_rewrite_rule;
+
+/*
+ * Is this terminated to the MSC, to the local machine (release
+ * handling for IMSI filtering) or to a USSD provider?
+ */
+enum {
+ NAT_CON_END_MSC,
+ NAT_CON_END_LOCAL,
+ NAT_CON_END_USSD,
+};
+
+/*
+ * Pending command entry
+ */
+struct bsc_cmd_list {
+ struct llist_head list_entry;
+
+ struct osmo_timer_list timeout;
+
+ /* The NATed ID used on the bsc_con*/
+ int nat_id;
+
+ /* The control connection from which the command originated */
+ struct ctrl_connection *ccon;
+
+ /* The command from the control connection */
+ struct ctrl_cmd *cmd;
+};
+
+/*
+ * Per BSC data structure
+ */
+struct bsc_connection {
+ struct llist_head list_entry;
+
+ /* do we know anything about this BSC? */
+ int authenticated;
+ uint8_t last_rand[16];
+
+ /* the fd we use to communicate */
+ struct osmo_wqueue write_queue;
+
+ /* incoming message buffer */
+ struct msgb *pending_msg;
+
+ /* the BSS associated */
+ struct bsc_config *cfg;
+
+ /* a timeout node */
+ struct osmo_timer_list id_timeout;
+
+ /* pong timeout */
+ struct osmo_timer_list ping_timeout;
+ struct osmo_timer_list pong_timeout;
+
+ /* mgcp related code */
+ char *_endpoint_status;
+ int number_multiplexes;
+ int max_endpoints;
+ int last_endpoint;
+ int next_transaction;
+ uint32_t pending_dlcx_count;
+ struct llist_head pending_dlcx;
+
+ /* track the pending commands for this BSC */
+ struct llist_head cmd_pending;
+ int last_id;
+
+ /* a back pointer */
+ struct bsc_nat *nat;
+};
+
+/**
+ * Stats per BSC
+ */
+struct bsc_config_stats {
+ struct rate_ctr_group *ctrg;
+};
+
+enum bsc_cfg_ctr {
+ BCFG_CTR_SCCP_CONN,
+ BCFG_CTR_SCCP_CALLS,
+ BCFG_CTR_NET_RECONN,
+ BCFG_CTR_DROPPED_SCCP,
+ BCFG_CTR_DROPPED_CALLS,
+ BCFG_CTR_REJECTED_CR,
+ BCFG_CTR_REJECTED_MSG,
+ BCFG_CTR_ILL_PACKET,
+ BCFG_CTR_CON_TYPE_LU,
+ BCFG_CTR_CON_CMSERV_RQ,
+ BCFG_CTR_CON_PAG_RESP,
+ BCFG_CTR_CON_SSA,
+ BCFG_CTR_CON_OTHER,
+};
+
+/**
+ * One BSC entry in the config
+ */
+struct bsc_config {
+ struct llist_head entry;
+
+ uint8_t key[16];
+ uint8_t key_present;
+ char *token;
+ int nr;
+
+ char *description;
+
+ /* imsi white and blacklist */
+ char *acc_lst_name;
+
+ int forbid_paging;
+ int paging_group;
+
+ /* audio handling */
+ int max_endpoints;
+
+ /* used internally for reload handling */
+ bool remove;
+ bool token_updated;
+
+ /* backpointer */
+ struct bsc_nat *nat;
+
+ struct bsc_config_stats stats;
+
+ struct llist_head lac_list;
+
+ /* Osmux is enabled/disabled per BSC */
+ int osmux;
+};
+
+struct bsc_lac_entry {
+ struct llist_head entry;
+ uint16_t lac;
+};
+
+struct bsc_nat_paging_group {
+ struct llist_head entry;
+
+ /* list of lac entries */
+ struct llist_head lists;
+ int nr;
+};
+
+/**
+ * BSCs point of view of endpoints
+ */
+struct bsc_endpoint {
+ /* the operation that is carried out */
+ int transaction_state;
+ /* the pending transaction id */
+ char *transaction_id;
+ /* the bsc we are talking to */
+ struct bsc_connection *bsc;
+};
+
+/**
+ * Statistic for the nat.
+ */
+struct bsc_nat_statistics {
+ struct {
+ struct osmo_counter *conn;
+ struct osmo_counter *calls;
+ } sccp;
+
+ struct {
+ struct osmo_counter *reconn;
+ struct osmo_counter *auth_fail;
+ } bsc;
+
+ struct {
+ struct osmo_counter *reconn;
+ } msc;
+
+ struct {
+ struct osmo_counter *reconn;
+ } ussd;
+};
+
+/**
+ * the structure of the "nat" network
+ */
+struct bsc_nat {
+ /* active SCCP connections that need patching */
+ struct llist_head sccp_connections;
+
+ /* active BSC connections that need patching */
+ struct llist_head bsc_connections;
+
+ /* access lists */
+ struct llist_head access_lists;
+
+ /* paging groups */
+ struct llist_head paging_groups;
+
+ /* known BSC's */
+ struct llist_head bsc_configs;
+ int num_bsc;
+ int bsc_ip_dscp;
+
+ /* MGCP config */
+ struct mgcp_config *mgcp_cfg;
+ uint8_t mgcp_msg[4096];
+ int mgcp_length;
+ int mgcp_ipa;
+ int sdp_ensure_amr_mode_set;
+
+ /* msc things */
+ struct llist_head dests;
+ struct bsc_msc_dest *main_dest;
+ struct bsc_msc_connection *msc_con;
+ char *token;
+
+ /* timeouts */
+ int auth_timeout;
+ int ping_timeout;
+ int pong_timeout;
+
+ struct bsc_endpoint *bsc_endpoints;
+
+ /* path to file with BSC config */
+ char *include_file;
+ char *include_base;
+ char *resolved_path;
+
+ /* filter */
+ char *acc_lst_name;
+
+ /* Barring of subscribers with a rb tree */
+ struct rb_root imsi_black_list;
+ char *imsi_black_list_fn;
+
+ /* number rewriting */
+ char *num_rewr_name;
+ struct llist_head num_rewr;
+ char *num_rewr_post_name;
+ struct llist_head num_rewr_post;
+
+ char *smsc_rewr_name;
+ struct llist_head smsc_rewr;
+ char *tpdest_match_name;
+ struct llist_head tpdest_match;
+ char *sms_clear_tp_srr_name;
+ struct llist_head sms_clear_tp_srr;
+ char *sms_num_rewr_name;
+ struct llist_head sms_num_rewr;
+
+ /* more rewriting */
+ char *num_rewr_trie_name;
+ struct nat_rewrite *num_rewr_trie;
+
+ /* USSD messages we want to match */
+ char *ussd_lst_name;
+ char *ussd_query;
+ regex_t ussd_query_re;
+ char *ussd_token;
+ char *ussd_local;
+ struct osmo_fd ussd_listen;
+ struct bsc_nat_ussd_con *ussd_con;
+
+ /* for maintainenance */
+ int blocked;
+
+ /* statistics */
+ struct bsc_nat_statistics stats;
+
+ /* control interface */
+ struct ctrl_handle *ctrl;
+};
+
+struct bsc_nat_ussd_con {
+ struct osmo_wqueue queue;
+ struct bsc_nat *nat;
+ int authorized;
+
+ struct msgb *pending_msg;
+
+ struct osmo_timer_list auth_timeout;
+};
+
+/* create and init the structures */
+struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
+ unsigned int number);
+struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
+struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len);
+void bsc_config_free(struct bsc_config *);
+void bsc_config_add_lac(struct bsc_config *cfg, int lac);
+void bsc_config_del_lac(struct bsc_config *cfg, int lac);
+int bsc_config_handles_lac(struct bsc_config *cfg, int lac);
+
+struct bsc_nat *bsc_nat_alloc(void);
+struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
+void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
+
+void sccp_connection_destroy(struct nat_sccp_connection *);
+void bsc_close_connection(struct bsc_connection *);
+
+const char *bsc_con_type_to_string(int type);
+
+/**
+ * parse the given message into the above structure
+ */
+struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
+
+/**
+ * filter based on IP Access header in both directions
+ */
+int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
+int bsc_nat_vty_init(struct bsc_nat *nat);
+int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len);
+
+/**
+ * SCCP patching and handling
+ */
+struct nat_sccp_connection *create_sccp_src_ref(struct bsc_connection *bsc, struct bsc_nat_parsed *parsed);
+int update_sccp_src_ref(struct nat_sccp_connection *sccp, struct bsc_nat_parsed *parsed);
+void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
+struct nat_sccp_connection *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
+struct nat_sccp_connection *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_connection *);
+struct nat_sccp_connection *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_source_reference *);
+
+/**
+ * MGCP/Audio handling
+ */
+int bsc_mgcp_nr_multiplexes(int max_endpoints);
+int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
+int bsc_mgcp_assign_patch(struct nat_sccp_connection *, struct msgb *msg);
+void bsc_mgcp_init(struct nat_sccp_connection *);
+void bsc_mgcp_dlcx(struct nat_sccp_connection *);
+void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
+int bsc_mgcp_nat_init(struct bsc_nat *nat);
+
+struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
+struct msgb *bsc_mgcp_rewrite(char *input, int length, int endp, const char *ip,
+ int port, int osmux, int *first_payload_type, int mode_set);
+void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
+
+void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc);
+int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
+uint32_t bsc_mgcp_extract_ci(const char *resp);
+
+
+int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
+int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int id);
+int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg);
+int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg);
+
+int bsc_nat_msc_is_connected(struct bsc_nat *nat);
+
+int bsc_conn_type_to_ctr(struct nat_sccp_connection *conn);
+
+struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed, struct msgb *msg, uint32_t *len);
+
+/** USSD filtering */
+int bsc_ussd_init(struct bsc_nat *nat);
+int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, struct msgb *msg);
+int bsc_ussd_close_connections(struct bsc_nat *nat);
+
+struct msgb *bsc_nat_rewrite_msg(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *, const char *imsi);
+
+/** paging group handling */
+struct bsc_nat_paging_group *bsc_nat_paging_group_num(struct bsc_nat *nat, int group);
+struct bsc_nat_paging_group *bsc_nat_paging_group_create(struct bsc_nat *nat, int group);
+void bsc_nat_paging_group_delete(struct bsc_nat_paging_group *);
+void bsc_nat_paging_group_add_lac(struct bsc_nat_paging_group *grp, int lac);
+void bsc_nat_paging_group_del_lac(struct bsc_nat_paging_group *grp, int lac);
+
+/**
+ * Number rewriting support below
+ */
+struct bsc_nat_num_rewr_entry {
+ struct llist_head list;
+
+ regex_t msisdn_reg;
+ regex_t num_reg;
+
+ char *replace;
+ uint8_t is_prefix_lookup;
+};
+
+void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head, const struct osmo_config_list *);
+
+void bsc_nat_send_mgcp_to_msc(struct bsc_nat *bsc_nat, struct msgb *msg);
+void bsc_nat_handle_mgcp(struct bsc_nat *bsc, struct msgb *msg);
+
+struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat,
+ const char *bind_addr, int port);
+void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending);
+int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg);
+
+int bsc_nat_extract_lac(struct bsc_connection *bsc, struct nat_sccp_connection *con,
+ struct bsc_nat_parsed *parsed, struct msgb *msg);
+
+int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
+ struct bsc_nat_parsed *, int *con_type, char **imsi,
+ struct bsc_filter_reject_cause *cause);
+int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
+ struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed,
+ struct bsc_filter_reject_cause *cause);
+
+/**
+ * CTRL interface helper
+ */
+void bsc_nat_inform_reject(struct bsc_connection *bsc, const char *imsi);
+
+/*
+ * Use for testing
+ */
+void bsc_nat_free(struct bsc_nat *nat);
+
+#endif
diff --git a/include/openbsc/bsc_nat_callstats.h b/include/openbsc/bsc_nat_callstats.h
new file mode 100644
index 000000000..64f9bfc0a
--- /dev/null
+++ b/include/openbsc/bsc_nat_callstats.h
@@ -0,0 +1,55 @@
+/*
+ * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2012 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_NAT_CALLSTATS_H
+#define BSC_NAT_CALLSTATS_H
+
+#include <osmocom/core/linuxlist.h>
+
+#include <osmocom/sccp/sccp_types.h>
+
+struct bsc_nat_call_stats {
+ struct llist_head entry;
+
+ struct sccp_source_reference remote_ref;
+ struct sccp_source_reference src_ref; /* as seen by the MSC */
+
+ /* mgcp options */
+ uint32_t ci;
+ int bts_rtp_port;
+ int net_rtp_port;
+ struct in_addr bts_addr;
+ struct in_addr net_addr;
+
+
+ /* as witnessed by the NAT */
+ uint32_t net_ps;
+ uint32_t net_os;
+ uint32_t bts_pr;
+ uint32_t bts_or;
+ uint32_t bts_expected;
+ uint32_t bts_jitter;
+ int bts_loss;
+
+ uint32_t trans_id;
+ int msc_endpoint;
+};
+
+#endif
diff --git a/include/openbsc/bsc_nat_sccp.h b/include/openbsc/bsc_nat_sccp.h
new file mode 100644
index 000000000..082466408
--- /dev/null
+++ b/include/openbsc/bsc_nat_sccp.h
@@ -0,0 +1,105 @@
+/* NAT utilities using SCCP types */
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BSC_NAT_SCCP_H
+#define BSC_NAT_SCCP_H
+
+#include "bsc_msg_filter.h"
+
+#include <osmocom/sccp/sccp_types.h>
+
+/*
+ * For the NAT we will need to analyze and later patch
+ * the received message. This would require us to parse
+ * the IPA and SCCP header twice. Instead of doing this
+ * we will have one analyze structure and have the patching
+ * and filter operate on the same structure.
+ */
+struct bsc_nat_parsed {
+ /* ip access prototype */
+ int ipa_proto;
+
+ /* source local reference */
+ struct sccp_source_reference *src_local_ref;
+
+ /* destination local reference */
+ struct sccp_source_reference *dest_local_ref;
+
+ /* original value */
+ struct sccp_source_reference original_dest_ref;
+
+ /* called ssn number */
+ int called_ssn;
+
+ /* calling ssn number */
+ int calling_ssn;
+
+ /* sccp message type */
+ int sccp_type;
+
+ /* bssap type, e.g. 0 for BSS Management */
+ int bssap;
+
+ /* the gsm0808 message type */
+ int gsm_type;
+};
+
+/*
+ * Per SCCP source local reference patch table. It needs to
+ * be updated on new SCCP connections, connection confirm and reject,
+ * and on the loss of the BSC connection.
+ */
+struct nat_sccp_connection {
+ struct llist_head list_entry;
+
+ struct bsc_connection *bsc;
+ struct bsc_msc_connection *msc_con;
+
+ struct sccp_source_reference real_ref;
+ struct sccp_source_reference patched_ref;
+ struct sccp_source_reference remote_ref;
+ int has_remote_ref;
+
+ /* status */
+ int con_local;
+ int authorized;
+
+ struct bsc_filter_state filter_state;
+
+ uint16_t lac;
+ uint16_t ci;
+
+ /* remember which Transactions we run over the bypass */
+ char ussd_ti[8];
+
+ /*
+ * audio handling. Remember if we have ever send a CRCX,
+ * remember the endpoint used by the MSC and BSC.
+ */
+ int msc_endp;
+ int bsc_endp;
+
+ /* timeout handling */
+ struct timespec creation_time;
+};
+
+
+#endif
diff --git a/include/openbsc/bsc_rll.h b/include/openbsc/bsc_rll.h
new file mode 100644
index 000000000..729ba6037
--- /dev/null
+++ b/include/openbsc/bsc_rll.h
@@ -0,0 +1,19 @@
+#ifndef _BSC_RLL_H
+#define _BSC_RLL_H
+
+#include <openbsc/gsm_data.h>
+
+enum bsc_rllr_ind {
+ BSC_RLLR_IND_EST_CONF,
+ BSC_RLLR_IND_REL_IND,
+ BSC_RLLR_IND_ERR_IND,
+ BSC_RLLR_IND_TIMEOUT,
+};
+
+int rll_establish(struct gsm_lchan *lchan, uint8_t link_id,
+ void (*cb)(struct gsm_lchan *, uint8_t, void *,
+ enum bsc_rllr_ind),
+ void *data);
+void rll_indication(struct gsm_lchan *lchan, uint8_t link_id, uint8_t type);
+
+#endif /* _BSC_RLL_H */
diff --git a/include/openbsc/bsc_subscriber.h b/include/openbsc/bsc_subscriber.h
new file mode 100644
index 000000000..324734f9a
--- /dev/null
+++ b/include/openbsc/bsc_subscriber.h
@@ -0,0 +1,43 @@
+/* GSM subscriber details for use in BSC land */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+struct log_target;
+
+struct bsc_subscr {
+ struct llist_head entry;
+ int use_count;
+
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ uint32_t tmsi;
+ uint16_t lac;
+};
+
+const char *bsc_subscr_name(struct bsc_subscr *bsub);
+
+struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list,
+ const char *imsi);
+struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list,
+ uint32_t tmsi);
+
+struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list,
+ const char *imsi);
+struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list,
+ uint32_t tmsi);
+
+void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi);
+
+struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub,
+ const char *file, int line);
+struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub,
+ const char *file, int line);
+#define bsc_subscr_get(bsub) _bsc_subscr_get(bsub, __BASE_FILE__, __LINE__)
+#define bsc_subscr_put(bsub) _bsc_subscr_put(bsub, __BASE_FILE__, __LINE__)
+
+void log_set_filter_bsc_subscr(struct log_target *target,
+ struct bsc_subscr *bsub);
diff --git a/include/openbsc/bss.h b/include/openbsc/bss.h
new file mode 100644
index 000000000..9f16bf7d7
--- /dev/null
+++ b/include/openbsc/bss.h
@@ -0,0 +1,20 @@
+#ifndef _BSS_H_
+#define _BSS_H_
+
+#include <openbsc/gsm_data.h>
+
+struct msgb;
+
+/* start and stop network */
+extern int bsc_network_alloc(mncc_recv_cb_t mncc_recv);
+extern int bsc_network_configure(const char *cfg_file);
+extern int bsc_shutdown_net(struct gsm_network *net);
+
+/* register all supported BTS */
+extern int bts_init(void);
+extern int bts_model_bs11_init(void);
+extern int bts_model_rbs2k_init(void);
+extern int bts_model_nanobts_init(void);
+extern int bts_model_nokia_site_init(void);
+extern int bts_model_sysmobts_init(void);
+#endif
diff --git a/include/openbsc/bts_ipaccess_nanobts_omlattr.h b/include/openbsc/bts_ipaccess_nanobts_omlattr.h
new file mode 100644
index 000000000..bc7860b2d
--- /dev/null
+++ b/include/openbsc/bts_ipaccess_nanobts_omlattr.h
@@ -0,0 +1,32 @@
+/* OML attribute table generator for ipaccess nanobts */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/msgb.h>
+
+struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts);
+struct msgb *nanobts_attr_nse_get(struct gsm_bts *bts);
+struct msgb *nanobts_attr_cell_get(struct gsm_bts *bts);
+struct msgb *nanobts_attr_nscv_get(struct gsm_bts *bts);
+struct msgb *nanobts_attr_radio_get(struct gsm_bts *bts,
+ struct gsm_bts_trx *trx);
diff --git a/include/openbsc/chan_alloc.h b/include/openbsc/chan_alloc.h
new file mode 100644
index 000000000..78242e5b7
--- /dev/null
+++ b/include/openbsc/chan_alloc.h
@@ -0,0 +1,54 @@
+/* Management functions to allocate/release struct gsm_lchan */
+/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef _CHAN_ALLOC_H
+#define _CHAN_ALLOC_H
+
+#include "gsm_data.h"
+
+struct gsm_subscriber_connection;
+
+/* Find an allocated channel for a specified subscriber */
+struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *subscr);
+
+/* Allocate a logical channel (SDCCH, TCH, ...) */
+struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
+
+/* Free a logical channel (SDCCH, TCH, ...) */
+void lchan_free(struct gsm_lchan *lchan);
+void lchan_reset(struct gsm_lchan *lchan);
+
+/* Release the given lchan */
+int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode release_mode);
+
+struct load_counter {
+ unsigned int total;
+ unsigned int used;
+};
+
+struct pchan_load {
+ struct load_counter pchan[_GSM_PCHAN_MAX];
+};
+
+void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts);
+void network_chan_load(struct pchan_load *pl, struct gsm_network *net);
+
+int trx_is_usable(struct gsm_bts_trx *trx);
+
+#endif /* _CHAN_ALLOC_H */
diff --git a/include/openbsc/common_bsc.h b/include/openbsc/common_bsc.h
new file mode 100644
index 000000000..796038323
--- /dev/null
+++ b/include/openbsc/common_bsc.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <stdint.h>
+#include <openbsc/common_cs.h>
+
+struct gsm_network *bsc_network_init(void *ctx,
+ uint16_t country_code,
+ uint16_t network_code,
+ mncc_recv_cb_t mncc_recv);
diff --git a/include/openbsc/common_cs.h b/include/openbsc/common_cs.h
new file mode 100644
index 000000000..6dc956f80
--- /dev/null
+++ b/include/openbsc/common_cs.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <stdint.h>
+
+struct msgb;
+struct gsm_network;
+
+typedef int (*mncc_recv_cb_t)(struct gsm_network *, struct msgb *);
+
+struct vty;
+
+#define MAX_A5_KEY_LEN (128/8)
+
+struct gsm_encr {
+ uint8_t alg_id;
+ uint8_t key_len;
+ uint8_t key[MAX_A5_KEY_LEN];
+};
+
+struct gsm_network *gsm_network_init(void *ctx,
+ uint16_t country_code,
+ uint16_t network_code,
+ mncc_recv_cb_t mncc_recv);
+
+int common_cs_vty_init(struct gsm_network *network,
+ int (* config_write_net )(struct vty *));
+struct gsm_network *gsmnet_from_vty(struct vty *v);
diff --git a/include/openbsc/crc24.h b/include/openbsc/crc24.h
new file mode 100644
index 000000000..756638c03
--- /dev/null
+++ b/include/openbsc/crc24.h
@@ -0,0 +1,10 @@
+#ifndef _CRC24_H
+#define _CRC24_H
+
+#include <stdint.h>
+
+#define INIT_CRC24 0xffffff
+
+uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
+
+#endif
diff --git a/include/openbsc/ctrl.h b/include/openbsc/ctrl.h
new file mode 100644
index 000000000..c5ac21092
--- /dev/null
+++ b/include/openbsc/ctrl.h
@@ -0,0 +1,4 @@
+#pragma once
+
+struct ctrl_handle *bsc_controlif_setup(struct gsm_network *net,
+ const char *bind_addr, uint16_t port);
diff --git a/include/openbsc/db.h b/include/openbsc/db.h
new file mode 100644
index 000000000..bb90705ab
--- /dev/null
+++ b/include/openbsc/db.h
@@ -0,0 +1,86 @@
+/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _DB_H
+#define _DB_H
+
+#include <stdbool.h>
+
+#include "gsm_subscriber.h"
+
+struct gsm_equipment;
+struct gsm_network;
+struct gsm_auth_info;
+struct gsm_auth_tuple;
+struct gsm_sms;
+struct gsm_subscriber;
+
+/* one time initialisation */
+int db_init(const char *name);
+int db_prepare(void);
+int db_fini(void);
+
+/* subscriber management */
+struct gsm_subscriber *db_create_subscriber(const char *imsi, uint64_t smin,
+ uint64_t smax, bool alloc_exten);
+struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field,
+ const char *subscr);
+int db_sync_subscriber(struct gsm_subscriber *subscriber);
+int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsigned int id));
+int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber);
+int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber, uint64_t smin,
+ uint64_t smax);
+int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t* token);
+int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
+int db_subscriber_delete(struct gsm_subscriber *subscriber);
+int db_sync_equipment(struct gsm_equipment *equip);
+int db_subscriber_update(struct gsm_subscriber *subscriber);
+int db_subscriber_list_active(void (*list_cb)(struct gsm_subscriber*,void*), void*);
+
+/* auth info */
+int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr);
+int db_sync_authinfo_for_subscr(struct gsm_auth_info *ainfo,
+ struct gsm_subscriber *subscr);
+int db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr);
+int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
+ struct gsm_subscriber *subscr);
+
+/* SMS store-and-forward */
+int db_sms_store(struct gsm_sms *sms);
+struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id);
+struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id);
+struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id, unsigned int failed);
+struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
+int db_sms_mark_delivered(struct gsm_sms *sms);
+int db_sms_inc_deliver_attempts(struct gsm_sms *sms);
+
+/* APDU blob storage */
+int db_apdu_blob_store(struct gsm_subscriber *subscr,
+ uint8_t apdu_id_flags, uint8_t len,
+ uint8_t *apdu);
+
+/* Statistics counter storage */
+struct osmo_counter;
+int db_store_counter(struct osmo_counter *ctr);
+struct rate_ctr_group;
+int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
+
+#endif /* _DB_H */
diff --git a/include/openbsc/debug.h b/include/openbsc/debug.h
new file mode 100644
index 000000000..8a4247b69
--- /dev/null
+++ b/include/openbsc/debug.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <stdio.h>
+#include <osmocom/core/linuxlist.h>
+
+#define DEBUG
+#include <osmocom/core/logging.h>
+
+/* Debug Areas of the code */
+enum {
+ DRLL,
+ DCC,
+ DMM,
+ DRR,
+ DRSL,
+ DNM,
+ DMNCC,
+ DPAG,
+ DMEAS,
+ DSCCP,
+ DMSC,
+ DMGCP,
+ DHO,
+ DDB,
+ DREF,
+ DGPRS,
+ DNS,
+ DBSSGP,
+ DLLC,
+ DSNDCP,
+ DSLHC,
+ DNAT,
+ DCTRL,
+ DSMPP,
+ DFILTER,
+ DGTPHUB,
+ DRANAP,
+ DSUA,
+ DV42BIS,
+ DPCU,
+ Debug_LastEntry,
+};
+
+struct gsm_subscriber;
+
+void log_set_filter_vlr_subscr(struct log_target *target,
+ struct gsm_subscriber *vlr_subscr);
+
+extern const struct log_info log_info;
diff --git a/include/openbsc/e1_config.h b/include/openbsc/e1_config.h
new file mode 100644
index 000000000..538c0b09d
--- /dev/null
+++ b/include/openbsc/e1_config.h
@@ -0,0 +1,11 @@
+#ifndef _E1_CONFIG_H
+#define _E1_CONFIG_H
+
+#include <openbsc/gsm_data_shared.h>
+
+int e1_reconfig_ts(struct gsm_bts_trx_ts *ts);
+int e1_reconfig_trx(struct gsm_bts_trx *trx);
+int e1_reconfig_bts(struct gsm_bts *bts);
+
+#endif /* _E1_CONFIG_H */
+
diff --git a/include/openbsc/gb_proxy.h b/include/openbsc/gb_proxy.h
new file mode 100644
index 000000000..e10894fc3
--- /dev/null
+++ b/include/openbsc/gb_proxy.h
@@ -0,0 +1,288 @@
+#ifndef _GB_PROXY_H
+#define _GB_PROXY_H
+
+
+#include <osmocom/core/msgb.h>
+
+#include <osmocom/gprs/gprs_ns.h>
+#include <osmocom/vty/command.h>
+
+#include <sys/types.h>
+#include <regex.h>
+
+#define GBPROXY_INIT_VU_GEN_TX 256
+
+struct rate_ctr_group;
+struct gprs_gb_parse_context;
+struct tlv_parsed;
+
+enum gbproxy_global_ctr {
+ GBPROX_GLOB_CTR_INV_BVCI,
+ GBPROX_GLOB_CTR_INV_LAI,
+ GBPROX_GLOB_CTR_INV_RAI,
+ GBPROX_GLOB_CTR_INV_NSEI,
+ GBPROX_GLOB_CTR_PROTO_ERR_BSS,
+ GBPROX_GLOB_CTR_PROTO_ERR_SGSN,
+ GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS,
+ GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN,
+ GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
+ GBPROX_GLOB_CTR_TX_ERR_SGSN,
+ GBPROX_GLOB_CTR_OTHER_ERR,
+ GBPROX_GLOB_CTR_PATCH_PEER_ERR,
+};
+
+enum gbproxy_peer_ctr {
+ GBPROX_PEER_CTR_BLOCKED,
+ GBPROX_PEER_CTR_UNBLOCKED,
+ GBPROX_PEER_CTR_DROPPED,
+ GBPROX_PEER_CTR_INV_NSEI,
+ GBPROX_PEER_CTR_TX_ERR,
+ GBPROX_PEER_CTR_RAID_PATCHED_BSS,
+ GBPROX_PEER_CTR_RAID_PATCHED_SGSN,
+ GBPROX_PEER_CTR_APN_PATCHED,
+ GBPROX_PEER_CTR_TLLI_PATCHED_BSS,
+ GBPROX_PEER_CTR_TLLI_PATCHED_SGSN,
+ GBPROX_PEER_CTR_PTMSI_PATCHED_BSS,
+ GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN,
+ GBPROX_PEER_CTR_PATCH_CRYPT_ERR,
+ GBPROX_PEER_CTR_PATCH_ERR,
+ GBPROX_PEER_CTR_ATTACH_REQS,
+ GBPROX_PEER_CTR_ATTACH_REJS,
+ GBPROX_PEER_CTR_ATTACH_ACKS,
+ GBPROX_PEER_CTR_ATTACH_COMPLS,
+ GBPROX_PEER_CTR_RA_UPD_REQS,
+ GBPROX_PEER_CTR_RA_UPD_REJS,
+ GBPROX_PEER_CTR_RA_UPD_ACKS,
+ GBPROX_PEER_CTR_RA_UPD_COMPLS,
+ GBPROX_PEER_CTR_GMM_STATUS_BSS,
+ GBPROX_PEER_CTR_GMM_STATUS_SGSN,
+ GBPROX_PEER_CTR_DETACH_REQS,
+ GBPROX_PEER_CTR_DETACH_ACKS,
+ GBPROX_PEER_CTR_PDP_ACT_REQS,
+ GBPROX_PEER_CTR_PDP_ACT_REJS,
+ GBPROX_PEER_CTR_PDP_ACT_ACKS,
+ GBPROX_PEER_CTR_PDP_DEACT_REQS,
+ GBPROX_PEER_CTR_PDP_DEACT_ACKS,
+ GBPROX_PEER_CTR_TLLI_UNKNOWN,
+ GBPROX_PEER_CTR_TLLI_CACHE_SIZE,
+ GBPROX_PEER_CTR_LAST,
+};
+
+enum gbproxy_keep_mode {
+ GBPROX_KEEP_NEVER,
+ GBPROX_KEEP_REATTACH,
+ GBPROX_KEEP_IDENTIFIED,
+ GBPROX_KEEP_ALWAYS,
+};
+
+enum gbproxy_match_id {
+ GBPROX_MATCH_PATCHING,
+ GBPROX_MATCH_ROUTING,
+ GBPROX_MATCH_LAST
+};
+
+struct gbproxy_match {
+ int enable;
+ char *re_str;
+ regex_t re_comp;
+};
+
+struct gbproxy_config {
+ /* parsed from config file */
+ uint16_t nsip_sgsn_nsei;
+
+ /* misc */
+ struct gprs_ns_inst *nsi;
+
+ /* Linked list of all Gb peers (except SGSN) */
+ struct llist_head bts_peers;
+
+ /* Counter */
+ struct rate_ctr_group *ctrg;
+
+ /* force mcc/mnc */
+ int core_mnc;
+ int core_mcc;
+ uint8_t* core_apn;
+ size_t core_apn_size;
+ int tlli_max_age;
+ int tlli_max_len;
+
+ /* Experimental config */
+ int patch_ptmsi;
+ int acquire_imsi;
+ int route_to_sgsn2;
+ uint16_t nsip_sgsn2_nsei;
+ enum gbproxy_keep_mode keep_link_infos;
+
+ /* IMSI checking/matching */
+ struct gbproxy_match matches[GBPROX_MATCH_LAST];
+};
+
+struct gbproxy_patch_state {
+ int local_mnc;
+ int local_mcc;
+
+ /* List of TLLIs for which patching is enabled */
+ struct llist_head logical_links;
+ int logical_link_count;
+};
+
+struct gbproxy_peer {
+ struct llist_head list;
+
+ /* point back to the config */
+ struct gbproxy_config *cfg;
+
+ /* NSEI of the peer entity */
+ uint16_t nsei;
+
+ /* BVCI used for Point-to-Point to this peer */
+ uint16_t bvci;
+ int blocked;
+
+ /* Routeing Area that this peer is part of (raw 04.08 encoding) */
+ uint8_t ra[6];
+
+ /* Counter */
+ struct rate_ctr_group *ctrg;
+
+ struct gbproxy_patch_state patch_state;
+};
+
+struct gbproxy_tlli_state {
+ uint32_t current;
+ uint32_t assigned;
+ int bss_validated;
+ int net_validated;
+
+ uint32_t ptmsi;
+};
+
+struct gbproxy_link_info {
+ struct llist_head list;
+
+ struct gbproxy_tlli_state tlli;
+ struct gbproxy_tlli_state sgsn_tlli;
+ uint32_t sgsn_nsei;
+
+ time_t timestamp;
+ uint8_t *imsi;
+ size_t imsi_len;
+
+ int imsi_acq_pending;
+ struct llist_head stored_msgs;
+ unsigned vu_gen_tx_bss;
+
+ int is_deregistered;
+
+ int is_matching[GBPROX_MATCH_LAST];
+};
+
+
+/* gb_proxy_vty .c */
+
+int gbproxy_vty_init(void);
+int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
+
+
+/* gb_proxy.c */
+int gbproxy_init_config(struct gbproxy_config *cfg);
+
+/* Main input function for Gb proxy */
+int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci);
+
+int gbprox_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data);
+
+/* Reset all persistent NS-VC's */
+int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
+
+void gbprox_reset(struct gbproxy_config *cfg);
+
+/* TLLI info handling */
+void gbproxy_delete_link_infos(struct gbproxy_peer *peer);
+struct gbproxy_link_info *gbproxy_update_link_state_ul(
+ struct gbproxy_peer *peer, time_t now,
+ struct gprs_gb_parse_context *parse_ctx);
+struct gbproxy_link_info *gbproxy_update_link_state_dl(
+ struct gbproxy_peer *peer, time_t now,
+ struct gprs_gb_parse_context *parse_ctx);
+int gbproxy_update_link_state_after(
+ struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
+ time_t now, struct gprs_gb_parse_context *parse_ctx);
+int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now);
+void gbproxy_delete_link_info(struct gbproxy_peer *peer,
+ struct gbproxy_link_info *link_info);
+void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info);
+
+void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
+ struct gbproxy_link_info *link_info);
+void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
+ const uint8_t *imsi, size_t imsi_len);
+void gbproxy_detach_link_info(struct gbproxy_peer *peer,
+ struct gbproxy_link_info *link_info);
+struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer);
+
+struct gbproxy_link_info *gbproxy_link_info_by_tlli(
+ struct gbproxy_peer *peer, uint32_t tlli);
+struct gbproxy_link_info *gbproxy_link_info_by_imsi(
+ struct gbproxy_peer *peer, const uint8_t *imsi, size_t imsi_len);
+struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
+ struct gbproxy_peer *peer, uint32_t tlli);
+struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
+ struct gbproxy_peer *peer,
+ uint32_t tlli, uint32_t sgsn_nsei);
+struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
+ struct gbproxy_peer *peer,
+ uint32_t ptmsi);
+
+int gbproxy_imsi_matches(
+ struct gbproxy_config *cfg,
+ enum gbproxy_match_id match_id,
+ struct gbproxy_link_info *link_info);
+uint32_t gbproxy_map_tlli(
+ uint32_t other_tlli, struct gbproxy_link_info *link_info, int to_bss);
+
+/* needed by gb_proxy_tlli.h */
+uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer, uint32_t sgsn_ptmsi);
+uint32_t gbproxy_make_sgsn_tlli(
+ struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
+ uint32_t bss_tlli);
+void gbproxy_reset_link(struct gbproxy_link_info *link_info);
+int gbproxy_check_imsi(
+ struct gbproxy_match *match, const uint8_t *imsi, size_t imsi_len);
+
+/* Message patching */
+void gbproxy_patch_bssgp(
+ struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
+ struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
+ int *len_change, struct gprs_gb_parse_context *parse_ctx);
+
+int gbproxy_patch_llc(
+ struct msgb *msg, uint8_t *llc, size_t llc_len,
+ struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
+ int *len_change, struct gprs_gb_parse_context *parse_ctx);
+
+int gbproxy_set_patch_filter(
+ struct gbproxy_match *match, const char *filter, const char **err_msg);
+void gbproxy_clear_patch_filter(struct gbproxy_match *match);
+
+/* Peer handling */
+struct gbproxy_peer *gbproxy_peer_by_bvci(
+ struct gbproxy_config *cfg, uint16_t bvci);
+struct gbproxy_peer *gbproxy_peer_by_nsei(
+ struct gbproxy_config *cfg, uint16_t nsei);
+struct gbproxy_peer *gbproxy_peer_by_rai(
+ struct gbproxy_config *cfg, const uint8_t *ra);
+struct gbproxy_peer *gbproxy_peer_by_lai(
+ struct gbproxy_config *cfg, const uint8_t *la);
+struct gbproxy_peer *gbproxy_peer_by_lac(
+ struct gbproxy_config *cfg, const uint8_t *la);
+struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(
+ struct gbproxy_config *cfg, struct tlv_parsed *tp);
+struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
+void gbproxy_peer_free(struct gbproxy_peer *peer);
+int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci);
+
+#endif
diff --git a/include/openbsc/gprs_gb_parse.h b/include/openbsc/gprs_gb_parse.h
new file mode 100644
index 000000000..246839286
--- /dev/null
+++ b/include/openbsc/gprs_gb_parse.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <openbsc/gprs_llc.h>
+
+#include <sys/types.h>
+
+struct gprs_gb_parse_context {
+ /* Pointer to protocol specific parts */
+ struct gsm48_hdr *g48_hdr;
+ struct bssgp_normal_hdr *bgp_hdr;
+ struct bssgp_ud_hdr *bud_hdr;
+ uint8_t *bssgp_data;
+ size_t bssgp_data_len;
+ uint8_t *llc;
+ size_t llc_len;
+
+ /* Extracted information */
+ struct gprs_llc_hdr_parsed llc_hdr_parsed;
+ struct tlv_parsed bssgp_tp;
+ int to_bss;
+ uint8_t *tlli_enc;
+ uint8_t *old_tlli_enc;
+ uint8_t *imsi;
+ size_t imsi_len;
+ uint8_t *apn_ie;
+ size_t apn_ie_len;
+ uint8_t *ptmsi_enc;
+ uint8_t *new_ptmsi_enc;
+ uint8_t *raid_enc;
+ uint8_t *old_raid_enc;
+ uint8_t *bssgp_raid_enc;
+ uint8_t *bssgp_ptmsi_enc;
+
+ /* General info */
+ const char *llc_msg_name;
+ int invalidate_tlli;
+ int await_reattach;
+ int need_decryption;
+ uint32_t tlli;
+ int pdu_type;
+ int old_raid_is_foreign;
+ int peer_nsei;
+};
+
+int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
+ struct gprs_gb_parse_context *parse_ctx);
+
+int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
+ struct gprs_gb_parse_context *parse_ctx);
+
+int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
+ struct gprs_gb_parse_context *parse_ctx);
+
+const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
+ const char *default_msg_name);
+
+void gprs_gb_log_parse_context(int log_level,
+ struct gprs_gb_parse_context *parse_ctx,
+ const char *default_msg_name);
diff --git a/include/openbsc/gprs_gmm.h b/include/openbsc/gprs_gmm.h
new file mode 100644
index 000000000..d210a3547
--- /dev/null
+++ b/include/openbsc/gprs_gmm.h
@@ -0,0 +1,35 @@
+#ifndef _GPRS_GMM_H
+#define _GPRS_GMM_H
+
+#include <osmocom/core/msgb.h>
+#include <openbsc/gprs_sgsn.h>
+
+#include <stdbool.h>
+
+int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
+int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
+ uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
+int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
+int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
+
+int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
+ bool drop_cipherable);
+int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
+ uint16_t *sai);
+int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx);
+int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
+ struct gprs_llc_llme *llme);
+void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *mmctx);
+void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *mmctx, int gmm_cause);
+void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *mmctx, int gmm_cause);
+void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *mmctx);
+
+int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
+int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
+ uint8_t suspend_ref);
+
+time_t gprs_max_time_to_idle(void);
+
+int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp, bool use_x213_nsap);
+
+#endif /* _GPRS_GMM_H */
diff --git a/include/openbsc/gprs_llc.h b/include/openbsc/gprs_llc.h
new file mode 100644
index 000000000..8bc226781
--- /dev/null
+++ b/include/openbsc/gprs_llc.h
@@ -0,0 +1,284 @@
+#ifndef _GPRS_LLC_H
+#define _GPRS_LLC_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/gprs_llc_xid.h>
+
+/* Section 4.7 LLC Layer Structure */
+enum gprs_llc_sapi {
+ GPRS_SAPI_GMM = 1,
+ GPRS_SAPI_TOM2 = 2,
+ GPRS_SAPI_SNDCP3 = 3,
+ GPRS_SAPI_SNDCP5 = 5,
+ GPRS_SAPI_SMS = 7,
+ GPRS_SAPI_TOM8 = 8,
+ GPRS_SAPI_SNDCP9 = 9,
+ GPRS_SAPI_SNDCP11 = 11,
+};
+
+/* Section 6.4 Commands and Responses */
+enum gprs_llc_u_cmd {
+ GPRS_LLC_U_DM_RESP = 0x01,
+ GPRS_LLC_U_DISC_CMD = 0x04,
+ GPRS_LLC_U_UA_RESP = 0x06,
+ GPRS_LLC_U_SABM_CMD = 0x07,
+ GPRS_LLC_U_FRMR_RESP = 0x08,
+ GPRS_LLC_U_XID = 0x0b,
+ GPRS_LLC_U_NULL_CMD = 0x00,
+};
+
+/* Section 6.4.1.6 / Table 6 */
+enum gprs_llc_xid_type {
+ GPRS_LLC_XID_T_VERSION = 0,
+ GPRS_LLC_XID_T_IOV_UI = 1,
+ GPRS_LLC_XID_T_IOV_I = 2,
+ GPRS_LLC_XID_T_T200 = 3,
+ GPRS_LLC_XID_T_N200 = 4,
+ GPRS_LLC_XID_T_N201_U = 5,
+ GPRS_LLC_XID_T_N201_I = 6,
+ GPRS_LLC_XID_T_mD = 7,
+ GPRS_LLC_XID_T_mU = 8,
+ GPRS_LLC_XID_T_kD = 9,
+ GPRS_LLC_XID_T_kU = 10,
+ GPRS_LLC_XID_T_L3_PAR = 11,
+ GPRS_LLC_XID_T_RESET = 12,
+};
+
+extern const struct value_string gprs_llc_xid_type_names[];
+
+/* TS 04.64 Section 7.1.2 Table 7: LLC layer primitives (GMM/SNDCP/SMS/TOM) */
+/* TS 04.65 Section 5.1.2 Table 2: Service primitives used by SNDCP */
+enum gprs_llc_primitive {
+ /* GMM <-> LLME */
+ LLGMM_ASSIGN_REQ, /* GMM tells us new TLLI: TLLI old, TLLI new, Kc, CiphAlg */
+ LLGMM_RESET_REQ, /* GMM tells us to perform XID negotiation: TLLI */
+ LLGMM_RESET_CNF, /* LLC informs GMM that XID has completed: TLLI */
+ LLGMM_SUSPEND_REQ, /* GMM tells us MS has suspended: TLLI, Page */
+ LLGMM_RESUME_REQ, /* GMM tells us MS has resumed: TLLI */
+ LLGMM_PAGE_IND, /* LLC asks GMM to page MS: TLLI */
+ LLGMM_IOV_REQ, /* GMM tells us to perform XID: TLLI */
+ LLGMM_STATUS_IND, /* LLC informs GMM about error: TLLI, Cause */
+ /* LLE <-> (GMM/SNDCP/SMS/TOM) */
+ LL_RESET_IND, /* TLLI */
+ LL_ESTABLISH_REQ, /* TLLI, XID Req */
+ LL_ESTABLISH_IND, /* TLLI, XID Req, N201-I, N201-U */
+ LL_ESTABLISH_RESP, /* TLLI, XID Negotiated */
+ LL_ESTABLISH_CONF, /* TLLI, XID Neg, N201-i, N201-U */
+ LL_RELEASE_REQ, /* TLLI, Local */
+ LL_RELEASE_IND, /* TLLI, Cause */
+ LL_RELEASE_CONF, /* TLLI */
+ LL_XID_REQ, /* TLLI, XID Requested */
+ LL_XID_IND, /* TLLI, XID Req, N201-I, N201-U */
+ LL_XID_RESP, /* TLLI, XID Negotiated */
+ LL_XID_CONF, /* TLLI, XID Neg, N201-I, N201-U */
+ LL_DATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
+ LL_DATA_IND, /* TLLI, SN-PDU */
+ LL_DATA_CONF, /* TLLI, Ref */
+ LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
+ LL_UNITDATA_IND, /* TLLI, SN-PDU */
+ LL_STATUS_IND, /* TLLI, Cause */
+};
+
+/* Section 4.5.2 Logical Link States + Annex C.2 */
+enum gprs_llc_lle_state {
+ GPRS_LLES_UNASSIGNED = 1, /* No TLLI yet */
+ GPRS_LLES_ASSIGNED_ADM = 2, /* TLLI assigned */
+ GPRS_LLES_LOCAL_EST = 3, /* Local Establishment */
+ GPRS_LLES_REMOTE_EST = 4, /* Remote Establishment */
+ GPRS_LLES_ABM = 5,
+ GPRS_LLES_LOCAL_REL = 6, /* Local Release */
+ GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
+};
+
+enum gprs_llc_llme_state {
+ GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
+ GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */
+};
+
+/* Section 8.9.9 LLC layer parameter default values */
+struct gprs_llc_params {
+ uint16_t iov_i_exp;
+ uint16_t t200_201;
+ uint16_t n200;
+ uint16_t n201_u;
+ uint16_t n201_i;
+ uint16_t mD;
+ uint16_t mU;
+ uint16_t kD;
+ uint16_t kU;
+};
+
+/* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
+struct gprs_llc_lle {
+ struct llist_head list;
+
+ uint32_t sapi;
+
+ struct gprs_llc_llme *llme;
+
+ enum gprs_llc_lle_state state;
+
+ struct osmo_timer_list t200;
+ struct osmo_timer_list t201; /* wait for acknowledgement */
+
+ uint16_t v_sent;
+ uint16_t v_ack;
+ uint16_t v_recv;
+
+ uint16_t vu_send;
+ uint16_t vu_recv;
+
+ /* non-standard LLC state */
+ uint16_t vu_recv_last;
+ uint16_t vu_recv_duplicates;
+
+ /* Overflow Counter for ABM */
+ uint32_t oc_i_send;
+ uint32_t oc_i_recv;
+
+ /* Overflow Counter for unconfirmed transfer */
+ uint32_t oc_ui_send;
+ uint32_t oc_ui_recv;
+
+ unsigned int retrans_ctr;
+
+ struct gprs_llc_params params;
+};
+
+#define NUM_SAPIS 16
+
+struct gprs_llc_llme {
+ struct llist_head list;
+
+ enum gprs_llc_llme_state state;
+
+ uint32_t tlli;
+ uint32_t old_tlli;
+
+ /* Crypto parameters */
+ enum gprs_ciph_algo algo;
+ uint8_t kc[16];
+ uint8_t cksn;
+ /* 3GPP TS 44.064 § 8.9.2: */
+ uint32_t iov_ui;
+
+ /* over which BSSGP BTS ctx do we need to transmit */
+ uint16_t bvci;
+ uint16_t nsei;
+ struct gprs_llc_lle lle[NUM_SAPIS];
+
+ /* Copy of the XID fields we have sent with the last
+ * network originated XID-Request. Since the phone
+ * may strip the optional fields in the confirmation
+ * we need to remeber those fields in order to be
+ * able to create the compression entity. */
+ struct llist_head *xid;
+
+ /* Compression entities */
+ struct {
+ /* In these two list_heads we will store the
+ * data and protocol compression entities,
+ * together with their compression states */
+ struct llist_head *proto;
+ struct llist_head *data;
+ } comp;
+
+ /* Internal management */
+ uint32_t age_timestamp;
+};
+
+#define GPRS_LLME_RESET_AGE (0)
+
+extern struct llist_head gprs_llc_llmes;
+
+/* LLC low level types */
+
+enum gprs_llc_cmd {
+ GPRS_LLC_NULL,
+ GPRS_LLC_RR,
+ GPRS_LLC_ACK,
+ GPRS_LLC_RNR,
+ GPRS_LLC_SACK,
+ GPRS_LLC_DM,
+ GPRS_LLC_DISC,
+ GPRS_LLC_UA,
+ GPRS_LLC_SABM,
+ GPRS_LLC_FRMR,
+ GPRS_LLC_XID,
+ GPRS_LLC_UI,
+};
+
+struct gprs_llc_hdr_parsed {
+ uint8_t sapi;
+ uint8_t is_cmd:1,
+ ack_req:1,
+ is_encrypted:1;
+ uint32_t seq_rx;
+ uint32_t seq_tx;
+ uint32_t fcs;
+ uint32_t fcs_calc;
+ uint8_t *data;
+ uint16_t data_len;
+ uint16_t crc_length;
+ enum gprs_llc_cmd cmd;
+};
+
+
+/* BSSGP-UL-UNITDATA.ind */
+int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv);
+
+/* LL-UNITDATA.req */
+int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
+ struct sgsn_mm_ctx *mmctx, bool encryptable);
+
+/* Chapter 7.2.1.2 LLGMM-RESET.req */
+int gprs_llgmm_reset(struct gprs_llc_llme *llme);
+int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
+ struct gprs_llc_llme *llme);
+
+/* Set of LL-XID negotiation (See also: TS 101 351, Section 7.2.2.4) */
+int gprs_ll_xid_req(struct gprs_llc_lle *lle,
+ struct gprs_llc_xid_field *l3_xid_field);
+
+/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
+int gprs_llgmm_assign(struct gprs_llc_llme *llme,
+ uint32_t old_tlli, uint32_t new_tlli);
+int gprs_llgmm_unassign(struct gprs_llc_llme *llme);
+
+int gprs_llc_init(const char *cipher_plugin_path);
+int gprs_llc_vty_init(void);
+
+/**
+ * \short Check if N(U) should be considered a retransmit
+ *
+ * Implements the range check as of GSM 04.64 8.4.2
+ * Receipt of unacknowledged information.
+ *
+ * @returns Returns 1 if (V(UR)-32) <= N(U) < V(UR)
+ * @param nu N(U) unconfirmed sequence number of the UI frame
+ * @param vur V(UR) unconfirmend received state variable
+ */
+static inline int gprs_llc_is_retransmit(uint16_t nu, uint16_t vur)
+{
+ int delta = (vur - nu) & 0x1ff;
+ return 0 < delta && delta < 32;
+}
+
+/* LLC low level functions */
+void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
+
+/* parse a GPRS LLC header, also check for invalid frames */
+int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
+ uint8_t *llc_hdr, int len);
+void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle);
+int gprs_llc_fcs(uint8_t *data, unsigned int len);
+
+
+/* LLME handling routines */
+struct llist_head *gprs_llme_list(void);
+struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi);
+
+
+#endif
diff --git a/include/openbsc/gprs_llc_xid.h b/include/openbsc/gprs_llc_xid.h
new file mode 100644
index 000000000..d340d40b7
--- /dev/null
+++ b/include/openbsc/gprs_llc_xid.h
@@ -0,0 +1,57 @@
+/* GPRS LLC XID field encoding/decoding as per 3GPP TS 44.064 */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+/* 3GPP TS 44.064 6.4.1.6 Exchange Identification (XID)
+ command/response parameter field */
+struct gprs_llc_xid_field {
+ struct llist_head list;
+ uint8_t type; /* See also Table 6: LLC layer parameter
+ negotiation */
+ uint8_t *data; /* Payload data (memory is owned by the
+ * creator of the struct) */
+ unsigned int data_len; /* Payload length */
+};
+
+/* Transform a list with XID fields into a XID message (dst) */
+int gprs_llc_compile_xid(uint8_t *dst, int dst_maxlen,
+ const struct llist_head *xid_fields);
+
+/* Transform a XID message (dst) into a list of XID fields */
+struct llist_head *gprs_llc_parse_xid(const void *ctx, const uint8_t *src,
+ int src_len);
+
+/* Create a duplicate of an XID-Field */
+struct gprs_llc_xid_field *gprs_llc_dup_xid_field(const void *ctx,
+ const struct gprs_llc_xid_field *xid_field);
+
+/* Copy an llist with xid fields */
+struct llist_head *gprs_llc_copy_xid(const void *ctx,
+ const struct llist_head *xid_fields);
+
+/* Dump a list with XID fields (Debug) */
+void gprs_llc_dump_xid_fields(const struct llist_head *xid_fields,
+ unsigned int logl);
+
diff --git a/include/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h
new file mode 100644
index 000000000..fd86174be
--- /dev/null
+++ b/include/openbsc/gprs_sgsn.h
@@ -0,0 +1,473 @@
+#ifndef _GPRS_SGSN_H
+#define _GPRS_SGSN_H
+
+#include <stdint.h>
+#include <netinet/in.h>
+
+#include <osmocom/core/timer.h>
+
+#include <osmocom/gsm/gsm48.h>
+
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+#include <openbsc/gsm_data.h>
+
+#define GSM_EXTENSION_LENGTH 15
+#define GSM_APN_LENGTH 102
+
+struct gprs_llc_lle;
+struct ctrl_handle;
+struct gprs_subscr;
+
+enum gsm48_gsm_cause;
+
+/* TS 04.08 4.1.3.3 GMM mobility management states on the network side */
+enum gprs_gmm_state {
+ GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
+ GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
+ GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
+ GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
+ GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
+};
+
+/* TS 23.060 6.1.1 and 6.1.2 Mobility management states A/Gb and Iu mode */
+enum gprs_pmm_state {
+ PMM_DETACHED,
+ PMM_CONNECTED,
+ PMM_IDLE,
+ MM_IDLE,
+ MM_READY,
+ MM_STANDBY,
+};
+
+enum gprs_mm_ctr {
+ GMM_CTR_PKTS_SIG_IN,
+ GMM_CTR_PKTS_SIG_OUT,
+ GMM_CTR_PKTS_UDATA_IN,
+ GMM_CTR_PKTS_UDATA_OUT,
+ GMM_CTR_BYTES_UDATA_IN,
+ GMM_CTR_BYTES_UDATA_OUT,
+ GMM_CTR_PDP_CTX_ACT,
+ GMM_CTR_SUSPEND,
+ GMM_CTR_PAGING_PS,
+ GMM_CTR_PAGING_CS,
+ GMM_CTR_RA_UPDATE,
+};
+
+enum gprs_pdp_ctx {
+ PDP_CTR_PKTS_UDATA_IN,
+ PDP_CTR_PKTS_UDATA_OUT,
+ PDP_CTR_BYTES_UDATA_IN,
+ PDP_CTR_BYTES_UDATA_OUT,
+};
+
+enum gprs_t3350_mode {
+ GMM_T3350_MODE_NONE,
+ GMM_T3350_MODE_ATT,
+ GMM_T3350_MODE_RAU,
+ GMM_T3350_MODE_PTMSI_REALL,
+};
+
+/* Authorization/ACL handling */
+enum sgsn_auth_state {
+ SGSN_AUTH_UNKNOWN,
+ SGSN_AUTH_AUTHENTICATE,
+ SGSN_AUTH_UMTS_RESYNC,
+ SGSN_AUTH_ACCEPTED,
+ SGSN_AUTH_REJECTED
+};
+
+#define MS_RADIO_ACCESS_CAPA
+
+enum sgsn_ggsn_lookup_state {
+ SGSN_GGSN_2DIGIT,
+ SGSN_GGSN_3DIGIT,
+};
+
+struct sgsn_ggsn_lookup {
+ int state;
+
+ struct sgsn_mm_ctx *mmctx;
+
+ /* APN string */
+ char apn_str[GSM_APN_LENGTH];
+
+ /* the original data */
+ struct msgb *orig_msg;
+ struct tlv_parsed tp;
+
+ /* for dealing with re-transmissions */
+ uint8_t nsapi;
+ uint8_t sapi;
+ uint8_t ti;
+};
+
+enum sgsn_ran_type {
+ /* GPRS/EDGE via Gb */
+ MM_CTX_T_GERAN_Gb,
+ /* UMTS via Iu */
+ MM_CTX_T_UTRAN_Iu,
+ /* GPRS/EDGE via Iu */
+ MM_CTX_T_GERAN_Iu,
+};
+
+struct service_info {
+ uint8_t type;
+ uint16_t pdp_status;
+};
+
+struct ue_conn_ctx;
+
+/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
+/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
+struct sgsn_mm_ctx {
+ struct llist_head list;
+
+ enum sgsn_ran_type ran_type;
+
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ enum gprs_gmm_state gmm_state;
+ enum gprs_pmm_state pmm_state; /* Iu: page when in PMM-IDLE mode */
+ uint32_t p_tmsi;
+ uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
+ uint32_t p_tmsi_sig;
+ char imei[GSM23003_IMEISV_NUM_DIGITS+1];
+ /* Opt: Software Version Numbber / TS 23.195 */
+ char msisdn[GSM_EXTENSION_LENGTH];
+ struct gprs_ra_id ra;
+ struct {
+ uint16_t cell_id; /* Gb only */
+ uint32_t cell_id_age; /* Gb only */
+ uint8_t radio_prio_sms;
+
+ /* Additional bits not present in the GSM TS */
+ uint16_t nsei;
+ uint16_t bvci;
+ struct gprs_llc_llme *llme;
+ uint32_t tlli;
+ uint32_t tlli_new;
+ } gb;
+ struct {
+ int new_key;
+ uint16_t sac; /* Iu: Service Area Code */
+ uint32_t sac_age; /* Iu: Service Area Code age */
+ /* CSG ID */
+ /* CSG Membership */
+ /* Access Mode */
+ /* Seelected CN Operator ID (TS 23.251) */
+ /* CSG Subscription Data */
+ /* LIPA Allowed */
+ /* Voice Support Match Indicator */
+ struct ue_conn_ctx *ue_ctx;
+ struct service_info service;
+ } iu;
+ /* VLR number */
+ uint32_t new_sgsn_addr;
+ /* Authentication Triplet */
+ struct gsm_auth_tuple auth_triplet;
+ /* Kc */
+ /* Iu: CK, IK, KSI */
+ /* CKSN */
+ enum gprs_ciph_algo ciph_algo;
+ /* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
+ uint8_t ac_ref_nr_used;
+
+ struct {
+ uint8_t len;
+ uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
+ } ms_radio_access_capa;
+ /* Supported Codecs (SRVCC) */
+ struct {
+ uint8_t len;
+ uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
+ } ms_network_capa;
+ /* UE Netowrk Capability (E-UTRAN) */
+ uint16_t drx_parms;
+ /* Active Time value for PSM */
+ int mnrg; /* MS reported to HLR? */
+ int ngaf; /* MS reported to MSC/VLR? */
+ int ppf; /* paging for GPRS + non-GPRS? */
+ /* Subscribed Charging Characteristics */
+ /* Trace Reference */
+ /* Trace Type */
+ /* Trigger ID */
+ /* OMC Identity */
+ /* SMS Parameters */
+ int recovery;
+ /* Access Restriction */
+ /* GPRS CSI (CAMEL) */
+ /* MG-CSI (CAMEL) */
+ /* Subscribed UE-AMBR */
+ /* UE-AMBR */
+ /* APN Subscribed */
+
+ struct llist_head pdp_list;
+
+ struct rate_ctr_group *ctrg;
+ struct osmo_timer_list timer;
+ unsigned int T; /* Txxxx number */
+ unsigned int num_T_exp; /* number of consecutive T expirations */
+
+ enum gprs_t3350_mode t3350_mode;
+ uint8_t t3370_id_type;
+ uint8_t pending_req; /* the request's message type */
+ /* TODO: There isn't much semantic difference between t3350_mode
+ * (refers to the timer) and pending_req (refers to the procedure),
+ * where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
+ * whether one of them can be dropped. */
+
+ enum sgsn_auth_state auth_state;
+ int is_authenticated;
+
+ /* the string representation of the current hlr */
+ char hlr[GSM_EXTENSION_LENGTH];
+
+ /* the current GGSN look-up operation */
+ struct sgsn_ggsn_lookup *ggsn_lookup;
+
+ struct gprs_subscr *subscr;
+};
+
+#define LOGMMCTXP(level, mm, fmt, args...) \
+ LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
+ (mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
+
+/* look-up a SGSN MM context based on TLLI + RAI */
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
+
+/* look-up by matching TLLI and P-TMSI (think twice before using this) */
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+
+/* Allocate a new SGSN MM context */
+struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
+
+void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
+
+struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
+ struct tlv_parsed *tp,
+ enum gsm48_gsm_cause *gsm_cause,
+ char *apn_str);
+
+enum pdp_ctx_state {
+ PDP_STATE_NONE,
+ PDP_STATE_CR_REQ,
+ PDP_STATE_CR_CONF,
+
+ /* 04.08 / Figure 6.2 / 6.1.2.2 */
+ PDP_STATE_INACT_PEND,
+ PDP_STATE_INACTIVE = PDP_STATE_NONE,
+};
+
+enum pdp_type {
+ PDP_TYPE_NONE,
+ PDP_TYPE_ETSI_PPP,
+ PDP_TYPE_IANA_IPv4,
+ PDP_TYPE_IANA_IPv6,
+};
+
+struct sgsn_pdp_ctx {
+ struct llist_head list; /* list_head for mmctx->pdp_list */
+ struct llist_head g_list; /* list_head for global list */
+ struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
+ int destroy_ggsn; /* destroy it on destruction */
+ struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
+ struct rate_ctr_group *ctrg;
+
+ //unsigned int id;
+ struct pdp_t *lib; /* pointer to libgtp PDP ctx */
+ enum pdp_ctx_state state;
+ enum pdp_type type;
+ uint32_t address;
+ char *apn_subscribed;
+ //char *apn_used;
+ uint16_t nsapi; /* SNDCP */
+ uint16_t sapi; /* LLC */
+ uint8_t ti; /* transaction identifier */
+ int vplmn_allowed;
+ uint32_t qos_profile_subscr;
+ //uint32_t qos_profile_req;
+ //uint32_t qos_profile_neg;
+ uint8_t radio_prio;
+ //uint32_t charging_id;
+
+ struct osmo_timer_list timer;
+ unsigned int T; /* Txxxx number */
+ unsigned int num_T_exp; /* number of consecutive T expirations */
+
+ struct osmo_timer_list cdr_timer; /* CDR record wird timer */
+ struct timespec cdr_start; /* The start of the CDR */
+ uint64_t cdr_bytes_in;
+ uint64_t cdr_bytes_out;
+ uint32_t cdr_charging_id;
+};
+
+#define LOGPDPCTXP(level, pdp, fmt, args...) \
+ LOGP(DGPRS, level, "PDP(%s/%u) " \
+ fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
+
+/* look up PDP context by MM context and NSAPI */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
+ uint8_t nsapi);
+/* look up PDP context by MM context and transaction ID */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
+ uint8_t tid);
+
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
+ uint8_t nsapi);
+void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
+void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
+
+
+struct sgsn_ggsn_ctx {
+ struct llist_head list;
+ uint32_t id;
+ unsigned int gtp_version;
+ struct in_addr remote_addr;
+ int remote_restart_ctr;
+ struct gsn_t *gsn;
+};
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
+void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
+struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
+
+struct apn_ctx {
+ struct llist_head list;
+ struct sgsn_ggsn_ctx *ggsn;
+ char *name;
+ char *imsi_prefix;
+ char *description;
+};
+
+struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
+void sgsn_apn_ctx_free(struct apn_ctx *actx);
+struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
+struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);
+
+extern struct llist_head sgsn_mm_ctxts;
+extern struct llist_head sgsn_ggsn_ctxts;
+extern struct llist_head sgsn_apn_ctxts;
+extern struct llist_head sgsn_pdp_ctxts;
+
+uint32_t sgsn_alloc_ptmsi(void);
+void sgsn_inst_init(void);
+
+/* High-level function to be called in case a GGSN has disappeared or
+ * ottherwise lost state (recovery procedure) */
+int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn);
+
+char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len);
+
+/*
+ * ctrl interface related work
+ */
+struct gsm_network;
+struct ctrl_handle *sgsn_controlif_setup(struct gsm_network *,
+ const char *bind_addr, uint16_t port);
+int sgsn_ctrl_cmds_install(void);
+
+/*
+ * Authorization/ACL handling
+ */
+struct imsi_acl_entry {
+ struct llist_head list;
+ char imsi[16+1];
+};
+
+/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
+/* see GSM 09.02, B.1, gprsSubscriptionData */
+struct sgsn_subscriber_pdp_data {
+ struct llist_head list;
+
+ unsigned int context_id;
+ uint16_t pdp_type;
+ char apn_str[GSM_APN_LENGTH];
+ uint8_t qos_subscribed[20];
+ size_t qos_subscribed_len;
+};
+
+struct sgsn_subscriber_data {
+ struct sgsn_mm_ctx *mm;
+ struct gsm_auth_tuple auth_triplets[5];
+ int auth_triplets_updated;
+ struct llist_head pdp_list;
+ int error_cause;
+
+ uint8_t msisdn[9];
+ size_t msisdn_len;
+
+ uint8_t hlr[9];
+ size_t hlr_len;
+};
+
+#define SGSN_ERROR_CAUSE_NONE (-1)
+
+#define LOGGSUBSCRP(level, subscr, fmt, args...) \
+ LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
+ (subscr) ? (subscr)->imsi : "---", \
+ ## args)
+
+struct sgsn_config;
+struct sgsn_instance;
+extern const struct value_string *sgsn_auth_state_names;
+
+void sgsn_auth_init(void);
+struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, struct sgsn_config *cfg);
+int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
+int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);
+/* Request authorization */
+int sgsn_auth_request(struct sgsn_mm_ctx *mm);
+enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
+void sgsn_auth_update(struct sgsn_mm_ctx *mm);
+struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
+ unsigned key_seq);
+
+/*
+ * GPRS subscriber data
+ */
+#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
+#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
+#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
+#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
+#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
+
+#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
+ GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
+ GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
+)
+
+int gprs_subscr_init(struct sgsn_instance *sgi);
+int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
+int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
+ const uint8_t *auts,
+ const uint8_t *auts_rand);
+int gprs_subscr_auth_sync(struct gprs_subscr *subscr,
+ const uint8_t *auts, const uint8_t *auts_rand);
+void gprs_subscr_cleanup(struct gprs_subscr *subscr);
+struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
+struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
+struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
+void gprs_subscr_cancel(struct gprs_subscr *subscr);
+void gprs_subscr_update(struct gprs_subscr *subscr);
+void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
+int gprs_subscr_rx_gsup_message(struct msgb *msg);
+
+/* Called on subscriber data updates */
+void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
+
+int gprs_sndcp_vty_init(void);
+struct sgsn_instance;
+int sgsn_gtp_init(struct sgsn_instance *sgi);
+
+void sgsn_rate_ctr_init();
+
+#endif /* _GPRS_SGSN_H */
diff --git a/include/openbsc/gprs_sndcp.h b/include/openbsc/gprs_sndcp.h
new file mode 100644
index 000000000..d970240e4
--- /dev/null
+++ b/include/openbsc/gprs_sndcp.h
@@ -0,0 +1,79 @@
+#ifndef _INT_SNDCP_H
+#define _INT_SNDCP_H
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+/* A fragment queue header, maintaining list of fragments for one N-PDU */
+struct defrag_state {
+ /* PDU number for which the defragmentation state applies */
+ uint16_t npdu;
+ /* highest segment number we have received so far */
+ uint8_t highest_seg;
+ /* bitmask of the segments we already have */
+ uint32_t seg_have;
+ /* do we still expect more segments? */
+ unsigned int no_more;
+ /* total length of all segments together */
+ unsigned int tot_len;
+
+ /* linked list of defrag_queue_entry: one for each fragment */
+ struct llist_head frag_list;
+
+ struct osmo_timer_list timer;
+
+ /* Holds state to know which compression mode is used
+ * when the packet is re-assembled */
+ uint8_t pcomp;
+ uint8_t dcomp;
+
+ /* Holds the pointers to the compression entity list
+ * that is used when the re-assembled packet is decompressed */
+ struct llist_head *proto;
+ struct llist_head *data;
+};
+
+/* See 6.7.1.2 Reassembly */
+enum sndcp_rx_state {
+ SNDCP_RX_S_FIRST,
+ SNDCP_RX_S_SUBSEQ,
+ SNDCP_RX_S_DISCARD,
+};
+
+struct gprs_sndcp_entity {
+ struct llist_head list;
+
+ /* FIXME: move this RA_ID up to the LLME or even higher */
+ struct gprs_ra_id ra_id;
+ /* reference to the LLC Entity below this SNDCP entity */
+ struct gprs_llc_lle *lle;
+ /* The NSAPI we shall use on top of LLC */
+ uint8_t nsapi;
+
+ /* NPDU number for the GTP->SNDCP side */
+ uint16_t tx_npdu_nr;
+ /* SNDCP eeceiver state */
+ enum sndcp_rx_state rx_state;
+ /* The defragmentation queue */
+ struct defrag_state defrag;
+};
+
+extern struct llist_head gprs_sndcp_entities;
+
+/* Set of SNDCP-XID negotiation (See also: TS 144 065,
+ * Section 6.8 XID parameter negotiation) */
+int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
+
+/* Process SNDCP-XID indication (See also: TS 144 065,
+ * Section 6.8 XID parameter negotiation) */
+int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
+ struct gprs_llc_xid_field *xid_field_response,
+ struct gprs_llc_lle *lle);
+
+/* Process SNDCP-XID indication
+ * (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
+int sndcp_sn_xid_conf(struct gprs_llc_xid_field *xid_field_conf,
+ struct gprs_llc_xid_field *xid_field_request,
+ struct gprs_llc_lle *lle);
+
+#endif /* INT_SNDCP_H */
diff --git a/include/openbsc/gprs_sndcp_comp.h b/include/openbsc/gprs_sndcp_comp.h
new file mode 100644
index 000000000..87ab6382a
--- /dev/null
+++ b/include/openbsc/gprs_sndcp_comp.h
@@ -0,0 +1,82 @@
+/* GPRS SNDCP header compression entity management tools */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <openbsc/gprs_sndcp_xid.h>
+
+/* Header / Data compression entity */
+struct gprs_sndcp_comp {
+ struct llist_head list;
+
+ /* Serves as an ID in case we want to delete this entity later */
+ unsigned int entity; /* see also: 6.5.1.1.3 and 6.6.1.1.3 */
+
+ /* Specifies to which NSAPIs the compression entity is assigned */
+ uint8_t nsapi_len; /* Number of applicable NSAPIs (default 0) */
+ uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
+
+ /* Assigned pcomp values */
+ uint8_t comp_len; /* Number of contained PCOMP / DCOMP values */
+ uint8_t comp[MAX_COMP]; /* see also: 6.5.1.1.5 and 6.6.1.1.5 */
+
+ /* Algorithm parameters */
+ int algo; /* Algorithm type (see gprs_sndcp_xid.h) */
+ int compclass; /* See gprs_sndcp_xid.h/c */
+ void *state; /* Algorithm status and parameters */
+};
+
+#define MAX_COMP 16 /* Maximum number of possible pcomp/dcomp values */
+#define MAX_NSAPI 11 /* Maximum number usable NSAPIs */
+
+/* Allocate a compression enitiy list */
+struct llist_head *gprs_sndcp_comp_alloc(const void *ctx);
+
+/* Free a compression entitiy list */
+void gprs_sndcp_comp_free(struct llist_head *comp_entities);
+
+/* Delete a compression entity */
+void gprs_sndcp_comp_delete(struct llist_head *comp_entities, unsigned int entity);
+
+/* Create and Add a new compression entity
+ * (returns a pointer to the compression entity that has just been created) */
+struct gprs_sndcp_comp *gprs_sndcp_comp_add(const void *ctx,
+ struct llist_head *comp_entities,
+ const struct gprs_sndcp_comp_field
+ *comp_field);
+
+/* Find which compression entity handles the specified pcomp/dcomp */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_comp(const struct llist_head
+ *comp_entities, uint8_t comp);
+
+/* Find which compression entity handles the specified nsapi */
+struct gprs_sndcp_comp *gprs_sndcp_comp_by_nsapi(const struct llist_head
+ *comp_entities, uint8_t nsapi);
+
+/* Find a comp_index for a given pcomp/dcomp value */
+uint8_t gprs_sndcp_comp_get_idx(const struct gprs_sndcp_comp *comp_entity,
+ uint8_t comp);
+
+/* Find a pcomp/dcomp value for a given comp_index */
+uint8_t gprs_sndcp_comp_get_comp(const struct gprs_sndcp_comp *comp_entity,
+ uint8_t comp_index);
diff --git a/include/openbsc/gprs_sndcp_dcomp.h b/include/openbsc/gprs_sndcp_dcomp.h
new file mode 100644
index 000000000..a76b4a4b3
--- /dev/null
+++ b/include/openbsc/gprs_sndcp_dcomp.h
@@ -0,0 +1,53 @@
+/* GPRS SNDCP data compression handler */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <openbsc/gprs_sndcp_comp.h>
+
+/* Note: The decompressed packet may have a maximum size of:
+ * Return value * MAX_DATADECOMPR_FAC */
+#define MAX_DATADECOMPR_FAC 10
+
+/* Note: In unacknowledged mode (SN_UNITDATA), the comression state is reset
+ * for every NPDU. The compressor needs a reasonably large payload to operate
+ * effectively (yield positive compression gain). For packets shorter than 100
+ * byte, no positive compression gain can be expected so we will skip the
+ * compression for short packets. */
+#define MIN_COMPR_PAYLOAD 100
+
+/* Initalize data compression */
+int gprs_sndcp_dcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
+ const struct gprs_sndcp_comp_field *comp_field);
+
+/* Terminate data compression */
+void gprs_sndcp_dcomp_term(struct gprs_sndcp_comp *comp_entity);
+
+/* Expand packet */
+int gprs_sndcp_dcomp_expand(uint8_t *data, unsigned int len, uint8_t pcomp,
+ const struct llist_head *comp_entities);
+
+/* Compress packet */
+int gprs_sndcp_dcomp_compress(uint8_t *data, unsigned int len, uint8_t *pcomp,
+ const struct llist_head *comp_entities,
+ uint8_t nsapi);
diff --git a/include/openbsc/gprs_sndcp_pcomp.h b/include/openbsc/gprs_sndcp_pcomp.h
new file mode 100644
index 000000000..4e15b9be2
--- /dev/null
+++ b/include/openbsc/gprs_sndcp_pcomp.h
@@ -0,0 +1,46 @@
+/* GPRS SNDCP header compression handler */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+#include <openbsc/gprs_sndcp_comp.h>
+
+/* Note: The decompressed packet may have a maximum size of:
+ * Return value + MAX_DECOMPR_INCR */
+#define MAX_HDRDECOMPR_INCR 64
+
+/* Initalize header compression */
+int gprs_sndcp_pcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
+ const struct gprs_sndcp_comp_field *comp_field);
+
+/* Terminate header compression */
+void gprs_sndcp_pcomp_term(struct gprs_sndcp_comp *comp_entity);
+
+/* Expand packet header */
+int gprs_sndcp_pcomp_expand(uint8_t *data, unsigned int len, uint8_t pcomp,
+ const struct llist_head *comp_entities);
+
+/* Compress packet header */
+int gprs_sndcp_pcomp_compress(uint8_t *data, unsigned int len, uint8_t *pcomp,
+ const struct llist_head *comp_entities,
+ uint8_t nsapi);
diff --git a/include/openbsc/gprs_sndcp_xid.h b/include/openbsc/gprs_sndcp_xid.h
new file mode 100644
index 000000000..e64bc5237
--- /dev/null
+++ b/include/openbsc/gprs_sndcp_xid.h
@@ -0,0 +1,218 @@
+/* GPRS SNDCP XID field encoding/decoding as per 3GPP TS 44.065 */
+
+/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Philipp Maier
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/linuxlist.h>
+
+#define DEFAULT_SNDCP_VERSION 0 /* See 3GPP TS 44.065, clause 8 */
+#define MAX_ENTITIES 32 /* 3GPP TS 44.065 reserves 5 bit
+ * for compression enitity number */
+
+#define MAX_COMP 16 /* Maximum number of possible pcomp/dcomp values */
+#define MAX_NSAPI 11 /* Maximum number usable NSAPIs */
+#define MAX_ROHC 16 /* Maximum number of ROHC compression profiles */
+
+/* According to: 3GPP TS 44.065, 6.5.1.1 Format of the protocol control
+ * information compression field (Figure 7) and 3GPP TS 44.065,
+ * 6.6.1.1 Format of the data compression field (Figure 9) */
+struct gprs_sndcp_comp_field {
+ struct llist_head list;
+
+ /* Propose bit (P), see also: 6.5.1.1.2 and 6.6.1.1.2 */
+ unsigned int p;
+
+ /* Entity number, see also: 6.5.1.1.3 and 6.6.1.1.3 */
+ unsigned int entity;
+
+ /* Algorithm identifier, see also: 6.5.1.1.4 and 6.6.1.1.4 */
+ int algo;
+
+ /* Number of contained PCOMP / DCOMP values */
+ uint8_t comp_len;
+
+ /* PCOMP / DCOMP values, see also: 6.5.1.1.5 and 6.6.1.1.5 */
+ uint8_t comp[MAX_COMP];
+
+ /* Note: Only one of the following struct pointers may,
+ be used. Unused pointers must be set to NULL! */
+ struct gprs_sndcp_pcomp_rfc1144_params *rfc1144_params;
+ struct gprs_sndcp_pcomp_rfc2507_params *rfc2507_params;
+ struct gprs_sndcp_pcomp_rohc_params *rohc_params;
+ struct gprs_sndcp_dcomp_v42bis_params *v42bis_params;
+ struct gprs_sndcp_dcomp_v44_params *v44_params;
+};
+
+/* According to: 3GPP TS 44.065, 6.5.1.1.4 Algorithm identifier */
+enum gprs_sndcp_hdr_comp_algo {
+ RFC_1144, /* TCP/IP header compression, see also 6.5.2 */
+ RFC_2507, /* TCP/UDP/IP header compression, see also: 6.5.3 */
+ ROHC /* Robust Header Compression, see also 6.5.4 */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.1.1.4 Algorithm identifier */
+enum gprs_sndcp_data_comp_algo {
+ V42BIS, /* V.42bis data compression, see also 6.6.2 */
+ V44 /* V44 data compression, see also: 6.6.3 */
+};
+
+/* According to: 3GPP TS 44.065, 8 SNDCP XID parameters */
+enum gprs_sndcp_xid_param_types {
+ SNDCP_XID_VERSION_NUMBER,
+ SNDCP_XID_DATA_COMPRESSION, /* See also: subclause 6.6.1 */
+ SNDCP_XID_PROTOCOL_COMPRESSION, /* See also: subclause 6.5.1 */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.2.1 Parameters (Table 5) */
+struct gprs_sndcp_pcomp_rfc1144_params {
+ uint8_t nsapi_len; /* Number of applicable NSAPIs
+ * (default 0) */
+ uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
+ int s01; /* (default 15) */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.2.2 Assignment of PCOMP values */
+enum gprs_sndcp_pcomp_rfc1144_pcomp {
+ RFC1144_PCOMP1, /* Uncompressed TCP */
+ RFC1144_PCOMP2, /* Compressed TCP */
+ RFC1144_PCOMP_NUM /* Number of pcomp values */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.3.1 Parameters (Table 6) */
+struct gprs_sndcp_pcomp_rfc2507_params {
+ uint8_t nsapi_len; /* Number of applicable NSAPIs
+ * (default 0) */
+ uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
+ int f_max_period; /* (default 256) */
+ int f_max_time; /* (default 5) */
+ int max_header; /* (default 168) */
+ int tcp_space; /* (default 15) */
+ int non_tcp_space; /* (default 15) */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.3.2 Assignment of PCOMP values for RFC2507 */
+enum gprs_sndcp_pcomp_rfc2507_pcomp {
+ RFC2507_PCOMP1, /* Full Header */
+ RFC2507_PCOMP2, /* Compressed TCP */
+ RFC2507_PCOMP3, /* Compressed TCP non delta */
+ RFC2507_PCOMP4, /* Compressed non TCP */
+ RFC2507_PCOMP5, /* Context state */
+ RFC2507_PCOMP_NUM /* Number of pcomp values */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.4.1 Parameter (Table 10) */
+struct gprs_sndcp_pcomp_rohc_params {
+ uint8_t nsapi_len; /* Number of applicable NSAPIs
+ * (default 0) */
+ uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
+ int max_cid; /* (default 15) */
+ int max_header; /* (default 168) */
+ uint8_t profile_len; /* (default 1) */
+ uint16_t profile[MAX_ROHC]; /* (default 0, ROHC uncompressed) */
+};
+
+/* According to: 3GPP TS 44.065, 6.5.4.2 Assignment of PCOMP values for ROHC */
+enum gprs_sndcp_pcomp_rohc_pcomp {
+ ROHC_PCOMP1, /* ROHC small CIDs */
+ ROHC_PCOMP2, /* ROHC large CIDs */
+ ROHC_PCOMP_NUM /* Number of pcomp values */
+};
+
+/* ROHC compression profiles, see also:
+ http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.xhtml */
+enum gprs_sndcp_xid_rohc_profiles {
+ ROHC_UNCOMPRESSED = 0x0000, /* ROHC uncompressed [RFC5795] */
+ ROHC_RTP = 0x0001, /* ROHC RTP [RFC3095] */
+ ROHCV2_RTP = 0x0101, /* ROHCv2 RTP [RFC5225] */
+ ROHC_UDP = 0x0002, /* ROHC UDP [RFC3095] */
+ ROHCv2_UDP = 0x0102, /* ROHCv2 UDP [RFC5225] */
+ ROHC_ESP = 0x0003, /* ROHC ESP [RFC3095] */
+ ROHCV2_ESP = 0x0103, /* ROHCv2 ESP [RFC5225] */
+ ROHC_IP = 0x0004, /* ROHC IP [RFC3843] */
+ ROHCV2_IP = 0x0104, /* ROHCv2 IP [RFC5225] */
+ ROHC_LLA = 0x0005, /* ROHC LLA [RFC4362] */
+ ROHC_LLA_WITH_R_MODE = 0x0105, /* ROHC LLA with R-mode [RFC3408] */
+ ROHC_TCP = 0x0006, /* ROHC TCP [RFC6846] */
+ ROHC_RTP_UDP_LITE = 0x0007, /* ROHC RTP/UDP-Lite [RFC4019] */
+ ROHCV2_RTP_UDP_LITE = 0x0107, /* ROHCv2 RTP/UDP-Lite [RFC5225] */
+ ROHC_UDP_LITE = 0x0008, /* ROHC UDP-Lite [RFC4019] */
+ ROHCV2_UDP_LITE = 0x0108, /* ROHCv2 UDP-Lite [RFC5225] */
+};
+
+/* According to: 3GPP TS 44.065, 6.6.2.1 Parameters (Table 7a) */
+struct gprs_sndcp_dcomp_v42bis_params {
+ uint8_t nsapi_len; /* Number of applicable NSAPIs
+ * (default 0) */
+ uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
+ int p0; /* (default 3) */
+ int p1; /* (default 2048) */
+ int p2; /* (default 20) */
+
+};
+
+/* According to: 3GPP TS 44.065, 6.6.2.2 Assignment of DCOMP values */
+enum gprs_sndcp_dcomp_v42bis_dcomp {
+ V42BIS_DCOMP1, /* V.42bis enabled */
+ V42BIS_DCOMP_NUM /* Number of dcomp values */
+};
+
+/* According to: 3GPP TS 44.065, 6.6.3.1 Parameters (Table 7c) */
+struct gprs_sndcp_dcomp_v44_params {
+ uint8_t nsapi_len; /* Number of applicable NSAPIs
+ * (default 0) */
+ uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
+ int c0; /* (default 10000000) */
+ int p0; /* (default 3) */
+ int p1t; /* Refer to subclause 6.6.3.1.4 */
+ int p1r; /* Refer to subclause 6.6.3.1.5 */
+ int p3t; /* (default 3 x p1t) */
+ int p3r; /* (default 3 x p1r) */
+};
+
+/* According to: 3GPP TS 44.065, 6.6.3.2 Assignment of DCOMP values */
+enum gprs_sndcp_dcomp_v44_dcomp {
+ V44_DCOMP1, /* Packet method compressed */
+ V44_DCOMP2, /* Multi packet method compressed */
+ V44_DCOMP_NUM /* Number of dcomp values */
+};
+
+/* Transform a list with compression fields into an SNDCP-XID message (dst) */
+int gprs_sndcp_compile_xid(uint8_t *dst, unsigned int dst_maxlen,
+ const struct llist_head *comp_fields, int version);
+
+/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
+struct llist_head *gprs_sndcp_parse_xid(int *version,
+ const void *ctx,
+ const uint8_t *src,
+ unsigned int src_len,
+ const struct llist_head
+ *comp_fields_req);
+
+/* Find out to which compression class the specified comp-field belongs
+ * (header compression or data compression?) */
+int gprs_sndcp_get_compression_class(
+ const struct gprs_sndcp_comp_field *comp_field);
+
+/* Dump a list with SNDCP-XID fields (Debug) */
+void gprs_sndcp_dump_comp_fields(const struct llist_head *comp_fields,
+ unsigned int logl);
+
diff --git a/include/openbsc/gprs_subscriber.h b/include/openbsc/gprs_subscriber.h
new file mode 100644
index 000000000..be78febff
--- /dev/null
+++ b/include/openbsc/gprs_subscriber.h
@@ -0,0 +1,31 @@
+/* GPRS subscriber details for use in SGSN land */
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+extern struct llist_head * const gprs_subscribers;
+
+struct gprs_subscr {
+ struct llist_head entry;
+ int use_count;
+
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ uint32_t tmsi;
+ char imei[GSM23003_IMEISV_NUM_DIGITS+1];
+ bool authorized;
+ bool keep_in_ram;
+ uint32_t flags;
+ uint16_t lac;
+
+ struct sgsn_subscriber_data *sgsn_data;
+};
+
+struct gprs_subscr *_gprs_subscr_get(struct gprs_subscr *gsub,
+ const char *file, int line);
+struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
+ const char *file, int line);
+#define gprs_subscr_get(gsub) _gprs_subscr_get(gsub, __BASE_FILE__, __LINE__)
+#define gprs_subscr_put(gsub) _gprs_subscr_put(gsub, __BASE_FILE__, __LINE__)
diff --git a/include/openbsc/gprs_utils.h b/include/openbsc/gprs_utils.h
new file mode 100644
index 000000000..603605c7a
--- /dev/null
+++ b/include/openbsc/gprs_utils.h
@@ -0,0 +1,45 @@
+/* GPRS utility functions */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010-2014 by On-Waves
+ * (C) 2013 by Holger Hans Peter Freyther
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+struct msgb;
+struct gprs_ra_id;
+
+struct msgb *gprs_msgb_copy(const struct msgb *msg, const char *name);
+int gprs_msgb_resize_area(struct msgb *msg, uint8_t *area,
+ size_t old_size, size_t new_size);
+char *gprs_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t rest_chars);
+int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
+
+/* GSM 04.08, 10.5.7.3 GPRS Timer */
+int gprs_tmr_to_secs(uint8_t tmr);
+uint8_t gprs_secs_to_tmr_floor(int secs);
+
+int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len);
+int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
+int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
+void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi);
+
+int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2);
diff --git a/include/openbsc/gsm_04_08.h b/include/openbsc/gsm_04_08.h
new file mode 100644
index 000000000..a8b2de958
--- /dev/null
+++ b/include/openbsc/gsm_04_08.h
@@ -0,0 +1,85 @@
+#ifndef _GSM_04_08_H
+#define _GSM_04_08_H
+
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+#include <openbsc/meas_rep.h>
+
+struct msgb;
+struct gsm_bts;
+struct gsm_subscriber;
+struct gsm_network;
+struct gsm_trans;
+struct gsm_subscriber_connection;
+struct amr_multirate_conf;
+struct amr_mode;
+struct bsc_subscr;
+
+#define GSM48_ALLOC_SIZE 2048
+#define GSM48_ALLOC_HEADROOM 256
+
+static inline struct msgb *gsm48_msgb_alloc_name(const char *name)
+{
+ return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
+ name);
+}
+
+/* config options controlling the behaviour of the lower leves */
+void gsm0408_allow_everyone(int allow);
+void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
+void gsm0408_clear_all_trans(struct gsm_network *net, int protocol);
+int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);
+int gsm0408_new_conn(struct gsm_subscriber_connection *conn);
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, uint8_t ra);
+/* don't use "enum gsm_chreq_reason_t" to avoid circular dependency */
+int get_reason_by_chreq(uint8_t ra, int neci);
+void gsm_net_update_ctype(struct gsm_network *net);
+
+int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn);
+int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand,
+ uint8_t *autn, int key_seq);
+int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn);
+int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
+int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
+ enum gsm48_reject_value value);
+int gsm48_send_rr_release(struct gsm_lchan *lchan);
+int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
+int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id,
+ uint8_t apdu_len, const uint8_t *apdu);
+int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_class);
+int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
+ uint8_t power_command, uint8_t ho_ref);
+
+int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg);
+
+/* convert a ASCII phone number to call-control BCD */
+int encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
+ int h_len, const char *input);
+int decode_bcd_number(char *output, int output_len, const uint8_t *bcd_lv,
+ int h_len);
+
+int send_siemens_mrpci(struct gsm_lchan *lchan, uint8_t *classmark2_lv);
+int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type);
+int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type);
+int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn,
+ struct msgb *msg, struct bsc_subscr *bsub);
+
+int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode);
+int gsm48_rx_rr_modif_ack(struct msgb *msg);
+int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg);
+
+struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value);
+struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);
+void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
+ const struct gsm_lchan *lchan);
+
+void release_security_operation(struct gsm_subscriber_connection *conn);
+void allocate_security_operation(struct gsm_subscriber_connection *conn);
+
+int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes);
+
+#endif
diff --git a/include/openbsc/gsm_04_11.h b/include/openbsc/gsm_04_11.h
new file mode 100644
index 000000000..017c88765
--- /dev/null
+++ b/include/openbsc/gsm_04_11.h
@@ -0,0 +1,47 @@
+#ifndef _GSM_04_11_H
+#define _GSM_04_11_H
+
+#include <osmocom/gsm/protocol/gsm_04_11.h>
+
+#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
+
+/* SMS deliver PDU */
+struct sms_deliver {
+ uint8_t mti:2; /* message type indicator */
+ uint8_t mms:1; /* more messages to send */
+ uint8_t rp:1; /* reply path */
+ uint8_t udhi:1; /* user data header indicator */
+ uint8_t sri:1; /* status report indication */
+ uint8_t *orig_addr; /* originating address */
+ uint8_t pid; /* protocol identifier */
+ uint8_t dcs; /* data coding scheme */
+ /* service centre time stamp */
+ uint8_t ud_len; /* user data length */
+ uint8_t *user_data; /* user data */
+
+ uint8_t msg_ref; /* message reference */
+ uint8_t *smsc;
+};
+
+struct msgb;
+
+int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+struct gsm_sms *sms_alloc(void);
+void sms_free(struct gsm_sms *sms);
+struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, struct gsm_subscriber *sender, int dcs, const char *text);
+
+void _gsm411_sms_trans_free(struct gsm_trans *trans);
+int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
+ struct gsm_sms *sms);
+int gsm411_send_sms(struct gsm_subscriber_connection *conn,
+ struct gsm_sms *sms);
+void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
+
+uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref);
+
+int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref);
+int gsm411_send_rp_error(struct gsm_trans *trans, uint8_t msg_ref,
+ uint8_t cause);
+
+#endif
diff --git a/include/openbsc/gsm_04_80.h b/include/openbsc/gsm_04_80.h
new file mode 100644
index 000000000..d65f640bc
--- /dev/null
+++ b/include/openbsc/gsm_04_80.h
@@ -0,0 +1,25 @@
+#ifndef _GSM_04_80_H
+#define _GSM_04_80_H
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_04_80.h>
+#include <osmocom/gsm/gsm0480.h>
+
+struct gsm_subscriber_connection;
+
+int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
+ const struct msgb *in_msg, const char* response_text,
+ const struct ss_request *req);
+int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
+ const struct msgb *msg,
+ const struct ss_request *request);
+
+int msc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level,
+ const char *text);
+int msc_send_ussd_release_complete(struct gsm_subscriber_connection *conn);
+
+int bsc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level,
+ const char *text);
+int bsc_send_ussd_release_complete(struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
new file mode 100644
index 000000000..a97405105
--- /dev/null
+++ b/include/openbsc/gsm_data.h
@@ -0,0 +1,596 @@
+#ifndef _GSM_DATA_H
+#define _GSM_DATA_H
+
+#include <stdint.h>
+#include <regex.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+#include <osmocom/core/timer.h>
+#include <osmocom/core/rate_ctr.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/stats.h>
+
+#include <osmocom/crypt/auth.h>
+
+#include <openbsc/rest_octets.h>
+#include <openbsc/common_cs.h>
+
+/** annotations for msgb ownership */
+#define __uses
+
+#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
+
+struct mncc_sock_state;
+struct gsm_subscriber_group;
+struct bsc_subscr;
+
+#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
+
+#define tmsi_from_string(str) strtoul(str, NULL, 10)
+
+/* 3-bit long values */
+#define EARFCN_PRIO_INVALID 8
+#define EARFCN_MEAS_BW_INVALID 8
+/* 5-bit long values */
+#define EARFCN_QRXLV_INVALID 32
+#define EARFCN_THRESH_LOW_INVALID 32
+
+enum gsm_security_event {
+ GSM_SECURITY_NOAVAIL,
+ GSM_SECURITY_AUTH_FAILED,
+ GSM_SECURITY_SUCCEEDED,
+ GSM_SECURITY_ALREADY,
+};
+
+struct msgb;
+typedef int gsm_cbfn(unsigned int hooknum,
+ unsigned int event,
+ struct msgb *msg,
+ void *data, void *param);
+
+/* Real authentication information containing Ki */
+enum gsm_auth_algo {
+ AUTH_ALGO_NONE,
+ AUTH_ALGO_XOR,
+ AUTH_ALGO_COMP128v1,
+};
+
+struct gsm_auth_info {
+ enum gsm_auth_algo auth_algo;
+ unsigned int a3a8_ki_len;
+ uint8_t a3a8_ki[16];
+};
+
+struct gsm_auth_tuple {
+ int use_count;
+ int key_seq;
+ struct osmo_auth_vector vec;
+};
+#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
+
+/*
+ * LOCATION UPDATING REQUEST state
+ *
+ * Our current operation is:
+ * - Get imei/tmsi
+ * - Accept/Reject according to global policy
+ */
+struct gsm_loc_updating_operation {
+ struct osmo_timer_list updating_timer;
+ unsigned int waiting_for_imsi : 1;
+ unsigned int waiting_for_imei : 1;
+ unsigned int key_seq : 4;
+};
+
+/*
+ * AUTHENTICATION/CIPHERING state
+ */
+struct gsm_security_operation {
+ struct gsm_auth_tuple atuple;
+ gsm_cbfn *cb;
+ void *cb_data;
+};
+
+/*
+ * A dummy to keep a connection up for at least
+ * a couple of seconds to work around MSC issues.
+ */
+struct gsm_anchor_operation {
+ struct osmo_timer_list timeout;
+};
+
+/* Maximum number of neighbor cells whose average we track */
+#define MAX_NEIGH_MEAS 10
+/* Maximum size of the averaging window for neighbor cells */
+#define MAX_WIN_NEIGH_AVG 10
+
+/* processed neighbor measurements for one cell */
+struct neigh_meas_proc {
+ uint16_t arfcn;
+ uint8_t bsic;
+ uint8_t rxlev[MAX_WIN_NEIGH_AVG];
+ unsigned int rxlev_cnt;
+ uint8_t last_seen_nr;
+};
+
+enum ran_type {
+ RAN_UNKNOWN,
+ RAN_GERAN_A, /* 2G / A-interface */
+ RAN_UTRAN_IU, /* 3G / Iu-interface (IuCS or IuPS) */
+};
+
+/* active radio connection of a mobile subscriber */
+struct gsm_subscriber_connection {
+ struct llist_head entry;
+
+ /* To whom we are allocated at the moment */
+ struct gsm_subscriber *subscr;
+
+ /* libbsc subscriber information */
+ struct bsc_subscr *bsub;
+
+ /* LU expiration handling */
+ uint8_t expire_timer_stopped;
+ /* SMS helpers for libmsc */
+ uint8_t next_rp_ref;
+
+ /*
+ * Operations that have a state and might be pending
+ */
+ struct gsm_loc_updating_operation *loc_operation;
+ struct gsm_security_operation *sec_operation;
+ struct gsm_anchor_operation *anch_operation;
+
+ /* Are we part of a special "silent" call */
+ int silent_call;
+
+ /* MNCC rtp bridge markers */
+ int mncc_rtp_bridge;
+ int mncc_rtp_create_pending;
+ int mncc_rtp_connect_pending;
+
+ /* bsc structures */
+ struct osmo_bsc_sccp_con *sccp_con; /* BSC */
+
+ /* back pointers */
+ struct gsm_network *network;
+
+ int in_release;
+ struct gsm_lchan *lchan; /* BSC */
+ struct gsm_lchan *ho_lchan; /* BSC */
+ struct gsm_bts *bts; /* BSC */
+
+ /* for assignment handling */
+ struct osmo_timer_list T10; /* BSC */
+ struct gsm_lchan *secondary_lchan; /* BSC */
+
+ /* connected via 2G or 3G? */
+ enum ran_type via_ran;
+};
+
+
+#define ROLE_BSC
+#include "gsm_data_shared.h"
+
+
+enum {
+ BSC_CTR_CHREQ_TOTAL,
+ BSC_CTR_CHREQ_NO_CHANNEL,
+ BSC_CTR_HANDOVER_ATTEMPTED,
+ BSC_CTR_HANDOVER_NO_CHANNEL,
+ BSC_CTR_HANDOVER_TIMEOUT,
+ BSC_CTR_HANDOVER_COMPLETED,
+ BSC_CTR_HANDOVER_FAILED,
+ BSC_CTR_PAGING_ATTEMPTED,
+ BSC_CTR_PAGING_DETACHED,
+ BSC_CTR_PAGING_COMPLETED,
+ BSC_CTR_PAGING_EXPIRED,
+ BSC_CTR_CHAN_RF_FAIL,
+ BSC_CTR_CHAN_RLL_ERR,
+ BSC_CTR_BTS_OML_FAIL,
+ BSC_CTR_BTS_RSL_FAIL,
+ BSC_CTR_CODEC_AMR_F,
+ BSC_CTR_CODEC_AMR_H,
+ BSC_CTR_CODEC_EFR,
+ BSC_CTR_CODEC_V1_FR,
+ BSC_CTR_CODEC_V1_HR,
+};
+
+static const struct rate_ctr_desc bsc_ctr_description[] = {
+ [BSC_CTR_CHREQ_TOTAL] = {"chreq.total", "Received channel requests."},
+ [BSC_CTR_CHREQ_NO_CHANNEL] = {"chreq.no_channel", "Sent to MS no channel available."},
+ [BSC_CTR_HANDOVER_ATTEMPTED] = {"handover.attempted", "Received handover attempts."},
+ [BSC_CTR_HANDOVER_NO_CHANNEL] = {"handover.no_channel", "Sent no channel available responses."},
+ [BSC_CTR_HANDOVER_TIMEOUT] = {"handover.timeout", "Count the amount of timeouts of timer T3103."},
+ [BSC_CTR_HANDOVER_COMPLETED] = {"handover.completed", "Received handover completed."},
+ [BSC_CTR_HANDOVER_FAILED] = {"handover.failed", "Receive HO FAIL messages."},
+ [BSC_CTR_PAGING_ATTEMPTED] = {"paging.attempted", "Paging attempts for a MS."},
+ [BSC_CTR_PAGING_DETACHED] = {"paging.detached", "Counts the amount of paging attempts which couldn't sent out any paging request because no responsible bts found."},
+ [BSC_CTR_PAGING_COMPLETED] = {"paging.completed", "Paging successful completed."},
+ [BSC_CTR_PAGING_EXPIRED] = {"paging.expired", "Paging Request expired because of timeout T3113."},
+ [BSC_CTR_CHAN_RF_FAIL] = {"chan.rf_fail", "Received a RF failure indication from BTS."},
+ [BSC_CTR_CHAN_RLL_ERR] = {"chan.rll_err", "Received a RLL failure with T200 cause from BTS."},
+ [BSC_CTR_BTS_OML_FAIL] = {"bts.oml_fail", "Received a TEI down on a OML link."},
+ [BSC_CTR_BTS_RSL_FAIL] = {"bts.rsl_fail", "Received a TEI down on a OML link."},
+ [BSC_CTR_CODEC_AMR_F] = {"bts.codec_amr_f", "Count the usage of AMR/F codec by channel mode requested."},
+ [BSC_CTR_CODEC_AMR_H] = {"bts.codec_amr_h", "Count the usage of AMR/H codec by channel mode requested."},
+ [BSC_CTR_CODEC_EFR] = {"bts.codec_efr", "Count the usage of EFR codec by channel mode requested."},
+ [BSC_CTR_CODEC_V1_FR] = {"bts.codec_fr", "Count the usage of FR codec by channel mode requested."},
+ [BSC_CTR_CODEC_V1_HR] = {"bts.codec_hr", "Count the usage of HR codec by channel mode requested."},
+};
+
+enum {
+ MSC_CTR_LOC_UPDATE_TYPE_ATTACH,
+ MSC_CTR_LOC_UPDATE_TYPE_NORMAL,
+ MSC_CTR_LOC_UPDATE_TYPE_PERIODIC,
+ MSC_CTR_LOC_UPDATE_TYPE_DETACH,
+ MSC_CTR_LOC_UPDATE_FAILED,
+ MSC_CTR_LOC_UPDATE_COMPLETED,
+ MSC_CTR_SMS_SUBMITTED,
+ MSC_CTR_SMS_NO_RECEIVER,
+ MSC_CTR_SMS_DELIVERED,
+ MSC_CTR_SMS_RP_ERR_MEM,
+ MSC_CTR_SMS_RP_ERR_OTHER,
+ MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR,
+ MSC_CTR_CALL_MO_SETUP,
+ MSC_CTR_CALL_MO_CONNECT_ACK,
+ MSC_CTR_CALL_MT_SETUP,
+ MSC_CTR_CALL_MT_CONNECT,
+ MSC_CTR_CALL_ACTIVE,
+ MSC_CTR_CALL_COMPLETE,
+ MSC_CTR_CALL_INCOMPLETE,
+};
+
+static const struct rate_ctr_desc msc_ctr_description[] = {
+ [MSC_CTR_LOC_UPDATE_TYPE_ATTACH] = {"loc_update_type.attach", "Received location update imsi attach requests."},
+ [MSC_CTR_LOC_UPDATE_TYPE_NORMAL] = {"loc_update_type.normal", "Received location update normal requests."},
+ [MSC_CTR_LOC_UPDATE_TYPE_PERIODIC] = {"loc_update_type.periodic", "Received location update periodic requests."},
+ [MSC_CTR_LOC_UPDATE_TYPE_DETACH] = {"loc_update_type.detach", "Received location update detach indication."},
+ [MSC_CTR_LOC_UPDATE_FAILED] = {"loc_update_resp.failed", "Rejected location updates."},
+ [MSC_CTR_LOC_UPDATE_COMPLETED] = {"loc_update_resp.completed", "Successful location updates."},
+ [MSC_CTR_SMS_SUBMITTED] = {"sms.submitted", "Received a RPDU from a MS (MO)."},
+ [MSC_CTR_SMS_NO_RECEIVER] = {"sms.no_receiver", "Counts SMS which couldn't routed because no receiver found."},
+ [MSC_CTR_SMS_DELIVERED] = {"sms.delivered", "Global SMS Deliver attempts."},
+ [MSC_CTR_SMS_RP_ERR_MEM] = {"sms.rp_err_mem", "CAUSE_MT_MEM_EXCEEDED errors of MS responses on a sms deliver attempt."},
+ [MSC_CTR_SMS_RP_ERR_OTHER] = {"sms.rp_err_other", "Other error of MS responses on a sms delive attempt."},
+ [MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR] = {"sms.deliver_unknown_error", "Unknown error occured during sms delivery."},
+ /* FIXME: count also sms delivered */
+ [MSC_CTR_CALL_MO_SETUP] = {"call.mo_setup", "Received setup requests from a MS to init a MO call."},
+ [MSC_CTR_CALL_MO_CONNECT_ACK] = {"call.mo_connect_ack", "Received a connect ack from MS of a MO call. Call is now succesful connected up."},
+ [MSC_CTR_CALL_MT_SETUP] = {"call.mt_setup", "Sent setup requests to the MS (MT)."},
+ [MSC_CTR_CALL_MT_CONNECT] = {"call.mt_connect", "Sent a connect to the MS (MT)."},
+ [MSC_CTR_CALL_ACTIVE] = {"call.active", "Count total amount of calls that ever reached active state."},
+ [MSC_CTR_CALL_COMPLETE] = {"call.complete", "Count total amount of calls which got terminated by disconnect req or ind after reaching active state."},
+ [MSC_CTR_CALL_INCOMPLETE] = {"call.incomplete", "Count total amount of call which got terminated by any other reason after reaching active state."},
+};
+
+
+static const struct rate_ctr_group_desc bsc_ctrg_desc = {
+ "bsc",
+ "base station controller",
+ OSMO_STATS_CLASS_GLOBAL,
+ ARRAY_SIZE(bsc_ctr_description),
+ bsc_ctr_description,
+};
+
+static const struct rate_ctr_group_desc msc_ctrg_desc = {
+ "msc",
+ "mobile switching center",
+ OSMO_STATS_CLASS_GLOBAL,
+ ARRAY_SIZE(msc_ctr_description),
+ msc_ctr_description,
+};
+
+enum gsm_auth_policy {
+ GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */
+ GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */
+ GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */
+ GSM_AUTH_POLICY_REGEXP, /* accept IMSIs matching given regexp */
+};
+
+#define GSM_T3101_DEFAULT 10
+#define GSM_T3105_DEFAULT 40
+#define GSM_T3113_DEFAULT 60
+#define GSM_T3122_DEFAULT 10
+
+struct gsm_tz {
+ int override; /* if 0, use system's time zone instead. */
+ int hr; /* hour */
+ int mn; /* minute */
+ int dst; /* daylight savings */
+};
+
+struct gsm_network {
+ /* global parameters */
+ uint16_t country_code;
+ uint16_t network_code;
+ char *name_long;
+ char *name_short;
+ enum gsm_auth_policy auth_policy;
+ regex_t authorized_regexp;
+ char *authorized_reg_str;
+ enum gsm48_reject_value reject_cause;
+ int a5_encryption;
+ int neci;
+ int send_mm_info;
+ struct {
+ int active;
+ /* Window RXLEV averaging */
+ unsigned int win_rxlev_avg; /* number of SACCH frames */
+ /* Window RXQUAL averaging */
+ unsigned int win_rxqual_avg; /* number of SACCH frames */
+ /* Window RXLEV neighbouring cells averaging */
+ unsigned int win_rxlev_avg_neigh; /* number of SACCH frames */
+
+ /* how often should we check for power budget HO */
+ unsigned int pwr_interval; /* SACCH frames */
+ /* how much better does a neighbor cell have to be ? */
+ unsigned int pwr_hysteresis; /* dBm */
+ /* maximum distacne before we try a handover */
+ unsigned int max_distance; /* TA values */
+ } handover;
+
+ struct rate_ctr_group *bsc_ctrs;
+ struct rate_ctr_group *msc_ctrs;
+ struct osmo_counter *active_calls;
+
+ /* layer 4 */
+ struct mncc_sock_state *mncc_state;
+ mncc_recv_cb_t mncc_recv;
+ struct llist_head upqueue;
+ struct llist_head trans_list;
+ struct bsc_api *bsc_api;
+
+ unsigned int num_bts;
+ struct llist_head bts_list;
+
+ /* timer values */
+ int T3101;
+ int T3103;
+ int T3105;
+ int T3107;
+ int T3109;
+ int T3111;
+ int T3113;
+ int T3115;
+ int T3117;
+ int T3119;
+ int T3122;
+ int T3141;
+
+ /* timer to expire old location updates */
+ struct osmo_timer_list subscr_expire_timer;
+
+ /* Radio Resource Location Protocol (TS 04.31) */
+ struct {
+ enum rrlp_mode mode;
+ } rrlp;
+
+ enum gsm_chan_t ctype_by_chreq[18];
+
+ /* Use a TCH for handling requests of type paging any */
+ int pag_any_tch;
+
+ /* MSC data in case we are a true BSC */
+ struct osmo_bsc_data *bsc_data;
+
+ /* subscriber related features */
+ bool auto_create_subscr;
+ bool auto_assign_exten;
+ uint64_t ext_min;
+ uint64_t ext_max;
+ struct gsm_subscriber_group *subscr_group;
+ struct gsm_sms_queue *sms_queue;
+
+ /* nitb related control */
+ int avoid_tmsi;
+
+ /* control interface */
+ struct ctrl_handle *ctrl;
+
+ /* Allow or disallow TCH/F on dynamic TCH/F_TCH/H_PDCH; OS#1778 */
+ bool dyn_ts_allow_tch_f;
+
+ /* all active subscriber connections. */
+ struct llist_head subscr_conns;
+
+ /* if override is nonzero, this timezone data is used for all MM
+ * contexts. */
+ /* TODO: in OsmoNITB, tz-override used to be BTS-specific. To enable
+ * BTS|RNC specific timezone overrides for multi-tz networks in
+ * OsmoMSC, this should be tied to the location area code (LAC). */
+ struct gsm_tz tz;
+
+ /* List of all struct bsc_subscr used in libbsc. This llist_head is
+ * allocated so that the llist_head pointer itself can serve as a
+ * talloc context (useful to not have to pass the entire gsm_network
+ * struct to the bsc_subscr_* API, and for bsc_susbscr unit tests to
+ * not require gsm_data.h). In an MSC-without-BSC environment, this
+ * pointer is NULL to indicate absence of a bsc_subscribers list. */
+ struct llist_head *bsc_subscribers;
+};
+
+struct osmo_esme;
+
+enum gsm_sms_source_id {
+ SMS_SOURCE_UNKNOWN = 0,
+ SMS_SOURCE_MS, /* received from MS */
+ SMS_SOURCE_VTY, /* received from VTY */
+ SMS_SOURCE_SMPP, /* received via SMPP */
+};
+
+#define SMS_HDR_SIZE 128
+#define SMS_TEXT_SIZE 256
+
+struct gsm_sms_addr {
+ uint8_t ton;
+ uint8_t npi;
+ char addr[21+1];
+};
+
+struct gsm_sms {
+ unsigned long long id;
+ struct gsm_subscriber *receiver;
+ struct gsm_sms_addr src, dst;
+ enum gsm_sms_source_id source;
+
+ struct {
+ uint8_t transaction_id;
+ uint32_t msg_ref;
+ } gsm411;
+
+ struct {
+ struct osmo_esme *esme;
+ uint32_t sequence_nr;
+ int transaction_mode;
+ char msg_id[16];
+ } smpp;
+
+ unsigned long validity_minutes;
+ uint8_t reply_path_req;
+ uint8_t status_rep_req;
+ uint8_t ud_hdr_ind;
+ uint8_t protocol_id;
+ uint8_t data_coding_scheme;
+ uint8_t msg_ref;
+ uint8_t user_data_len;
+ uint8_t user_data[SMS_TEXT_SIZE];
+
+ char text[SMS_TEXT_SIZE];
+};
+
+extern void talloc_ctx_init(void *ctx_root);
+
+int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
+
+/* Get reference to a neighbor cell on a given BCCH ARFCN */
+struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
+ uint16_t arfcn, uint8_t bsic);
+
+enum gsm_bts_type parse_btstype(const char *arg);
+const char *btstype2str(enum gsm_bts_type type);
+struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
+ struct gsm_bts *start_bts);
+
+extern void *tall_bsc_ctx;
+extern int ipacc_rtp_direct;
+
+/* this actaully refers to the IPA transport, not the BTS model */
+static inline int is_ipaccess_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ case GSM_BTS_TYPE_OSMOBTS:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static inline int is_sysmobts_v2(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_OSMOBTS:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static inline int is_siemens_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_BS11:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline int is_nokia_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NOKIA_SITE:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static inline int is_e1_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_BS11:
+ case GSM_BTS_TYPE_RBS2000:
+ case GSM_BTS_TYPE_NOKIA_SITE:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+enum gsm_auth_policy gsm_auth_policy_parse(const char *arg);
+const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
+
+enum rrlp_mode rrlp_mode_parse(const char *arg);
+const char *rrlp_mode_name(enum rrlp_mode mode);
+
+enum bts_gprs_mode bts_gprs_mode_parse(const char *arg, int *valid);
+const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
+int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode);
+
+int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts);
+void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
+struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
+
+int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
+int gsm_bts_model_register(struct gsm_bts_model *model);
+
+struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lchan);
+void bsc_subscr_con_free(struct gsm_subscriber_connection *conn);
+
+struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network);
+void msc_subscr_con_free(struct gsm_subscriber_connection *conn);
+
+struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net,
+ enum gsm_bts_type type,
+ uint8_t bsic);
+
+void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr,
+ uint8_t e1_ts, uint8_t e1_ts_ss);
+
+void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
+bool gsm_btsmodel_has_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
+struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr);
+int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx);
+int gsm_bts_set_system_infos(struct gsm_bts *bts);
+
+/* generic E1 line operations for all ISDN-based BTS. */
+extern struct e1inp_line_ops bts_isdn_e1inp_line_ops;
+
+extern const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE+1];
+extern const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1];
+
+/* control interface handling */
+int bsc_base_ctrl_cmds_install(void);
+int msc_ctrl_cmds_install(void);
+
+/* dependency handling */
+void bts_depend_mark(struct gsm_bts *bts, int dep);
+void bts_depend_clear(struct gsm_bts *bts, int dep);
+int bts_depend_check(struct gsm_bts *bts);
+int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other);
+
+int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts);
+void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value);
+
+#endif /* _GSM_DATA_H */
diff --git a/include/openbsc/gsm_data_shared.h b/include/openbsc/gsm_data_shared.h
new file mode 100644
index 000000000..4c71a075e
--- /dev/null
+++ b/include/openbsc/gsm_data_shared.h
@@ -0,0 +1,994 @@
+#ifndef _GSM_DATA_SHAREDH
+#define _GSM_DATA_SHAREDH
+
+#include <regex.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <osmocom/core/timer.h>
+#include <osmocom/core/bitvec.h>
+#include <osmocom/core/statistics.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/rxlev_stat.h>
+#include <osmocom/gsm/sysinfo.h>
+#include <osmocom/gsm/meas_rep.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
+
+#include <osmocom/abis/e1_input.h>
+
+#ifndef ROLE_BSC
+#include <osmocom/gsm/lapdm.h>
+#endif
+
+#include <openbsc/common_cs.h>
+
+/* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1:
+ 4-bit index is used (2#1111 = 10#15) */
+#define SI2Q_MAX_NUM 16
+/* length in bits (for single SI2quater message) */
+#define SI2Q_MAX_LEN 160
+#define SI2Q_MIN_LEN 18
+
+struct osmo_bsc_data;
+
+struct osmo_bsc_sccp_con;
+struct gsm_sms_queue;
+
+/* RRLP mode of operation */
+enum rrlp_mode {
+ RRLP_MODE_NONE,
+ RRLP_MODE_MS_BASED,
+ RRLP_MODE_MS_PREF,
+ RRLP_MODE_ASS_PREF,
+};
+
+/* Channel Request reason */
+enum gsm_chreq_reason_t {
+ GSM_CHREQ_REASON_EMERG,
+ GSM_CHREQ_REASON_PAG,
+ GSM_CHREQ_REASON_CALL,
+ GSM_CHREQ_REASON_LOCATION_UPD,
+ GSM_CHREQ_REASON_OTHER,
+ GSM_CHREQ_REASON_PDCH,
+};
+
+/* lchans 0..3 are SDCCH in combined channel configuration,
+ use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */
+#define CCCH_LCHAN 4
+
+#define TRX_NR_TS 8
+#define TS_MAX_LCHAN 8
+
+#define HARDCODED_ARFCN 123
+#define HARDCODED_BSIC 0x3f /* NCC = 7 / BCC = 7 */
+
+/* for multi-drop config */
+#define HARDCODED_BTS0_TS 1
+#define HARDCODED_BTS1_TS 6
+#define HARDCODED_BTS2_TS 11
+
+#define MAX_VERSION_LENGTH 64
+
+#define MAX_BTS_FEATURES 128
+
+enum gsm_hooks {
+ GSM_HOOK_NM_SWLOAD,
+ GSM_HOOK_RR_PAGING,
+ GSM_HOOK_RR_SECURITY,
+};
+
+enum gsm_paging_event {
+ GSM_PAGING_SUCCEEDED,
+ GSM_PAGING_EXPIRED,
+ GSM_PAGING_OOM,
+ GSM_PAGING_BUSY,
+};
+
+enum bts_gprs_mode {
+ BTS_GPRS_NONE = 0,
+ BTS_GPRS_GPRS = 1,
+ BTS_GPRS_EGPRS = 2,
+};
+
+struct gsm_lchan;
+struct gsm_subscriber;
+struct gsm_mncc;
+struct osmo_rtp_socket;
+struct rtp_socket;
+struct bsc_api;
+
+/* Network Management State */
+struct gsm_nm_state {
+ uint8_t operational;
+ uint8_t administrative;
+ uint8_t availability;
+};
+
+struct gsm_abis_mo {
+ uint8_t obj_class;
+ uint8_t procedure_pending;
+ struct abis_om_obj_inst obj_inst;
+ const char *name;
+ struct gsm_nm_state nm_state;
+ struct tlv_parsed *nm_attr;
+ struct gsm_bts *bts;
+};
+
+/* Ericsson OM2000 Managed Object */
+struct abis_om2k_mo {
+ uint8_t class;
+ uint8_t bts;
+ uint8_t assoc_so;
+ uint8_t inst;
+} __attribute__ ((packed));
+
+struct om2k_mo {
+ struct abis_om2k_mo addr;
+ struct osmo_fsm_inst *fsm;
+};
+
+#define A38_XOR_MIN_KEY_LEN 12
+#define A38_XOR_MAX_KEY_LEN 16
+#define A38_COMP128_KEY_LEN 16
+#define RSL_ENC_ALG_A5(x) (x+1)
+#define MAX_EARFCN_LIST 32
+
+/* is the data link established? who established it? */
+#define LCHAN_SAPI_UNUSED 0
+#define LCHAN_SAPI_MS 1
+#define LCHAN_SAPI_NET 2
+#define LCHAN_SAPI_REL 3
+
+/* state of a logical channel */
+enum gsm_lchan_state {
+ LCHAN_S_NONE, /* channel is not active */
+ LCHAN_S_ACT_REQ, /* channel activation requested */
+ LCHAN_S_ACTIVE, /* channel is active and operational */
+ LCHAN_S_REL_REQ, /* channel release has been requested */
+ LCHAN_S_REL_ERR, /* channel is in an error state */
+ LCHAN_S_BROKEN, /* channel is somehow unusable */
+ LCHAN_S_INACTIVE, /* channel is set inactive */
+};
+
+/* BTS ONLY */
+#define MAX_NUM_UL_MEAS 104
+#define LC_UL_M_F_L1_VALID (1 << 0)
+#define LC_UL_M_F_RES_VALID (1 << 1)
+
+struct bts_ul_meas {
+ /* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */
+ uint16_t ber10k;
+ /* timing advance offset (in quarter bits) */
+ int16_t ta_offs_qbits;
+ /* C/I ratio in dB */
+ float c_i;
+ /* flags */
+ uint8_t is_sub:1;
+ /* RSSI in dBm * -1 */
+ uint8_t inv_rssi;
+};
+
+struct bts_codec_conf {
+ uint8_t hr;
+ uint8_t efr;
+ uint8_t amr;
+};
+
+struct amr_mode {
+ uint8_t mode;
+ uint8_t threshold;
+ uint8_t hysteresis;
+};
+
+struct amr_multirate_conf {
+ uint8_t gsm48_ie[2];
+ struct amr_mode ms_mode[4];
+ struct amr_mode bts_mode[4];
+ uint8_t num_modes;
+};
+/* /BTS ONLY */
+
+enum lchan_csd_mode {
+ LCHAN_CSD_M_NT,
+ LCHAN_CSD_M_T_1200_75,
+ LCHAN_CSD_M_T_600,
+ LCHAN_CSD_M_T_1200,
+ LCHAN_CSD_M_T_2400,
+ LCHAN_CSD_M_T_9600,
+ LCHAN_CSD_M_T_14400,
+ LCHAN_CSD_M_T_29000,
+ LCHAN_CSD_M_T_32000,
+};
+
+/* State of the SAPIs in the lchan */
+enum lchan_sapi_state {
+ LCHAN_SAPI_S_NONE,
+ LCHAN_SAPI_S_REQ,
+ LCHAN_SAPI_S_ASSIGNED,
+ LCHAN_SAPI_S_REL,
+ LCHAN_SAPI_S_ERROR,
+};
+
+struct gsm_lchan {
+ /* The TS that we're part of */
+ struct gsm_bts_trx_ts *ts;
+ /* The logical subslot number in the TS */
+ uint8_t nr;
+ /* The logical channel type */
+ enum gsm_chan_t type;
+ /* RSL channel mode */
+ enum rsl_cmod_spd rsl_cmode;
+ /* If TCH, traffic channel mode */
+ enum gsm48_chan_mode tch_mode;
+ enum lchan_csd_mode csd_mode;
+ /* State */
+ enum gsm_lchan_state state;
+ const char *broken_reason;
+ /* Power levels for MS and BTS */
+ uint8_t bs_power;
+ uint8_t ms_power;
+ /* Encryption information */
+ struct gsm_encr encr;
+
+ /* AMR bits */
+ uint8_t mr_ms_lv[7];
+ uint8_t mr_bts_lv[7];
+
+ /* Established data link layer services */
+ uint8_t sapis[8];
+ int sacch_deact;
+
+ struct {
+ uint32_t bound_ip;
+ uint32_t connect_ip;
+ uint16_t bound_port;
+ uint16_t connect_port;
+ uint16_t conn_id;
+ uint8_t rtp_payload;
+ uint8_t rtp_payload2;
+ uint8_t speech_mode;
+#ifdef ROLE_BSC
+ struct rtp_socket *rtp_socket;
+#else
+ struct osmo_rtp_socket *rtp_socket;
+#endif
+ } abis_ip;
+
+ uint8_t rqd_ta;
+
+ char *name;
+
+#ifdef ROLE_BSC
+ struct osmo_timer_list T3101;
+ struct osmo_timer_list T3109;
+ struct osmo_timer_list T3111;
+ struct osmo_timer_list error_timer;
+ struct osmo_timer_list act_timer;
+ struct osmo_timer_list rel_work;
+ uint8_t error_cause;
+
+ /* table of neighbor cell measurements */
+ struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
+
+ /* cache of last measurement reports on this lchan */
+ struct gsm_meas_rep meas_rep[6];
+ int meas_rep_idx;
+
+ /* GSM Random Access data */
+ struct gsm48_req_ref *rqd_ref;
+
+ struct gsm_subscriber_connection *conn;
+
+ struct {
+ /* channel activation type and handover ref */
+ uint8_t act_type;
+ uint8_t ho_ref;
+ struct gsm48_req_ref *rqd_ref;
+ uint8_t rqd_ta;
+ } dyn;
+#else
+ /* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23.
+ * Currently we don't share these headers so this is a magic number. */
+ struct llist_head sapi_cmds;
+ uint8_t sapis_dl[23];
+ uint8_t sapis_ul[23];
+ struct lapdm_channel lapdm_ch;
+ struct llist_head dl_tch_queue;
+ struct {
+ /* bitmask of all SI that are present/valid in si_buf */
+ uint32_t valid;
+ uint32_t last;
+ /* buffers where we put the pre-computed SI:
+ SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */
+ sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
+ } si;
+ struct {
+ uint8_t flags;
+ /* RSL measurment result number, 0 at lchan_act */
+ uint8_t res_nr;
+ /* current Tx power level of the BTS */
+ uint8_t bts_tx_pwr;
+ /* number of measurements stored in array below */
+ uint8_t num_ul_meas;
+ struct bts_ul_meas uplink[MAX_NUM_UL_MEAS];
+ /* last L1 header from the MS */
+ uint8_t l1_info[2];
+ struct gsm_meas_rep_unidir ul_res;
+ } meas;
+ struct {
+ struct amr_multirate_conf amr_mr;
+ struct {
+ struct osmo_fsm_inst *dl_amr_fsm;
+ /* TCH cache */
+ uint8_t cache[20];
+ /* FACCH cache */
+ uint8_t facch[GSM_MACBLOCK_LEN];
+ uint8_t len;
+ uint32_t fn;
+ bool is_update;
+ /* set for each SID frame to detect talkspurt for codecs
+ without explicit ONSET event */
+ bool ul_sid;
+ /* indicates if DTXd was active during DL measurement
+ period */
+ bool dl_active;
+ } dtx;
+ uint8_t last_cmr;
+ uint32_t last_fn;
+ } tch;
+
+ /* 3GPP TS 48.058 § 9.3.37: [0; 255] ok, -1 means invalid*/
+ int16_t ms_t_offs;
+ /* 3GPP TS 45.010 § 1.2 round trip propagation delay (in symbols) or -1 */
+ int16_t p_offs;
+
+ /* BTS-side ciphering state (rx only, bi-directional, ...) */
+ uint8_t ciph_state;
+ uint8_t ciph_ns;
+ uint8_t loopback;
+ struct {
+ uint8_t active;
+ uint8_t ref;
+ /* T3105: PHYS INF retransmission */
+ struct osmo_timer_list t3105;
+ /* counts up to Ny1 */
+ unsigned int phys_info_count;
+ } ho;
+ /* S counter for link loss */
+ int s;
+ /* Kind of the release/activation. E.g. RSL or PCU */
+ int rel_act_kind;
+ /* RTP header Marker bit to indicate beginning of speech after pause */
+ bool rtp_tx_marker;
+ /* power handling */
+ struct {
+ uint8_t current;
+ uint8_t fixed;
+ } ms_power_ctrl;
+
+ struct msgb *pending_rel_ind_msg;
+#endif
+};
+
+enum {
+ TS_F_PDCH_ACTIVE = 0x1000,
+ TS_F_PDCH_ACT_PENDING = 0x2000,
+ TS_F_PDCH_DEACT_PENDING = 0x4000,
+ TS_F_PDCH_PENDING_MASK = 0x6000 /*<
+ TS_F_PDCH_ACT_PENDING | TS_F_PDCH_DEACT_PENDING */
+} gsm_bts_trx_ts_flags;
+
+/* One Timeslot in a TRX */
+struct gsm_bts_trx_ts {
+ struct gsm_bts_trx *trx;
+ /* number of this timeslot at the TRX */
+ uint8_t nr;
+
+ enum gsm_phys_chan_config pchan;
+
+ struct {
+ enum gsm_phys_chan_config pchan_is;
+ enum gsm_phys_chan_config pchan_want;
+ struct msgb *pending_chan_activ;
+ } dyn;
+
+ unsigned int flags;
+ struct gsm_abis_mo mo;
+ struct tlv_parsed nm_attr;
+ uint8_t nm_chan_comb;
+ int tsc; /* -1 == use BTS TSC */
+
+ struct {
+ /* Parameters below are configured by VTY */
+ int enabled;
+ uint8_t maio;
+ uint8_t hsn;
+ struct bitvec arfcns;
+ uint8_t arfcns_data[1024/8];
+ /* This is the pre-computed MA for channel assignments */
+ struct bitvec ma;
+ uint8_t ma_len; /* part of ma_data that is used */
+ uint8_t ma_data[8]; /* 10.5.2.21: max 8 bytes value part */
+ } hopping;
+
+ /* To which E1 subslot are we connected */
+ struct gsm_e1_subslot e1_link;
+
+ union {
+ struct {
+ struct om2k_mo om2k_mo;
+ } rbs2000;
+ };
+
+ struct gsm_lchan lchan[TS_MAX_LCHAN];
+};
+
+/* One TRX in a BTS */
+struct gsm_bts_trx {
+ /* list header in bts->trx_list */
+ struct llist_head list;
+
+ struct gsm_bts *bts;
+ /* number of this TRX in the BTS */
+ uint8_t nr;
+ /* human readable name / description */
+ char *description;
+ /* how do we talk RSL with this TRX? */
+ struct gsm_e1_subslot rsl_e1_link;
+ uint8_t rsl_tei;
+ struct e1inp_sign_link *rsl_link;
+
+ /* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
+ struct e1inp_sign_link *oml_link;
+
+ struct gsm_abis_mo mo;
+ struct tlv_parsed nm_attr;
+ struct {
+ struct gsm_abis_mo mo;
+ } bb_transc;
+
+ uint16_t arfcn;
+ int nominal_power; /* in dBm */
+ unsigned int max_power_red; /* in actual dB */
+
+#ifndef ROLE_BSC
+ struct trx_power_params power_params;
+ int ms_power_control;
+
+ struct {
+ void *l1h;
+ } role_bts;
+#endif
+
+ union {
+ struct {
+ struct {
+ struct gsm_abis_mo mo;
+ } bbsig;
+ struct {
+ struct gsm_abis_mo mo;
+ } pa;
+ } bs11;
+ struct {
+ unsigned int test_state;
+ uint8_t test_nr;
+ struct rxlev_stats rxlev_stat;
+ } ipaccess;
+ struct {
+ struct {
+ struct om2k_mo om2k_mo;
+ } trxc;
+ struct {
+ struct om2k_mo om2k_mo;
+ } rx;
+ struct {
+ struct om2k_mo om2k_mo;
+ } tx;
+ } rbs2000;
+ };
+ struct gsm_bts_trx_ts ts[TRX_NR_TS];
+};
+
+#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater *)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
+#define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i))
+#define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i][0])
+#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0])
+
+enum gsm_bts_type {
+ GSM_BTS_TYPE_UNKNOWN,
+ GSM_BTS_TYPE_BS11,
+ GSM_BTS_TYPE_NANOBTS,
+ GSM_BTS_TYPE_RBS2000,
+ GSM_BTS_TYPE_NOKIA_SITE,
+ GSM_BTS_TYPE_OSMOBTS,
+ _NUM_GSM_BTS_TYPE
+};
+
+enum gsm_bts_type_variant {
+ BTS_UNKNOWN,
+ BTS_OSMO_LITECELL15,
+ BTS_OSMO_OCTPHY,
+ BTS_OSMO_SYSMO,
+ BTS_OSMO_TRX,
+ _NUM_BTS_VARIANT
+};
+
+/* Used by OML layer for BTS Attribute reporting */
+enum bts_attribute {
+ BTS_TYPE_VARIANT,
+ BTS_SUB_MODEL,
+ TRX_PHY_VERSION,
+};
+
+struct vty;
+
+struct gsm_bts_model {
+ struct llist_head list;
+
+ enum gsm_bts_type type;
+ enum gsm_bts_type_variant variant;
+ const char *name;
+
+ bool started;
+ int (*start)(struct gsm_network *net);
+ int (*oml_rcvmsg)(struct msgb *msg);
+
+ void (*e1line_bind_ops)(struct e1inp_line *line);
+
+ void (*config_write_bts)(struct vty *vty, struct gsm_bts *bts);
+ void (*config_write_trx)(struct vty *vty, struct gsm_bts_trx *trx);
+ void (*config_write_ts)(struct vty *vty, struct gsm_bts_trx_ts *ts);
+
+ struct tlv_definition nm_att_tlvdef;
+
+ /* features of a given BTS model set via gsm_bts_model_register() locally */
+ struct bitvec features;
+ uint8_t _features_data[MAX_BTS_FEATURES/8];
+};
+
+/* N. B: always add new features to the end of the list (right before _NUM_BTS_FEAT) to avoid breaking compatibility
+ with BTS compiled against earlier version of this header */
+enum gsm_bts_features {
+ BTS_FEAT_HSCSD,
+ BTS_FEAT_GPRS,
+ BTS_FEAT_EGPRS,
+ BTS_FEAT_ECSD,
+ BTS_FEAT_HOPPING,
+ BTS_FEAT_MULTI_TSC,
+ BTS_FEAT_OML_ALERTS,
+ BTS_FEAT_AGCH_PCH_PROP,
+ BTS_FEAT_CBCH,
+ _NUM_BTS_FEAT
+};
+
+extern const struct value_string gsm_bts_features_descs[];
+
+/*
+ * This keeps track of the paging status of one BTS. It
+ * includes a number of pending requests, a back pointer
+ * to the gsm_bts, a timer and some more state.
+ */
+struct gsm_bts_paging_state {
+ /* pending requests */
+ struct llist_head pending_requests;
+ struct gsm_bts *bts;
+
+ struct osmo_timer_list work_timer;
+ struct osmo_timer_list credit_timer;
+
+ /* free chans needed */
+ int free_chans_need;
+
+ /* load */
+ uint16_t available_slots;
+};
+
+struct gsm_envabtse {
+ struct gsm_abis_mo mo;
+};
+
+struct gsm_bts_gprs_nsvc {
+ struct gsm_bts *bts;
+ /* data read via VTY config file, to configure the BTS
+ * via OML from BSC */
+ int id;
+ uint16_t nsvci;
+ uint16_t local_port; /* on the BTS */
+ uint16_t remote_port; /* on the SGSN */
+ uint32_t remote_ip; /* on the SGSN */
+
+ struct gsm_abis_mo mo;
+};
+
+enum gprs_rlc_par {
+ RLC_T3142,
+ RLC_T3169,
+ RLC_T3191,
+ RLC_T3193,
+ RLC_T3195,
+ RLC_N3101,
+ RLC_N3103,
+ RLC_N3105,
+ CV_COUNTDOWN,
+ T_DL_TBF_EXT, /* ms */
+ T_UL_TBF_EXT, /* ms */
+ _NUM_RLC_PAR
+};
+
+enum gprs_cs {
+ GPRS_CS1,
+ GPRS_CS2,
+ GPRS_CS3,
+ GPRS_CS4,
+ GPRS_MCS1,
+ GPRS_MCS2,
+ GPRS_MCS3,
+ GPRS_MCS4,
+ GPRS_MCS5,
+ GPRS_MCS6,
+ GPRS_MCS7,
+ GPRS_MCS8,
+ GPRS_MCS9,
+ _NUM_GRPS_CS
+};
+
+struct gprs_rlc_cfg {
+ uint16_t parameter[_NUM_RLC_PAR];
+ struct {
+ uint16_t repeat_time; /* ms */
+ uint8_t repeat_count;
+ } paging;
+ uint32_t cs_mask; /* bitmask of gprs_cs */
+ uint8_t initial_cs;
+ uint8_t initial_mcs;
+};
+
+
+enum neigh_list_manual_mode {
+ NL_MODE_AUTOMATIC = 0,
+ NL_MODE_MANUAL = 1,
+ NL_MODE_MANUAL_SI5SEP = 2, /* SI2 and SI5 have separate neighbor lists */
+};
+
+enum bts_loc_fix {
+ BTS_LOC_FIX_INVALID = 0,
+ BTS_LOC_FIX_2D = 1,
+ BTS_LOC_FIX_3D = 2,
+};
+
+extern const struct value_string bts_loc_fix_names[];
+
+struct bts_location {
+ struct llist_head list;
+ time_t tstamp;
+ enum bts_loc_fix valid;
+ double lat;
+ double lon;
+ double height;
+};
+
+/* One BTS */
+struct gsm_bts {
+ /* list header in net->bts_list */
+ struct llist_head list;
+
+ /* Geographical location of the BTS */
+ struct llist_head loc_list;
+
+ /* number of ths BTS in network */
+ uint8_t nr;
+ /* human readable name / description */
+ char *description;
+ /* Cell Identity */
+ uint16_t cell_identity;
+ /* location area code of this BTS */
+ uint16_t location_area_code;
+ /* Base Station Identification Code (BSIC), lower 3 bits is BCC,
+ * which is used as TSC for the CCCH */
+ uint8_t bsic;
+ /* type of BTS */
+ enum gsm_bts_type type;
+ enum gsm_bts_type_variant variant;
+ struct gsm_bts_model *model;
+ enum gsm_band band;
+ char version[MAX_VERSION_LENGTH];
+ char sub_model[MAX_VERSION_LENGTH];
+
+ /* features of a given BTS set/reported via OML */
+ struct bitvec features;
+ uint8_t _features_data[MAX_BTS_FEATURES/8];
+
+ /* Connected PCU version (if any) */
+ char pcu_version[MAX_VERSION_LENGTH];
+
+ /* maximum Tx power that the MS is permitted to use in this cell */
+ int ms_max_power;
+
+ /* how do we talk OML with this TRX? */
+ struct gsm_e1_subslot oml_e1_link;
+ uint8_t oml_tei;
+ struct e1inp_sign_link *oml_link;
+
+ /* Abis network management O&M handle */
+ struct abis_nm_h *nmh;
+
+ struct gsm_abis_mo mo;
+
+ /* number of this BTS on given E1 link */
+ uint8_t bts_nr;
+
+ /* DTX features of this BTS */
+ enum gsm48_dtx_mode dtxu;
+ bool dtxd;
+
+ /* paging state and control */
+ struct gsm_bts_paging_state paging;
+
+ /* CCCH is on C0 */
+ struct gsm_bts_trx *c0;
+
+ struct {
+ struct gsm_abis_mo mo;
+ } site_mgr;
+
+ /* bitmask of all SI that are present/valid in si_buf */
+ uint32_t si_valid;
+ /* 3GPP TS 44.018 Table 10.5.2.33b.1 INDEX and COUNT for SI2quater */
+ uint8_t si2q_index; /* distinguish individual SI2quater messages */
+ uint8_t si2q_count; /* si2q_index for the last (highest indexed) individual SI2quater message */
+ /* buffers where we put the pre-computed SI */
+ sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM];
+ /* offsets used while generating SI2quater */
+ size_t e_offset;
+ size_t u_offset;
+
+ /* ip.accesss Unit ID's have Site/BTS/TRX layout */
+ union {
+ struct {
+ uint16_t site_id;
+ uint16_t bts_id;
+ uint32_t flags;
+ uint32_t rsl_ip;
+ } ip_access;
+ struct {
+ struct {
+ struct gsm_abis_mo mo;
+ } cclk;
+ struct {
+ struct gsm_abis_mo mo;
+ } rack;
+ struct gsm_envabtse envabtse[4];
+ } bs11;
+ struct {
+ struct {
+ struct om2k_mo om2k_mo;
+ struct gsm_abis_mo mo;
+ struct llist_head conn_groups;
+ } cf;
+ struct {
+ struct om2k_mo om2k_mo;
+ struct gsm_abis_mo mo;
+ struct llist_head conn_groups;
+ } is;
+ struct {
+ struct om2k_mo om2k_mo;
+ struct gsm_abis_mo mo;
+ struct llist_head conn_groups;
+ } con;
+ struct {
+ struct om2k_mo om2k_mo;
+ struct gsm_abis_mo mo;
+ } dp;
+ struct {
+ struct om2k_mo om2k_mo;
+ struct gsm_abis_mo mo;
+ } tf;
+ uint32_t use_superchannel:1;
+ } rbs2000;
+ struct {
+ uint8_t bts_type;
+ unsigned int configured:1,
+ skip_reset:1,
+ no_loc_rel_cnf:1,
+ bts_reset_timer_cnf,
+ did_reset:1,
+ wait_reset:1;
+ struct osmo_timer_list reset_timer;
+ } nokia;
+ };
+
+ /* Not entirely sure how ip.access specific this is */
+ struct {
+ uint8_t supports_egprs_11bit_rach;
+ enum bts_gprs_mode mode;
+ struct {
+ struct gsm_abis_mo mo;
+ uint16_t nsei;
+ uint8_t timer[7];
+ } nse;
+ struct {
+ struct gsm_abis_mo mo;
+ uint16_t bvci;
+ uint8_t timer[11];
+ struct gprs_rlc_cfg rlc_cfg;
+ } cell;
+ struct gsm_bts_gprs_nsvc nsvc[2];
+ uint8_t rac;
+ uint8_t net_ctrl_ord;
+ bool ctrl_ack_type_use_block;
+ } gprs;
+
+ /* RACH NM values */
+ int rach_b_thresh;
+ int rach_ldavg_slots;
+
+ /* transceivers */
+ int num_trx;
+ struct llist_head trx_list;
+
+ /* SI related items */
+ int force_combined_si;
+ int bcch_change_mark;
+
+#ifdef ROLE_BSC
+ /* Abis NM queue */
+ struct llist_head abis_queue;
+ int abis_nm_pend;
+
+ struct gsm_network *network;
+
+ /* should the channel allocator allocate channels from high TRX to TRX0,
+ * rather than starting from TRX0 and go upwards? */
+ int chan_alloc_reverse;
+
+ enum neigh_list_manual_mode neigh_list_manual_mode;
+ /* parameters from which we build SYSTEM INFORMATION */
+ struct {
+ struct gsm48_rach_control rach_control;
+ uint8_t ncc_permitted;
+ struct gsm48_cell_sel_par cell_sel_par;
+ struct gsm48_si_selection_params cell_ro_sel_par; /* rest octet */
+ struct gsm48_cell_options cell_options;
+ struct gsm48_control_channel_descr chan_desc;
+ struct bitvec neigh_list;
+ struct bitvec cell_alloc;
+ struct bitvec si5_neigh_list;
+ struct osmo_earfcn_si2q si2quater_neigh_list;
+ size_t uarfcn_length; /* index for uarfcn and scramble lists */
+ struct {
+ /* bitmask large enough for all possible ARFCN's */
+ uint8_t neigh_list[1024/8];
+ uint8_t cell_alloc[1024/8];
+ /* If the user wants a different neighbor list in SI5 than in SI2 */
+ uint8_t si5_neigh_list[1024/8];
+ uint8_t meas_bw_list[MAX_EARFCN_LIST];
+ uint16_t earfcn_list[MAX_EARFCN_LIST];
+ uint16_t uarfcn_list[MAX_EARFCN_LIST];
+ uint16_t scramble_list[MAX_EARFCN_LIST];
+ } data;
+ } si_common;
+ bool early_classmark_allowed;
+ /* for testing only: Have an infinitely long radio link timeout */
+ bool infinite_radio_link_timeout;
+
+ /* do we use static (user-defined) system information messages? (bitmask) */
+ uint32_t si_mode_static;
+
+ /* exclude the BTS from the global RF Lock handling */
+ int excl_from_rf_lock;
+
+ /* supported codecs beside FR */
+ struct bts_codec_conf codec;
+
+ /* BTS dependencies bit field */
+ uint32_t depends_on[256/(8*4)];
+
+ /* full and half rate multirate config */
+ struct amr_multirate_conf mr_full;
+ struct amr_multirate_conf mr_half;
+
+ /* PCU socket state */
+ char *pcu_sock_path;
+ struct pcu_sock_state *pcu_state;
+
+#endif /* ROLE_BSC */
+ void *role;
+};
+
+
+struct gsm_bts *gsm_bts_alloc(void *talloc_ctx);
+struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
+
+struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
+struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num);
+
+enum gsm_bts_type str2btstype(const char *arg);
+const char *btstype2str(enum gsm_bts_type type);
+
+enum bts_attribute str2btsattr(const char *s);
+const char *btsatttr2str(enum bts_attribute v);
+
+enum gsm_bts_type_variant str2btsvariant(const char *arg);
+const char *btsvariant2str(enum gsm_bts_type_variant v);
+
+extern const struct value_string gsm_chreq_descs[];
+const struct value_string gsm_pchant_names[13];
+const struct value_string gsm_pchant_descs[13];
+const char *gsm_pchan_name(enum gsm_phys_chan_config c);
+enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
+const char *gsm_lchant_name(enum gsm_chan_t c);
+const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
+char *gsm_trx_name(const struct gsm_bts_trx *trx);
+char *gsm_ts_name(const struct gsm_bts_trx_ts *ts);
+char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts);
+char *gsm_lchan_name_compute(const struct gsm_lchan *lchan);
+const char *gsm_lchans_name(enum gsm_lchan_state s);
+
+static inline char *gsm_lchan_name(const struct gsm_lchan *lchan)
+{
+ return lchan->name;
+}
+
+static inline int gsm_bts_set_feature(struct gsm_bts *bts, enum gsm_bts_features feat)
+{
+ OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
+ return bitvec_set_bit_pos(&bts->features, feat, 1);
+}
+
+static inline bool gsm_bts_has_feature(const struct gsm_bts *bts, enum gsm_bts_features feat)
+{
+ OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
+ return bitvec_get_bit_pos(&bts->features, feat);
+}
+
+void gsm_abis_mo_reset(struct gsm_abis_mo *mo);
+
+struct gsm_abis_mo *
+gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
+ const struct abis_om_obj_inst *obj_inst);
+
+struct gsm_nm_state *
+gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
+ const struct abis_om_obj_inst *obj_inst);
+void *
+gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class,
+ const struct abis_om_obj_inst *obj_inst);
+
+/* reset the state of all MO in the BTS */
+void gsm_bts_mo_reset(struct gsm_bts *bts);
+
+uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan,
+ uint8_t ts_nr, uint8_t lchan_nr);
+uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan);
+uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan,
+ enum gsm_phys_chan_config as_pchan);
+
+/* return the gsm_lchan for the CBCH (if it exists at all) */
+struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts);
+
+/*
+ * help with parsing regexps
+ */
+int gsm_parse_reg(void *ctx, regex_t *reg, char **str,
+ int argc, const char **argv) __attribute__ ((warn_unused_result));
+
+static inline uint8_t gsm_ts_tsc(const struct gsm_bts_trx_ts *ts)
+{
+ if (ts->tsc != -1)
+ return ts->tsc;
+ else
+ return ts->trx->bts->bsic & 7;
+}
+
+struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr,
+ int *rc);
+
+enum gsm_phys_chan_config ts_pchan(struct gsm_bts_trx_ts *ts);
+uint8_t ts_subslots(struct gsm_bts_trx_ts *ts);
+bool ts_is_tch(struct gsm_bts_trx_ts *ts);
+
+#endif
diff --git a/include/openbsc/gsm_subscriber.h b/include/openbsc/gsm_subscriber.h
new file mode 100644
index 000000000..7e656145a
--- /dev/null
+++ b/include/openbsc/gsm_subscriber.h
@@ -0,0 +1,130 @@
+#ifndef _GSM_SUBSCR_H
+#define _GSM_SUBSCR_H
+
+#include <stdbool.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+#include <openbsc/gsm_data.h>
+
+#define GSM_NAME_LENGTH 160
+
+#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
+#define GSM_MIN_EXTEN 20000
+#define GSM_MAX_EXTEN 49999
+
+#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
+/* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */
+
+#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0
+
+struct vty;
+struct sgsn_mm_ctx;
+struct sgsn_subscriber_data;
+
+struct subscr_request;
+
+struct gsm_subscriber_group {
+ struct gsm_network *net;
+
+ int keep_subscr;
+};
+
+struct gsm_equipment {
+ long long unsigned int id;
+ char imei[GSM23003_IMEISV_NUM_DIGITS+1];
+ char name[GSM_NAME_LENGTH];
+
+ struct gsm48_classmark1 classmark1;
+ uint8_t classmark2_len;
+ uint8_t classmark2[3];
+ uint8_t classmark3_len;
+ uint8_t classmark3[14];
+};
+
+struct gsm_subscriber {
+ struct gsm_subscriber_group *group;
+ long long unsigned int id;
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ uint32_t tmsi;
+ uint16_t lac;
+ char name[GSM_NAME_LENGTH];
+ char extension[GSM_EXTENSION_LENGTH];
+ int authorized;
+ time_t expire_lu;
+
+ /* Don't delete subscribers even if group->keep_subscr is not set */
+ int keep_in_ram;
+
+ /* Temporary field which is not stored in the DB/HLR */
+ uint32_t flags;
+
+ /* Every user can only have one equipment in use at any given
+ * point in time */
+ struct gsm_equipment equipment;
+
+ /* for internal management */
+ int use_count;
+ struct llist_head entry;
+
+ /* pending requests */
+ int is_paging;
+ struct llist_head requests;
+
+ /* GPRS/SGSN related fields */
+ struct sgsn_subscriber_data *sgsn_data;
+};
+
+enum gsm_subscriber_field {
+ GSM_SUBSCRIBER_IMSI,
+ GSM_SUBSCRIBER_TMSI,
+ GSM_SUBSCRIBER_EXTENSION,
+ GSM_SUBSCRIBER_ID,
+};
+
+enum gsm_subscriber_update_reason {
+ GSM_SUBSCRIBER_UPDATE_ATTACHED,
+ GSM_SUBSCRIBER_UPDATE_DETACHED,
+ GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
+};
+
+struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
+struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
+struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
+ const char *imsi);
+struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp,
+ uint32_t tmsi);
+struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp,
+ const char *imsi);
+struct gsm_subscriber *subscr_get_by_extension(struct gsm_subscriber_group *sgrp,
+ const char *ext);
+struct gsm_subscriber *subscr_get_by_id(struct gsm_subscriber_group *sgrp,
+ unsigned long long id);
+struct gsm_subscriber *subscr_get_or_create(struct gsm_subscriber_group *sgrp,
+ const char *imsi);
+int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
+struct gsm_subscriber *subscr_active_by_tmsi(struct gsm_subscriber_group *sgrp,
+ uint32_t tmsi);
+struct gsm_subscriber *subscr_active_by_imsi(struct gsm_subscriber_group *sgrp,
+ const char *imsi);
+
+char *subscr_name(struct gsm_subscriber *subscr);
+
+int subscr_purge_inactive(struct gsm_subscriber_group *sgrp);
+void subscr_update_from_db(struct gsm_subscriber *subscr);
+void subscr_expire(struct gsm_subscriber_group *sgrp);
+int subscr_update_expire_lu(struct gsm_subscriber *subscr, struct gsm_bts *bts);
+
+/*
+ * Paging handling with authentication
+ */
+struct subscr_request *subscr_request_channel(struct gsm_subscriber *subscr,
+ int type, gsm_cbfn *cbfn, void *param);
+void subscr_remove_request(struct subscr_request *req);
+
+/* internal */
+struct gsm_subscriber *subscr_alloc(void);
+extern struct llist_head active_subscribers;
+
+#endif /* _GSM_SUBSCR_H */
diff --git a/include/openbsc/gsup_client.h b/include/openbsc/gsup_client.h
new file mode 100644
index 000000000..a113225e1
--- /dev/null
+++ b/include/openbsc/gsup_client.h
@@ -0,0 +1,60 @@
+/* GPRS Subscriber Update Protocol client */
+
+/* (C) 2014 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Jacob Erlbeck
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#pragma once
+
+#include <osmocom/core/timer.h>
+
+#include <openbsc/oap_client.h>
+
+#define GSUP_CLIENT_RECONNECT_INTERVAL 10
+#define GSUP_CLIENT_PING_INTERVAL 20
+
+struct msgb;
+struct ipa_client_conn;
+struct gsup_client;
+
+/* Expects message in msg->l2h */
+typedef int (*gsup_client_read_cb_t)(struct gsup_client *gsupc,
+ struct msgb *msg);
+
+struct gsup_client {
+ struct ipa_client_conn *link;
+ gsup_client_read_cb_t read_cb;
+ void *data;
+
+ struct oap_client_state oap_state;
+
+ struct osmo_timer_list ping_timer;
+ struct osmo_timer_list connect_timer;
+ int is_connected;
+ int got_ipa_pong;
+};
+
+struct gsup_client *gsup_client_create(const char *ip_addr,
+ unsigned int tcp_port,
+ gsup_client_read_cb_t read_cb,
+ struct oap_client_config *oap_config);
+
+void gsup_client_destroy(struct gsup_client *gsupc);
+int gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
+struct msgb *gsup_client_msgb_alloc(void);
+
diff --git a/include/openbsc/gtphub.h b/include/openbsc/gtphub.h
new file mode 100644
index 000000000..9cb7605f8
--- /dev/null
+++ b/include/openbsc/gtphub.h
@@ -0,0 +1,523 @@
+/* GTP Hub Implementation */
+
+/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/socket.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/rate_ctr.h>
+
+#include <openbsc/gprs_sgsn.h>
+
+
+/* support */
+
+/* TODO move to osmocom/core/socket.c ? */
+#include <netdb.h> /* for IPPROTO_* etc */
+struct osmo_sockaddr {
+ struct sockaddr_storage a;
+ socklen_t l;
+};
+
+/* TODO move to osmocom/core/socket.c ? */
+/*! \brief Initialize a sockaddr
+ * \param[out] addr Valid osmo_sockaddr pointer to write result to
+ * \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
+ * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
+ * \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
+ * \param[in] host Remote host name or IP address in string form
+ * \param[in] port Remote port number in host byte order
+ * \returns 0 on success, otherwise an error code (from getaddrinfo()).
+ *
+ * Copy the first result from a getaddrinfo() call with the given parameters to
+ * *addr and *addr_len. On error, do not change *addr and return nonzero.
+ */
+int osmo_sockaddr_init(struct osmo_sockaddr *addr,
+ uint16_t family, uint16_t type, uint8_t proto,
+ const char *host, uint16_t port);
+
+/* Conveniently pass AF_UNSPEC, SOCK_DGRAM and IPPROTO_UDP to
+ * osmo_sockaddr_init(). */
+static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
+ const char *host, uint16_t port)
+{
+ return osmo_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
+ host, port);
+}
+
+/*! \brief convert sockaddr to human readable string.
+ * \param[out] addr_str Valid pointer to a buffer of length addr_str_len.
+ * \param[in] addr_str_len Size of buffer addr_str points at.
+ * \param[out] port_str Valid pointer to a buffer of length port_str_len.
+ * \param[in] port_str_len Size of buffer port_str points at.
+ * \param[in] addr Binary representation as returned by osmo_sockaddr_init().
+ * \param[in] flags flags as passed to getnameinfo().
+ * \returns 0 on success, an error code on error.
+ *
+ * Return the IPv4 or IPv6 address string and the port (a.k.a. service) string
+ * representations of the given struct osmo_sockaddr in two caller provided
+ * char buffers. Flags of (NI_NUMERICHOST | NI_NUMERICSERV) return numeric
+ * address and port. Either one of addr_str or port_str may be NULL, in which
+ * case nothing is returned there.
+ *
+ * See also osmo_sockaddr_to_str() (less flexible, but much more convenient). */
+int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
+ char *port_str, size_t port_str_len,
+ const struct osmo_sockaddr *addr,
+ int flags);
+
+
+/*! \brief concatenate the parts returned by osmo_sockaddr_to_strs().
+ * \param[in] addr Binary representation as returned by osmo_sockaddr_init().
+ * \param[in] buf A buffer to use for string operations.
+ * \param[in] buf_len Length of the buffer.
+ * \returns Address string (in buffer).
+ *
+ * Compose a string of the numeric IP-address and port represented by *addr of
+ * the form "<ip-addr> port <port>". The returned string is valid until the
+ * next invocation of this function.
+ */
+const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
+ char *buf, size_t buf_len);
+
+/*! \brief conveniently return osmo_sockaddr_to_strb() in a static buffer.
+ * \param[in] addr Binary representation as returned by osmo_sockaddr_init().
+ * \returns Address string in static buffer.
+ *
+ * See osmo_sockaddr_to_strb().
+ *
+ * Note: only one osmo_sockaddr_to_str() call will work per print/log
+ * statement. For two or more, use osmo_sockaddr_to_strb() with a separate
+ * buffer each.
+ */
+const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr);
+
+/*! \brief compare two osmo_sockaddr.
+ * \param[in] a The first address to compare.
+ * \param[in] b The other address to compare.
+ * \returns 0 if equal, otherwise -1 or 1.
+ */
+int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
+ const struct osmo_sockaddr *b);
+
+/*! \brief Overwrite *dst with *src.
+ * Like memcpy(), but copy only the valid bytes. */
+void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
+ const struct osmo_sockaddr *src);
+
+
+/* general */
+
+enum gtphub_plane_idx {
+ GTPH_PLANE_CTRL = 0,
+ GTPH_PLANE_USER = 1,
+ GTPH_PLANE_N
+};
+
+enum gtphub_side_idx {
+ GTPH_SIDE_SGSN = 0,
+ GTPH_SIDE_GGSN = 1,
+ GTPH_SIDE_N
+};
+
+#define for_each_side(I) for (I = 0; I < GTPH_SIDE_N; I++)
+#define for_each_plane(I) for (I = 0; I < GTPH_PLANE_N; I++)
+#define for_each_side_and_plane(I,J) for_each_side(I) for_each_plane(J)
+
+static inline int other_side_idx(int side_idx)
+{
+ return (side_idx + 1) & 1;
+}
+
+extern const char* const gtphub_plane_idx_names[GTPH_PLANE_N];
+extern const uint16_t gtphub_plane_idx_default_port[GTPH_PLANE_N];
+
+extern const char* const gtphub_side_idx_names[GTPH_SIDE_N];
+
+/* A host address in the form that is expected in the 7.7.32 GSN Address IE.
+ * len is either 4 (IPv4) or 16 (IPv6), any other value is invalid. If no
+ * address is set, len shall be 0. */
+struct gsn_addr {
+ uint16_t len;
+ uint8_t buf[16];
+};
+
+void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src);
+int gsn_addr_from_str(struct gsn_addr *gsna, const char *numeric_addr_str);
+
+/* Return gsna in numeric string form, in a static buffer. */
+const char *gsn_addr_to_str(const struct gsn_addr *gsna);
+
+/* note: strbuf_len doesn't need to be larger than INET6_ADDRSTRLEN + 1. */
+const char *gsn_addr_to_strb(const struct gsn_addr *gsna,
+ char *strbuf, int strbuf_len);
+
+/* Return 1 on match, zero otherwise. */
+int gsn_addr_same(const struct gsn_addr *a, const struct gsn_addr *b);
+
+/* Decode sa to gsna. Return 0 on success. If port is non-NULL, the port number
+ * from sa is also returned. */
+int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
+ const struct osmo_sockaddr *sa);
+
+/* expiry */
+
+struct expiring_item;
+typedef void (*del_cb_t)(struct expiring_item *);
+
+struct expiring_item {
+ struct llist_head entry;
+ time_t expiry;
+ del_cb_t del_cb;
+};
+
+struct expiry {
+ int expiry_in_seconds;
+ struct llist_head items;
+};
+
+/* Initialize an expiry queue. */
+void expiry_init(struct expiry *exq, int expiry_in_seconds);
+
+/* Add a new mapping, or restart the expiry timeout for an already listed
+ * mapping. */
+void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now);
+
+/* Initialize to all-empty; must be called before using the item in any way. */
+void expiring_item_init(struct expiring_item *item);
+
+/* Remove the given item from its expiry queue, and call item->del_cb, if set.
+ * This sets item->del_cb to NULL and is harmless when run a second time on the
+ * same item, so the del_cb may choose to call this function, too, to allow
+ * deleting items from several code paths. */
+void expiring_item_del(struct expiring_item *item);
+
+/* Carry out due expiry of mappings. Must be invoked regularly.
+ * 'now' is the current clock count in seconds and must correspond to the clock
+ * count passed to nr_map_add(). A monotonous clock counter should be used. */
+int expiry_tick(struct expiry *exq, time_t now);
+
+/* Expire all items. */
+void expiry_clear(struct expiry *exq);
+
+
+/* number map */
+
+/* A number map assigns a "random" mapped number to each user provided number.
+ * If the same number is requested multiple times, the same mapped number is
+ * returned.
+ *
+ * Number maps plug into possibly shared pools and expiry queues, for example:
+ *
+ * mapA -----------+-> pool1 <-+-- mapB
+ * {10->1, 11->5} | {1, 2, 3, ...} | {10->2, 11->3}
+ * | |
+ * | |
+ * /-> \-> expiry1 <-/
+ * | (30 seconds)
+ * |
+ * mapC -------+-----> pool2 <-+-- mapD
+ * {10->1, 11->3} {1, 2, 3, ...} | {10->2, 11->5}
+ * |
+ * expiry2 <-/
+ * (60 seconds)
+ *
+ * A map contains mappings ("10->1"). Each map needs a number pool, which can
+ * be shared with other maps. Each new mapping receives a number from the pool,
+ * which is then unavailable to any other map using the same pool.
+ *
+ * A map may point at an expiry queue, in which case all mappings added to it
+ * are also appended to the expiry queue (using a separate llist entry in the
+ * mapping). Any number of maps may submit to the same expiry queue, if they
+ * desire the same expiry timeout. An expiry queue stores the mappings in
+ * chronological order, so that expiry checking is needed only from the start
+ * of the queue; hence only mappings with identical expiry timeout can be added
+ * to the same expiry queue. Upon expiry, a mapping is dropped from the map it
+ * was submitted at. expiry_tick() needs to be called regularly for each expiry
+ * queue.
+ *
+ * A nr_mapping can be embedded in a larger struct: each mapping can have a
+ * distinct destructor (del_cb), and each del_cb can figure out the container
+ * struct's address and free that upon expiry or manual deletion. So in expiry
+ * queues (and even maps), mappings of different container types can be mixed.
+ * This can help to drastically reduce the amount of unnecessary visits during
+ * expiry checking, for the case that no expiry is pending. An expiry queue
+ * always knows which mappings to expire next, because they are right at the
+ * start of its list.
+ *
+ * Mapping allocation and a del_cb are provided by the caller. If del_cb is
+ * NULL, no deallocation will be done (allowing statically allocated entries).
+ */
+
+typedef unsigned int nr_t;
+
+/* Generator for unused numbers. So far this counts upwards from zero, but the
+ * implementation may change in the future. Treat this like an opaque struct.
+ * If this becomes random, the tests need to be fixed. */
+struct nr_pool {
+ nr_t last_nr;
+ nr_t nr_min;
+ nr_t nr_max;
+};
+
+struct nr_mapping {
+ struct llist_head entry;
+ struct expiring_item expiry_entry;
+
+ void *origin;
+ nr_t orig;
+ nr_t repl;
+};
+
+struct nr_map {
+ struct nr_pool *pool; /* multiple nr_maps can share a nr_pool. */
+ struct expiry *add_items_to_expiry;
+ struct llist_head mappings;
+};
+
+
+void nr_pool_init(struct nr_pool *pool, nr_t nr_min, nr_t nr_max);
+
+/* Return the next unused number from the nr_pool. */
+nr_t nr_pool_next(struct nr_pool *pool);
+
+/* Initialize the nr_mapping to zero/empty values. */
+void nr_mapping_init(struct nr_mapping *mapping);
+
+/* Remove the given mapping from its parent map and expiry queue, and call
+ * mapping->del_cb, if set. */
+void nr_mapping_del(struct nr_mapping *mapping);
+
+/* Initialize an (already allocated) nr_map, and set the map's number pool.
+ * Multiple nr_map instances may use the same nr_pool. Set the nr_map's expiry
+ * queue to exq, so that all added mappings are automatically expired after the
+ * time configured in exq. exq may be NULL to disable automatic expiry. */
+void nr_map_init(struct nr_map *map, struct nr_pool *pool,
+ struct expiry *exq);
+
+/* Add a new entry to the map. mapping->orig, mapping->origin and
+ * mapping->del_cb must be set before calling this function. The remaining
+ * fields of *mapping will be overwritten. mapping->repl is set to the next
+ * available mapped number from map->pool. 'now' is the current clock count in
+ * seconds; if no map->expiry is used, just pass 0 for 'now'. */
+void nr_map_add(struct nr_map *map, struct nr_mapping *mapping,
+ time_t now);
+
+/* Restart the timeout for the given mapping. mapping must be a member of map.
+ */
+void nr_map_refresh(struct nr_map *map, struct nr_mapping *mapping,
+ time_t now);
+
+/* Return a known mapping from nr_orig and the given origin. If nr_orig is
+ * unknown, return NULL. */
+struct nr_mapping *nr_map_get(const struct nr_map *map,
+ void *origin, nr_t nr_orig);
+
+/* Return a known mapping to nr_repl. If nr_repl is unknown, return NULL. */
+struct nr_mapping *nr_map_get_inv(const struct nr_map *map, nr_t nr_repl);
+
+/* Remove all mappings from map. */
+void nr_map_clear(struct nr_map *map);
+
+/* Return 1 if map has no entries, 0 otherwise. */
+int nr_map_empty(const struct nr_map *map);
+
+
+/* config */
+
+static const int GTPH_EXPIRE_QUICKLY_SECS = 30; /* TODO is there a spec for this? */
+static const int GTPH_EXPIRE_SLOWLY_MINUTES = 6 * 60; /* TODO is there a spec for this? */
+
+struct gtphub_cfg_addr {
+ const char *addr_str;
+ uint16_t port;
+};
+
+struct gtphub_cfg_bind {
+ struct gtphub_cfg_addr bind;
+};
+
+struct gtphub_cfg {
+ struct gtphub_cfg_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N];
+ struct gtphub_cfg_addr proxy[GTPH_SIDE_N][GTPH_PLANE_N];
+ int sgsn_use_sender; /* Use sender, not GSN addr IE with std ports */
+};
+
+
+/* state */
+
+struct gtphub_peer {
+ struct llist_head entry;
+
+ struct llist_head addresses; /* Alternatives, not load balancing. */
+ struct nr_pool seq_pool;
+ struct nr_map seq_map;
+};
+
+struct gtphub_peer_addr {
+ struct llist_head entry;
+
+ struct gtphub_peer *peer;
+ struct gsn_addr addr;
+ struct llist_head ports;
+};
+
+struct gtphub_peer_port {
+ struct llist_head entry;
+
+ struct gtphub_peer_addr *peer_addr;
+ uint16_t port;
+ unsigned int ref_count; /* references from other peers' seq_maps */
+ struct osmo_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
+ int last_restart_count; /* 0..255 = valid, all else means unknown */
+
+ struct rate_ctr_group *counters_io;
+};
+
+struct gtphub_tunnel_endpoint {
+ struct gtphub_peer_port *peer;
+ uint32_t tei_orig; /* from/to peer */
+
+ struct rate_ctr_group *counters_io;
+};
+
+struct gtphub_tunnel {
+ struct llist_head entry;
+ struct expiring_item expiry_entry;
+
+ uint32_t tei_repl; /* unique TEI to replace peers' TEIs */
+ struct gtphub_tunnel_endpoint endpoint[GTPH_SIDE_N][GTPH_PLANE_N];
+};
+
+struct gtphub_bind {
+ struct gsn_addr local_addr;
+ uint16_t local_port;
+ struct osmo_fd ofd;
+
+ /* list of struct gtphub_peer */
+ struct llist_head peers;
+
+ const char *label; /* For logging */
+ struct rate_ctr_group *counters_io;
+};
+
+struct gtphub_resolved_ggsn {
+ struct llist_head entry;
+ struct expiring_item expiry_entry;
+
+ /* The APN OI, the Operator Identifier, is the combined address,
+ * including parts of the IMSI and APN NI, and ending with ".gprs". */
+ char apn_oi_str[GSM_APN_LENGTH];
+
+ /* Which address and port we resolved that to. */
+ struct gtphub_peer_port *peer;
+};
+
+struct gtphub {
+ struct gtphub_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N];
+
+ /* pointers to an entry of to_gsns[s][p].peers */
+ struct gtphub_peer_port *proxy[GTPH_SIDE_N][GTPH_PLANE_N];
+
+ /* The TEI numbers will simply wrap and be reused, which will work out
+ * in practice. Problems would arise if one given peer maintained the
+ * same TEI for a time long enough for the TEI nr map to wrap an entire
+ * uint32_t; if a new TEI were mapped every second, this would take
+ * more than 100 years (in which a single given TEI must not time out)
+ * to cause a problem. */
+ struct nr_pool tei_pool;
+
+ struct llist_head tunnels; /* struct gtphub_tunnel */
+ struct llist_head pending_deletes; /* opaque (gtphub.c) */
+
+ struct llist_head ggsn_lookups; /* opaque (gtphub_ares.c) */
+ struct llist_head resolved_ggsns; /* struct gtphub_resolved_ggsn */
+
+ struct osmo_timer_list gc_timer;
+ struct expiry expire_quickly;
+ struct expiry expire_slowly;
+
+ uint8_t restart_counter;
+
+ int sgsn_use_sender;
+};
+
+struct gtp_packet_desc;
+
+
+/* api */
+
+int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg);
+int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file);
+
+/* Initialize and start gtphub: bind to ports, run expiry timers. */
+int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg,
+ uint8_t restart_counter);
+
+/* Close all sockets, expire all maps and peers and free all allocations. The
+ * struct is then unusable, unless gtphub_start() is run on it again. */
+void gtphub_stop(struct gtphub *hub);
+
+time_t gtphub_now(void);
+
+/* Remove expired items, empty peers, ... */
+void gtphub_gc(struct gtphub *hub, time_t now);
+
+/* Return the string of the first address for this peer. */
+const char *gtphub_peer_str(struct gtphub_peer *peer);
+
+/* Return a human readable description of tun in a static buffer. */
+const char *gtphub_tunnel_str(struct gtphub_tunnel *tun);
+
+/* Return 1 if all of tun's endpoints are fully established, 0 otherwise. */
+int gtphub_tunnel_complete(struct gtphub_tunnel *tun);
+
+int gtphub_handle_buf(struct gtphub *hub,
+ unsigned int side_idx,
+ unsigned int port_idx,
+ const struct osmo_sockaddr *from_addr,
+ uint8_t *buf,
+ size_t received,
+ time_t now,
+ uint8_t **reply_buf,
+ struct osmo_fd **to_ofd,
+ struct osmo_sockaddr *to_addr);
+
+struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
+ struct gtphub_bind *bind,
+ const struct gsn_addr *addr,
+ uint16_t port);
+
+struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
+ const struct osmo_sockaddr *addr);
+
+void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
+ struct gsn_addr *resolved_addr,
+ time_t now);
+
+const char *gtphub_port_str(struct gtphub_peer_port *port);
+
+int gtphub_write(const struct osmo_fd *to,
+ const struct osmo_sockaddr *to_addr,
+ const uint8_t *buf, size_t buf_len);
diff --git a/include/openbsc/handover.h b/include/openbsc/handover.h
new file mode 100644
index 000000000..3fe71a28b
--- /dev/null
+++ b/include/openbsc/handover.h
@@ -0,0 +1,14 @@
+#ifndef _HANDOVER_H
+#define _HANDOVER_H
+
+struct gsm_subscriber_connection;
+
+int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
+
+/* clear any operation for this connection */
+void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
+
+/* Return the old lchan or NULL. This is meant for audio handling */
+struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan);
+
+#endif /* _HANDOVER_H */
diff --git a/include/openbsc/handover_decision.h b/include/openbsc/handover_decision.h
new file mode 100644
index 000000000..81078b05d
--- /dev/null
+++ b/include/openbsc/handover_decision.h
@@ -0,0 +1,7 @@
+#ifndef _HANDOVER_DECISION_H
+#define _HANDOVER_DECISION_H
+
+void on_dso_load_ho_dec(void);
+
+#endif /* _HANDOVER_DECISION_H */
+
diff --git a/include/openbsc/ipaccess.h b/include/openbsc/ipaccess.h
new file mode 100644
index 000000000..82e89c27d
--- /dev/null
+++ b/include/openbsc/ipaccess.h
@@ -0,0 +1,52 @@
+#ifndef _IPACCESS_H
+#define _IPACCESS_H
+
+#include <osmocom/abis/e1_input.h>
+#include "gsm_subscriber.h"
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/ipaccess.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+struct ipac_msgt_sccp_state {
+ uint8_t src_ref[3];
+ uint8_t dst_ref[3];
+ uint8_t trans_id;
+ uint8_t invoke_id;
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ uint8_t data[0];
+} __attribute__((packed));
+
+/*
+ * @add_remove 0 for remove, 1 for add, 3 to asK
+ * @nr_lacs Number of extra lacs inside this package
+ * @lac One lac entry
+ */
+struct ipac_ext_lac_cmd {
+ uint8_t add_remove;
+ uint8_t nr_extra_lacs;
+ uint16_t lac;
+ uint8_t data[0];
+} __attribute__((packed));
+
+void ipaccess_drop_oml(struct gsm_bts *bts);
+void ipaccess_drop_rsl(struct gsm_bts_trx *trx);
+
+struct sdp_header_item {
+ struct sdp_header_entry header_entry;
+ struct llist_head entry;
+ off_t absolute_offset;
+};
+
+struct sdp_header {
+ struct sdp_firmware firmware_info;
+
+ /* for more_magic a list of sdp_header_entry_list */
+ struct llist_head header_list;
+
+ /* the entry of the sdp_header */
+ struct llist_head entry;
+};
+
+int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned base_offset, struct llist_head *list);
+
+#endif /* _IPACCESS_H */
diff --git a/include/openbsc/iu.h b/include/openbsc/iu.h
new file mode 100644
index 000000000..f973ac1ba
--- /dev/null
+++ b/include/openbsc/iu.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <stdbool.h>
+
+struct sgsn_pdp_ctx;
+struct msgb;
+struct gprs_ra_id;
+
+struct RANAP_RAB_SetupOrModifiedItemIEs_s;
+struct RANAP_GlobalRNC_ID;
+
+struct ue_conn_ctx {
+ struct llist_head list;
+ struct osmo_sccp_link *link;
+ uint32_t conn_id;
+ int integrity_active;
+ struct gprs_ra_id ra_id;
+};
+
+enum iu_event_type {
+ IU_EVENT_RAB_ASSIGN,
+ IU_EVENT_SECURITY_MODE_COMPLETE,
+ IU_EVENT_IU_RELEASE, /* An actual Iu Release message was received */
+ IU_EVENT_LINK_INVALIDATED, /* A SUA link was lost or closed down */
+ /* FIXME: maybe IU_EVENT_IU_RELEASE and IU_EVENT_LINK_INVALIDATED
+ * should be combined to one generic event that simply means the
+ * ue_conn_ctx should no longer be used, for whatever reason. */
+};
+
+extern const struct value_string iu_event_type_names[];
+static inline const char *iu_event_type_str(enum iu_event_type e)
+{
+ return get_value_string(iu_event_type_names, e);
+}
+
+/* Implementations of iu_recv_cb_t shall find the ue_conn_ctx in msg->dst. */
+typedef int (* iu_recv_cb_t )(struct msgb *msg, struct gprs_ra_id *ra_id,
+ /* TODO "gprs_" in generic CS+PS domain ^ */
+ uint16_t *sai);
+
+typedef int (* iu_event_cb_t )(struct ue_conn_ctx *ue_ctx,
+ enum iu_event_type type, void *data);
+
+typedef int (* iu_rab_ass_resp_cb_t )(struct ue_conn_ctx *ue_ctx, uint8_t rab_id,
+ struct RANAP_RAB_SetupOrModifiedItemIEs_s *setup_ies);
+
+int iu_init(void *ctx, const char *listen_addr, uint16_t listen_port,
+ iu_recv_cb_t iu_recv_cb, iu_event_cb_t iu_event_cb);
+
+void iu_link_del(struct osmo_sccp_link *link);
+
+int iu_tx(struct msgb *msg, uint8_t sapi);
+
+int iu_page_cs(const char *imsi, const uint32_t *tmsi, uint16_t lac);
+int iu_page_ps(const char *imsi, const uint32_t *ptmsi, uint16_t lac, uint8_t rac);
+
+int iu_rab_act(struct ue_conn_ctx *ue_ctx, struct msgb *msg);
+int iu_rab_deact(struct ue_conn_ctx *ue_ctx, uint8_t rab_id);
+int iu_tx_sec_mode_cmd(struct ue_conn_ctx *uectx, struct gsm_auth_tuple *tp,
+ int send_ck, int new_key);
+
+void iu_vty_init(int *asn_debug_p);
diff --git a/include/openbsc/meas_feed.h b/include/openbsc/meas_feed.h
new file mode 100644
index 000000000..f77ee075f
--- /dev/null
+++ b/include/openbsc/meas_feed.h
@@ -0,0 +1,41 @@
+#ifndef _OPENBSC_MEAS_FEED_H
+#define _OPENBSC_MEAS_FEED_H
+
+#include <stdint.h>
+
+#include <openbsc/meas_rep.h>
+
+struct meas_feed_hdr {
+ uint8_t msg_type;
+ uint8_t reserved;
+ uint16_t version;
+};
+
+struct meas_feed_meas {
+ struct meas_feed_hdr hdr;
+ char imsi[15+1];
+ char name[31+1];
+ char scenario[31+1];
+ struct gsm_meas_rep mr;
+ /* The logical channel type, enum gsm_chan_t */
+ uint8_t lchan_type;
+ /* The physical channel type, enum gsm_phys_chan_config */
+ uint8_t pchan_type;
+ /* number of ths BTS in network */
+ uint8_t bts_nr;
+ /* number of this TRX in the BTS */
+ uint8_t trx_nr;
+ /* number of this timeslot at the TRX */
+ uint8_t ts_nr;
+ /* The logical subslot number in the TS */
+ uint8_t ss_nr;
+};
+
+enum meas_feed_msgtype {
+ MEAS_FEED_MEAS = 0,
+};
+
+#define MEAS_FEED_VERSION 1
+
+
+#endif
diff --git a/include/openbsc/meas_rep.h b/include/openbsc/meas_rep.h
new file mode 100644
index 000000000..b0c03f0bb
--- /dev/null
+++ b/include/openbsc/meas_rep.h
@@ -0,0 +1,67 @@
+#ifndef _MEAS_REP_H
+#define _MEAS_REP_H
+
+#include <stdint.h>
+
+#include <osmocom/gsm/meas_rep.h>
+
+#define MRC_F_PROCESSED 0x0001
+
+/* extracted from a L3 measurement report IE */
+struct gsm_meas_rep_cell {
+ uint8_t rxlev;
+ uint8_t bsic;
+ uint8_t neigh_idx;
+ uint16_t arfcn;
+ unsigned int flags;
+};
+
+#define MEAS_REP_F_UL_DTX 0x01
+#define MEAS_REP_F_DL_VALID 0x02
+#define MEAS_REP_F_BA1 0x04
+#define MEAS_REP_F_DL_DTX 0x08
+#define MEAS_REP_F_MS_TO 0x10
+#define MEAS_REP_F_MS_L1 0x20
+#define MEAS_REP_F_FPC 0x40
+
+/* parsed uplink and downlink measurement result */
+struct gsm_meas_rep {
+ /* back-pointer to the logical channel */
+ struct gsm_lchan *lchan;
+
+ /* number of the measurement report */
+ uint8_t nr;
+ /* flags, see MEAS_REP_F_* */
+ unsigned int flags;
+
+ /* uplink and downlink rxlev, rxqual; full and sub */
+ struct gsm_meas_rep_unidir ul;
+ struct gsm_meas_rep_unidir dl;
+
+ uint8_t bs_power;
+ /* according to 3GPP TS 48.058 § MS Timing Offset [-63; 192] */
+ int16_t ms_timing_offset;
+ struct {
+ int8_t pwr; /* MS power in dBm */
+ uint8_t ta; /* MS timing advance */
+ } ms_l1;
+
+ /* neighbor measurement reports for up to 6 cells */
+ int num_cell;
+ struct gsm_meas_rep_cell cell[6];
+};
+
+/* obtain an average over the last 'num' fields in the meas reps */
+int get_meas_rep_avg(const struct gsm_lchan *lchan,
+ enum meas_rep_field field, unsigned int num);
+
+/* Check if N out of M last values for FIELD are >= bd */
+int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
+ enum meas_rep_field field,
+ unsigned int n, unsigned int m, int be);
+
+unsigned int calc_initial_idx(unsigned int array_size,
+ unsigned int meas_rep_idx,
+ unsigned int num_values);
+
+#endif /* _MEAS_REP_H */
diff --git a/include/openbsc/mgcp.h b/include/openbsc/mgcp.h
new file mode 100644
index 000000000..b2262bc8d
--- /dev/null
+++ b/include/openbsc/mgcp.h
@@ -0,0 +1,285 @@
+/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSC_MGCP_H
+#define OPENBSC_MGCP_H
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
+
+#include "debug.h"
+
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define RTP_PORT_DEFAULT 4000
+#define RTP_PORT_NET_DEFAULT 16000
+
+/**
+ * Calculate the RTP audio port for the given multiplex
+ * and the direction. This allows a semi static endpoint
+ * to port calculation removing the need for the BSC
+ * and the MediaGateway to communicate.
+ *
+ * Port usage explained:
+ * base + (multiplex * 2) + 0 == local port to wait for network packets
+ * base + (multiplex * 2) + 1 == local port for rtcp
+ *
+ * The above port will receive packets from the BTS that need
+ * to be patched and forwarded to the network.
+ * The above port will receive packets from the network that
+ * need to be patched and forwarded to the BTS.
+ *
+ * We assume to have a static BTS IP address so we can differentiate
+ * network and BTS.
+ *
+ */
+static inline int rtp_calculate_port(int multiplex, int base)
+{
+ return base + (multiplex * 2);
+}
+
+
+/*
+ * Handling of MGCP Endpoints and the MGCP Config
+ */
+struct mgcp_endpoint;
+struct mgcp_config;
+struct mgcp_trunk_config;
+struct mgcp_rtp_end;
+
+#define MGCP_ENDP_CRCX 1
+#define MGCP_ENDP_DLCX 2
+#define MGCP_ENDP_MDCX 3
+
+/*
+ * what to do with the msg?
+ * - continue as usual?
+ * - reject and send a failure code?
+ * - defer? do not send anything
+ */
+#define MGCP_POLICY_CONT 4
+#define MGCP_POLICY_REJECT 5
+#define MGCP_POLICY_DEFER 6
+
+typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
+typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
+typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
+typedef int (*mgcp_rqnt)(struct mgcp_endpoint *endp, char tone);
+
+/**
+ * Return:
+ * < 0 in case no audio was processed
+ * >= 0 in case audio was processed. The remaining payload
+ * length will be returned.
+ */
+typedef int (*mgcp_processing)(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end,
+ char *data, int *len, int buf_size);
+typedef int (*mgcp_processing_setup)(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end,
+ struct mgcp_rtp_end *src_end);
+
+typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
+ int *payload_type,
+ const char**subtype_name,
+ const char**fmtp_extra);
+
+#define PORT_ALLOC_STATIC 0
+#define PORT_ALLOC_DYNAMIC 1
+
+/**
+ * This holds information on how to allocate ports
+ */
+struct mgcp_port_range {
+ int mode;
+
+ /* addr or NULL to fall-back to default */
+ char *bind_addr;
+
+ /* pre-allocated from a base? */
+ int base_port;
+
+ /* dynamically allocated */
+ int range_start;
+ int range_end;
+ int last_port;
+};
+
+#define MGCP_KEEPALIVE_ONCE (-1)
+
+struct mgcp_trunk_config {
+ struct llist_head entry;
+
+ struct mgcp_config *cfg;
+
+ int trunk_nr;
+ int trunk_type;
+
+ char *audio_fmtp_extra;
+ char *audio_name;
+ int audio_payload;
+ int audio_send_ptime;
+ int audio_send_name;
+ int audio_loop;
+
+ int no_audio_transcoding;
+
+ int omit_rtcp;
+ int keepalive_interval;
+
+ /* RTP patching */
+ int force_constant_ssrc; /* 0: don't, 1: once */
+ int force_aligned_timing;
+
+ /* spec handling */
+ int force_realloc;
+
+ /* timer */
+ struct osmo_timer_list keepalive_timer;
+
+ unsigned int number_endpoints;
+ struct mgcp_endpoint *endpoints;
+};
+
+enum mgcp_role {
+ MGCP_BSC = 0,
+ MGCP_BSC_NAT,
+};
+
+struct mgcp_config {
+ int source_port;
+ char *local_ip;
+ char *source_addr;
+ char *bts_ip;
+ char *call_agent_addr;
+
+ struct in_addr bts_in;
+
+ /* transcoder handling */
+ char *transcoder_ip;
+ struct in_addr transcoder_in;
+ int transcoder_remote_base;
+
+ /* RTP processing */
+ mgcp_processing rtp_processing_cb;
+ mgcp_processing_setup setup_rtp_processing_cb;
+
+ mgcp_get_format get_net_downlink_format_cb;
+
+ struct osmo_wqueue gw_fd;
+
+ struct mgcp_port_range bts_ports;
+ struct mgcp_port_range net_ports;
+ struct mgcp_port_range transcoder_ports;
+ int endp_dscp;
+
+ int bts_force_ptime;
+
+ mgcp_change change_cb;
+ mgcp_policy policy_cb;
+ mgcp_reset reset_cb;
+ mgcp_realloc realloc_cb;
+ mgcp_rqnt rqnt_cb;
+ void *data;
+
+ uint32_t last_call_id;
+
+ /* trunk handling */
+ struct mgcp_trunk_config trunk;
+ struct llist_head trunks;
+
+ /* only used for start with a static configuration */
+ int last_net_port;
+ int last_bts_port;
+
+ enum mgcp_role role;
+
+ /* osmux translator: 0 means disabled, 1 means enabled */
+ int osmux;
+ /* addr to bind the server to */
+ char *osmux_addr;
+ /* The BSC-NAT may ask for enabling osmux on demand. This tells us if
+ * the osmux socket is already initialized.
+ */
+ int osmux_init;
+ /* osmux batch factor: from 1 to 4 maximum */
+ int osmux_batch;
+ /* osmux batch size (in bytes) */
+ int osmux_batch_size;
+ /* osmux port */
+ uint16_t osmux_port;
+ /* Pad circuit with dummy messages until we see the first voice
+ * message.
+ */
+ uint16_t osmux_dummy;
+};
+
+/* config management */
+struct mgcp_config *mgcp_config_alloc(void);
+int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
+ enum mgcp_role role);
+int mgcp_vty_init(void);
+int mgcp_endpoints_allocate(struct mgcp_trunk_config *cfg);
+void mgcp_release_endp(struct mgcp_endpoint *endp);
+void mgcp_initialize_endp(struct mgcp_endpoint *endp);
+int mgcp_reset_transcoder(struct mgcp_config *cfg);
+void mgcp_format_stats(struct mgcp_endpoint *endp, char *stats, size_t size);
+int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, uint32_t *pr, uint32_t *_or, int *loss, uint32_t *jitter);
+
+void mgcp_trunk_set_keepalive(struct mgcp_trunk_config *tcfg, int interval);
+
+/*
+ * format helper functions
+ */
+struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
+
+/* adc helper */
+static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
+{
+ if (timeslot == 0) {
+ LOGP(DMGCP, LOGL_ERROR, "Timeslot should not be 0\n");
+ timeslot = 255;
+ }
+
+ return timeslot + (32 * multiplex);
+}
+
+static inline void mgcp_endpoint_to_timeslot(int endpoint, int *multiplex, int *timeslot)
+{
+ *multiplex = endpoint / 32;
+ *timeslot = endpoint % 32;
+}
+
+int mgcp_send_reset_ep(struct mgcp_endpoint *endp, int endpoint);
+int mgcp_send_reset_all(struct mgcp_config *cfg);
+
+
+int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
+int mgcp_send(struct mgcp_endpoint *endp, int dest, int is_rtp, struct sockaddr_in *addr, char *buf, int rc);
+int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
+
+#endif
diff --git a/include/openbsc/mgcp_internal.h b/include/openbsc/mgcp_internal.h
new file mode 100644
index 000000000..7c89d1021
--- /dev/null
+++ b/include/openbsc/mgcp_internal.h
@@ -0,0 +1,342 @@
+/* MGCP Private Data */
+
+/*
+ * (C) 2009-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2012 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <string.h>
+
+#include <osmocom/core/select.h>
+
+#define CI_UNUSED 0
+
+enum mgcp_connection_mode {
+ MGCP_CONN_NONE = 0,
+ MGCP_CONN_RECV_ONLY = 1,
+ MGCP_CONN_SEND_ONLY = 2,
+ MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
+ MGCP_CONN_LOOPBACK = 4 | MGCP_CONN_RECV_SEND,
+};
+
+enum mgcp_trunk_type {
+ MGCP_TRUNK_VIRTUAL,
+ MGCP_TRUNK_E1,
+};
+
+struct mgcp_rtp_stream_state {
+ uint32_t ssrc;
+ uint16_t last_seq;
+ uint32_t last_timestamp;
+ uint32_t err_ts_counter;
+ int32_t last_tsdelta;
+ uint32_t last_arrival_time;
+};
+
+struct mgcp_rtp_state {
+ int initialized;
+ int patch_ssrc;
+
+ uint32_t orig_ssrc;
+
+ int seq_offset;
+
+ int32_t timestamp_offset;
+ uint32_t packet_duration;
+
+ struct mgcp_rtp_stream_state in_stream;
+ struct mgcp_rtp_stream_state out_stream;
+
+ /* jitter and packet loss calculation */
+ int stats_initialized;
+ uint16_t stats_base_seq;
+ uint16_t stats_max_seq;
+ uint32_t stats_ssrc;
+ uint32_t stats_jitter;
+ int32_t stats_transit;
+ int stats_cycles;
+};
+
+struct mgcp_rtp_codec {
+ uint32_t rate;
+ int channels;
+ uint32_t frame_duration_num;
+ uint32_t frame_duration_den;
+
+ int payload_type;
+ char *audio_name;
+ char *subtype_name;
+};
+
+struct mgcp_rtp_end {
+ /* statistics */
+ unsigned int packets;
+ unsigned int octets;
+ unsigned int dropped_packets;
+ struct in_addr addr;
+
+ /* in network byte order */
+ int rtp_port, rtcp_port;
+
+ /* audio codec information */
+ struct mgcp_rtp_codec codec;
+ struct mgcp_rtp_codec alt_codec; /* TODO/XXX: make it generic */
+
+ /* per endpoint data */
+ int frames_per_packet;
+ uint32_t packet_duration_ms;
+ char *fmtp_extra;
+ int output_enabled;
+ int force_output_ptime;
+
+ /* RTP patching */
+ int force_constant_ssrc; /* -1: always, 0: don't, 1: once */
+ int force_aligned_timing;
+ void *rtp_process_data;
+
+ /*
+ * Each end has a socket...
+ */
+ struct osmo_fd rtp;
+ struct osmo_fd rtcp;
+
+ int local_port;
+ int local_alloc;
+};
+
+enum {
+ MGCP_TAP_BTS_IN,
+ MGCP_TAP_BTS_OUT,
+ MGCP_TAP_NET_IN,
+ MGCP_TAP_NET_OUT,
+
+ /* last element */
+ MGCP_TAP_COUNT
+};
+
+struct mgcp_rtp_tap {
+ int enabled;
+ struct sockaddr_in forward;
+};
+
+struct mgcp_lco {
+ char *string;
+ char *codec;
+ int pkt_period_min; /* time in ms */
+ int pkt_period_max; /* time in ms */
+};
+
+enum mgcp_type {
+ MGCP_RTP_DEFAULT = 0,
+ MGCP_RTP_TRANSCODED,
+ MGCP_OSMUX_BSC,
+ MGCP_OSMUX_BSC_NAT,
+};
+
+#include <openbsc/osmux.h>
+
+struct mgcp_endpoint {
+ int allocated;
+ uint32_t ci;
+ char *callid;
+ struct mgcp_lco local_options;
+ int conn_mode;
+ int orig_mode;
+
+ /* backpointer */
+ struct mgcp_config *cfg;
+ struct mgcp_trunk_config *tcfg;
+
+ /* port status for bts/net */
+ struct mgcp_rtp_end bts_end;
+ struct mgcp_rtp_end net_end;
+
+ /*
+ * For transcoding we will send from the local_port
+ * of trans_bts and it will arrive at trans_net from
+ * where we will forward it to the network.
+ */
+ struct mgcp_rtp_end trans_bts;
+ struct mgcp_rtp_end trans_net;
+ enum mgcp_type type;
+
+ /* sequence bits */
+ struct mgcp_rtp_state net_state;
+ struct mgcp_rtp_state bts_state;
+
+ /* fields for re-transmission */
+ char *last_trans;
+ char *last_response;
+
+ /* tap for the endpoint */
+ struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
+
+ struct {
+ /* Osmux state: disabled, activating, active */
+ enum osmux_state state;
+ /* Allocated Osmux circuit ID for this endpoint */
+ int allocated_cid;
+ /* Used Osmux circuit ID for this endpoint */
+ uint8_t cid;
+ /* handle to batch messages */
+ struct osmux_in_handle *in;
+ /* handle to unbatch messages */
+ struct osmux_out_handle out;
+ /* statistics */
+ struct {
+ uint32_t chunks;
+ uint32_t octets;
+ } stats;
+ } osmux;
+};
+
+#define for_each_line(line, save) \
+ for (line = strline_r(NULL, &save); line;\
+ line = strline_r(NULL, &save))
+
+static inline char *strline_r(char *str, char **saveptr)
+{
+ char *result;
+
+ if (str)
+ *saveptr = str;
+
+ result = *saveptr;
+
+ if (*saveptr != NULL) {
+ *saveptr = strpbrk(*saveptr, "\r\n");
+
+ if (*saveptr != NULL) {
+ char *eos = *saveptr;
+
+ if ((*saveptr)[0] == '\r' && (*saveptr)[1] == '\n')
+ (*saveptr)++;
+ (*saveptr)++;
+ if ((*saveptr)[0] == '\0')
+ *saveptr = NULL;
+
+ *eos = '\0';
+ }
+ }
+
+ return result;
+}
+
+
+
+#define ENDPOINT_NUMBER(endp) abs((int)(endp - endp->tcfg->endpoints))
+
+/**
+ * Internal structure while parsing a request
+ */
+struct mgcp_parse_data {
+ struct mgcp_config *cfg;
+ struct mgcp_endpoint *endp;
+ char *trans;
+ char *save;
+ int found;
+};
+
+int mgcp_send_dummy(struct mgcp_endpoint *endp);
+int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
+int mgcp_bind_trans_bts_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
+int mgcp_bind_trans_net_rtp_port(struct mgcp_endpoint *enp, int rtp_port);
+int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
+
+/* For transcoding we need to manage an in and an output that are connected */
+static inline int endp_back_channel(int endpoint)
+{
+ return endpoint + 60;
+}
+
+struct mgcp_trunk_config *mgcp_trunk_alloc(struct mgcp_config *cfg, int index);
+struct mgcp_trunk_config *mgcp_trunk_num(struct mgcp_config *cfg, int index);
+
+void mgcp_rtp_end_config(struct mgcp_endpoint *endp, int expect_ssrc_change,
+ struct mgcp_rtp_end *rtp);
+uint32_t mgcp_rtp_packet_duration(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *rtp);
+
+void mgcp_state_calc_loss(struct mgcp_rtp_state *s, struct mgcp_rtp_end *,
+ uint32_t *expected, int *loss);
+uint32_t mgcp_state_calc_jitter(struct mgcp_rtp_state *);
+
+/* payload processing default functions */
+int mgcp_rtp_processing_default(struct mgcp_endpoint *endp, struct mgcp_rtp_end *dst_end,
+ char *data, int *len, int buf_size);
+
+int mgcp_setup_rtp_processing_default(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end,
+ struct mgcp_rtp_end *src_end);
+
+void mgcp_get_net_downlink_format_default(struct mgcp_endpoint *endp,
+ int *payload_type,
+ const char**subtype_name,
+ const char**fmtp_extra);
+
+/* internal RTP Annex A counting */
+void mgcp_rtp_annex_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state,
+ const uint16_t seq, const int32_t transit,
+ const uint32_t ssrc);
+
+int mgcp_set_ip_tos(int fd, int tos);
+
+enum {
+ MGCP_DEST_NET = 0,
+ MGCP_DEST_BTS,
+};
+
+
+#define MGCP_DUMMY_LOAD 0x23
+
+
+/**
+ * SDP related information
+ */
+/* Assume audio frame length of 20ms */
+#define DEFAULT_RTP_AUDIO_FRAME_DUR_NUM 20
+#define DEFAULT_RTP_AUDIO_FRAME_DUR_DEN 1000
+#define DEFAULT_RTP_AUDIO_PACKET_DURATION_MS 20
+#define DEFAULT_RTP_AUDIO_DEFAULT_RATE 8000
+#define DEFAULT_RTP_AUDIO_DEFAULT_CHANNELS 1
+
+#define PTYPE_UNDEFINED (-1)
+int mgcp_parse_sdp_data(struct mgcp_endpoint *endp, struct mgcp_rtp_end *rtp, struct mgcp_parse_data *p);
+int mgcp_set_audio_info(void *ctx, struct mgcp_rtp_codec *codec,
+ int payload_type, const char *audio_name);
+
+
+/**
+ * Internal network related
+ */
+static inline const char *mgcp_net_src_addr(struct mgcp_endpoint *endp)
+{
+ if (endp->cfg->net_ports.bind_addr)
+ return endp->cfg->net_ports.bind_addr;
+ return endp->cfg->source_addr;
+}
+
+static inline const char *mgcp_bts_src_addr(struct mgcp_endpoint *endp)
+{
+ if (endp->cfg->bts_ports.bind_addr)
+ return endp->cfg->bts_ports.bind_addr;
+ return endp->cfg->source_addr;
+}
diff --git a/include/openbsc/mgcp_transcode.h b/include/openbsc/mgcp_transcode.h
new file mode 100644
index 000000000..147e48bba
--- /dev/null
+++ b/include/openbsc/mgcp_transcode.h
@@ -0,0 +1,90 @@
+/*
+ * (C) 2014 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef OPENBSC_MGCP_TRANSCODE_H
+#define OPENBSC_MGCP_TRANSCODE_H
+
+#include "bscconfig.h"
+
+#include <gsm.h>
+#ifdef HAVE_BCG729
+#include <bcg729/decoder.h>
+#include <bcg729/encoder.h>
+#endif
+
+enum audio_format {
+ AF_INVALID,
+ AF_S16,
+ AF_L16,
+ AF_GSM,
+ AF_G729,
+ AF_PCMA,
+ AF_PCMU
+};
+
+
+struct mgcp_process_rtp_state {
+ /* decoding */
+ enum audio_format src_fmt;
+ union {
+ gsm gsm_handle;
+#ifdef HAVE_BCG729
+ bcg729DecoderChannelContextStruct *g729_dec;
+#endif
+ } src;
+ size_t src_frame_size;
+ size_t src_samples_per_frame;
+
+ /* processing */
+
+ /* encoding */
+ enum audio_format dst_fmt;
+ union {
+ gsm gsm_handle;
+#ifdef HAVE_BCG729
+ bcg729EncoderChannelContextStruct *g729_enc;
+#endif
+ } dst;
+ size_t dst_frame_size;
+ size_t dst_samples_per_frame;
+ int dst_packet_duration;
+
+ int is_running;
+ uint16_t next_seq;
+ uint32_t next_time;
+ int16_t samples[10*160];
+ size_t sample_cnt;
+ size_t sample_offs;
+};
+
+
+int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end,
+ struct mgcp_rtp_end *src_end);
+
+void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
+ int *payload_type,
+ const char**audio_name,
+ const char**fmtp_extra);
+
+int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
+ struct mgcp_rtp_end *dst_end,
+ char *data, int *len, int buf_size);
+
+int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst);
+#endif /* OPENBSC_MGCP_TRANSCODE_H */
diff --git a/include/openbsc/misdn.h b/include/openbsc/misdn.h
new file mode 100644
index 000000000..9851ad32c
--- /dev/null
+++ b/include/openbsc/misdn.h
@@ -0,0 +1,27 @@
+/* (C) 2008 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 Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MISDN_H
+#define MISDN_H
+
+#include <osmocom/abis/e1_input.h>
+
+int mi_setup(int cardnr, struct e1inp_line *line, int release_l2);
+int mi_e1_line_update(struct e1inp_line *line);
+
+#endif
diff --git a/include/openbsc/mncc.h b/include/openbsc/mncc.h
new file mode 100644
index 000000000..49f0c8b83
--- /dev/null
+++ b/include/openbsc/mncc.h
@@ -0,0 +1,219 @@
+/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
+ * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
+
+/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _MNCC_H
+#define _MNCC_H
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/mncc.h>
+
+#include <stdint.h>
+
+struct gsm_network;
+struct msgb;
+
+
+/* One end of a call */
+struct gsm_call {
+ struct llist_head entry;
+
+ /* network handle */
+ void *net;
+
+ /* the 'local' transaction */
+ uint32_t callref;
+ /* the 'remote' transaction */
+ uint32_t remote_ref;
+};
+
+#define MNCC_SETUP_REQ 0x0101
+#define MNCC_SETUP_IND 0x0102
+#define MNCC_SETUP_RSP 0x0103
+#define MNCC_SETUP_CNF 0x0104
+#define MNCC_SETUP_COMPL_REQ 0x0105
+#define MNCC_SETUP_COMPL_IND 0x0106
+/* MNCC_REJ_* is perfomed via MNCC_REL_* */
+#define MNCC_CALL_CONF_IND 0x0107
+#define MNCC_CALL_PROC_REQ 0x0108
+#define MNCC_PROGRESS_REQ 0x0109
+#define MNCC_ALERT_REQ 0x010a
+#define MNCC_ALERT_IND 0x010b
+#define MNCC_NOTIFY_REQ 0x010c
+#define MNCC_NOTIFY_IND 0x010d
+#define MNCC_DISC_REQ 0x010e
+#define MNCC_DISC_IND 0x010f
+#define MNCC_REL_REQ 0x0110
+#define MNCC_REL_IND 0x0111
+#define MNCC_REL_CNF 0x0112
+#define MNCC_FACILITY_REQ 0x0113
+#define MNCC_FACILITY_IND 0x0114
+#define MNCC_START_DTMF_IND 0x0115
+#define MNCC_START_DTMF_RSP 0x0116
+#define MNCC_START_DTMF_REJ 0x0117
+#define MNCC_STOP_DTMF_IND 0x0118
+#define MNCC_STOP_DTMF_RSP 0x0119
+#define MNCC_MODIFY_REQ 0x011a
+#define MNCC_MODIFY_IND 0x011b
+#define MNCC_MODIFY_RSP 0x011c
+#define MNCC_MODIFY_CNF 0x011d
+#define MNCC_MODIFY_REJ 0x011e
+#define MNCC_HOLD_IND 0x011f
+#define MNCC_HOLD_CNF 0x0120
+#define MNCC_HOLD_REJ 0x0121
+#define MNCC_RETRIEVE_IND 0x0122
+#define MNCC_RETRIEVE_CNF 0x0123
+#define MNCC_RETRIEVE_REJ 0x0124
+#define MNCC_USERINFO_REQ 0x0125
+#define MNCC_USERINFO_IND 0x0126
+#define MNCC_REJ_REQ 0x0127
+#define MNCC_REJ_IND 0x0128
+
+#define MNCC_BRIDGE 0x0200
+#define MNCC_FRAME_RECV 0x0201
+#define MNCC_FRAME_DROP 0x0202
+#define MNCC_LCHAN_MODIFY 0x0203
+#define MNCC_RTP_CREATE 0x0204
+#define MNCC_RTP_CONNECT 0x0205
+#define MNCC_RTP_FREE 0x0206
+
+#define GSM_TCHF_FRAME 0x0300
+#define GSM_TCHF_FRAME_EFR 0x0301
+#define GSM_TCHH_FRAME 0x0302
+#define GSM_TCH_FRAME_AMR 0x0303
+#define GSM_BAD_FRAME 0x03ff
+
+#define MNCC_SOCKET_HELLO 0x0400
+
+#define GSM_MAX_FACILITY 128
+#define GSM_MAX_SSVERSION 128
+#define GSM_MAX_USERUSER 128
+
+#define MNCC_F_BEARER_CAP 0x0001
+#define MNCC_F_CALLED 0x0002
+#define MNCC_F_CALLING 0x0004
+#define MNCC_F_REDIRECTING 0x0008
+#define MNCC_F_CONNECTED 0x0010
+#define MNCC_F_CAUSE 0x0020
+#define MNCC_F_USERUSER 0x0040
+#define MNCC_F_PROGRESS 0x0080
+#define MNCC_F_EMERGENCY 0x0100
+#define MNCC_F_FACILITY 0x0200
+#define MNCC_F_SSVERSION 0x0400
+#define MNCC_F_CCCAP 0x0800
+#define MNCC_F_KEYPAD 0x1000
+#define MNCC_F_SIGNAL 0x2000
+
+struct gsm_mncc {
+ /* context based information */
+ uint32_t msg_type;
+ uint32_t callref;
+
+ /* which fields are present */
+ uint32_t fields;
+
+ /* data derived informations (MNCC_F_ based) */
+ struct gsm_mncc_bearer_cap bearer_cap;
+ struct gsm_mncc_number called;
+ struct gsm_mncc_number calling;
+ struct gsm_mncc_number redirecting;
+ struct gsm_mncc_number connected;
+ struct gsm_mncc_cause cause;
+ struct gsm_mncc_progress progress;
+ struct gsm_mncc_useruser useruser;
+ struct gsm_mncc_facility facility;
+ struct gsm_mncc_cccap cccap;
+ struct gsm_mncc_ssversion ssversion;
+ struct {
+ int sup;
+ int inv;
+ } clir;
+ int signal;
+
+ /* data derived information, not MNCC_F based */
+ int keypad;
+ int more;
+ int notify; /* 0..127 */
+ int emergency;
+ char imsi[16];
+
+ unsigned char lchan_type;
+ unsigned char lchan_mode;
+};
+
+struct gsm_data_frame {
+ uint32_t msg_type;
+ uint32_t callref;
+ unsigned char data[0];
+};
+
+#define MNCC_SOCK_VERSION 5
+struct gsm_mncc_hello {
+ uint32_t msg_type;
+ uint32_t version;
+
+ /* send the sizes of the structs */
+ uint32_t mncc_size;
+ uint32_t data_frame_size;
+
+ /* send some offsets */
+ uint32_t called_offset;
+ uint32_t signal_offset;
+ uint32_t emergency_offset;
+ uint32_t lchan_type_offset;
+};
+
+struct gsm_mncc_rtp {
+ uint32_t msg_type;
+ uint32_t callref;
+ uint32_t ip;
+ uint16_t port;
+ uint32_t payload_type;
+ uint32_t payload_msg_type;
+};
+
+struct gsm_mncc_bridge {
+ uint32_t msg_type;
+ uint32_t callref[2];
+};
+
+const char *get_mncc_name(int value);
+void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
+void cc_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
+
+/* input from CC code into mncc_builtin */
+int int_mncc_recv(struct gsm_network *net, struct msgb *msg);
+
+/* input from CC code into mncc_sock */
+int mncc_sock_from_cc(struct gsm_network *net, struct msgb *msg);
+
+int mncc_sock_init(struct gsm_network *net, const char *sock_path);
+
+#define mncc_is_data_frame(msg_type) \
+ (msg_type == GSM_TCHF_FRAME \
+ || msg_type == GSM_TCHF_FRAME_EFR \
+ || msg_type == GSM_TCHH_FRAME \
+ || msg_type == GSM_TCH_FRAME_AMR \
+ || msg_type == GSM_BAD_FRAME)
+
+
+#endif
diff --git a/include/openbsc/mncc_int.h b/include/openbsc/mncc_int.h
new file mode 100644
index 000000000..213ce1414
--- /dev/null
+++ b/include/openbsc/mncc_int.h
@@ -0,0 +1,14 @@
+#ifndef _MNCC_INT_H
+#define _MNCC_INT_H
+
+#include <stdint.h>
+
+struct mncc_int {
+ uint8_t def_codec[2];
+};
+
+extern struct mncc_int mncc_int;
+
+uint8_t mncc_codec_for_mode(int lchan_type);
+
+#endif
diff --git a/include/openbsc/nat_rewrite_trie.h b/include/openbsc/nat_rewrite_trie.h
new file mode 100644
index 000000000..0571099c6
--- /dev/null
+++ b/include/openbsc/nat_rewrite_trie.h
@@ -0,0 +1,47 @@
+/*
+ * (C) 2013 by On-Waves
+ * (C) 2013 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef NAT_REWRITE_FILE_H
+#define NAT_REWRITE_FILE_H
+
+#include <osmocom/core/linuxrbtree.h>
+
+struct vty;
+
+struct nat_rewrite_rule {
+ /* For digits 0-9 and + */
+ struct nat_rewrite_rule *rules[11];
+
+ char empty;
+ char prefix[14];
+ char rewrite[6];
+};
+
+struct nat_rewrite {
+ struct nat_rewrite_rule rule;
+ size_t prefixes;
+};
+
+
+struct nat_rewrite *nat_rewrite_parse(void *ctx, const char *filename);
+struct nat_rewrite_rule *nat_rewrite_lookup(struct nat_rewrite *, const char *prefix);
+void nat_rewrite_dump(struct nat_rewrite *rewr);
+void nat_rewrite_dump_vty(struct vty *vty, struct nat_rewrite *rewr);
+
+#endif
diff --git a/include/openbsc/network_listen.h b/include/openbsc/network_listen.h
new file mode 100644
index 000000000..67d1f4ef7
--- /dev/null
+++ b/include/openbsc/network_listen.h
@@ -0,0 +1,16 @@
+#ifndef _OPENBSC_NWL_H
+#define _OPENBSC_NWL_H
+
+#include <stdint.h>
+#include <openbsc/gsm_data.h>
+
+void ipac_nwl_init(void);
+
+/* Start a NWL test. It will raise the S_IPAC_TEST_COMPLETE signal. */
+int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr,
+ const uint8_t *phys_conf, unsigned int phys_conf_len);
+
+int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev,
+ uint16_t max_num_arfcns);
+
+#endif /* _OPENBSC_NWL_H */
diff --git a/include/openbsc/oap_client.h b/include/openbsc/oap_client.h
new file mode 100644
index 000000000..80c86d5d6
--- /dev/null
+++ b/include/openbsc/oap_client.h
@@ -0,0 +1,82 @@
+/* Osmocom Authentication Protocol API */
+
+/* (C) 2015 by Sysmocom s.f.m.c. GmbH
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+struct msgb;
+struct osmo_oap_message;
+
+/* This is the config part for vty. It is essentially copied in
+ * oap_client_state, where values are copied over once the config is
+ * considered valid. */
+struct oap_client_config {
+ uint16_t client_id;
+ int secret_k_present;
+ uint8_t secret_k[16];
+ int secret_opc_present;
+ uint8_t secret_opc[16];
+};
+
+/* The runtime state of the OAP client. client_id and the secrets are in fact
+ * duplicated from oap_client_config, so that a separate validation of the
+ * config data is possible, and so that only a struct oap_client_state* is
+ * passed around. */
+struct oap_client_state {
+ enum {
+ OAP_UNINITIALIZED = 0, /* just allocated. */
+ OAP_DISABLED, /* disabled by config. */
+ OAP_INITIALIZED, /* enabled, config is valid. */
+ OAP_REQUESTED_CHALLENGE,
+ OAP_SENT_CHALLENGE_RESULT,
+ OAP_REGISTERED
+ } state;
+ uint16_t client_id;
+ uint8_t secret_k[16];
+ uint8_t secret_opc[16];
+ int registration_failures;
+};
+
+/* From config, initialize state. Return 0 on success. */
+int oap_client_init(struct oap_client_config *config,
+ struct oap_client_state *state);
+
+/* Construct an OAP registration message and return in *msg_tx. Use
+ * state->client_id and update state->state.
+ * Return 0 on success, or a negative value on error.
+ * If an error is returned, *msg_tx is guaranteed to be NULL. */
+int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx);
+
+/* Decode and act on a received OAP message msg_rx. Update state->state. If a
+ * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP
+ * server (and freed) by the caller. The received msg_rx is not freed.
+ * Return 0 on success, or a negative value on error.
+ * If an error is returned, *msg_tx is guaranteed to be NULL. */
+int oap_client_handle(struct oap_client_state *state,
+ const struct msgb *msg_rx, struct msgb **msg_tx);
+
+/* Allocate a msgb and in it, return the encoded oap_client_msg. Return
+ * NULL on error. (Like oap_client_encode(), but also allocates a msgb.)
+ * About the name: the idea is do_something(oap_client_encoded(my_struct))
+ */
+struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_client_msg);
diff --git a/include/openbsc/openbscdefines.h b/include/openbsc/openbscdefines.h
new file mode 100644
index 000000000..c6ac153b8
--- /dev/null
+++ b/include/openbsc/openbscdefines.h
@@ -0,0 +1,34 @@
+/*
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSCDEFINES_H
+#define OPENBSCDEFINES_H
+
+#ifdef BUILDING_ON_WINDOWS
+ #ifdef BUILDING_OPENBSC
+ #define BSC_API __declspec(dllexport)
+ #else
+ #define BSC_API __declspec(dllimport)
+ #endif
+#else
+ #define BSC_API __attribute__((visibility("default")))
+#endif
+
+#endif
diff --git a/include/openbsc/osmo_bsc.h b/include/openbsc/osmo_bsc.h
new file mode 100644
index 000000000..9e688fd59
--- /dev/null
+++ b/include/openbsc/osmo_bsc.h
@@ -0,0 +1,71 @@
+/* OpenBSC BSC code */
+
+#ifndef OSMO_BSC_H
+#define OSMO_BSC_H
+
+#include "bsc_api.h"
+#include "bsc_msg_filter.h"
+
+#define BSS_SEND_USSD 1
+
+enum bsc_con {
+ BSC_CON_SUCCESS,
+ BSC_CON_REJECT_NO_LINK,
+ BSC_CON_REJECT_RF_GRACE,
+ BSC_CON_NO_MEM,
+};
+
+struct sccp_connection;
+struct bsc_msc_data;
+struct bsc_msc_connection;
+
+struct osmo_bsc_sccp_con {
+ struct llist_head entry;
+
+ int ciphering_handled;
+
+ /* for audio handling */
+ uint16_t cic;
+ int rtp_port;
+
+ /* for advanced ping/pong */
+ int send_ping;
+
+ /* SCCP connection realted */
+ struct sccp_connection *sccp;
+ struct bsc_msc_data *msc;
+ struct osmo_timer_list sccp_it_timeout;
+ struct osmo_timer_list sccp_cc_timeout;
+
+ struct llist_head sccp_queue;
+ unsigned int sccp_queue_size;
+
+ struct gsm_subscriber_connection *conn;
+ uint8_t new_subscriber;
+
+ struct bsc_filter_state filter_state;
+};
+
+struct bsc_api *osmo_bsc_api();
+
+int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
+int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
+enum bsc_con bsc_create_new_connection(struct gsm_subscriber_connection *conn,
+ struct bsc_msc_data *msc, int send_ping);
+int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
+
+struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *);
+int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
+int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
+int bsc_send_welcome_ussd(struct gsm_subscriber_connection *conn);
+
+int bsc_handle_udt(struct bsc_msc_data *msc, struct msgb *msg, unsigned int length);
+int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
+
+int bsc_ctrl_cmds_install();
+
+void bsc_gen_location_state_trap(struct gsm_bts *bts);
+
+struct llist_head *bsc_access_lists(void);
+
+#endif
diff --git a/include/openbsc/osmo_bsc_grace.h b/include/openbsc/osmo_bsc_grace.h
new file mode 100644
index 000000000..5a81cd137
--- /dev/null
+++ b/include/openbsc/osmo_bsc_grace.h
@@ -0,0 +1,35 @@
+/*
+ * (C) 2010-2013 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2010-2013 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OSMO_BSC_GRACE_H
+#define OSMO_BSC_GRACE_H
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/signal.h>
+
+struct bsc_msc_data;
+
+int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts);
+int bsc_grace_paging_request(enum signal_rf rf_policy,
+ struct bsc_subscr *subscr,
+ int chan_needed,
+ struct bsc_msc_data *msc);
+
+#endif
diff --git a/include/openbsc/osmo_bsc_rf.h b/include/openbsc/osmo_bsc_rf.h
new file mode 100644
index 000000000..19ccd080d
--- /dev/null
+++ b/include/openbsc/osmo_bsc_rf.h
@@ -0,0 +1,66 @@
+#ifndef OSMO_BSC_RF
+#define OSMO_BSC_RF
+
+#include <openbsc/gsm_data.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/core/timer.h>
+
+enum osmo_bsc_rf_opstate {
+ OSMO_BSC_RF_OPSTATE_INOPERATIONAL,
+ OSMO_BSC_RF_OPSTATE_OPERATIONAL,
+};
+
+enum osmo_bsc_rf_adminstate {
+ OSMO_BSC_RF_ADMINSTATE_UNLOCKED,
+ OSMO_BSC_RF_ADMINSTATE_LOCKED,
+};
+
+enum osmo_bsc_rf_policy {
+ OSMO_BSC_RF_POLICY_OFF,
+ OSMO_BSC_RF_POLICY_ON,
+ OSMO_BSC_RF_POLICY_GRACE,
+ OSMO_BSC_RF_POLICY_UNKNOWN,
+};
+
+
+struct gsm_network;
+
+struct osmo_bsc_rf {
+ /* the value of signal.h */
+ int policy;
+ struct osmo_fd listen;
+ struct gsm_network *gsm_network;
+
+ const char *last_state_command;
+
+ char *last_rf_lock_ctrl_command;
+
+ /* delay the command */
+ char last_request;
+ struct osmo_timer_list delay_cmd;
+
+ /* verify that RF is up as it should be */
+ struct osmo_timer_list rf_check;
+
+ /* some handling for the automatic grace switch */
+ struct osmo_timer_list grace_timeout;
+
+ /* auto RF switch-off due lack of MSC connection */
+ struct osmo_timer_list auto_off_timer;
+};
+
+struct osmo_bsc_rf_conn {
+ struct osmo_wqueue queue;
+ struct osmo_bsc_rf *rf;
+};
+
+const char *osmo_bsc_rf_get_opstate_name(enum osmo_bsc_rf_opstate opstate);
+const char *osmo_bsc_rf_get_adminstate_name(enum osmo_bsc_rf_adminstate adminstate);
+const char *osmo_bsc_rf_get_policy_name(enum osmo_bsc_rf_policy policy);
+enum osmo_bsc_rf_opstate osmo_bsc_rf_get_opstate_by_bts(struct gsm_bts *bts);
+enum osmo_bsc_rf_adminstate osmo_bsc_rf_get_adminstate_by_bts(struct gsm_bts *bts);
+enum osmo_bsc_rf_policy osmo_bsc_rf_get_policy_by_bts(struct gsm_bts *bts);
+struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net);
+void osmo_bsc_rf_schedule_lock(struct osmo_bsc_rf *rf, char cmd);
+
+#endif
diff --git a/include/openbsc/osmo_msc.h b/include/openbsc/osmo_msc.h
new file mode 100644
index 000000000..beb3f5e4c
--- /dev/null
+++ b/include/openbsc/osmo_msc.h
@@ -0,0 +1,11 @@
+/* Routines for the MSC handling */
+
+#ifndef OSMO_MSC_H
+#define OSMO_MSC_H
+
+#include "bsc_api.h"
+
+struct bsc_api *msc_bsc_api();
+void msc_release_connection(struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/osmux.h b/include/openbsc/osmux.h
new file mode 100644
index 000000000..0b64a7f1e
--- /dev/null
+++ b/include/openbsc/osmux.h
@@ -0,0 +1,42 @@
+#ifndef _OPENBSC_OSMUX_H_
+#define _OPENBSC_OSMUX_H_
+
+#include <osmocom/netif/osmux.h>
+
+#define OSMUX_PORT 1984
+
+enum {
+ OSMUX_ROLE_BSC = 0,
+ OSMUX_ROLE_BSC_NAT,
+};
+
+int osmux_init(int role, struct mgcp_config *cfg);
+int osmux_enable_endpoint(struct mgcp_endpoint *endp, int role,
+ struct in_addr *addr, uint16_t port);
+void osmux_disable_endpoint(struct mgcp_endpoint *endp);
+void osmux_allocate_cid(struct mgcp_endpoint *endp);
+void osmux_release_cid(struct mgcp_endpoint *endp);
+
+int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc);
+int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp);
+
+int osmux_send_dummy(struct mgcp_endpoint *endp);
+
+int osmux_get_cid(void);
+void osmux_put_cid(uint8_t osmux_cid);
+int osmux_used_cid(void);
+
+enum osmux_state {
+ OSMUX_STATE_DISABLED = 0,
+ OSMUX_STATE_NEGOTIATING,
+ OSMUX_STATE_ACTIVATING,
+ OSMUX_STATE_ENABLED,
+};
+
+enum osmux_usage {
+ OSMUX_USAGE_OFF = 0,
+ OSMUX_USAGE_ON = 1,
+ OSMUX_USAGE_ONLY = 2,
+};
+
+#endif
diff --git a/include/openbsc/paging.h b/include/openbsc/paging.h
new file mode 100644
index 000000000..7dd8500ac
--- /dev/null
+++ b/include/openbsc/paging.h
@@ -0,0 +1,77 @@
+/* Paging helper and manager.... */
+/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef PAGING_H
+#define PAGING_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/timer.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/bsc_subscriber.h>
+
+/**
+ * A pending paging request
+ */
+struct gsm_paging_request {
+ /* list_head for list of all paging requests */
+ struct llist_head entry;
+ /* the subscriber which we're paging. Later gsm_paging_request
+ * should probably become a part of the bsc_subsrc struct? */
+ struct bsc_subscr *bsub;
+ /* back-pointer to the BTS on which we are paging */
+ struct gsm_bts *bts;
+ /* what kind of channel type do we ask the MS to establish */
+ int chan_type;
+
+ /* Timer 3113: how long do we try to page? */
+ struct osmo_timer_list T3113;
+
+ /* How often did we ask the BTS to page? */
+ int attempts;
+
+ /* callback to be called in case paging completes */
+ gsm_cbfn *cbfn;
+ void *cbfn_param;
+};
+
+/* schedule paging request */
+int paging_request(struct gsm_network *network, struct bsc_subscr *bsub,
+ int type, gsm_cbfn *cbfn, void *data);
+int paging_request_bts(struct gsm_bts *bts, struct bsc_subscr *bsub,
+ int type, gsm_cbfn *cbfn, void *data);
+
+/* stop paging requests */
+void paging_request_stop(struct llist_head *bts_list,
+ struct gsm_bts *_bts, struct bsc_subscr *bsub,
+ struct gsm_subscriber_connection *conn,
+ struct msgb *msg);
+
+/* update paging load */
+void paging_update_buffer_space(struct gsm_bts *bts, uint16_t);
+
+/* pending paging requests */
+unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
+
+void *paging_get_data(struct gsm_bts *bts, struct bsc_subscr *bsub);
+
+#endif
diff --git a/include/openbsc/pcu_if.h b/include/openbsc/pcu_if.h
new file mode 100644
index 000000000..1f398b4aa
--- /dev/null
+++ b/include/openbsc/pcu_if.h
@@ -0,0 +1,35 @@
+#ifndef _PCU_IF_H
+#define _PCU_IF_H
+
+#include <osmocom/gsm/l1sap.h>
+
+extern int pcu_direct;
+
+struct pcu_sock_state {
+ struct gsm_network *net;
+ struct osmo_fd listen_bfd; /* fd for listen socket */
+ struct osmo_fd conn_bfd; /* fd for connection to lcr */
+ struct llist_head upqueue; /* queue for sending messages */
+};
+
+/* PCU relevant information has changed; Inform PCU (if connected) */
+void pcu_info_update(struct gsm_bts *bts);
+
+/* Forward rach indication to PCU */
+int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
+ uint8_t is_11bit, enum ph_burst_type burst_type);
+
+/* Confirm the sending of an immediate assignment to the pcu */
+int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli);
+
+
+/* Confirm the sending of an immediate assignment to the pcu */
+int pcu_tx_imm_ass_sent(struct gsm_bts *bts, uint32_t tlli);
+
+/* Open connection to PCU */
+int pcu_sock_init(const char *path, struct gsm_bts *bts);
+
+/* Close connection to PCU */
+void pcu_sock_exit(struct gsm_bts *bts);
+
+#endif /* _PCU_IF_H */
diff --git a/include/openbsc/pcuif_proto.h b/include/openbsc/pcuif_proto.h
new file mode 100644
index 000000000..eb28d66bc
--- /dev/null
+++ b/include/openbsc/pcuif_proto.h
@@ -0,0 +1,176 @@
+#ifndef _PCUIF_PROTO_H
+#define _PCUIF_PROTO_H
+
+#define PCU_IF_VERSION 0x08
+
+/* msg_type */
+#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
+#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */
+#define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */
+#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */
+#define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */
+#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */
+#define PCU_IF_MSG_INFO_IND 0x32 /* retrieve BTS info */
+#define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */
+#define PCU_IF_MSG_TIME_IND 0x52 /* GSM time indication */
+#define PCU_IF_MSG_PAG_REQ 0x60 /* paging request */
+
+/* sapi */
+#define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */
+#define PCU_IF_SAPI_AGCH 0x02 /* assignment on AGCH */
+#define PCU_IF_SAPI_PCH 0x03 /* paging/assignment on PCH */
+#define PCU_IF_SAPI_BCCH 0x04 /* SI on BCCH */
+#define PCU_IF_SAPI_PDTCH 0x05 /* packet data/control/ccch block */
+#define PCU_IF_SAPI_PRACH 0x06 /* packet random access channel */
+#define PCU_IF_SAPI_PTCCH 0x07 /* packet TA control channel */
+#define PCU_IF_SAPI_AGCH_DT 0x08 /* assignment on AGCH but with additional TLLI */
+
+/* flags */
+#define PCU_IF_FLAG_ACTIVE (1 << 0)/* BTS is active */
+#define PCU_IF_FLAG_SYSMO (1 << 1)/* access PDCH of sysmoBTS directly */
+#define PCU_IF_FLAG_CS1 (1 << 16)
+#define PCU_IF_FLAG_CS2 (1 << 17)
+#define PCU_IF_FLAG_CS3 (1 << 18)
+#define PCU_IF_FLAG_CS4 (1 << 19)
+#define PCU_IF_FLAG_MCS1 (1 << 20)
+#define PCU_IF_FLAG_MCS2 (1 << 21)
+#define PCU_IF_FLAG_MCS3 (1 << 22)
+#define PCU_IF_FLAG_MCS4 (1 << 23)
+#define PCU_IF_FLAG_MCS5 (1 << 24)
+#define PCU_IF_FLAG_MCS6 (1 << 25)
+#define PCU_IF_FLAG_MCS7 (1 << 26)
+#define PCU_IF_FLAG_MCS8 (1 << 27)
+#define PCU_IF_FLAG_MCS9 (1 << 28)
+
+struct gsm_pcu_if_data {
+ uint8_t sapi;
+ uint8_t len;
+ uint8_t data[162];
+ uint32_t fn;
+ uint16_t arfcn;
+ uint8_t trx_nr;
+ uint8_t ts_nr;
+ uint8_t block_nr;
+ int8_t rssi;
+ uint16_t ber10k; /*!< \brief BER in units of 0.01% */
+ int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */
+ int16_t lqual_cb; /* !< \brief Link quality in centiBel */
+} __attribute__ ((packed));
+
+/* data confirmation with direct tlli (instead of raw mac block with tlli) */
+struct gsm_pcu_if_data_cnf_dt {
+ uint8_t sapi;
+ uint32_t tlli;
+ uint32_t fn;
+ uint16_t arfcn;
+ uint8_t trx_nr;
+ uint8_t ts_nr;
+ uint8_t block_nr;
+ int8_t rssi;
+ uint16_t ber10k; /*!< \brief BER in units of 0.01% */
+ int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */
+ int16_t lqual_cb; /* !< \brief Link quality in centiBel */
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_rts_req {
+ uint8_t sapi;
+ uint8_t spare[3];
+ uint32_t fn;
+ uint16_t arfcn;
+ uint8_t trx_nr;
+ uint8_t ts_nr;
+ uint8_t block_nr;
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_rach_ind {
+ uint8_t sapi;
+ uint16_t ra;
+ int16_t qta;
+ uint32_t fn;
+ uint16_t arfcn;
+ uint8_t is_11bit;
+ uint8_t burst_type;
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_info_trx {
+ uint16_t arfcn;
+ uint8_t pdch_mask; /* PDCH channels per TS */
+ uint8_t spare;
+ uint8_t tsc[8]; /* TSC per channel */
+ uint32_t hlayer1;
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_info_ind {
+ uint32_t version;
+ uint32_t flags;
+ struct gsm_pcu_if_info_trx trx[8]; /* TRX infos per BTS */
+ uint8_t bsic;
+ /* RAI */
+ uint16_t mcc, mnc, lac, rac;
+ /* NSE */
+ uint16_t nsei;
+ uint8_t nse_timer[7];
+ uint8_t cell_timer[11];
+ /* cell */
+ uint16_t cell_id;
+ uint16_t repeat_time;
+ uint8_t repeat_count;
+ uint16_t bvci;
+ uint8_t t3142;
+ uint8_t t3169;
+ uint8_t t3191;
+ uint8_t t3193_10ms;
+ uint8_t t3195;
+ uint8_t n3101;
+ uint8_t n3103;
+ uint8_t n3105;
+ uint8_t cv_countdown;
+ uint16_t dl_tbf_ext;
+ uint16_t ul_tbf_ext;
+ uint8_t initial_cs;
+ uint8_t initial_mcs;
+ /* NSVC */
+ uint16_t nsvci[2];
+ uint16_t local_port[2];
+ uint16_t remote_port[2];
+ uint32_t remote_ip[2];
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_act_req {
+ uint8_t activate;
+ uint8_t trx_nr;
+ uint8_t ts_nr;
+ uint8_t spare;
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_time_ind {
+ uint32_t fn;
+} __attribute__ ((packed));
+
+struct gsm_pcu_if_pag_req {
+ uint8_t sapi;
+ uint8_t chan_needed;
+ uint8_t identity_lv[9];
+} __attribute__ ((packed));
+
+struct gsm_pcu_if {
+ /* context based information */
+ uint8_t msg_type; /* message type */
+ uint8_t bts_nr; /* bts number */
+ uint8_t spare[2];
+
+ union {
+ struct gsm_pcu_if_data data_req;
+ struct gsm_pcu_if_data data_cnf;
+ struct gsm_pcu_if_data_cnf_dt data_cnf_dt;
+ struct gsm_pcu_if_data data_ind;
+ struct gsm_pcu_if_rts_req rts_req;
+ struct gsm_pcu_if_rach_ind rach_ind;
+ struct gsm_pcu_if_info_ind info_ind;
+ struct gsm_pcu_if_act_req act_req;
+ struct gsm_pcu_if_time_ind time_ind;
+ struct gsm_pcu_if_pag_req pag_req;
+ } u;
+} __attribute__ ((packed));
+
+#endif /* _PCUIF_PROTO_H */
diff --git a/include/openbsc/rest_octets.h b/include/openbsc/rest_octets.h
new file mode 100644
index 000000000..49a231296
--- /dev/null
+++ b/include/openbsc/rest_octets.h
@@ -0,0 +1,139 @@
+#ifndef _REST_OCTETS_H
+#define _REST_OCTETS_H
+
+#include <stdbool.h>
+#include <openbsc/gsm_04_08.h>
+#include <osmocom/gsm/sysinfo.h>
+
+/* generate SI1 rest octets */
+int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net);
+int rest_octets_si2quater(uint8_t *data, struct gsm_bts *bts);
+int rest_octets_si6(uint8_t *data, bool is1800_net);
+
+struct gsm48_si_selection_params {
+ uint16_t penalty_time:5,
+ temp_offs:3,
+ cell_resel_off:6,
+ cbq:1,
+ present:1;
+};
+
+struct gsm48_si_power_offset {
+ uint8_t power_offset:2,
+ present:1;
+};
+
+struct gsm48_si3_gprs_ind {
+ uint8_t si13_position:1,
+ ra_colour:3,
+ present:1;
+};
+
+struct gsm48_lsa_params {
+ uint32_t prio_thr:3,
+ lsa_offset:3,
+ mcc:12,
+ mnc:12;
+ unsigned int present;
+};
+
+struct gsm48_si_ro_info {
+ struct gsm48_si_selection_params selection_params;
+ struct gsm48_si_power_offset power_offset;
+ uint8_t si2ter_indicator;
+ uint8_t early_cm_ctrl;
+ struct {
+ uint8_t where:3,
+ present:1;
+ } scheduling;
+ struct gsm48_si3_gprs_ind gprs_ind;
+ /* SI 3 specific */
+ uint8_t si2quater_indicator;
+ /* SI 4 specific */
+ struct gsm48_lsa_params lsa_params;
+ uint16_t cell_id;
+ uint8_t break_ind; /* do we have SI7 + SI8 ? */
+};
+
+
+/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
+int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3);
+
+/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
+int rest_octets_si4(uint8_t *data, const struct gsm48_si_ro_info *si4, int len);
+
+enum pbcch_carrier_type {
+ PBCCH_BCCH,
+ PBCCH_ARFCN,
+ PBCCH_MAIO
+};
+
+/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */
+enum gprs_nmo {
+ GPRS_NMO_I = 0, /* CS pagin on GPRS paging or traffic channel */
+ GPRS_NMO_II = 1, /* all paging on CCCH */
+ GPRS_NMO_III = 2, /* no paging coordination */
+};
+
+/* TS 04.60 12.24 */
+struct gprs_cell_options {
+ enum gprs_nmo nmo;
+ /* T3168: wait for packet uplink assignment message */
+ uint32_t t3168; /* in milliseconds */
+ /* T3192: wait for release of the TBF after reception of the final block */
+ uint32_t t3192; /* in milliseconds */
+ uint32_t drx_timer_max;/* in seconds */
+ uint32_t bs_cv_max;
+ uint8_t supports_egprs_11bit_rach;
+ bool ctrl_ack_type_use_block; /* use PACKET CONTROL ACKNOWLEDGMENT */
+
+ uint8_t ext_info_present;
+ struct {
+ uint8_t egprs_supported;
+ uint8_t use_egprs_p_ch_req;
+ uint8_t bep_period;
+ uint8_t pfc_supported;
+ uint8_t dtm_supported;
+ uint8_t bss_paging_coordination;
+ } ext_info;
+};
+
+/* TS 04.60 Table 12.9.2 */
+struct gprs_power_ctrl_pars {
+ uint8_t alpha;
+ uint8_t t_avg_w;
+ uint8_t t_avg_t;
+ uint8_t pc_meas_chan;
+ uint8_t n_avg_i;
+};
+
+struct gsm48_si13_info {
+ struct gprs_cell_options cell_opts;
+ struct gprs_power_ctrl_pars pwr_ctrl_pars;
+ uint8_t bcch_change_mark;
+ uint8_t si_change_field;
+ uint8_t pbcch_present;
+
+ union {
+ struct {
+ uint8_t rac;
+ uint8_t spgc_ccch_sup;
+ uint8_t net_ctrl_ord;
+ uint8_t prio_acc_thr;
+ } no_pbcch;
+ struct {
+ uint8_t psi1_rep_per;
+ uint8_t pb;
+ uint8_t tsc;
+ uint8_t tn;
+ enum pbcch_carrier_type carrier_type;
+ uint16_t arfcn;
+ uint8_t maio;
+ } pbcch;
+ };
+};
+
+/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
+int rest_octets_si13(uint8_t *data, const struct gsm48_si13_info *si13);
+
+#endif /* _REST_OCTETS_H */
diff --git a/include/openbsc/rrlp.h b/include/openbsc/rrlp.h
new file mode 100644
index 000000000..c89402a2d
--- /dev/null
+++ b/include/openbsc/rrlp.h
@@ -0,0 +1,7 @@
+#ifndef _RRLP_H
+#define _RRLP_H
+
+void on_dso_load_rrlp(void);
+
+#endif /* _RRLP_H */
+
diff --git a/include/openbsc/rs232.h b/include/openbsc/rs232.h
new file mode 100644
index 000000000..61187ca62
--- /dev/null
+++ b/include/openbsc/rs232.h
@@ -0,0 +1,9 @@
+#ifndef _RS232_H
+#define _RS232_H
+
+int rs232_setup(const char *serial_port, unsigned int delay_ms,
+ struct gsm_bts *bts);
+
+int handle_serial_msg(struct msgb *msg);
+
+#endif /* _RS232_H */
diff --git a/include/openbsc/rtp_proxy.h b/include/openbsc/rtp_proxy.h
new file mode 100644
index 000000000..52ffefd27
--- /dev/null
+++ b/include/openbsc/rtp_proxy.h
@@ -0,0 +1,95 @@
+#ifndef _RTP_PROXY_H
+#define _RTP_PROXY_H
+
+/* RTP proxy handling for ip.access nanoBTS */
+
+/* (C) 2009 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 Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <netinet/in.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/select.h>
+
+#include <openbsc/mncc.h>
+
+#define RTP_PT_GSM_FULL 3
+#define RTP_PT_GSM_HALF 96
+#define RTP_PT_GSM_EFR 97
+#define RTP_PT_AMR 98
+#define RTP_LEN_GSM_FULL 33
+#define RTP_LEN_GSM_HALF 15
+#define RTP_LEN_GSM_EFR 31
+#define RTP_GSM_DURATION 160
+
+enum rtp_rx_action {
+ RTP_NONE,
+ RTP_PROXY,
+ RTP_RECV_UPSTREAM,
+};
+
+enum rtp_tx_action {
+ RTP_SEND_NONE,
+ RTP_SEND_DOWNSTREAM,
+};
+
+struct rtp_sub_socket {
+ struct sockaddr_in sin_local;
+ struct sockaddr_in sin_remote;
+
+ struct osmo_fd bfd;
+ /* linked list of to-be-transmitted msgb's */
+ struct llist_head tx_queue;
+};
+
+struct rtp_socket {
+ struct llist_head list;
+
+ struct rtp_sub_socket rtp;
+ struct rtp_sub_socket rtcp;
+
+ /* what should we do on receive? */
+ enum rtp_rx_action rx_action;
+ union {
+ struct {
+ struct rtp_socket *other_sock;
+ } proxy;
+ struct {
+ struct gsm_network *net;
+ uint32_t callref;
+ } receive;
+ };
+ enum rtp_tx_action tx_action;
+ struct {
+ uint16_t sequence;
+ uint32_t timestamp;
+ uint32_t ssrc;
+ struct timeval last_tv;
+ } transmit;
+};
+
+struct rtp_socket *rtp_socket_create(void);
+int rtp_socket_bind(struct rtp_socket *rs, uint32_t ip);
+int rtp_socket_connect(struct rtp_socket *rs, uint32_t ip, uint16_t port);
+int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other);
+int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, uint32_t callref);
+int rtp_socket_free(struct rtp_socket *rs);
+int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame);
+
+#endif /* _RTP_PROXY_H */
diff --git a/include/openbsc/sgsn.h b/include/openbsc/sgsn.h
new file mode 100644
index 000000000..1ede2c930
--- /dev/null
+++ b/include/openbsc/sgsn.h
@@ -0,0 +1,186 @@
+#ifndef _SGSN_H
+#define _SGSN_H
+
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gprs/gprs_ns.h>
+#include <openbsc/gprs_sgsn.h>
+#include <openbsc/oap_client.h>
+
+#include <ares.h>
+
+struct gprs_gsup_client;
+struct hostent;
+
+enum sgsn_auth_policy {
+ SGSN_AUTH_POLICY_OPEN,
+ SGSN_AUTH_POLICY_CLOSED,
+ SGSN_AUTH_POLICY_ACL_ONLY,
+ SGSN_AUTH_POLICY_REMOTE
+};
+
+
+enum sgsn_rate_ctr_keys {
+ CTR_LLC_DL_BYTES,
+ CTR_LLC_UL_BYTES,
+ CTR_LLC_DL_PACKETS,
+ CTR_LLC_UL_PACKETS,
+ CTR_GPRS_ATTACH_REQUEST,
+ CTR_GPRS_ATTACH_ACKED,
+ CTR_GPRS_ATTACH_REJECTED,
+ CTR_GPRS_DETACH_REQUEST,
+ CTR_GPRS_DETACH_ACKED,
+ CTR_GPRS_ROUTING_AREA_REQUEST,
+ CTR_GPRS_ROUTING_AREA_ACKED,
+ CTR_GPRS_ROUTING_AREA_REJECT,
+ /* PDP single packet counter / GSM 04.08 9.5.1 - 9.5.9 */
+ CTR_PDP_ACTIVATE_REQUEST,
+ CTR_PDP_ACTIVATE_REJECT,
+ CTR_PDP_ACTIVATE_ACCEPT,
+ CTR_PDP_REQUEST_ACTIVATE, /* unused */
+ CTR_PDP_REQUEST_ACTIVATE_REJ, /* unused */
+ CTR_PDP_MODIFY_REQUEST, /* unsued */
+ CTR_PDP_MODIFY_ACCEPT, /* unused */
+ CTR_PDP_DL_DEACTIVATE_REQUEST,
+ CTR_PDP_DL_DEACTIVATE_ACCEPT,
+ CTR_PDP_UL_DEACTIVATE_REQUEST,
+ CTR_PDP_UL_DEACTIVATE_ACCEPT,
+};
+
+struct sgsn_cdr {
+ char *filename;
+ int interval;
+};
+
+struct sgsn_config {
+ /* parsed from config file */
+
+ char *gtp_statedir;
+ struct sockaddr_in gtp_listenaddr;
+
+ /* misc */
+ struct gprs_ns_inst *nsi;
+
+ enum sgsn_auth_policy auth_policy;
+ enum gprs_ciph_algo cipher;
+ struct llist_head imsi_acl;
+
+ struct sockaddr_in gsup_server_addr;
+ int gsup_server_port;
+
+ int require_authentication;
+ int require_update_location;
+
+ /* CDR configuration */
+ struct sgsn_cdr cdr;
+
+ struct {
+ int T3312;
+ int T3322;
+ int T3350;
+ int T3360;
+ int T3370;
+ int T3313;
+ int T3314;
+ int T3316;
+ int T3385;
+ int T3386;
+ int T3395;
+ int T3397;
+ } timers;
+
+ int dynamic_lookup;
+
+ struct oap_client_config oap;
+
+ /* RFC1144 TCP/IP header compression */
+ struct {
+ int active;
+ int passive;
+ int s01;
+ } pcomp_rfc1144;
+
+ /* V.42vis data compression */
+ struct {
+ int active;
+ int passive;
+ int p0;
+ int p1;
+ int p2;
+ } dcomp_v42bis;
+};
+
+struct sgsn_instance {
+ char *config_file;
+ struct sgsn_config cfg;
+ /* File descriptor wrappers for LibGTP */
+ struct osmo_fd gtp_fd0;
+ struct osmo_fd gtp_fd1c;
+ struct osmo_fd gtp_fd1u;
+ /* Timer for libGTP */
+ struct osmo_timer_list gtp_timer;
+ /* GSN instance for libgtp */
+ struct gsn_t *gsn;
+ /* Subscriber */
+ struct gsup_client *gsup_client;
+ /* LLME inactivity timer */
+ struct osmo_timer_list llme_timer;
+
+ /* c-ares event loop integration */
+ struct osmo_timer_list ares_timer;
+ struct llist_head ares_fds;
+ ares_channel ares_channel;
+ struct ares_addr_node *ares_servers;
+
+ struct rate_ctr_group *rate_ctrs;
+};
+
+extern struct sgsn_instance *sgsn;
+
+/* sgsn_vty.c */
+
+int sgsn_vty_init(void);
+int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg);
+
+/* sgsn.c */
+
+/* Main input function for Gb proxy */
+int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
+
+
+struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
+ struct sgsn_mm_ctx *mmctx,
+ uint16_t nsapi,
+ struct tlv_parsed *tp);
+int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
+void sgsn_pdp_upd_gtp_u(struct sgsn_pdp_ctx *pdp, void *addr, size_t alen);
+
+/* gprs_sndcp.c */
+
+/* Entry point for the SNSM-ACTIVATE.indication */
+int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
+/* Entry point for the SNSM-DEACTIVATE.indication */
+int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
+/* Called by SNDCP when it has received/re-assembled a N-PDU */
+int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
+ struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
+int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
+ void *mmcontext);
+int sndcp_llunitdata_ind(struct msgb *msg, struct gprs_llc_lle *lle,
+ uint8_t *hdr, uint16_t len);
+
+
+/*
+ * CDR related functionality
+ */
+int sgsn_cdr_init(struct sgsn_instance *sgsn);
+
+
+/*
+ * C-ARES related functionality
+ */
+int sgsn_ares_init(struct sgsn_instance *sgsn);
+int sgsn_ares_query(struct sgsn_instance *sgsm, const char *name, ares_host_callback cb, void *data);
+
+#endif
diff --git a/include/openbsc/signal.h b/include/openbsc/signal.h
new file mode 100644
index 000000000..d4ccf80da
--- /dev/null
+++ b/include/openbsc/signal.h
@@ -0,0 +1,262 @@
+/* Generic signalling/notification infrastructure */
+/* (C) 2009-2010, 2015 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef OPENBSC_SIGNAL_H
+#define OPENBSC_SIGNAL_H
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <openbsc/gsm_data.h>
+
+#include <osmocom/core/signal.h>
+
+/*
+ * Signalling subsystems
+ */
+enum signal_subsystems {
+ SS_PAGING,
+ SS_SMS,
+ SS_ABISIP,
+ SS_NM,
+ SS_LCHAN,
+ SS_SUBSCR,
+ SS_SCALL,
+ SS_CHALLOC,
+ SS_IPAC_NWL,
+ SS_RF,
+ SS_MSC,
+ SS_HO,
+ SS_CCCH,
+ SS_SGSN,
+};
+
+/* SS_PAGING signals */
+enum signal_paging {
+ S_PAGING_SUCCEEDED,
+ S_PAGING_EXPIRED,
+};
+
+/* SS_SMS signals */
+enum signal_sms {
+ S_SMS_SUBMITTED, /* A SMS has been successfully submitted to us */
+ S_SMS_DELIVERED, /* A SMS has been successfully delivered to a MS */
+ S_SMS_SMMA, /* A MS tells us it has more space available */
+ S_SMS_MEM_EXCEEDED, /* A MS tells us it has no more space available */
+ S_SMS_UNKNOWN_ERROR, /* A MS tells us it has an error */
+};
+
+/* SS_ABISIP signals */
+enum signal_abisip {
+ S_ABISIP_CRCX_ACK,
+ S_ABISIP_MDCX_ACK,
+ S_ABISIP_DLCX_IND,
+};
+
+/* SS_NM signals */
+enum signal_nm {
+ S_NM_SW_ACTIV_REP, /* GSM 12.21 software activated report */
+ S_NM_FAIL_REP, /* GSM 12.21 failure event report */
+ S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */
+ S_NM_IPACC_NACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */
+ S_NM_IPACC_ACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_ACK happened */
+ S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
+ S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
+ S_NM_TEST_REP, /* GSM 12.21 Test Report */
+ S_NM_STATECHG_OPER, /* Operational State changed*/
+ S_NM_STATECHG_ADM, /* Administrative State changed */
+ S_NM_OM2K_CONF_RES, /* OM2K Configuration Result */
+};
+
+/* SS_LCHAN signals */
+enum signal_lchan {
+ /*
+ * The lchan got freed with an use_count != 0 and error
+ * recovery needs to be carried out from within the
+ * signal handler.
+ */
+ S_LCHAN_UNEXPECTED_RELEASE,
+ S_LCHAN_ACTIVATE_ACK, /* 08.58 Channel Activate ACK */
+ S_LCHAN_ACTIVATE_NACK, /* 08.58 Channel Activate NACK */
+ S_LCHAN_HANDOVER_COMPL, /* 04.08 Handover Completed */
+ S_LCHAN_HANDOVER_FAIL, /* 04.08 Handover Failed */
+ S_LCHAN_HANDOVER_DETECT, /* 08.58 Handover Detect */
+ S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */
+};
+
+/* SS_CHALLOC signals */
+enum signal_challoc {
+ S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */
+ S_CHALLOC_FREED, /* lchan has been successfully freed */
+};
+
+/* SS_SUBSCR signals */
+enum signal_subscr {
+ S_SUBSCR_ATTACHED,
+ S_SUBSCR_DETACHED,
+ S_SUBSCR_IDENTITY, /* we've received some identity information */
+};
+
+/* SS_SCALL signals */
+enum signal_scall {
+ S_SCALL_SUCCESS,
+ S_SCALL_EXPIRED,
+ S_SCALL_DETACHED,
+};
+
+/* SS_IPAC_NWL signals */
+enum signal_ipaccess {
+ S_IPAC_NWL_COMPLETE,
+};
+
+enum signal_global {
+ S_GLOBAL_BTS_CLOSE_OM,
+};
+
+/* SS_RF signals */
+enum signal_rf {
+ S_RF_OFF,
+ S_RF_ON,
+ S_RF_GRACE,
+};
+
+struct gsm_subscriber;
+
+struct paging_signal_data {
+ struct gsm_subscriber *subscr;
+ struct gsm_bts *bts;
+
+ int paging_result;
+
+ /* NULL in case the paging didn't work */
+ struct gsm_subscriber_connection *conn;
+};
+
+struct scall_signal_data {
+ struct gsm_subscriber_connection *conn;
+ void *data;
+};
+
+struct ipacc_ack_signal_data {
+ struct gsm_bts_trx *trx;
+ uint8_t msg_type;
+};
+
+struct abis_om2k_mo;
+
+struct nm_statechg_signal_data {
+ struct gsm_bts *bts;
+ uint8_t obj_class;
+ void *obj;
+ struct gsm_nm_state *old_state;
+ struct gsm_nm_state *new_state;
+
+ /* This pointer is vaold for TS 12.21 MO */
+ struct abis_om_obj_inst *obj_inst;
+ /* This pointer is vaold for RBS2000 MO */
+ struct abis_om2k_mo *om2k_mo;
+};
+
+struct nm_om2k_signal_data {
+ struct gsm_bts *bts;
+ void *obj;
+ struct abis_om2k_mo *om2k_mo;
+
+ uint8_t accordance_ind;
+};
+
+struct nm_nack_signal_data {
+ struct msgb *msg;
+ struct gsm_bts *bts;
+ uint8_t mt;
+};
+
+struct challoc_signal_data {
+ struct gsm_bts *bts;
+ struct gsm_lchan *lchan;
+ enum gsm_chan_t type;
+};
+
+struct rf_signal_data {
+ struct gsm_network *net;
+};
+
+struct sms_signal_data {
+ /* The transaction where this occured */
+ struct gsm_trans *trans;
+ /* Can be NULL for SMMA */
+ struct gsm_sms *sms;
+ /* int paging result. Only the ones with > 0 */
+ int paging_result;
+};
+
+struct lchan_signal_data {
+ /* The lchan the signal happened on */
+ struct gsm_lchan *lchan;
+ /* Measurement reports on this lchan */
+ struct gsm_meas_rep *mr;
+};
+
+/* MSC signals */
+enum signal_msc {
+ S_MSC_LOST,
+ S_MSC_CONNECTED,
+ S_MSC_AUTHENTICATED,
+};
+
+struct bsc_msc_data;
+struct msc_signal_data {
+ struct bsc_msc_data *data;
+};
+
+/* SS_CCCH signals */
+enum signal_ccch {
+ S_CCCH_PAGING_LOAD,
+ S_CCCH_RACH_LOAD,
+};
+
+struct ccch_signal_data {
+ struct gsm_bts *bts;
+ uint16_t pg_buf_space;
+ uint16_t rach_slot_count;
+ uint16_t rach_busy_count;
+ uint16_t rach_access_count;
+};
+
+/* GPRS SGSN signals SS_SGSN */
+enum signal_sgsn {
+ S_SGSN_ATTACH,
+ S_SGSN_DETACH,
+ S_SGSN_UPDATE,
+ S_SGSN_PDP_ACT,
+ S_SGSN_PDP_DEACT,
+ S_SGSN_PDP_TERMINATE,
+ S_SGSN_PDP_FREE,
+ S_SGSN_MM_FREE,
+};
+
+struct sgsn_mm_ctx;
+struct sgsn_signal_data {
+ struct sgsn_mm_ctx *mm;
+ struct sgsn_pdp_ctx *pdp; /* non-NULL for PDP_ACT, PDP_DEACT, PDP_FREE */
+};
+
+#endif
diff --git a/include/openbsc/silent_call.h b/include/openbsc/silent_call.h
new file mode 100644
index 000000000..619a54327
--- /dev/null
+++ b/include/openbsc/silent_call.h
@@ -0,0 +1,15 @@
+#ifndef _SILENT_CALL_H
+#define _SILENT_CALL_H
+
+struct gsm_subscriber_connection;
+
+extern int gsm_silent_call_start(struct gsm_subscriber *subscr,
+ void *data, int type);
+extern int gsm_silent_call_stop(struct gsm_subscriber *subscr);
+
+#if 0
+extern int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg);
+extern int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg);
+#endif
+
+#endif /* _SILENT_CALL_H */
diff --git a/include/openbsc/slhc.h b/include/openbsc/slhc.h
new file mode 100644
index 000000000..cd5a47cf4
--- /dev/null
+++ b/include/openbsc/slhc.h
@@ -0,0 +1,187 @@
+#ifndef _SLHC_H
+#define _SLHC_H
+/*
+ * Definitions for tcp compression routines.
+ *
+ * $Header: slcompress.h,v 1.10 89/12/31 08:53:02 van Exp $
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ * - Initial distribution.
+ *
+ *
+ * modified for KA9Q Internet Software Package by
+ * Katie Stevens (dkstevens@ucdavis.edu)
+ * University of California, Davis
+ * Computing Services
+ * - 01-31-90 initial adaptation
+ *
+ * - Feb 1991 Bill_Simpson@um.cc.umich.edu
+ * variable number of conversation slots
+ * allow zero or one slots
+ * separate routines
+ * status display
+ */
+
+/*
+ * Compressed packet format:
+ *
+ * The first octet contains the packet type (top 3 bits), TCP
+ * 'push' bit, and flags that indicate which of the 4 TCP sequence
+ * numbers have changed (bottom 5 bits). The next octet is a
+ * conversation number that associates a saved IP/TCP header with
+ * the compressed packet. The next two octets are the TCP checksum
+ * from the original datagram. The next 0 to 15 octets are
+ * sequence number changes, one change per bit set in the header
+ * (there may be no changes and there are two special cases where
+ * the receiver implicitly knows what changed -- see below).
+ *
+ * There are 5 numbers which can change (they are always inserted
+ * in the following order): TCP urgent pointer, window,
+ * acknowledgment, sequence number and IP ID. (The urgent pointer
+ * is different from the others in that its value is sent, not the
+ * change in value.) Since typical use of SLIP links is biased
+ * toward small packets (see comments on MTU/MSS below), changes
+ * use a variable length coding with one octet for numbers in the
+ * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
+ * range 256 - 65535 or 0. (If the change in sequence number or
+ * ack is more than 65535, an uncompressed packet is sent.)
+ */
+
+/*
+ * Packet types (must not conflict with IP protocol version)
+ *
+ * The top nibble of the first octet is the packet type. There are
+ * three possible types: IP (not proto TCP or tcp with one of the
+ * control flags set); uncompressed TCP (a normal IP/TCP packet but
+ * with the 8-bit protocol field replaced by an 8-bit connection id --
+ * this type of packet syncs the sender & receiver); and compressed
+ * TCP (described above).
+ *
+ * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
+ * is logically part of the 4-bit "changes" field that follows. Top
+ * three bits are actual packet type. For backward compatibility
+ * and in the interest of conserving bits, numbers are chosen so the
+ * IP protocol version number (4) which normally appears in this nibble
+ * means "IP packet".
+ */
+
+
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+/* SLIP compression masks for len/vers byte */
+#define SL_TYPE_IP 0x40
+#define SL_TYPE_UNCOMPRESSED_TCP 0x70
+#define SL_TYPE_COMPRESSED_TCP 0x80
+#define SL_TYPE_ERROR 0x00
+
+/* Bits in first octet of compressed packet */
+#define NEW_C 0x40 /* flag bits for what changed in a packet */
+#define NEW_I 0x20
+#define NEW_S 0x08
+#define NEW_A 0x04
+#define NEW_W 0x02
+#define NEW_U 0x01
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+#define TCP_PUSH_BIT 0x10
+
+/*
+ * data type and sizes conversion assumptions:
+ *
+ * VJ code KA9Q style generic
+ * u_char byte_t unsigned char 8 bits
+ * u_short int16 unsigned short 16 bits
+ * u_int int16 unsigned short 16 bits
+ * u_long unsigned long unsigned long 32 bits
+ * int int32 long 32 bits
+ */
+
+typedef __u8 byte_t;
+typedef __u32 int32;
+
+/*
+ * "state" data for each active tcp conversation on the wire. This is
+ * basically a copy of the entire IP/TCP header from the last packet
+ * we saw from the conversation together with a small identifier
+ * the transmit & receive ends of the line use to locate saved header.
+ */
+struct cstate {
+ byte_t cs_this; /* connection id number (xmit) */
+ struct cstate *next; /* next in ring (xmit) */
+ struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */
+ struct tcphdr cs_tcp;
+ unsigned char cs_ipopt[64];
+ unsigned char cs_tcpopt[64];
+ int cs_hsize;
+};
+#define NULLSLSTATE (struct cstate *)0
+
+/*
+ * all the state data for one serial line (we need one of these per line).
+ */
+struct slcompress {
+ struct cstate *tstate; /* transmit connection states (array)*/
+ struct cstate *rstate; /* receive connection states (array)*/
+
+ byte_t tslot_limit; /* highest transmit slot id (0-l)*/
+ byte_t rslot_limit; /* highest receive slot id (0-l)*/
+
+ byte_t xmit_oldest; /* oldest xmit in ring */
+ byte_t xmit_current; /* most recent xmit id */
+ byte_t recv_current; /* most recent rcvd id */
+
+ byte_t flags;
+#define SLF_TOSS 0x01 /* tossing rcvd frames until id received */
+
+ int32 sls_o_nontcp; /* outbound non-TCP packets */
+ int32 sls_o_tcp; /* outbound TCP packets */
+ int32 sls_o_uncompressed; /* outbound uncompressed packets */
+ int32 sls_o_compressed; /* outbound compressed packets */
+ int32 sls_o_searches; /* searches for connection state */
+ int32 sls_o_misses; /* times couldn't find conn. state */
+
+ int32 sls_i_uncompressed; /* inbound uncompressed packets */
+ int32 sls_i_compressed; /* inbound compressed packets */
+ int32 sls_i_error; /* inbound error packets */
+ int32 sls_i_tossed; /* inbound packets tossed because of error */
+
+ int32 sls_i_runt;
+ int32 sls_i_badcheck;
+};
+#define NULLSLCOMPR (struct slcompress *)0
+
+/* In slhc.c: */
+struct slcompress *slhc_init(const void *ctx, int rslots, int tslots);
+
+void slhc_free(struct slcompress *comp);
+
+int slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
+ unsigned char *ocp, unsigned char **cpp, int compress_cid);
+int slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize);
+int slhc_remember(struct slcompress *comp, unsigned char *icp, int isize);
+int slhc_toss(struct slcompress *comp);
+
+void slhc_i_status(struct slcompress *comp);
+void slhc_o_status(struct slcompress *comp);
+
+#endif /* _SLHC_H */
diff --git a/include/openbsc/smpp.h b/include/openbsc/smpp.h
new file mode 100644
index 000000000..bcdac8f0b
--- /dev/null
+++ b/include/openbsc/smpp.h
@@ -0,0 +1,4 @@
+#pragma once
+
+int smpp_openbsc_alloc_init(void *ctx);
+int smpp_openbsc_start(struct gsm_network *net);
diff --git a/include/openbsc/sms_queue.h b/include/openbsc/sms_queue.h
new file mode 100644
index 000000000..2a8bd5850
--- /dev/null
+++ b/include/openbsc/sms_queue.h
@@ -0,0 +1,17 @@
+#ifndef SMS_QUEUE_H
+#define SMS_QUEUE_H
+
+struct gsm_network;
+struct gsm_sms_queue;
+struct vty;
+
+int sms_queue_start(struct gsm_network *, int in_flight);
+int sms_queue_trigger(struct gsm_sms_queue *);
+
+/* vty helper functions */
+int sms_queue_stats(struct gsm_sms_queue *, struct vty* vty);
+int sms_queue_set_max_pending(struct gsm_sms_queue *, int max);
+int sms_queue_set_max_failure(struct gsm_sms_queue *, int fail);
+int sms_queue_clear(struct gsm_sms_queue *);
+
+#endif
diff --git a/include/openbsc/socket.h b/include/openbsc/socket.h
new file mode 100644
index 000000000..0fd85f104
--- /dev/null
+++ b/include/openbsc/socket.h
@@ -0,0 +1,14 @@
+#ifndef _BSC_SOCKET_H
+#define _BSC_SOCKET_H
+
+#include <osmocom/core/select.h>
+
+#ifndef IPPROTO_GRE
+#define IPPROTO_GRE 47
+#endif
+
+int make_sock(struct osmo_fd *bfd, int proto,
+ uint32_t ip, uint16_t port, int priv_nr,
+ int (*cb)(struct osmo_fd *fd, unsigned int what), void *data);
+
+#endif /* _BSC_SOCKET_H */
diff --git a/include/openbsc/system_information.h b/include/openbsc/system_information.h
new file mode 100644
index 000000000..71bea2660
--- /dev/null
+++ b/include/openbsc/system_information.h
@@ -0,0 +1,22 @@
+#ifndef _SYSTEM_INFO_H
+#define _SYSTEM_INFO_H
+
+#include <osmocom/gsm/sysinfo.h>
+
+#include <openbsc/arfcn_range_encode.h>
+
+struct gsm_bts;
+
+int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
+size_t si2q_earfcn_count(const struct osmo_earfcn_si2q *e);
+unsigned range1024_p(unsigned n);
+unsigned range512_q(unsigned m);
+int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w,
+ int f0, uint8_t *chan_list);
+uint8_t si2q_num(struct gsm_bts *bts);
+int bts_earfcn_add(struct gsm_bts *bts, uint16_t earfcn, uint8_t thresh_hi, uint8_t thresh_lo, uint8_t prio,
+ uint8_t qrx, uint8_t meas_bw);
+int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble);
+int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble,
+ bool diversity);
+#endif
diff --git a/include/openbsc/token_auth.h b/include/openbsc/token_auth.h
new file mode 100644
index 000000000..47dc7aa94
--- /dev/null
+++ b/include/openbsc/token_auth.h
@@ -0,0 +1,7 @@
+#ifndef _TOKEN_AUTH_H
+#define _TOKEN_AUTH_H
+
+void on_dso_load_token(void);
+
+#endif /* _TOKEN_AUTH_H */
+
diff --git a/include/openbsc/transaction.h b/include/openbsc/transaction.h
new file mode 100644
index 000000000..9a87d04e4
--- /dev/null
+++ b/include/openbsc/transaction.h
@@ -0,0 +1,79 @@
+#ifndef _TRANSACT_H
+#define _TRANSACT_H
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <osmocom/core/linuxlist.h>
+#include <openbsc/gsm_04_11.h>
+#include <openbsc/mncc.h>
+#include <osmocom/gsm/gsm0411_smc.h>
+#include <osmocom/gsm/gsm0411_smr.h>
+
+/* One transaction */
+struct gsm_trans {
+ /* Entry in list of all transactions */
+ struct llist_head entry;
+
+ /* Back pointer to the network struct */
+ struct gsm_network *net;
+
+ /* The protocol within which we live */
+ uint8_t protocol;
+
+ /* The current transaction ID */
+ uint8_t transaction_id;
+
+ /* To whom we belong, unique identifier of remote MM entity */
+ struct gsm_subscriber *subscr;
+
+ /* The associated connection we are using to transmit messages */
+ struct gsm_subscriber_connection *conn;
+
+ /* reference from MNCC or other application */
+ uint32_t callref;
+
+ /* if traffic channel receive was requested */
+ int tch_recv;
+
+ /* is thats one paging? */
+ struct subscr_request *paging_request;
+
+ union {
+ struct {
+
+ /* current call state */
+ int state;
+
+ /* current timer and message queue */
+ int Tcurrent; /* current CC timer */
+ int T308_second; /* used to send release again */
+ struct osmo_timer_list timer;
+ struct gsm_mncc msg; /* stores setup/disconnect/release message */
+ } cc;
+ struct {
+ struct gsm411_smc_inst smc_inst;
+ struct gsm411_smr_inst smr_inst;
+
+ struct gsm_sms *sms;
+ } sms;
+ };
+};
+
+
+
+struct gsm_trans *trans_find_by_id(struct gsm_subscriber_connection *conn,
+ uint8_t proto, uint8_t trans_id);
+struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
+ uint32_t callref);
+
+struct gsm_trans *trans_alloc(struct gsm_network *net,
+ struct gsm_subscriber *subscr,
+ uint8_t protocol, uint8_t trans_id,
+ uint32_t callref);
+void trans_free(struct gsm_trans *trans);
+
+int trans_assign_trans_id(struct gsm_network *net, struct gsm_subscriber *subscr,
+ uint8_t protocol, uint8_t ti_flag);
+int trans_has_conn(const struct gsm_subscriber_connection *conn);
+
+#endif
diff --git a/include/openbsc/trau_mux.h b/include/openbsc/trau_mux.h
new file mode 100644
index 000000000..75c359b56
--- /dev/null
+++ b/include/openbsc/trau_mux.h
@@ -0,0 +1,70 @@
+/* Simple TRAU frame reflector to route voice calls */
+
+/* (C) 2009 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 Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* The "TRAU mux map" defines which particular 16kbit sub-slot (in which E1
+ * timeslot on which E1 interface) should be directly muxed to which other
+ * sub-slot. Entries in the mux map are always bi-directional.
+ *
+ * The idea of all this is to directly switch voice channels in the BSC
+ * from one phone to another. We do this right now since we don't support
+ * any external interface for voice channels, and in the future as an
+ * optimization to routing them externally.
+ */
+
+#include <stdint.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/mncc.h>
+
+struct decoded_trau_frame;
+
+/* map a TRAU mux map entry */
+int trau_mux_map(const struct gsm_e1_subslot *src,
+ const struct gsm_e1_subslot *dst);
+int trau_mux_map_lchan(const struct gsm_lchan *src,
+ const struct gsm_lchan *dst);
+
+/* unmap a TRAU mux map entry */
+int trau_mux_unmap(const struct gsm_e1_subslot *ss, uint32_t callref);
+
+/* we get called by subchan_demux */
+int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
+ const uint8_t *trau_bits, int num_bits);
+
+/* add a trau receiver */
+int trau_recv_lchan(struct gsm_lchan *lchan, uint32_t callref);
+
+/* send trau from application */
+int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame);
+
+/* switch trau muxer to new lchan */
+int switch_trau_mux(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan);
+
+/* callback invoked if we receive TRAU frames */
+int subch_cb(struct subch_demux *dmx, int ch, uint8_t *data, int len, void *_priv);
+
+/* TRAU frame transcoding */
+struct msgb *trau_decode_fr(uint32_t callref,
+ const struct decoded_trau_frame *tf);
+struct msgb *trau_decode_efr(uint32_t callref,
+ const struct decoded_trau_frame *tf);
+void trau_encode_fr(struct decoded_trau_frame *tf,
+ const unsigned char *data);
+void trau_encode_efr(struct decoded_trau_frame *tf,
+ const unsigned char *data);
diff --git a/include/openbsc/trau_upqueue.h b/include/openbsc/trau_upqueue.h
new file mode 100644
index 000000000..ecc765843
--- /dev/null
+++ b/include/openbsc/trau_upqueue.h
@@ -0,0 +1,7 @@
+#ifndef _TRAU_UPQUEUE_H
+#define _TRAU_UPQUEUE_H
+
+void trau_tx_to_mncc(struct gsm_network *net, struct msgb *msg);
+
+#endif /* _TRAU_UPQUEUE_H */
+
diff --git a/include/openbsc/ussd.h b/include/openbsc/ussd.h
new file mode 100644
index 000000000..266546811
--- /dev/null
+++ b/include/openbsc/ussd.h
@@ -0,0 +1,10 @@
+#ifndef _USSD_H
+#define _USSD_H
+
+/* Handler function for mobile-originated USSD messages */
+
+#include <osmocom/core/msgb.h>
+
+int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
+
+#endif
diff --git a/include/openbsc/v42bis.h b/include/openbsc/v42bis.h
new file mode 100644
index 000000000..607a58e51
--- /dev/null
+++ b/include/openbsc/v42bis.h
@@ -0,0 +1,147 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * v42bis.h
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005, 2011 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*! \page v42bis_page V.42bis modem data compression
+\section v42bis_page_sec_1 What does it do?
+The v.42bis specification defines a data compression scheme, to work in
+conjunction with the error correction scheme defined in V.42.
+
+\section v42bis_page_sec_2 How does it work?
+*/
+
+#include <stdint.h>
+
+#if !defined(_SPANDSP_V42BIS_H_)
+#define _SPANDSP_V42BIS_H_
+
+#define SPAN_DECLARE(x) x
+
+#define V42BIS_MIN_STRING_SIZE 6
+#define V42BIS_MAX_STRING_SIZE 250
+#define V42BIS_MIN_DICTIONARY_SIZE 512
+#define V42BIS_MAX_BITS 12
+#define V42BIS_MAX_CODEWORDS 4096 /* 2^V42BIS_MAX_BITS */
+#define V42BIS_MAX_OUTPUT_LENGTH 1024
+
+enum
+{
+ V42BIS_P0_NEITHER_DIRECTION = 0,
+ V42BIS_P0_INITIATOR_RESPONDER,
+ V42BIS_P0_RESPONDER_INITIATOR,
+ V42BIS_P0_BOTH_DIRECTIONS
+};
+
+enum
+{
+ V42BIS_COMPRESSION_MODE_DYNAMIC = 0,
+ V42BIS_COMPRESSION_MODE_ALWAYS,
+ V42BIS_COMPRESSION_MODE_NEVER
+};
+
+typedef void (*put_msg_func_t)(void *user_data, const uint8_t *msg, int len);
+
+/*!
+ V.42bis compression/decompression descriptor. This defines the working state for a
+ single instance of V.42bis compress/decompression.
+*/
+typedef struct v42bis_state_s v42bis_state_t;
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/*! Compress a block of octets.
+ \param s The V.42bis context.
+ \param buf The data to be compressed.
+ \param len The length of the data buffer.
+ \return 0 */
+SPAN_DECLARE(int) v42bis_compress(v42bis_state_t *s, const uint8_t buf[], int len);
+
+/*! Flush out any data remaining in a compression buffer.
+ \param s The V.42bis context.
+ \return 0 */
+SPAN_DECLARE(int) v42bis_compress_flush(v42bis_state_t *s);
+
+/*! Decompress a block of octets.
+ \param s The V.42bis context.
+ \param buf The data to be decompressed.
+ \param len The length of the data buffer.
+ \return 0 */
+SPAN_DECLARE(int) v42bis_decompress(v42bis_state_t *s, const uint8_t buf[], int len);
+
+/*! Flush out any data remaining in the decompression buffer.
+ \param s The V.42bis context.
+ \return 0 */
+SPAN_DECLARE(int) v42bis_decompress_flush(v42bis_state_t *s);
+
+/*! Set the compression mode.
+ \param s The V.42bis context.
+ \param mode One of the V.42bis compression modes -
+ V42BIS_COMPRESSION_MODE_DYNAMIC,
+ V42BIS_COMPRESSION_MODE_ALWAYS,
+ V42BIS_COMPRESSION_MODE_NEVER */
+SPAN_DECLARE(void) v42bis_compression_control(v42bis_state_t *s, int mode);
+
+/*! Initialise a V.42bis context.
+ \param s The V.42bis context.
+ \param negotiated_p0 The negotiated P0 parameter, from the V.42bis spec.
+ \param negotiated_p1 The negotiated P1 parameter, from the V.42bis spec.
+ \param negotiated_p2 The negotiated P2 parameter, from the V.42bis spec.
+ \param encode_handler Encode callback handler.
+ \param encode_user_data An opaque pointer passed to the encode callback handler.
+ \param max_encode_len The maximum length that should be passed to the encode handler.
+ \param decode_handler Decode callback handler.
+ \param decode_user_data An opaque pointer passed to the decode callback handler.
+ \param max_decode_len The maximum length that should be passed to the decode handler.
+ \return The V.42bis context. */
+SPAN_DECLARE(v42bis_state_t *) v42bis_init(const void *ctx,
+ v42bis_state_t *s,
+ int negotiated_p0,
+ int negotiated_p1,
+ int negotiated_p2,
+ put_msg_func_t encode_handler,
+ void *encode_user_data,
+ int max_encode_len,
+ put_msg_func_t decode_handler,
+ void *decode_user_data,
+ int max_decode_len);
+
+/*! Release a V.42bis context.
+ \param s The V.42bis context.
+ \return 0 if OK */
+SPAN_DECLARE(int) v42bis_release(v42bis_state_t *s);
+
+/*! Free a V.42bis context.
+ \param s The V.42bis context.
+ \return 0 if OK */
+SPAN_DECLARE(int) v42bis_free(v42bis_state_t *s);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+/*- End of file ------------------------------------------------------------*/
diff --git a/include/openbsc/v42bis_private.h b/include/openbsc/v42bis_private.h
new file mode 100644
index 000000000..daa5ea315
--- /dev/null
+++ b/include/openbsc/v42bis_private.h
@@ -0,0 +1,126 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * private/v42bis.h
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1,
+ * as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if !defined(_SPANDSP_PRIVATE_V42BIS_H_)
+#define _SPANDSP_PRIVATE_V42BIS_H_
+
+/*!
+ V.42bis dictionary node.
+ Note that 0 is not a valid node to point to (0 is always a control code), so 0 is used
+ as a "no such value" marker in this structure.
+*/
+typedef struct
+{
+ /*! \brief The value of the octet represented by the current dictionary node */
+ uint8_t node_octet;
+ /*! \brief The parent of this node */
+ uint16_t parent;
+ /*! \brief The first child of this node */
+ uint16_t child;
+ /*! \brief The next node at the same depth */
+ uint16_t next;
+} v42bis_dict_node_t;
+
+/*!
+ V.42bis compression or decompression. This defines the working state for a single instance
+ of V.42bis compression or decompression.
+*/
+typedef struct
+{
+ /*! \brief Compression enabled. */
+ int v42bis_parm_p0;
+ /*! \brief Compression mode. */
+ int compression_mode;
+ /*! \brief Callback function to handle output data. */
+ put_msg_func_t handler;
+ /*! \brief An opaque pointer passed in calls to the data handler. */
+ void *user_data;
+ /*! \brief The maximum amount to be passed to the data handler. */
+ int max_output_len;
+
+ /*! \brief TRUE if we are in transparent (i.e. uncompressable) mode */
+ int transparent;
+ /*! \brief Next empty dictionary entry */
+ uint16_t v42bis_parm_c1;
+ /*! \brief Current codeword size */
+ uint16_t v42bis_parm_c2;
+ /*! \brief Threshold for codeword size change */
+ uint16_t v42bis_parm_c3;
+ /*! \brief The current update point in the dictionary */
+ uint16_t update_at;
+ /*! \brief The last entry matched in the dictionary */
+ uint16_t last_matched;
+ /*! \brief The last entry added to the dictionary */
+ uint16_t last_added;
+ /*! \brief Total number of codewords in the dictionary */
+ int v42bis_parm_n2;
+ /*! \brief Maximum permitted string length */
+ int v42bis_parm_n7;
+ /*! \brief The dictionary */
+ v42bis_dict_node_t dict[V42BIS_MAX_CODEWORDS];
+
+ /*! \brief The octet string in progress */
+ uint8_t string[V42BIS_MAX_STRING_SIZE];
+ /*! \brief The current length of the octet string in progress */
+ int string_length;
+ /*! \brief The amount of the octet string in progress which has already
+ been flushed out of the buffer */
+ int flushed_length;
+
+ /*! \brief Compression performance metric */
+ uint16_t compression_performance;
+
+ /*! \brief Outgoing bit buffer (compression), or incoming bit buffer (decompression) */
+ uint32_t bit_buffer;
+ /*! \brief Outgoing bit count (compression), or incoming bit count (decompression) */
+ int bit_count;
+
+ /*! \brief The output composition buffer */
+ uint8_t output_buf[V42BIS_MAX_OUTPUT_LENGTH];
+ /*! \brief The length of the contents of the output composition buffer */
+ int output_octet_count;
+
+ /*! \brief The current value of the escape code */
+ uint8_t escape_code;
+ /*! \brief TRUE if we just hit an escape code, and are waiting for the following octet */
+ int escaped;
+} v42bis_comp_state_t;
+
+/*!
+ V.42bis compression/decompression descriptor. This defines the working state for a
+ single instance of V.42bis compress/decompression.
+*/
+struct v42bis_state_s
+{
+ /*! \brief Compression state. */
+ v42bis_comp_state_t compress;
+ /*! \brief Decompression state. */
+ v42bis_comp_state_t decompress;
+
+ /*! \brief Error and flow logging control */
+};
+
+#endif
+/*- End of file ------------------------------------------------------------*/
diff --git a/include/openbsc/vty.h b/include/openbsc/vty.h
new file mode 100644
index 000000000..60b7d2d76
--- /dev/null
+++ b/include/openbsc/vty.h
@@ -0,0 +1,51 @@
+#ifndef OPENBSC_VTY_H
+#define OPENBSC_VTY_H
+
+#include <osmocom/vty/vty.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/command.h>
+
+struct gsm_network;
+struct vty;
+
+void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
+
+struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
+
+extern struct cmd_element cfg_description_cmd;
+extern struct cmd_element cfg_no_description_cmd;
+
+enum bsc_vty_node {
+ GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,
+ BTS_NODE,
+ TRX_NODE,
+ TS_NODE,
+ SUBSCR_NODE,
+ MGCP_NODE,
+ GBPROXY_NODE,
+ SGSN_NODE,
+ OML_NODE,
+ NAT_NODE,
+ NAT_BSC_NODE,
+ MSC_NODE,
+ OM2K_NODE,
+ OM2K_CON_GROUP_NODE,
+ TRUNK_NODE,
+ PGROUP_NODE,
+ MNCC_INT_NODE,
+ NITB_NODE,
+ BSC_NODE,
+ SMPP_NODE,
+ SMPP_ESME_NODE,
+ GTPHUB_NODE,
+};
+
+extern int bsc_vty_is_config_node(struct vty *vty, int node);
+
+struct log_info;
+int bsc_vty_init(struct gsm_network *network);
+int bsc_vty_init_extra(void);
+
+struct gsm_network *gsmnet_from_vty(struct vty *vty);
+
+#endif