summaryrefslogtreecommitdiffstats
path: root/openbsc/include
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-06-10 05:40:52 +0800
committerHarald Welte <laforge@gnumonks.org>2009-06-10 05:40:52 +0800
commit13e10daa330ea2b699c9aa9d14b3adbd01111fd6 (patch)
treebf9144f9cf625baab472492b3047970cab14ef83 /openbsc/include
parentf7c43524cfc6e30a0223d3aaff89fe955d6e5146 (diff)
move openbsc into its own subdirectory
Diffstat (limited to 'openbsc/include')
-rw-r--r--openbsc/include/Makefile.am3
-rw-r--r--openbsc/include/compat_af_isdn.h39
-rw-r--r--openbsc/include/mISDNif.h387
-rw-r--r--openbsc/include/openbsc/Makefile.am5
-rw-r--r--openbsc/include/openbsc/abis_nm.h635
-rw-r--r--openbsc/include/openbsc/abis_rsl.h415
-rw-r--r--openbsc/include/openbsc/call_handling.h64
-rw-r--r--openbsc/include/openbsc/chan_alloc.h49
-rw-r--r--openbsc/include/openbsc/db.h44
-rw-r--r--openbsc/include/openbsc/debug.h39
-rw-r--r--openbsc/include/openbsc/e1_input.h159
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h568
-rw-r--r--openbsc/include/openbsc/gsm_04_11.h172
-rw-r--r--openbsc/include/openbsc/gsm_data.h406
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h58
-rw-r--r--openbsc/include/openbsc/gsm_utils.h33
-rw-r--r--openbsc/include/openbsc/ipaccess.h37
-rw-r--r--openbsc/include/openbsc/linuxlist.h360
-rw-r--r--openbsc/include/openbsc/misdn.h28
-rw-r--r--openbsc/include/openbsc/msgb.h111
-rw-r--r--openbsc/include/openbsc/openbscdefines.h35
-rw-r--r--openbsc/include/openbsc/paging.h46
-rw-r--r--openbsc/include/openbsc/rs232.h9
-rw-r--r--openbsc/include/openbsc/select.h22
-rw-r--r--openbsc/include/openbsc/signal.h88
-rw-r--r--openbsc/include/openbsc/subchan_demux.h102
-rw-r--r--openbsc/include/openbsc/telnet_interface.h52
-rw-r--r--openbsc/include/openbsc/timer.h71
-rw-r--r--openbsc/include/openbsc/tlv.h171
-rw-r--r--openbsc/include/openbsc/trau_frame.h65
-rw-r--r--openbsc/include/openbsc/trau_mux.h49
-rw-r--r--openbsc/include/vty/Makefile.am1
-rw-r--r--openbsc/include/vty/buffer.h102
-rw-r--r--openbsc/include/vty/command.h355
-rw-r--r--openbsc/include/vty/vector.h62
-rw-r--r--openbsc/include/vty/vty.h150
36 files changed, 4992 insertions, 0 deletions
diff --git a/openbsc/include/Makefile.am b/openbsc/include/Makefile.am
new file mode 100644
index 000000000..36d57a3c5
--- /dev/null
+++ b/openbsc/include/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = openbsc vty
+
+noinst_HEADERS = mISDNif.h
diff --git a/openbsc/include/compat_af_isdn.h b/openbsc/include/compat_af_isdn.h
new file mode 100644
index 000000000..56cbfb3f2
--- /dev/null
+++ b/openbsc/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/openbsc/include/mISDNif.h b/openbsc/include/mISDNif.h
new file mode 100644
index 000000000..8e065d24b
--- /dev/null
+++ b/openbsc/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/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
new file mode 100644
index 000000000..86f056d26
--- /dev/null
+++ b/openbsc/include/openbsc/Makefile.am
@@ -0,0 +1,5 @@
+noinst_HEADERS = abis_nm.h abis_rsl.h debug.h db.h gsm_04_08.h gsm_data.h \
+ gsm_subscriber.h linuxlist.h msgb.h select.h tlv.h gsm_04_11.h \
+ timer.h misdn.h chan_alloc.h telnet_interface.h paging.h \
+ subchan_demux.h trau_frame.h e1_input.h trau_mux.h signal.h \
+ gsm_utils.h ipaccess.h rs232.h openbscdefines.h
diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h
new file mode 100644
index 000000000..3aac31f3a
--- /dev/null
+++ b/openbsc/include/openbsc/abis_nm.h
@@ -0,0 +1,635 @@
+/* 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _NM_H
+#define _NM_H
+
+#include <sys/types.h>
+
+#include <openbsc/tlv.h>
+
+/* PRIVATE */
+
+/* generic header in front of every OML message according to TS 08.59 */
+struct abis_om_hdr {
+ u_int8_t mdisc;
+ u_int8_t placement;
+ u_int8_t sequence;
+ u_int8_t length;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+#define ABIS_OM_MDISC_FOM 0x80
+#define ABIS_OM_MDISC_MMI 0x40
+#define ABIS_OM_MDISC_TRAU 0x20
+#define ABIS_OM_MDISC_MANUF 0x10
+#define ABIS_OM_PLACEMENT_ONLY 0x80
+#define ABIS_OM_PLACEMENT_FIRST 0x40
+#define ABIS_OM_PLACEMENT_MIDDLE 0x20
+#define ABIS_OM_PLACEMENT_LAST 0x10
+
+struct abis_om_obj_inst {
+ u_int8_t bts_nr;
+ u_int8_t trx_nr;
+ u_int8_t ts_nr;
+} __attribute__ ((packed));
+
+struct abis_om_fom_hdr {
+ u_int8_t msg_type;
+ u_int8_t obj_class;
+ struct abis_om_obj_inst obj_inst;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr))
+
+/* Section 9.1: Message Types */
+enum abis_nm_msgtype {
+ /* SW Download Management Messages */
+ NM_MT_LOAD_INIT = 0x01,
+ NM_MT_LOAD_INIT_ACK,
+ NM_MT_LOAD_INIT_NACK,
+ NM_MT_LOAD_SEG,
+ NM_MT_LOAD_SEG_ACK,
+ NM_MT_LOAD_ABORT,
+ NM_MT_LOAD_END,
+ NM_MT_LOAD_END_ACK,
+ NM_MT_LOAD_END_NACK,
+ NM_MT_SW_ACT_REQ, /* BTS->BSC */
+ NM_MT_SW_ACT_REQ_ACK,
+ NM_MT_SW_ACT_REQ_NACK,
+ NM_MT_ACTIVATE_SW, /* BSC->BTS */
+ NM_MT_ACTIVATE_SW_ACK,
+ NM_MT_ACTIVATE_SW_NACK,
+ NM_MT_SW_ACTIVATED_REP, /* 0x10 */
+ /* A-bis Interface Management Messages */
+ NM_MT_ESTABLISH_TEI = 0x21,
+ NM_MT_ESTABLISH_TEI_ACK,
+ NM_MT_ESTABLISH_TEI_NACK,
+ NM_MT_CONN_TERR_SIGN,
+ NM_MT_CONN_TERR_SIGN_ACK,
+ NM_MT_CONN_TERR_SIGN_NACK,
+ NM_MT_DISC_TERR_SIGN,
+ NM_MT_DISC_TERR_SIGN_ACK,
+ NM_MT_DISC_TERR_SIGN_NACK,
+ NM_MT_CONN_TERR_TRAF,
+ NM_MT_CONN_TERR_TRAF_ACK,
+ NM_MT_CONN_TERR_TRAF_NACK,
+ NM_MT_DISC_TERR_TRAF,
+ NM_MT_DISC_TERR_TRAF_ACK,
+ NM_MT_DISC_TERR_TRAF_NACK,
+ /* Transmission Management Messages */
+ NM_MT_CONN_MDROP_LINK = 0x31,
+ NM_MT_CONN_MDROP_LINK_ACK,
+ NM_MT_CONN_MDROP_LINK_NACK,
+ NM_MT_DISC_MDROP_LINK,
+ NM_MT_DISC_MDROP_LINK_ACK,
+ NM_MT_DISC_MDROP_LINK_NACK,
+ /* Air Interface Management Messages */
+ NM_MT_SET_BTS_ATTR = 0x41,
+ NM_MT_SET_BTS_ATTR_ACK,
+ NM_MT_SET_BTS_ATTR_NACK,
+ NM_MT_SET_RADIO_ATTR,
+ NM_MT_SET_RADIO_ATTR_ACK,
+ NM_MT_SET_RADIO_ATTR_NACK,
+ NM_MT_SET_CHAN_ATTR,
+ NM_MT_SET_CHAN_ATTR_ACK,
+ NM_MT_SET_CHAN_ATTR_NACK,
+ /* Test Management Messages */
+ NM_MT_PERF_TEST = 0x51,
+ NM_MT_PERF_TESET_ACK,
+ NM_MT_PERF_TEST_NACK,
+ NM_MT_TEST_REP,
+ NM_MT_SEND_TEST_REP,
+ NM_MT_SEND_TEST_REP_ACK,
+ NM_MT_SEND_TEST_REP_NACK,
+ NM_MT_STOP_TEST,
+ NM_MT_STOP_TEST_ACK,
+ NM_MT_STOP_TEST_NACK,
+ /* State Management and Event Report Messages */
+ NM_MT_STATECHG_EVENT_REP = 0x61,
+ NM_MT_FAILURE_EVENT_REP,
+ NM_MT_STOP_EVENT_REP,
+ NM_MT_STOP_EVENT_REP_ACK,
+ NM_MT_STOP_EVENT_REP_NACK,
+ NM_MT_REST_EVENT_REP,
+ NM_MT_REST_EVENT_REP_ACK,
+ NM_MT_REST_EVENT_REP_NACK,
+ NM_MT_CHG_ADM_STATE,
+ NM_MT_CHG_ADM_STATE_ACK,
+ NM_MT_CHG_ADM_STATE_NACK,
+ NM_MT_CHG_ADM_STATE_REQ,
+ NM_MT_CHG_ADM_STATE_REQ_ACK,
+ NM_MT_CHG_ADM_STATE_REQ_NACK,
+ NM_MT_REP_OUTST_ALARMS = 0x93,
+ NM_MT_REP_OUTST_ALARMS_ACK,
+ NM_MT_REP_OUTST_ALARMS_NACK,
+ /* Equipment Management Messages */
+ NM_MT_CHANGEOVER = 0x71,
+ NM_MT_CHANGEOVER_ACK,
+ NM_MT_CHANGEOVER_NACK,
+ NM_MT_OPSTART,
+ NM_MT_OPSTART_ACK,
+ NM_MT_OPSTART_NACK,
+ NM_MT_REINIT,
+ NM_MT_REINIT_ACK,
+ NM_MT_REINIT_NACK,
+ NM_MT_SET_SITE_OUT, /* BS11: get alarm ?!? */
+ NM_MT_SET_SITE_OUT_ACK,
+ NM_MT_SET_SITE_OUT_NACK,
+ NM_MT_CHG_HW_CONF = 0x90,
+ NM_MT_CHG_HW_CONF_ACK,
+ NM_MT_CHG_HW_CONF_NACK,
+ /* Measurement Management Messages */
+ NM_MT_MEAS_RES_REQ = 0x8a,
+ NM_MT_MEAS_RES_RESP,
+ NM_MT_STOP_MEAS,
+ NM_MT_START_MEAS,
+ /* Other Messages */
+ NM_MT_GET_ATTR = 0x81,
+ NM_MT_GET_ATTR_RESP,
+ NM_MT_GET_ATTR_NACK,
+ NM_MT_SET_ALARM_THRES,
+ NM_MT_SET_ALARM_THRES_ACK,
+ NM_MT_SET_ALARM_THRES_NACK,
+
+ NM_MT_IPACC_RESTART = 0x87,
+ NM_MT_IPACC_RESTART_ACK,
+};
+
+enum abis_nm_msgtype_bs11 {
+ NM_MT_BS11_RESET_RESOURCE = 0x74,
+
+ NM_MT_BS11_BEGIN_DB_TX = 0xa3,
+ NM_MT_BS11_BEGIN_DB_TX_ACK,
+ NM_MT_BS11_BEGIN_DB_TX_NACK,
+ NM_MT_BS11_END_DB_TX = 0xa6,
+ NM_MT_BS11_END_DB_TX_ACK,
+ NM_MT_BS11_END_DB_TX_NACK,
+ NM_MT_BS11_CREATE_OBJ = 0xa9,
+ NM_MT_BS11_CREATE_OBJ_ACK,
+ NM_MT_BS11_CREATE_OBJ_NACK,
+ NM_MT_BS11_DELETE_OBJ = 0xac,
+ NM_MT_BS11_DELETE_OBJ_ACK,
+ NM_MT_BS11_DELETE_OBJ_NACK,
+
+ NM_MT_BS11_SET_ATTR = 0xd0,
+ NM_MT_BS11_SET_ATTR_ACK,
+ NM_MT_BS11_SET_ATTR_NACK,
+ NM_MT_BS11_LMT_SESSION = 0xdc,
+
+ NM_MT_BS11_GET_STATE = 0xe3,
+ NM_MT_BS11_GET_STATE_ACK,
+ NM_MT_BS11_LMT_LOGON = 0xe5,
+ NM_MT_BS11_LMT_LOGON_ACK,
+ NM_MT_BS11_RESTART = 0xe7,
+ NM_MT_BS11_RESTART_ACK,
+ NM_MT_BS11_DISCONNECT = 0xe9,
+ NM_MT_BS11_DISCONNECT_ACK,
+ NM_MT_BS11_LMT_LOGOFF = 0xec,
+ NM_MT_BS11_LMT_LOGOFF_ACK,
+ NM_MT_BS11_RECONNECT = 0xf1,
+ NM_MT_BS11_RECONNECT_ACK,
+};
+
+enum abis_nm_msgtype_ipacc {
+ NM_MT_IPACC_RSL_CONNECT = 0xe0,
+ NM_MT_IPACC_RSL_CONNECT_ACK,
+ NM_MT_IPACC_RSL_CONNECT_NACK,
+ NM_MT_IPACC_SET_NVATTR = 0xef,
+ NM_MT_IPACC_SET_NVATTR_ACK,
+ NM_MT_IPACC_SET_NVATTR_NACK,
+ NM_MT_IPACC_GET_NVATTR = 0xf2,
+ NM_MT_IPACC_GET_NVATTR_ACK,
+ NM_MT_IPACC_GET_NVATTR_NACK,
+};
+
+enum abis_nm_bs11_cell_alloc {
+ NM_BS11_CANR_GSM = 0x00,
+ NM_BS11_CANR_DCS1800 = 0x01,
+};
+
+/* Section 9.2: Object Class */
+enum abis_nm_obj_class {
+ NM_OC_SITE_MANAGER = 0x00,
+ NM_OC_BTS,
+ NM_OC_RADIO_CARRIER,
+ NM_OC_CHANNEL,
+ NM_OC_BASEB_TRANSC,
+ /* RFU: 05-FE */
+ NM_OC_BS11_ADJC = 0xa0,
+ NM_OC_BS11_HANDOVER = 0xa1,
+ NM_OC_BS11_PWR_CTRL = 0xa2,
+ NM_OC_BS11_BTSE = 0xa3, /* LMT? */
+ NM_OC_BS11_RACK = 0xa4,
+ NM_OC_BS11 = 0xa5, /* 01: ALCO */
+ NM_OC_BS11_TEST = 0xa6,
+ NM_OC_BS11_ENVABTSE = 0xa8,
+ NM_OC_BS11_BPORT = 0xa9,
+
+ NM_OC_GPRS_NSE = 0xf0,
+ NM_OC_GPRS_CELL = 0xf1,
+ NM_OC_GPRS_NSVC0 = 0xf2,
+ NM_OC_GPRS_NSVC1 = 0xf3,
+
+ NM_OC_NULL = 0xff,
+};
+
+/* Section 9.4: Attributes */
+enum abis_nm_attr {
+ NM_ATT_ABIS_CHANNEL = 0x01,
+ NM_ATT_ADD_INFO,
+ NM_ATT_ADD_TEXT,
+ NM_ATT_ADM_STATE,
+ NM_ATT_ARFCN_LIST,
+ NM_ATT_AUTON_REPORT,
+ NM_ATT_AVAIL_STATUS,
+ NM_ATT_BCCH_ARFCN,
+ NM_ATT_BSIC,
+ NM_ATT_BTS_AIR_TIMER,
+ NM_ATT_CCCH_L_I_P,
+ NM_ATT_CCCH_L_T,
+ NM_ATT_CHAN_COMB,
+ NM_ATT_CONN_FAIL_CRIT,
+ NM_ATT_DEST,
+ /* res */
+ NM_ATT_EVENT_TYPE = 0x11, /* BS11: file data ?!? */
+ NM_ATT_FILE_ID,
+ NM_ATT_FILE_VERSION,
+ NM_ATT_GSM_TIME,
+ NM_ATT_HSN,
+ NM_ATT_HW_CONFIG,
+ NM_ATT_HW_DESC,
+ NM_ATT_INTAVE_PARAM,
+ NM_ATT_INTERF_BOUND,
+ NM_ATT_LIST_REQ_ATTR,
+ NM_ATT_MAIO,
+ NM_ATT_MANUF_STATE,
+ NM_ATT_MANUF_THRESH,
+ NM_ATT_MANUF_ID,
+ NM_ATT_MAX_TA,
+ NM_ATT_MDROP_LINK, /* 0x20 */
+ NM_ATT_MDROP_NEXT,
+ NM_ATT_NACK_CAUSES,
+ NM_ATT_NY1,
+ NM_ATT_OPER_STATE,
+ NM_ATT_OVERL_PERIOD,
+ NM_ATT_PHYS_CONF,
+ NM_ATT_POWER_CLASS,
+ NM_ATT_POWER_THRESH,
+ NM_ATT_PROB_CAUSE,
+ NM_ATT_RACH_B_THRESH,
+ NM_ATT_LDAVG_SLOTS,
+ NM_ATT_RAD_SUBC,
+ NM_ATT_RF_MAXPOWR_R,
+ NM_ATT_SITE_INPUTS,
+ NM_ATT_SITE_OUTPUTS,
+ NM_ATT_SOURCE, /* 0x30 */
+ NM_ATT_SPEC_PROB,
+ NM_ATT_START_TIME,
+ NM_ATT_T200,
+ NM_ATT_TEI,
+ NM_ATT_TEST_DUR,
+ NM_ATT_TEST_NO,
+ NM_ATT_TEST_REPORT,
+ NM_ATT_VSWR_THRESH,
+ NM_ATT_WINDOW_SIZE,
+ /* Res */
+ NM_ATT_BS11_RSSI_OFFS = 0x3d,
+ NM_ATT_BS11_TXPWR = 0x3e,
+ NM_ATT_BS11_DIVERSITY = 0x3f,
+ /* Res */
+ NM_ATT_TSC = 0x40,
+ NM_ATT_SW_CONFIG,
+ NM_ATT_SW_DESCR,
+ NM_ATT_SEVERITY,
+ NM_ATT_GET_ARI,
+ NM_ATT_HW_CONF_CHG,
+ NM_ATT_OUTST_ALARM,
+ NM_ATT_FILE_DATA,
+ NM_ATT_MEAS_RES,
+ NM_ATT_MEAS_TYPE,
+
+ NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c,
+ NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f,
+
+ NM_ATT_BS11_ESN_PCB_SERIAL = 0x55,
+ NM_ATT_BS11_EXCESSIVE_DISTANCE = 0x58,
+
+ NM_ATT_BS11_ALL_TEST_CATG = 0x60,
+ NM_ATT_BS11_BTSLS_HOPPING,
+ NM_ATT_BS11_CELL_ALLOC_NR,
+ NM_ATT_BS11_CALL_GLOBAL_ID,
+ NM_ATT_BS11_ENA_INTERF_CLASS = 0x66,
+ NM_ATT_BS11_ENA_INT_INTEC_HANDO = 0x67,
+ NM_ATT_BS11_ENA_INT_INTRC_HANDO = 0x68,
+ NM_ATT_BS11_ENA_MS_PWR_CTRL = 0x69,
+ NM_ATT_BS11_ENA_PWR_BDGT_HO = 0x6a,
+ NM_ATT_BS11_ENA_PWR_CTRL_RLFW = 0x6b,
+ NM_ATT_BS11_ENA_RXLEV_HO = 0x6c,
+ NM_ATT_BS11_ENA_RXQUAL_HO = 0x6d,
+ NM_ATT_BS11_FACCH_QUAL = 0x6e,
+
+ NM_ATT_IPACC_RSL_BSC_IP = 0x80,
+ NM_ATT_IPACC_RSL_BSC_PORT = 0x81,
+ NM_ATT_IPACC_LOCATION = 0x8e, /* string describing location */
+ NM_ATT_IPACC_UNIT_ID = 0x91, /* Site/BTS/TRX */
+ NM_ATT_IPACC_UNIT_NAME = 0x93, /* default: nbts-<mac-as-string> */
+ NM_ATT_IPACC_PRIM_OML_IP = 0x95,
+ NM_ATT_IPACC_SEC_OML_IP = 0x96,
+
+ NM_ATT_BS11_RF_RES_IND_PER = 0x8f,
+
+ NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90,
+ NM_ATT_BS11_ABIS_EXT_TIME = 0x91,
+ NM_ATT_BS11_TIMER_HO_REQUEST = 0x92,
+ NM_ATT_BS11_TIMER_NCELL = 0x93,
+ NM_ATT_BS11_TSYNC = 0x94,
+ NM_ATT_BS11_TTRAU = 0x95,
+ NM_ATT_BS11_EMRG_CFG_MEMBER = 0x9b,
+ NM_ATT_BS11_TRX_AREA = 0x9f,
+
+ NM_ATT_BS11_BCCH_RECONF = 0xd7,
+ NM_ATT_BS11_BIT_ERR_THESH = 0xa0,
+ NM_ATT_BS11_BOOT_SW_VERS = 0xa1,
+ NM_ATT_BS11_CCLK_ACCURACY = 0xa3,
+ NM_ATT_BS11_CCLK_TYPE = 0xa4,
+ NM_ATT_BS11_INP_IMPEDANCE = 0xaa,
+ NM_ATT_BS11_L1_PROT_TYPE = 0xab,
+ NM_ATT_BS11_LINE_CFG = 0xac,
+ NM_ATT_BS11_LI_PORT_1 = 0xad,
+ NM_ATT_BS11_LI_PORT_2 = 0xae,
+
+ NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0,
+ NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb,
+ NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc,
+ NM_ATT_BS11_SW_LOAD_STORED = 0xbd,
+
+ NM_ATT_BS11_VENDOR_NAME = 0xc1,
+ NM_ATT_BS11_HOPPING_MODE = 0xc5,
+ NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6,
+ NM_ATT_BS11_LMT_LOGIN_TIME = 0xc7,
+ NM_ATT_BS11_LMT_USER_ACC_LEV = 0xc8,
+ NM_ATT_BS11_LMT_USER_NAME = 0xc9,
+
+ NM_ATT_BS11_L1_CONTROL_TS = 0xd8,
+ NM_ATT_BS11_RADIO_MEAS_GRAN = 0xdc, /* in SACCH multiframes */
+ NM_ATT_BS11_RADIO_MEAS_REP = 0xdd,
+
+ NM_ATT_BS11_SH_LAPD_INT_TIMER = 0xe8,
+
+ NM_ATT_BS11_BTS_STATE = 0xf0,
+ NM_ATT_BS11_E1_STATE = 0xf1,
+ NM_ATT_BS11_PLL = 0xf2,
+ NM_ATT_BS11_RX_OFFSET = 0xf3,
+ NM_ATT_BS11_ANT_TYPE = 0xf4,
+ NM_ATT_BS11_PLL_MODE = 0xfc,
+ NM_ATT_BS11_PASSWORD = 0xfd,
+};
+#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE
+
+/* Section 9.4.4: Administrative State */
+enum abis_nm_adm_state {
+ NM_STATE_LOCKED = 0x01,
+ NM_STATE_UNLOCKED = 0x02,
+ NM_STATE_SHUTDOWN = 0x03,
+ NM_STATE_NULL = 0xff,
+};
+
+/* Section 9.4.13: Channel Combination */
+enum abis_nm_chan_comb {
+ NM_CHANC_TCHFull = 0x00,
+ NM_CHANC_TCHHalf = 0x01,
+ NM_CHANC_TCHHalf2 = 0x02,
+ NM_CHANC_SDCCH = 0x03,
+ NM_CHANC_mainBCCH = 0x04,
+ NM_CHANC_BCCCHComb = 0x05,
+ NM_CHANC_BCCH = 0x06,
+ NM_CHANC_BCCH_CBCH = 0x07,
+ NM_CHANC_SDCCH_CBCH = 0x08,
+};
+
+/* Section 9.4.16: Event Type */
+enum abis_nm_event_type {
+ NM_EVT_COMM_FAIL = 0x00,
+ NM_EVT_QOS_FAIL = 0x01,
+ NM_EVT_PROC_FAIL = 0x02,
+ NM_EVT_EQUIP_FAIL = 0x03,
+ NM_EVT_ENV_FAIL = 0x04,
+};
+
+/* Section: 9.4.63: Perceived Severity */
+enum abis_nm_severity {
+ NM_SEVER_CEASED = 0x00,
+ NM_SEVER_CRITICAL = 0x01,
+ NM_SEVER_MAJOR = 0x02,
+ NM_SEVER_MINOR = 0x03,
+ NM_SEVER_WARNING = 0x04,
+ NM_SEVER_INDETERMINATE = 0x05,
+};
+
+/* Section 9.4.43: Probable Cause Type */
+enum abis_nm_pcause_type {
+ NM_PCAUSE_T_X721 = 0x01,
+ NM_PCAUSE_T_GSM = 0x02,
+ NM_PCAUSE_T_MANUF = 0x03,
+};
+
+/* Section 9.4.36: NACK Causes */
+enum abis_nm_nack_cause {
+ /* General Nack Causes */
+ NM_NACK_INCORR_STRUCT = 0x01,
+ NM_NACK_MSGTYPE_INVAL = 0x02,
+ NM_NACK_OBJCLASS_INVAL = 0x05,
+ NM_NACK_OBJCLASS_NOTSUPP = 0x06,
+ NM_NACK_BTSNR_UNKN = 0x07,
+ NM_NACK_TRXNR_UNKN = 0x08,
+ NM_NACK_OBJINST_UNKN = 0x09,
+ NM_NACK_ATTRID_INVAL = 0x0c,
+ NM_NACK_ATTRID_NOTSUPP = 0x0d,
+ NM_NACK_PARAM_RANGE = 0x0e,
+ NM_NACK_ATTRLIST_INCONSISTENT = 0x0f,
+ NM_NACK_SPEC_IMPL_NOTSUPP = 0x10,
+ NM_NACK_CANT_PERFORM = 0x11,
+ /* Specific Nack Causes */
+ NM_NACK_RES_NOTIMPL = 0x19,
+ NM_NACK_RES_NOTAVAIL = 0x1a,
+ NM_NACK_FREQ_NOTAVAIL = 0x1b,
+ NM_NACK_TEST_NOTSUPP = 0x1c,
+ NM_NACK_CAPACITY_RESTR = 0x1d,
+ NM_NACK_PHYSCFG_NOTPERFORM = 0x1e,
+ NM_NACK_TEST_NOTINIT = 0x1f,
+ NM_NACK_PHYSCFG_NOTRESTORE = 0x20,
+ NM_NACK_TEST_NOSUCH = 0x21,
+ NM_NACK_TEST_NOSTOP = 0x22,
+ NM_NACK_MSGINCONSIST_PHYSCFG = 0x23,
+ NM_NACK_FILE_INCOMPLETE = 0x25,
+ NM_NACK_FILE_NOTAVAIL = 0x26,
+ MN_NACK_FILE_NOTACTIVATE = 0x27,
+ NM_NACK_REQ_NOT_GRANT = 0x28,
+ NM_NACK_WAIT = 0x29,
+ NM_NACK_NOTH_REPORT_EXIST = 0x2a,
+ NM_NACK_MEAS_NOTSUPP = 0x2b,
+ NM_NACK_MEAS_NOTSTART = 0x2c,
+};
+
+/* Section 9.4.1 */
+struct abis_nm_channel {
+ u_int8_t attrib;
+ u_int8_t bts_port;
+ u_int8_t timeslot;
+ u_int8_t subslot;
+} __attribute__ ((packed));
+
+/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */
+enum abis_bs11_objtype {
+ BS11_OBJ_ALCO = 0x01,
+ BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */
+ BS11_OBJ_TRX1 = 0x03, /* only DEACTIVATE TRX1 */
+ BS11_OBJ_CCLK = 0x04,
+ BS11_OBJ_GPSU = 0x06,
+ BS11_OBJ_LI = 0x07,
+ BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/
+};
+
+enum abis_bs11_trx_power {
+ BS11_TRX_POWER_GSM_2W = 0x06,
+ BS11_TRX_POWER_GSM_250mW= 0x07,
+ BS11_TRX_POWER_GSM_80mW = 0x08,
+ BS11_TRX_POWER_GSM_30mW = 0x09,
+ BS11_TRX_POWER_DCS_3W = 0x0a,
+ BS11_TRX_POWER_DCS_1W6 = 0x0b,
+ BS11_TRX_POWER_DCS_500mW= 0x0c,
+ BS11_TRX_POWER_DCS_160mW= 0x0d,
+};
+
+enum abis_bs11_li_pll_mode {
+ BS11_LI_PLL_LOCKED = 2,
+ BS11_LI_PLL_STANDALONE = 3,
+};
+
+enum abis_bs11_phase {
+ BS11_STATE_SOFTWARE_RQD = 0x01,
+ BS11_STATE_LOAD_SMU_INTENDED = 0x11,
+ BS11_STATE_LOAD_SMU_SAFETY = 0x21,
+ BS11_STATE_LOAD_FAILED = 0x31,
+ BS11_STATE_LOAD_DIAGNOSTIC = 0x41,
+ BS11_STATE_WARM_UP = 0x51,
+ BS11_STATE_WARM_UP_2 = 0x52,
+ BS11_STATE_WAIT_MIN_CFG = 0x62,
+ BS11_STATE_MAINTENANCE = 0x72,
+ BS11_STATE_LOAD_MBCCU = 0x92,
+ BS11_STATE_WAIT_MIN_CFG_2 = 0xA2,
+ BS11_STATE_NORMAL = 0x03,
+ BS11_STATE_ABIS_LOAD = 0x13,
+};
+
+
+/* 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, const u_int8_t *buf, int len);
+int abis_nm_rx(struct msgb *msg);
+int abis_nm_opstart(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1, u_int8_t i2);
+int abis_nm_chg_adm_state(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0,
+ u_int8_t i1, u_int8_t i2, u_int8_t adm_state);
+int abis_nm_establish_tei(struct gsm_bts *bts, u_int8_t trx_nr,
+ u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot,
+ u_int8_t tei);
+int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
+ u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot);
+int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
+ u_int8_t e1_port, u_int8_t e1_timeslot,
+ u_int8_t e1_subslot);
+int abis_nm_set_bts_attr(struct gsm_bts *bts, u_int8_t *attr, int attr_len);
+int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, u_int8_t *attr, int attr_len);
+int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb);
+int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
+ u_int8_t i2, u_int8_t i3, int nack, u_int8_t *attr, int att_len);
+int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_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, const char *fname,
+ u_int8_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);
+
+/* 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,
+ u_int8_t idx, u_int8_t attr_len, const u_int8_t *attr);
+int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, u_int8_t idx);
+int abis_nm_bs11_create_bport(struct gsm_bts *bts, u_int8_t idx);
+int abis_nm_bs11_delete_object(struct gsm_bts *bts,
+ enum abis_bs11_objtype type, u_int8_t idx);
+int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port,
+ u_int8_t e1_timeslot, u_int8_t e1_subslot, u_int8_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, u_int8_t level);
+int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx);
+int abis_nm_bs11_factory_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_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,
+ u_int8_t win_size, int forced, gsm_cbfn *cbfn);
+int abis_nm_bs11_set_ext_time(struct gsm_bts *bts);
+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, u_int8_t msg_type,
+ u_int8_t obj_class, u_int8_t bts_nr,
+ u_int8_t trx_nr, u_int8_t ts_nr,
+ u_int8_t *attr, int attr_len);
+int abis_nm_ipaccess_set_nvattr(struct gsm_bts *bts, u_int8_t *attr,
+ int attr_len);
+int abis_nm_ipaccess_restart(struct gsm_bts *bts);
+
+/* Functions calling into other code parts */
+enum nm_evt {
+ EVT_STATECHG_OPER,
+ EVT_STATECHG_ADM,
+};
+int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
+ struct gsm_nm_state *old_state, struct gsm_nm_state *new_state);
+
+const char *nm_opstate_name(u_int8_t os);
+const char *nm_avail_name(u_int8_t avail);
+#endif /* _NM_H */
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h
new file mode 100644
index 000000000..532595b90
--- /dev/null
+++ b/openbsc/include/openbsc/abis_rsl.h
@@ -0,0 +1,415 @@
+/* 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _RSL_H
+#define _RSL_H
+
+struct abis_rsl_common_hdr {
+ u_int8_t msg_discr;
+ u_int8_t msg_type;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Chapter 8.3 */
+struct abis_rsl_rll_hdr {
+ struct abis_rsl_common_hdr c;
+ u_int8_t ie_chan;
+ u_int8_t chan_nr;
+ u_int8_t ie_link_id;
+ u_int8_t link_id;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Chapter 8.3 and 8.4 */
+struct abis_rsl_dchan_hdr {
+ struct abis_rsl_common_hdr c;
+ u_int8_t ie_chan;
+ u_int8_t chan_nr;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+
+/* Chapter 9.1 */
+#define ABIS_RSL_MDISC_RLL 0x02
+#define ABIS_RSL_MDISC_DED_CHAN 0x08
+#define ABIS_RSL_MDISC_COM_CHAN 0x0c
+#define ABIS_RSL_MDISC_TRX 0x10
+#define ABIS_RSL_MDISC_LOC 0x20
+#define ABIS_RSL_MDISC_IPACCESS 0x7e
+#define ABIS_RSL_MDISC_TRANSP 0x01
+
+#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01)
+
+/* Chapter 9.1 */
+enum abis_rsl_msgtype {
+ /* Radio Link Layer Management */
+ RSL_MT_DATA_REQ = 0x01,
+ RSL_MT_DATA_IND,
+ RSL_MT_ERROR_IND,
+ RSL_MT_EST_REQ,
+ RSL_MT_EST_CONF,
+ RSL_MT_EST_IND,
+ RSL_MT_REL_REQ,
+ RSL_MT_REL_CONF,
+ RSL_MT_REL_IND,
+ RSL_MT_UNIT_DATA_REQ,
+ RSL_MT_UNIT_DATA_IND, /* 0x0b */
+
+ /* Common Channel Management / TRX Management */
+ RSL_MT_BCCH_INFO = 0x11,
+ RSL_MT_CCCH_LOAD_IND,
+ RSL_MT_CHAN_RQD,
+ RSL_MT_DELETE_IND,
+ RSL_MT_PAGING_CMD,
+ RSL_MT_IMMEDIATE_ASSIGN_CMD,
+ RSL_MT_SMS_BC_REQ,
+ /* empty */
+ RSL_MT_RF_RES_IND = 0x19,
+ RSL_MT_SACCH_FILL,
+ RSL_MT_OVERLOAD,
+ RSL_MT_ERROR_REPORT,
+ RSL_MT_SMS_BC_CMD,
+ RSL_MT_CBCH_LOAD_IND,
+ RSL_MT_NOT_CMD, /* 0x1f */
+
+ /* Dedicate Channel Management */
+ RSL_MT_CHAN_ACTIV = 0x21,
+ RSL_MT_CHAN_ACTIV_ACK,
+ RSL_MT_CHAN_ACTIV_NACK,
+ RSL_MT_CONN_FAIL,
+ RSL_MT_DEACTIVATE_SACCH,
+ RSL_MT_ENCR_CMD,
+ RSL_MT_HANDO_DET,
+ RSL_MT_MEAS_RES,
+ RSL_MT_MODE_MODIFY_REQ,
+ RSL_MT_MODE_MODIFY_ACK,
+ RSL_MT_MODE_MODIFY_NACK,
+ RSL_MT_PHY_CONTEXT_REQ,
+ RSL_MT_PHY_CONTEXT_CONF,
+ RSL_MT_RF_CHAN_REL,
+ RSL_MT_MS_POWER_CONTROL,
+ RSL_MT_BS_POWER_CONTROL, /* 0x30 */
+ RSL_MT_PREPROC_CONFIG,
+ RSL_MT_PREPROC_MEAS_RES,
+ RSL_MT_RF_CHAN_REL_ACK,
+ RSL_MT_SACCH_INFO_MODIFY,
+ RSL_MT_TALKER_DET,
+ RSL_MT_LISTENER_DET,
+ RSL_MT_REMOTE_CODEC_CONF_REP,
+ RSL_MT_RTD_REP,
+ RSL_MT_PRE_HANDO_NOTIF,
+ RSL_MT_MR_CODEC_MOD_REQ,
+ RSL_MT_MR_CODEC_MOD_ACK,
+ RSL_MT_MR_CODEC_MOD_NACK,
+ RSL_MT_MR_CODEC_MOD_PER,
+ RSL_MT_TFO_REP,
+ RSL_MT_TFO_MOD_REQ, /* 0x3f */
+
+ /* ip.access specific RSL message types */
+ RSL_MT_IPAC_BIND = 0x70, /* Bind to local BTS RTP port */
+ RSL_MT_IPAC_BIND_ACK,
+ RSL_MT_IPAC_BIND_NACK,
+ RSL_MT_IPAC_CONNECT = 0x73,
+ RSL_MT_IPAC_CONNECT_ACK,
+ RSL_MT_IPAC_CONNECT_NACK,
+ RSL_MT_IPAC_DISCONNECT_IND = 0x76,
+
+};
+
+/* Chapter 9.3 */
+enum abis_rsl_ie {
+ RSL_IE_CHAN_NR = 0x01,
+ RSL_IE_LINK_IDENT,
+ RSL_IE_ACT_TYPE,
+ RSL_IE_BS_POWER,
+ RSL_IE_CHAN_IDENT,
+ RSL_IE_CHAN_MODE,
+ RSL_IE_ENCR_INFO,
+ RSL_IE_FRAME_NUMBER,
+ RSL_IE_HANDO_REF,
+ RSL_IE_L1_INFO,
+ RSL_IE_L3_INFO,
+ RSL_IE_MS_IDENTITY,
+ RSL_IE_MS_POWER,
+ RSL_IE_PAGING_GROUP,
+ RSL_IE_PAGING_LOAD,
+ RSL_IE_PYHS_CONTEXT = 0x10,
+ RSL_IE_ACCESS_DELAY,
+ RSL_IE_RACH_LOAD,
+ RSL_IE_REQ_REFERENCE,
+ RSL_IE_RELEASE_MODE,
+ RSL_IE_RESOURCE_INFO,
+ RSL_IE_RLM_CAUSE,
+ RSL_IE_STARTNG_TIME,
+ RSL_IE_TIMING_ADVANCE,
+ RSL_IE_UPLINK_MEAS,
+ RSL_IE_CAUSE,
+ RSL_IE_MEAS_RES_NR,
+ RSL_IE_MSG_ID,
+ /* reserved */
+ RSL_IE_SYSINFO_TYPE = 0x1e,
+ RSL_IE_MS_POWER_PARAM,
+ RSL_IE_BS_POWER_PARAM,
+ RSL_IE_PREPROC_PARAM,
+ RSL_IE_PREPROC_MEAS,
+ RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */
+ RSL_IE_SMSCB_INFO = 0x24,
+ RSL_IE_MS_TIMING_OFFSET,
+ RSL_IE_ERR_MSG,
+ RSL_IE_FULL_BCCH_INFO,
+ RSL_IE_CHAN_NEEDED,
+ RSL_IE_CB_CMD_TYPE,
+ RSL_IE_SMSCB_MSG,
+ RSL_IE_FULL_IMM_ASS_INFO,
+ RSL_IE_SACCH_INFO,
+ RSL_IE_CBCH_LOAD_INFO,
+ RSL_IE_SMSCB_CHAN_INDICATOR,
+ RSL_IE_GROUP_CALL_REF,
+ RSL_IE_CHAN_DESC,
+ RSL_IE_NCH_DRX_INFO,
+ RSL_IE_CMD_INDICATOR,
+ RSL_IE_EMLPP_PRIO,
+ RSL_IE_UIC,
+ RSL_IE_MAIN_CHAN_REF,
+ RSL_IE_MR_CONFIG,
+ RSL_IE_MR_CONTROL,
+ RSL_IE_SUP_CODEC_TYPES,
+ RSL_IE_CODEC_CONFIG,
+ RSL_IE_RTD,
+ RSL_IE_TFO_STATUS,
+ RSL_IE_LLP_APDU,
+
+ RSL_IE_IPAC_REMOTE_IP = 0xf0,
+ RSL_IE_IPAC_REMOTE_PORT = 0xf1,
+ RSL_IE_IPAC_LOCAL_PORT = 0xf3,
+ RSL_IE_IPAC_LOCAL_IP = 0xf5,
+};
+
+/* Chapter 9.3.1 */
+#define RSL_CHAN_NR_MASK 0xf8
+#define RSL_CHAN_Bm_ACCHs 0x08
+#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */
+#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */
+#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */
+#define RSL_CHAN_BCCH 0x80
+#define RSL_CHAN_RACH 0x88
+#define RSL_CHAN_PCH_AGCH 0x90
+
+/* Chapter 9.3.3 */
+#define RSL_ACT_TYPE_INITIAL 0x00
+#define RSL_ACT_TYPE_REACT 0x80
+#define RSL_ACT_INTRA_IMM_ASS 0x00
+#define RSL_ACT_INTRA_NORM_ASS 0x01
+#define RSL_ACT_INTER_ASYNC 0x02
+#define RSL_ACT_INTER_SYNC 0x03
+#define RSL_ACT_SECOND_ADD 0x04
+#define RSL_ACT_SECOND_MULTI 0x05
+
+/* Chapter 9.3.6 */
+struct rsl_ie_chan_mode {
+ u_int8_t dtx_dtu;
+ u_int8_t spd_ind;
+ u_int8_t chan_rt;
+ u_int8_t chan_rate;
+} __attribute__ ((packed));
+#define RSL_CMOD_DTXu 0x01 /* uplink */
+#define RSL_CMOD_DTXd 0x02 /* downlink */
+#define RSL_CMOD_SPD_SPEECH 0x01
+#define RSL_CMOD_SPD_DATA 0x02
+#define RSL_CMOD_SPD_SIGN 0x03
+#define RSL_CMOD_CRT_SDCCH 0x01
+#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */
+#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */
+/* FIXME: More CRT types */
+#define RSL_CMOD_SP_GSM1 0x01
+#define RSL_CMOD_SP_GSM2 0x11
+#define RSL_CMOD_SP_GSM3 0x21
+
+/* Chapter 9.3.5 */
+struct rsl_ie_chan_ident {
+ /* GSM 04.08 10.5.2.5 */
+ struct {
+ u_int8_t iei;
+ u_int8_t chan_nr; /* enc_chan_nr */
+ u_int8_t oct3;
+ u_int8_t oct4;
+ } chan_desc;
+#if 0 /* spec says we need this but Abissim doesn't use it */
+ struct {
+ u_int8_t tag;
+ u_int8_t len;
+ } mobile_alloc;
+#endif
+} __attribute__ ((packed));
+
+/* Chapter 9.3.22 */
+#define RLL_CAUSE_T200_EXPIRED 0x01
+#define RLL_CAUSE_REEST_REQ 0x02
+#define RLL_CAUSE_UNSOL_UA_RESP 0x03
+#define RLL_CAUSE_UNSOL_DM_RESP 0x04
+#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05
+#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06
+#define RLL_CAUSE_SEQ_ERR 0x07
+#define RLL_CAUSE_UFRM_INC_PARAM 0x08
+#define RLL_CAUSE_SFRM_INC_PARAM 0x09
+#define RLL_CAUSE_IFRM_INC_MBITS 0x0a
+#define RLL_CAUSE_IFRM_INC_LEN 0x0b
+#define RLL_CAUSE_FRM_UNIMPL 0x0c
+#define RLL_CAUSE_SABM_MF 0x0d
+#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e
+
+/* Chapter 9.3.26 */
+#define RSL_ERRCLS_NORMAL 0x00
+#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20
+#define RSL_ERRCLS_SERVICE_UNAVAIL 0x30
+#define RSL_ERRCLS_SERVICE_UNIMPL 0x40
+#define RSL_ERRCLS_INVAL_MSG 0x50
+#define RSL_ERRCLS_PROTO_ERROR 0x60
+#define RSL_ERRCLS_INTERWORKING 0x70
+
+#define RSL_ERR_RADIO_IF_FAIL 0x00
+#define RSL_ERR_RADIO_LINK_FAIL 0x01
+#define RSL_ERR_HANDOVER_ACC_FAIL 0x02
+#define RSL_ERR_TALKER_ACC_FAIL 0x03
+#define RSL_ERR_OM_INTERVENTION 0x07
+#define RSL_ERR_EQUIPMENT_FAIL 0x20
+#define RSL_ERR_RR_UNAVAIL 0x21
+#define RSL_ERR_TERR_CH_FAIL 0x22
+#define RSL_ERR_CCCH_OVERLOAD 0x23
+#define RSL_ERR_ACCH_OVERLOAD 0x24
+#define RSL_ERR_PROCESSOR_OVERLOAD 0x25
+#define RSL_ERR_RES_UNAVAIL 0x2f
+#define RSL_ERR_TRANSC_UNAVAIL 0x30
+#define RSL_ERR_SERV_OPT_UNAVAIL 0x3f
+#define RSL_ERR_ENCR_UNIMPL 0x40
+#define RSL_ERR_SEV_OPT_UNIMPL 0x4f
+#define RSL_ERR_RCH_ALR_ACTV_ALLOC 0x50
+#define RSL_ERR_INVALID_MESSAGE 0x5f
+#define RSL_ERR_MSG_DISCR 0x60
+#define RSL_ERR_MSG_TYPE 0x61
+#define RSL_ERR_MSG_SEQA 0x62
+#define RSL_ERR_IE_ERROR 0x63
+#define RSL_ERR_MAND_IE_ERROR 0x64
+#define RSL_ERR_OPT_IE_ERROR 0x65
+#define RSL_ERR_IE_NONEXIST 0x66
+#define RSL_ERR_IE_LENGTH 0x67
+#define RSL_ERR_IE_CONTENT 0x68
+#define RSL_ERR_PROTO 0x6f
+#define RSL_ERR_INTERWORKING 0x7f
+
+/* Chapter 9.3.30 */
+#define RSL_SYSTEM_INFO_8 0x00
+#define RSL_SYSTEM_INFO_1 0x01
+#define RSL_SYSTEM_INFO_2 0x02
+#define RSL_SYSTEM_INFO_3 0x03
+#define RSL_SYSTEM_INFO_4 0x04
+#define RSL_SYSTEM_INFO_5 0x05
+#define RSL_SYSTEM_INFO_6 0x06
+#define RSL_SYSTEM_INFO_7 0x07
+#define RSL_SYSTEM_INFO_16 0x08
+#define RSL_SYSTEM_INFO_17 0x09
+#define RSL_SYSTEM_INFO_2bis 0x0a
+#define RSL_SYSTEM_INFO_2ter 0x0b
+#define RSL_SYSTEM_INFO_5bis 0x0d
+#define RSL_SYSTEM_INFO_5ter 0x0e
+#define RSL_SYSTEM_INFO_10 0x0f
+#define REL_EXT_MEAS_ORDER 0x47
+#define RSL_MEAS_INFO 0x48
+#define RSL_SYSTEM_INFO_13 0x28
+#define RSL_SYSTEM_INFO_2quater 0x29
+#define RSL_SYSTEM_INFO_9 0x2a
+#define RSL_SYSTEM_INFO_18 0x2b
+#define RSL_SYSTEM_INFO_19 0x2c
+#define RSL_SYSTEM_INFO_20 0x2d
+
+/* Chapter 9.3.40 */
+#define RSL_CHANNEED_ANY 0x00
+#define RSL_CHANNEED_SDCCH 0x01
+#define RSL_CHANNEED_TCH_F 0x02
+#define RSL_CHANNEED_TCH_ForH 0x03
+
+/* Chapter 3.3.2.3 Brocast control channel */
+/* CCCH-CONF, NC is not combined */
+#define RSL_BCCH_CCCH_CONF_1_NC 0x00
+#define RSL_BCCH_CCCH_CONF_1_C 0x01
+#define RSL_BCCH_CCCH_CONF_2_NC 0x02
+#define RSL_BCCH_CCCH_CONF_3_NC 0x04
+#define RSL_BCCH_CCCH_CONF_4_NC 0x06
+
+/* BS-PA-MFRMS */
+#define RSL_BS_PA_MFRMS_2 0x00
+#define RSL_BS_PA_MFRMS_3 0x01
+#define RSL_BS_PA_MFRMS_4 0x02
+#define RSL_BS_PA_MFRMS_5 0x03
+#define RSL_BS_PA_MFRMS_6 0x04
+#define RSL_BS_PA_MFRMS_7 0x05
+#define RSL_BS_PA_MFRMS_8 0x06
+#define RSL_BS_PA_MFRMS_9 0x07
+
+
+#include "msgb.h"
+
+int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
+ const u_int8_t *data, int len);
+int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type,
+ const u_int8_t *data, int len);
+int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
+ u_int8_t act_type,
+ struct rsl_ie_chan_mode *chan_mode,
+ struct rsl_ie_chan_ident *chan_ident,
+ u_int8_t bs_power, u_int8_t ms_power,
+ u_int8_t ta);
+int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
+ u_int8_t ta, u_int8_t mode);
+int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
+int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
+ u_int8_t *ms_ident, u_int8_t chan_needed);
+int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_needed,
+ struct gsm_subscriber *subscr);
+int rsl_imm_assign_cmd(struct gsm_bts *bts, u_int8_t len, u_int8_t *val);
+
+int rsl_data_request(struct msgb *msg, u_int8_t link_id);
+
+/* ip.access specfic RSL extensions */
+int rsl_ipacc_bind(struct gsm_lchan *lchan);
+int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip,
+ u_int16_t port, u_int16_t f8, u_int8_t fc);
+
+int abis_rsl_rcvmsg(struct msgb *msg);
+
+unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
+ int n_pag_blocks);
+unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res);
+u_int64_t str_to_imsi(const char *imsi_str);
+u_int8_t lchan2chan_nr(struct gsm_lchan *lchan);
+
+/* to be provided by external code */
+int abis_rsl_sendmsg(struct msgb *msg);
+int rsl_chan_release(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_number_of_paging_subchannels(struct gsm_bts *bts);
+
+#endif /* RSL_MT_H */
+
diff --git a/openbsc/include/openbsc/call_handling.h b/openbsc/include/openbsc/call_handling.h
new file mode 100644
index 000000000..02027889e
--- /dev/null
+++ b/openbsc/include/openbsc/call_handling.h
@@ -0,0 +1,64 @@
+/*
+ * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2008 by Stefan Schmidt <stefan@datenfreihafen.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _CALL_HANDLING_H
+#define _CALL_HANDLING_H
+
+#include "linuxlist.h"
+#include "gsm_subscriber.h"
+#include "timer.h"
+
+/*
+ * State transitions to be seen from the outside
+ */
+#define CALL_STATE_NULL 0
+#define CALL_STATE_SETUP 1
+#define CALL_STATE_PROCEED 2
+#define CALL_STATE_ALERT 3
+#define CALL_STATE_CONNECT 4
+#define CALL_STATE_ACTIVE 5
+#define CALL_STATE_RELEASE 6
+
+struct call_data {
+ struct llist_head entry;
+ void (*state_change_cb)(int oldstate, int newstate, int event, void *data);
+ void *data;
+ char *destination_number;
+
+ /* Internal */
+ int state;
+ char tmsi[GSM_TMSI_LENGTH];
+ struct timer_list t30x; /* to be added for... */
+};
+
+
+int call_initiate(struct call_data *call, char *tmsi);
+void call_abort(struct call_data *call);
+
+/**
+ * Get notified about new incoming calls. The call_data is owned
+ * and managed by the internal call handling.
+ */
+void call_set_callback(void (*cb)(struct call_data *call, void *data), void* data);
+void call_proceed(struct call_data *call_data);
+void call_connect(struct call_data *call_data);
+
+#endif /* _CALL_HANDLING_H */
diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h
new file mode 100644
index 000000000..d6d367c84
--- /dev/null
+++ b/openbsc/include/openbsc/chan_alloc.h
@@ -0,0 +1,49 @@
+/* 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _CHAN_ALLOC_H
+#define _CHAN_ALLOC_H
+
+#include "gsm_subscriber.h"
+
+/* Special allocator for C0 of BTS */
+struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
+ enum gsm_phys_chan_config pchan);
+
+/* Regular physical channel allocator */
+struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
+ enum gsm_phys_chan_config pchan);
+
+/* Regular physical channel (TS) */
+void ts_free(struct gsm_bts_trx_ts *ts);
+
+/* Find an allocated channel */
+struct gsm_lchan *lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr);
+
+/* Allocate a logical channel (SDCCH, TCH, ...) */
+struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
+
+/* Free a logical channel (SDCCH, TCH, ...) */
+void lchan_free(struct gsm_lchan *lchan);
+
+/* Consider releasing the channel */
+int lchan_auto_release(struct gsm_lchan *lchan);
+
+#endif /* _CHAN_ALLOC_H */
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h
new file mode 100644
index 000000000..61a3ac47c
--- /dev/null
+++ b/openbsc/include/openbsc/db.h
@@ -0,0 +1,44 @@
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _DB_H
+#define _DB_H
+
+#include <sys/types.h>
+
+#include <openbsc/gsm_subscriber.h>
+
+/* one time initialisation */
+int db_init(const char *name);
+int db_prepare();
+int db_fini();
+
+/* subscriber management */
+struct gsm_subscriber* db_create_subscriber(char *imsi);
+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_alloc_tmsi(struct gsm_subscriber* subscriber);
+int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char *imei);
+
+/* SMS store-and-forward */
+int db_sms_store(struct gsm_sms *sms);
+struct gsm_sms *db_sms_get_unsent(int min_id);
+int db_sms_mark_sent(struct gsm_sms *sms);
+#endif /* _DB_H */
diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h
new file mode 100644
index 000000000..63f9e671c
--- /dev/null
+++ b/openbsc/include/openbsc/debug.h
@@ -0,0 +1,39 @@
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#define DEBUG
+
+#define DRLL 0x0001
+#define DCC 0x0002
+#define DMM 0x0004
+#define DRR 0x0008
+#define DRSL 0x0010
+#define DNM 0x0020
+
+#define DMNCC 0x0080
+#define DSMS 0x0100
+#define DPAG 0x0200
+
+#define DMI 0x1000
+#define DMIB 0x2000
+#define DMUX 0x4000
+#define DINP 0x8000
+
+#ifdef DEBUG
+#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args)
+#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args)
+#else
+#define DEBUGP(xss, fmt, args...)
+#define DEBUGPC(ss, fmt, args...)
+#endif
+
+#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
+
+char *hexdump(unsigned char *buf, int len);
+void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...);
+void debug_parse_category_mask(const char* mask);
+void debug_use_color(int use_color);
+void debug_timestamp(int enable);
+extern unsigned int debug_mask;
+
+#endif /* _DEBUG_H */
diff --git a/openbsc/include/openbsc/e1_input.h b/openbsc/include/openbsc/e1_input.h
new file mode 100644
index 000000000..132672364
--- /dev/null
+++ b/openbsc/include/openbsc/e1_input.h
@@ -0,0 +1,159 @@
+#ifndef _E1_INPUT_H
+#define _E1_INPUT_H
+
+#include <stdlib.h>
+#include <netinet/in.h>
+
+#include <openbsc/linuxlist.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/msgb.h>
+#include <openbsc/select.h>
+#include <openbsc/subchan_demux.h>
+
+#define NUM_E1_TS 32
+
+enum e1inp_sign_type {
+ E1INP_SIGN_NONE,
+ E1INP_SIGN_OML,
+ E1INP_SIGN_RSL,
+};
+const char *e1inp_signtype_name(enum e1inp_sign_type tp);
+
+struct e1inp_ts;
+
+struct e1inp_sign_link {
+ /* list of signalling links */
+ struct llist_head list;
+
+ /* to which timeslot do we belong? */
+ struct e1inp_ts *ts;
+
+ enum e1inp_sign_type type;
+
+ /* trx for msg->trx of received msgs */
+ struct gsm_bts_trx *trx;
+
+ /* msgb queue of to-be-transmitted msgs */
+ struct llist_head tx_list;
+
+ /* SAPI and TEI on the E1 TS */
+ u_int8_t sapi;
+ u_int8_t tei;
+
+ union {
+ struct {
+ u_int8_t channel;
+ } misdn;
+ } driver;
+};
+
+enum e1inp_ts_type {
+ E1INP_TS_TYPE_NONE,
+ E1INP_TS_TYPE_SIGN,
+ E1INP_TS_TYPE_TRAU,
+};
+const char *e1inp_tstype_name(enum e1inp_ts_type tp);
+
+/* A timeslot in the E1 interface */
+struct e1inp_ts {
+ enum e1inp_ts_type type;
+ int num;
+
+ /* to which line do we belong ? */
+ struct e1inp_line *line;
+
+ union {
+ struct {
+ /* list of all signalling links on this TS */
+ struct llist_head sign_links;
+ /* timer when to dequeue next frame */
+ struct timer_list tx_timer;
+ } sign;
+ struct {
+ /* subchannel demuxer for frames from E1 */
+ struct subch_demux demux;
+ /* subchannel muxer for frames to E1 */
+ struct subch_mux mux;
+ } trau;
+ };
+ union {
+ struct {
+ /* mISDN driver has one fd for each ts */
+ struct bsc_fd fd;
+ } misdn;
+ struct {
+ /* ip.access driver has one fd for each ts */
+ struct bsc_fd fd;
+ } ipaccess;
+
+ } driver;
+};
+
+struct e1inp_driver {
+ struct llist_head list;
+ const char *name;
+ int (*want_write)(struct e1inp_ts *ts);
+};
+
+struct e1inp_line {
+ struct llist_head list;
+ unsigned int num;
+ const char *name;
+
+ /* array of timestlots */
+ struct e1inp_ts ts[NUM_E1_TS];
+
+ struct e1inp_driver *driver;
+ void *driver_data;
+};
+
+/* register a driver with the E1 core */
+int e1inp_driver_register(struct e1inp_driver *drv);
+
+/* register a line with the E1 core */
+int e1inp_line_register(struct e1inp_line *line);
+
+/* find a sign_link for given TEI and SAPI in a TS */
+struct e1inp_sign_link *
+e1inp_lookup_sign_link(struct e1inp_ts *ts, u_int8_t tei,
+ u_int8_t sapi);
+
+/* create a new signalling link in a E1 timeslot */
+struct e1inp_sign_link *
+e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
+ struct gsm_bts_trx *trx, u_int8_t tei,
+ u_int8_t sapi);
+
+/* configure and initialize one e1inp_ts */
+int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
+ enum e1inp_ts_type type);
+
+/* Call from the Stack: configuration of this TS has changed */
+int e1inp_update_ts(struct e1inp_ts *ts);
+
+/* Receive a packet from the E1 driver */
+int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg,
+ u_int8_t tei, u_int8_t sapi);
+
+/* called by driver if it wants to transmit on a given TS */
+struct msgb *e1inp_tx_ts(struct e1inp_ts *e1i_ts,
+ struct e1inp_sign_link **sign_link);
+
+/* called by driver in case some kind of link state event */
+int e1inp_event(struct e1inp_ts *ts, int evt, u_int8_t tei, u_int8_t sapi);
+
+/* Write LAPD frames to the fd. */
+void e1_set_pcap_fd(int fd);
+
+/* called by TRAU muxer to obtain the destination mux entity */
+struct subch_mux *e1inp_get_mux(u_int8_t e1_nr, u_int8_t ts_nr);
+
+/* e1_config.c */
+int e1_config(struct gsm_bts *bts, int cardnr, int release_l2);
+int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin);
+int ipaccess_setup(struct gsm_network *gsmnet);
+
+extern struct llist_head e1inp_driver_list;
+extern struct llist_head e1inp_line_list;
+
+#endif /* _E1_INPUT_H */
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
new file mode 100644
index 000000000..fe18f4ee5
--- /dev/null
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -0,0 +1,568 @@
+#ifndef _GSM_04_08_H
+#define _GSM_04_08_H
+
+/* GSM TS 04.08 definitions */
+struct gsm_lchan;
+
+struct gsm48_classmark1 {
+ u_int8_t spare:1,
+ rev_level:2,
+ es_ind:1,
+ a5_1:1,
+ pwr_lev:3;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.5 */
+struct gsm48_chan_desc {
+ u_int8_t chan_nr;
+ union {
+ struct {
+ u_int8_t maio_high:4,
+ h:1,
+ tsc:3;
+ u_int8_t hsn:6,
+ maio_low:2;
+ } h1;
+ struct {
+ u_int8_t arfcn_high:2,
+ spare:2,
+ h:1,
+ tsc:3;
+ u_int8_t arfcn_low;
+ } h0;
+ };
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.30 */
+struct gsm48_req_ref {
+ u_int8_t ra;
+ u_int8_t t3_high:3,
+ t1_:5;
+ u_int8_t t2:5,
+ t3_low:3;
+} __attribute__ ((packed));
+
+/* Chapter 9.1.5 */
+struct gsm48_chan_mode_modify {
+ struct gsm48_chan_desc chan_desc;
+ u_int8_t mode;
+} __attribute__ ((packed));
+
+#define GSM48_CMODE_SIGN 0x00
+#define GSM48_CMODE_SPEECH_V1 0x01
+#define GSM48_CMODE_SPEECH_EFR 0x21
+#define GSM48_CMODE_SPEECH_AMR 0x41
+#define GSM48_CMODE_DATA_14k5 0x0f
+#define GSM48_CMODE_DATA_12k0 0x03
+#define GSM48_CMODE_DATA_6k0 0x0b
+#define GSM48_CMODE_DATA_3k6 0x23
+
+/* Chapter 9.1.18 */
+struct gsm48_imm_ass {
+ u_int8_t l2_plen;
+ u_int8_t proto_discr;
+ u_int8_t msg_type;
+ u_int8_t page_mode;
+ struct gsm48_chan_desc chan_desc;
+ struct gsm48_req_ref req_ref;
+ u_int8_t timing_advance;
+ u_int8_t mob_alloc_len;
+ u_int8_t mob_alloc[0];
+} __attribute__ ((packed));
+
+/* Chapter 10.5.1.3 */
+struct gsm48_loc_area_id {
+ u_int8_t digits[3]; /* BCD! */
+ u_int16_t lac;
+} __attribute__ ((packed));
+
+/* Section 9.2.15 */
+struct gsm48_loc_upd_req {
+ u_int8_t type:4,
+ key_seq:4;
+ struct gsm48_loc_area_id lai;
+ struct gsm48_classmark1 classmark1;
+ u_int8_t mi_len;
+ u_int8_t mi[0];
+} __attribute__ ((packed));
+
+/* Section 10.1 */
+struct gsm48_hdr {
+ u_int8_t proto_discr;
+ u_int8_t msg_type;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Section 9.1.3x System information Type header */
+struct gsm48_system_information_type_header {
+ u_int8_t l2_plen;
+ u_int8_t rr_protocol_discriminator :4,
+ skip_indicator:4;
+ u_int8_t system_information;
+} __attribute__ ((packed));
+
+struct gsm48_rach_control {
+ u_int8_t re :1,
+ cell_bar :1,
+ tx_integer :4,
+ max_trans :2;
+ u_int8_t t2;
+ u_int8_t t3;
+} __attribute__ ((packed));
+
+/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */
+struct gsm48_control_channel_descr {
+ u_int8_t ccch_conf :3,
+ bs_ag_blks_res :3,
+ att :1,
+ spare1 :1;
+ u_int8_t bs_pa_mfrms : 3,
+ spare2 :5;
+ u_int8_t t3212;
+} __attribute__ ((packed));
+
+/* Section 9.2.9 CM service request */
+struct gsm48_service_request {
+ u_int8_t cm_service_type : 4,
+ cipher_key_seq : 4;
+ /* length + 3 bytes */
+ u_int32_t classmark;
+ u_int8_t mi_len;
+ u_int8_t mi[0];
+ /* optional priority level */
+} __attribute__ ((packed));
+
+/* Section 9.1.31 System information Type 1 */
+struct gsm48_system_information_type_1 {
+ struct gsm48_system_information_type_header header;
+ u_int8_t cell_channel_description[16];
+ struct gsm48_rach_control rach_control;
+ u_int8_t s1_reset;
+} __attribute__ ((packed));
+
+/* Section 9.1.32 System information Type 2 */
+struct gsm48_system_information_type_2 {
+ struct gsm48_system_information_type_header header;
+ u_int8_t bcch_frequency_list[16];
+ u_int8_t ncc_permitted;
+ struct gsm48_rach_control rach_control;
+} __attribute__ ((packed));
+
+/* Section 9.1.35 System information Type 3 */
+struct gsm48_system_information_type_3 {
+ struct gsm48_system_information_type_header header;
+ u_int16_t cell_identity;
+ struct gsm48_loc_area_id lai;
+ struct gsm48_control_channel_descr control_channel_desc;
+ u_int8_t cell_options;
+ u_int8_t cell_selection[2];
+ struct gsm48_rach_control rach_control;
+ u_int8_t s3_reset_octets[4];
+} __attribute__ ((packed));
+
+/* Section 9.1.36 System information Type 4 */
+struct gsm48_system_information_type_4 {
+ struct gsm48_system_information_type_header header;
+ struct gsm48_loc_area_id lai;
+ u_int8_t cell_selection[2];
+ struct gsm48_rach_control rach_control;
+ /* optional CBCH conditional CBCH... followed by
+ mandantory SI 4 Reset Octets
+ */
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* Section 9.1.37 System information Type 5 */
+struct gsm48_system_information_type_5 {
+ u_int8_t rr_protocol_discriminator :4,
+ skip_indicator:4;
+ u_int8_t system_information;
+ u_int8_t bcch_frequency_list[16];
+} __attribute__ ((packed));
+
+/* Section 9.1.40 System information Type 6 */
+struct gsm48_system_information_type_6 {
+ u_int8_t rr_protocol_discriminator :4,
+ skip_indicator:4;
+ u_int8_t system_information;
+ u_int8_t cell_identity[2];
+ struct gsm48_loc_area_id lai;
+ u_int8_t cell_options;
+ u_int8_t ncc_permitted;
+ u_int8_t si_6_reset[0];
+} __attribute__ ((packed));
+
+/* Section 9.2.12 IMSI Detach Indication */
+struct gsm48_imsi_detach_ind {
+ struct gsm48_classmark1 classmark1;
+ u_int8_t mi_len;
+ u_int8_t mi[0];
+} __attribute__ ((packed));
+
+/* Section 10.2 + GSM 04.07 12.2.3.1.1 */
+#define GSM48_PDISC_GROUP_CC 0x00
+#define GSM48_PDISC_BCAST_CC 0x01
+#define GSM48_PDISC_PDSS1 0x02
+#define GSM48_PDISC_CC 0x03
+#define GSM48_PDISC_PDSS2 0x04
+#define GSM48_PDISC_MM 0x05
+#define GSM48_PDISC_RR 0x06
+#define GSM48_PDISC_MM_GPRS 0x08
+#define GSM48_PDISC_SMS 0x09
+#define GSM48_PDISC_SM_GPRS 0x0a
+#define GSM48_PDISC_NC_SS 0x0b
+#define GSM48_PDISC_LOC 0x0c
+#define GSM48_PDISC_MASK 0x0f
+#define GSM48_PDISC_USSD 0x11
+
+/* Section 10.4 */
+#define GSM48_MT_RR_INIT_REQ 0x3c
+#define GSM48_MT_RR_ADD_ASS 0x3b
+#define GSM48_MT_RR_IMM_ASS 0x3f
+#define GSM48_MT_RR_IMM_ASS_EXT 0x39
+#define GSM48_MT_RR_IMM_ASS_REJ 0x3a
+
+#define GSM48_MT_RR_CIPH_M_CMD 0x35
+#define GSM48_MT_RR_CIPH_M_COMPL 0x32
+
+#define GSM48_MT_RR_CFG_CHG_CMD 0x30
+#define GSM48_MT_RR_CFG_CHG_ACK 0x31
+#define GSM48_MT_RR_CFG_CHG_REJ 0x33
+
+#define GSM48_MT_RR_ASS_CMD 0x2e
+#define GSM48_MT_RR_ASS_COMPL 0x29
+#define GSM48_MT_RR_ASS_FAIL 0x2f
+#define GSM48_MT_RR_HANDO_CMD 0x2b
+#define GSM48_MT_RR_HANDO_COMPL 0x2c
+#define GSM48_MT_RR_HANDO_FAIL 0x28
+#define GSM48_MT_RR_HANDO_INFO 0x2d
+
+#define GSM48_MT_RR_CELL_CHG_ORDER 0x08
+#define GSM48_MT_RR_PDCH_ASS_CMD 0x23
+
+#define GSM48_MT_RR_CHAN_REL 0x0d
+#define GSM48_MT_RR_PART_REL 0x0a
+#define GSM48_MT_RR_PART_REL_COMP 0x0f
+
+#define GSM48_MT_RR_PAG_REQ_1 0x21
+#define GSM48_MT_RR_PAG_REQ_2 0x22
+#define GSM48_MT_RR_PAG_REQ_3 0x24
+#define GSM48_MT_RR_PAG_RESP 0x27
+#define GSM48_MT_RR_NOTIF_NCH 0x20
+#define GSM48_MT_RR_NOTIF_FACCH 0x25
+#define GSM48_MT_RR_NOTIF_RESP 0x26
+
+#define GSM48_MT_RR_SYSINFO_8 0x18
+#define GSM48_MT_RR_SYSINFO_1 0x19
+#define GSM48_MT_RR_SYSINFO_2 0x1a
+#define GSM48_MT_RR_SYSINFO_3 0x1b
+#define GSM48_MT_RR_SYSINFO_4 0x1c
+#define GSM48_MT_RR_SYSINFO_5 0x1d
+#define GSM48_MT_RR_SYSINFO_6 0x1e
+#define GSM48_MT_RR_SYSINFO_7 0x1f
+
+#define GSM48_MT_RR_SYSINFO_2bis 0x02
+#define GSM48_MT_RR_SYSINFO_2ter 0x03
+#define GSM48_MT_RR_SYSINFO_5bis 0x05
+#define GSM48_MT_RR_SYSINFO_5ter 0x06
+#define GSM48_MT_RR_SYSINFO_9 0x04
+#define GSM48_MT_RR_SYSINFO_13 0x00
+
+#define GSM48_MT_RR_SYSINFO_16 0x3d
+#define GSM48_MT_RR_SYSINFO_17 0x3e
+
+#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10
+#define GSM48_MT_RR_STATUS 0x12
+#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17
+#define GSM48_MT_RR_FREQ_REDEF 0x14
+#define GSM48_MT_RR_MEAS_REP 0x15
+#define GSM48_MT_RR_CLSM_CHG 0x16
+#define GSM48_MT_RR_CLSM_ENQ 0x13
+#define GSM48_MT_RR_EXT_MEAS_REP 0x36
+#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37
+#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34
+
+#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08
+#define GSM48_MT_RR_UPLINK_RELEASE 0x0e
+#define GSM48_MT_RR_UPLINK_FREE 0x0c
+#define GSM48_MT_RR_UPLINK_BUSY 0x2a
+#define GSM48_MT_RR_TALKER_IND 0x11
+
+#define GSM48_MT_RR_APP_INFO 0x38
+
+/* Table 10.2/3GPP TS 04.08 */
+#define GSM48_MT_MM_IMSI_DETACH_IND 0x01
+#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02
+#define GSM48_MT_MM_LOC_UPD_REJECT 0x04
+#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08
+
+#define GSM48_MT_MM_AUTH_REJ 0x11
+#define GSM48_MT_MM_AUTH_REQ 0x12
+#define GSM48_MT_MM_AUTH_RESP 0x14
+#define GSM48_MT_MM_ID_REQ 0x18
+#define GSM48_MT_MM_ID_RESP 0x19
+#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a
+#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b
+
+#define GSM48_MT_MM_CM_SERV_ACC 0x21
+#define GSM48_MT_MM_CM_SERV_REJ 0x22
+#define GSM48_MT_MM_CM_SERV_ABORT 0x23
+#define GSM48_MT_MM_CM_SERV_REQ 0x24
+#define GSM48_MT_MM_CM_SERV_PROMPT 0x25
+#define GSM48_MT_MM_CM_REEST_REQ 0x28
+#define GSM48_MT_MM_ABORT 0x29
+
+#define GSM48_MT_MM_NULL 0x30
+#define GSM48_MT_MM_STATUS 0x31
+#define GSM48_MT_MM_INFO 0x32
+
+/* Table 10.3/3GPP TS 04.08 */
+#define GSM48_MT_CC_ALERTING 0x01
+#define GSM48_MT_CC_CALL_CONF 0x08
+#define GSM48_MT_CC_CALL_PROC 0x02
+#define GSM48_MT_CC_CONNECT 0x07
+#define GSM48_MT_CC_CONNECT_ACK 0x0f
+#define GSM48_MT_CC_EMERG_SETUP 0x0e
+#define GSM48_MT_CC_PROGRESS 0x03
+#define GSM48_MT_CC_ESTAB 0x04
+#define GSM48_MT_CC_ESTAB_CONF 0x06
+#define GSM48_MT_CC_RECALL 0x0b
+#define GSM48_MT_CC_START_CC 0x09
+#define GSM48_MT_CC_SETUP 0x05
+
+#define GSM48_MT_CC_MODIFY 0x17
+#define GSM48_MT_CC_MODIFY_COMPL 0x1f
+#define GSM48_MT_CC_MODIFY_REJECT 0x13
+#define GSM48_MT_CC_USER_INFO 0x10
+#define GSM48_MT_CC_HOLD 0x18
+#define GSM48_MT_CC_HOLD_ACK 0x19
+#define GSM48_MT_CC_HOLD_REJ 0x1a
+#define GSM48_MT_CC_RETR 0x1c
+#define GSM48_MT_CC_RETR_ACK 0x1d
+#define GSM48_MT_CC_RETR_REJ 0x1e
+
+#define GSM48_MT_CC_DISCONNECT 0x25
+#define GSM48_MT_CC_RELEASE 0x2d
+#define GSM48_MT_CC_RELEASE_COMPL 0x2a
+
+#define GSM48_MT_CC_CONG_CTRL 0x39
+#define GSM48_MT_CC_NOTIFY 0x3e
+#define GSM48_MT_CC_STATUS 0x3d
+#define GSM48_MT_CC_STATUS_ENQ 0x34
+#define GSM48_MT_CC_START_DTMF 0x35
+#define GSM48_MT_CC_STOP_DTMF 0x31
+#define GSM48_MT_CC_STOP_DTMF_ACK 0x32
+#define GSM48_MT_CC_START_DTMF_ACK 0x36
+#define GSM48_MT_CC_START_DTMF_REJ 0x37
+#define GSM48_MT_CC_FACILITY 0x3a
+
+/* FIXME: Table 10.4 / 10.4a (GPRS) */
+
+/* Section 10.5.2.26, Table 10.5.64 */
+#define GSM48_PM_MASK 0x03
+#define GSM48_PM_NORMAL 0x00
+#define GSM48_PM_EXTENDED 0x01
+#define GSM48_PM_REORG 0x02
+#define GSM48_PM_SAME 0x03
+
+/* Chapter 10.5.3.5 / Table 10.5.93 */
+#define GSM48_LUPD_NORMAL 0x0
+#define GSM48_LUPD_PERIODIC 0x1
+#define GSM48_LUPD_IMSI_ATT 0x2
+#define GSM48_LUPD_RESERVED 0x3
+
+/* Table 10.5.4 */
+#define GSM_MI_TYPE_MASK 0x07
+#define GSM_MI_TYPE_NONE 0x00
+#define GSM_MI_TYPE_IMSI 0x01
+#define GSM_MI_TYPE_IMEI 0x02
+#define GSM_MI_TYPE_IMEISV 0x03
+#define GSM_MI_TYPE_TMSI 0x04
+#define GSM_MI_ODD 0x08
+
+#define GSM48_IE_MOBILE_ID 0x17
+#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */
+#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */
+#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */
+#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */
+#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */
+
+#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */
+#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */
+#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */
+#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */
+#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */
+#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */
+#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */
+#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */
+#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */
+#define GSM48_IE_CONN_NUM 0x4c /* 10.5.4.13 */
+#define GSM48_IE_CONN_SUBADDR 0x4d /* 10.5.4.14 */
+#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */
+#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */
+#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */
+#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */
+#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */
+#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */
+#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */
+#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */
+#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */
+#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */
+#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */
+#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */
+#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */
+#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */
+
+/* Section 10.5.4.11 / Table 10.5.122 */
+#define GSM48_CAUSE_CS_GSM 0x60
+
+/* Section 9.1.2 / Table 9.3 */
+#define GSM48_IE_FRQLIST_AFTER 0x05
+#define GSM48_IE_CELL_CH_DESC 0x62
+#define GSM48_IE_MSLOT_DESC 0x10
+#define GSM48_IE_CHANMODE_1 0x63
+#define GSM48_IE_CHANMODE_2 0x11
+#define GSM48_IE_CHANMODE_3 0x13
+#define GSM48_IE_CHANMODE_4 0x14
+#define GSM48_IE_CHANMODE_5 0x15
+#define GSM48_IE_CHANMODE_6 0x16
+#define GSM48_IE_CHANMODE_7 0x17
+#define GSM48_IE_CHANMODE_8 0x18
+#define GSM48_IE_CHANDESC_2 0x64
+/* FIXME */
+
+/* Section 10.5.4.23 / Table 10.5.130 */
+enum gsm48_signal_val {
+ GSM48_SIGNAL_DIALTONE = 0x00,
+ GSM48_SIGNAL_RINGBACK = 0x01,
+ GSM48_SIGNAL_INTERCEPT = 0x02,
+ GSM48_SIGNAL_NET_CONG = 0x03,
+ GSM48_SIGNAL_BUSY = 0x04,
+ GSM48_SIGNAL_CONFIRM = 0x05,
+ GSM48_SIGNAL_ANSWER = 0x06,
+ GSM48_SIGNAL_CALL_WAIT = 0x07,
+ GSM48_SIGNAL_OFF_HOOK = 0x08,
+ GSM48_SIGNAL_OFF = 0x3f,
+ GSM48_SIGNAL_ALERT_OFF = 0x4f,
+};
+
+enum gsm48_cause_loc {
+ GSM48_CAUSE_LOC_USER = 0x00,
+ GSM48_CAUSE_LOC_PRN_S_LU = 0x01,
+ GSM48_CAUSE_LOC_PUN_S_LU = 0x02,
+ GSM48_CAUSE_LOC_TRANS_NET = 0x03,
+ GSM48_CAUSE_LOC_PUN_S_RU = 0x04,
+ GSM48_CAUSE_LOC_PRN_S_RU = 0x05,
+ /* not defined */
+ GSM48_CAUSE_LOC_INN_NET = 0x07,
+ GSM48_CAUSE_LOC_NET_BEYOND = 0x0a,
+};
+
+/* Section 10.5.2.31 RR Cause / Table 10.5.70 */
+enum gsm48_rr_cause {
+ GSM48_RR_CAUSE_NORMAL = 0x00,
+ GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01,
+ GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02,
+ GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03,
+ GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04,
+ GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05,
+ GSM48_RR_CAUSE_HNDOVER_IMP = 0x06,
+ GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07,
+ GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08,
+ GSM48_RR_CAUSE_CALL_CLEARED = 0x41,
+ GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f,
+ GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60,
+ GSM48_RR_CAUSE_MSG_TYPE_N = 0x61,
+ GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62,
+ GSM48_RR_CAUSE_COND_IE_ERROR = 0x64,
+ GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65,
+ GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f,
+};
+
+/* Annex G, GSM specific cause values for mobility management */
+enum gsm48_reject_value {
+ GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2,
+ GSM48_REJECT_ILLEGAL_MS = 3,
+ GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4,
+ GSM48_REJECT_IMEI_NOT_ACCEPTED = 5,
+ GSM48_REJECT_ILLEGAL_ME = 6,
+ GSM48_REJECT_PLMN_NOT_ALLOWED = 11,
+ GSM48_REJECT_LOC_NOT_ALLOWED = 12,
+ GSM48_REJECT_ROAMING_NOT_ALLOWED = 13,
+ GSM48_REJECT_NETWORK_FAILURE = 17,
+ GSM48_REJECT_CONGESTION = 22,
+ GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32,
+ GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33,
+ GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34,
+ GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38,
+ GSM48_REJECT_INCORRECT_MESSAGE = 95,
+ GSM48_REJECT_INVALID_MANDANTORY_INF = 96,
+ GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97,
+ GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98,
+ GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99,
+ GSM48_REJECT_CONDTIONAL_IE_ERROR = 100,
+ GSM48_REJECT_MSG_NOT_COMPATIBLE = 101,
+ GSM48_REJECT_PROTOCOL_ERROR = 111,
+
+ /* according to G.6 Additional cause codes for GMM */
+ GSM48_REJECT_GPRS_NOT_ALLOWED = 7,
+ GSM48_REJECT_SERVICES_NOT_ALLOWED = 8,
+ GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9,
+ GSM48_REJECT_IMPLICITLY_DETACHED = 10,
+ GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14,
+ GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16,
+};
+
+
+/* extracted from a L3 measurement report IE */
+struct gsm_meas_rep_cell {
+ u_int8_t rxlev;
+ u_int8_t bcch_freq; /* fixme: translate to ARFCN */
+ u_int8_t bsic;
+};
+
+struct gsm_meas_rep {
+ unsigned int flags;
+ u_int8_t rxlev_full;
+ u_int8_t rxqual_full;
+ u_int8_t rxlev_sub;
+ u_int8_t rxqual_sub;
+ int num_cell;
+ struct gsm_meas_rep_cell cell[6];
+};
+#define MEAS_REP_F_DTX 0x01
+#define MEAS_REP_F_VALID 0x02
+#define MEAS_REP_F_BA1 0x04
+
+void gsm48_parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
+ int len);
+
+
+struct msgb;
+struct gsm_bts;
+struct gsm_subscriber;
+
+/* config options controlling the behaviour of the lower leves */
+void gsm0408_allow_everyone(int allow);
+void gsm0408_set_reject_cause(int cause);
+
+int gsm0408_rcvmsg(struct msgb *msg);
+void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
+ u_int16_t mnc, u_int16_t lac);
+int gsm48_cc_tx_setup(struct gsm_lchan *lchan, struct gsm_subscriber *calling);
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra);
+enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra);
+
+int gsm48_tx_mm_info(struct gsm_lchan *lchan);
+struct msgb *gsm48_msgb_alloc(void);
+int gsm48_sendmsg(struct msgb *msg);
+int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi);
+
+int gsm48_send_rr_release(struct gsm_lchan *lchan);
+
+/* convert a ASCII phone number to call-control BCD */
+int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
+ u_int8_t type, const char *input);
+u_int8_t decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv);
+
+#endif
diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h
new file mode 100644
index 000000000..12c607f54
--- /dev/null
+++ b/openbsc/include/openbsc/gsm_04_11.h
@@ -0,0 +1,172 @@
+#ifndef _GSM_04_11_H
+#define _GSM_04_11_H
+
+/* GSM TS 04.11 definitions */
+
+/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */
+#define GSM411_PDISC_SMS 0x09
+
+/* Chapter 8.1.3 */
+#define GSM411_MT_CP_DATA 0x01
+#define GSM411_MT_CP_ACK 0x04
+#define GSM411_MT_CP_ERROR 0x10
+
+enum gsm411_cp_ie {
+ GSM411_CP_IE_USER_DATA = 0x01, /* 8.1.4.1 */
+ GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */
+};
+
+/* Chapter 8.2.2 */
+#define GSM411_MT_RP_DATA_MO 0x00
+#define GSM411_MT_RP_DATA_MT 0x01
+#define GSM411_MT_RP_ACK_MO 0x02
+#define GSM411_MT_RP_ACK_MT 0x03
+#define GSM411_MT_RP_ERROR_MO 0x04
+#define GSM411_MT_RP_ERROR_MT 0x04
+#define GSM411_MT_RP_SMMA_MO 0x05
+
+enum gsm411_rp_ie {
+ GSM411_IE_RP_USER_DATA = 0x41, /* 8.2.5.3 */
+ GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */
+};
+
+/* Chapter 8.2.1 */
+struct gsm411_rp_hdr {
+ u_int8_t len;
+ u_int8_t msg_type;
+ u_int8_t msg_ref;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+/* our own enum, not related to on-air protocol */
+enum sms_alphabet {
+ DCS_NONE,
+ DCS_7BIT_DEFAULT,
+ DCS_UCS2,
+ DCS_8BIT_DATA,
+};
+
+/* SMS submit PDU */
+struct sms_submit {
+ u_int8_t *smsc;
+ u_int8_t mti:2;
+ u_int8_t vpf:2;
+ u_int8_t msg_ref;
+ u_int8_t pid;
+ u_int8_t dcs;
+ u_int8_t *vp;
+ u_int8_t ud_len;
+ u_int8_t *user_data;
+
+ /* interpreted */
+ u_int8_t mms:1;
+ u_int8_t sri:1;
+ u_int8_t udhi:1;
+ u_int8_t rp:1;
+ enum sms_alphabet alphabet;
+ char dest_addr[20+1]; /* DA LV is 12 bytes max, i.e. 10 bytes BCD == 20 bytes string */
+ unsigned long validity_mins;
+ char decoded[256];
+};
+
+/* GSM 03.40 / Chapter 9.2.3.1: TP-Message-Type-Indicator */
+#define GSM340_SMS_DELIVER_SC2MS 0x00
+#define GSM340_SMS_DELIVER_REP_MS2SC 0x00
+#define GSM340_SMS_STATUS_REP_SC2MS 0x02
+#define GSM340_SMS_COMMAND_MS2SC 0x02
+#define GSM340_SMS_SUBMIT_MS2SC 0x01
+#define GSM340_SMS_SUBMIT_REP_SC2MS 0x01
+#define GSM340_SMS_RESSERVED 0x03
+
+/* GSM 03.40 / Chapter 9.2.3.2: TP-More-Messages-to-Send */
+#define GSM340_TP_MMS_MORE 0
+#define GSM340_TP_MMS_NO_MORE 1
+
+/* GSM 03.40 / Chapter 9.2.3.3: TP-Validity-Period-Format */
+#define GSM340_TP_VPF_NONE 0
+#define GSM340_TP_VPF_RELATIVE 2
+#define GSM340_TP_VPF_ENHANCED 1
+#define GSM340_TP_VPF_ABSOLUTE 3
+
+/* GSM 03.40 / Chapter 9.2.3.4: TP-Status-Report-Indication */
+#define GSM340_TP_SRI_NONE 0
+#define GSM340_TP_SRI_PRESENT 1
+
+/* GSM 03.40 / Chapter 9.2.3.5: TP-Status-Report-Request */
+#define GSM340_TP_SRR_NONE 0
+#define GSM340_TP_SRR_REQUESTED 1
+
+/* GSM 03.40 / Chapter 9.2.3.9: TP-Protocol-Identifier */
+/* telematic interworking (001 or 111 in bits 7-5) */
+#define GSM340_TP_PID_IMPLICIT 0x00
+#define GSM340_TP_PID_TELEX 0x01
+#define GSM340_TP_PID_FAX_G3 0x02
+#define GSM340_TP_PID_FAX_G4 0x03
+#define GSM340_TP_PID_VOICE 0x04
+#define GSM430_TP_PID_ERMES 0x05
+#define GSM430_TP_PID_NATIONAL_PAGING 0x06
+#define GSM430_TP_PID_VIDEOTEX 0x07
+#define GSM430_TP_PID_TELETEX_UNSPEC 0x08
+#define GSM430_TP_PID_TELETEX_PSPDN 0x09
+#define GSM430_TP_PID_TELETEX_CSPDN 0x0a
+#define GSM430_TP_PID_TELETEX_PSTN 0x0b
+#define GSM430_TP_PID_TELETEX_ISDN 0x0c
+#define GSM430_TP_PID_TELETEX_UCI 0x0d
+#define GSM430_TP_PID_MSG_HANDLING 0x10
+#define GSM430_TP_PID_MSG_X400 0x11
+#define GSM430_TP_PID_EMAIL 0x12
+#define GSM430_TP_PID_GSM_MS 0x1f
+/* if bit 7 = 0 and bit 6 = 1 */
+#define GSM430_TP_PID_SMS_TYPE_0 0
+#define GSM430_TP_PID_SMS_TYPE_1 1
+#define GSM430_TP_PID_SMS_TYPE_2 2
+#define GSM430_TP_PID_SMS_TYPE_3 3
+#define GSM430_TP_PID_SMS_TYPE_4 4
+#define GSM430_TP_PID_SMS_TYPE_5 5
+#define GSM430_TP_PID_SMS_TYPE_6 6
+#define GSM430_TP_PID_SMS_TYPE_7 7
+#define GSM430_TP_PID_RETURN_CALL_MSG 0x1f
+#define GSM430_TP_PID_ME_DATA_DNLOAD 0x3d
+#define GSM430_TP_PID_ME_DE_PERSONAL 0x3e
+#define GSM430_TP_PID_ME_SIM_DNLOAD 0x3f
+
+/* GSM 03.38 Chapter 4: SMS Data Coding Scheme */
+#define GSM338_DCS_00_
+
+#define GSM338_DCS_1110_7BIT (0 << 2)
+#define GSM338_DCS_1111_7BIT (0 << 2)
+#define GSM338_DCS_1111_8BIT_DATA (1 << 2)
+#define GSM338_DCS_1111_CLASS0 0
+#define GSM338_DCS_1111_CLASS1_ME 1
+#define GSM338_DCS_1111_CLASS2_SIM 2
+#define GSM338_DCS_1111_CLASS3_TE 3 /* See TS 07.05 */
+
+
+/* SMS deliver PDU */
+struct sms_deliver {
+ u_int8_t *smsc;
+ u_int8_t mti:2;
+ u_int8_t rd:1;
+ u_int8_t vpf:2;
+ u_int8_t srr:1;
+ u_int8_t udhi:1;
+ u_int8_t rp:1;
+ u_int8_t msg_ref;
+ u_int8_t *orig_addr;
+ u_int8_t pid;
+ u_int8_t dcs;
+ u_int8_t vp;
+ u_int8_t ud_len;
+ u_int8_t *user_data;
+};
+
+struct msgb;
+
+int gsm0411_rcv_sms(struct msgb *msg);
+
+int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms);
+
+struct msgb *gsm411_msgb_alloc(void);
+int gsm0411_sendmsg(struct msgb *msg);
+
+#endif
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
new file mode 100644
index 000000000..e85adf829
--- /dev/null
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -0,0 +1,406 @@
+#ifndef _GSM_DATA_H
+#define _GSM_DATA_H
+
+#include <sys/types.h>
+
+#include <openbsc/timer.h>
+#include <openbsc/gsm_04_08.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define GSM_MAX_BTS 8
+#define BTS_MAX_TRX 8
+#define TRX_NR_TS 8
+#define TS_MAX_LCHAN 8
+
+#define HARDCODED_ARFCN 123
+#define HARDCODED_TSC 7
+#define HARDCODED_BSIC 0x3f /* NCC = 7 / BCC = 7 */
+
+enum gsm_hooks {
+ GSM_HOOK_NM_SWLOAD,
+ GSM_HOOK_RR_PAGING,
+};
+
+enum gsm_paging_event {
+ GSM_PAGING_SUCCEEDED,
+ GSM_PAGING_EXPIRED,
+};
+
+struct msgb;
+typedef int gsm_cbfn(unsigned int hooknum,
+ unsigned int event,
+ struct msgb *msg,
+ void *data, void *param);
+
+/*
+ * Use the channel. As side effect the lchannel recycle timer
+ * will be started.
+ */
+#define LCHAN_RELEASE_TIMEOUT 4, 0
+#define use_lchan(lchan) \
+ do { lchan->use_count++; \
+ DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \
+ lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
+ lchan->nr, lchan->use_count); \
+ bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT); } while(0);
+
+#define put_lchan(lchan) \
+ do { lchan->use_count--; \
+ DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \
+ lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \
+ lchan->nr, lchan->use_count); \
+ } while(0);
+
+
+/* communications link with a BTS */
+struct gsm_bts_link {
+ struct gsm_bts *bts;
+};
+
+enum gsm_call_type {
+ GSM_CT_NONE,
+ GSM_CT_MO,
+ GSM_CT_MT,
+};
+
+enum gsm_call_state {
+ GSM_CSTATE_NULL,
+ GSM_CSTATE_INITIATED,
+ GSM_CSTATE_ACTIVE,
+ GSM_CSTATE_RELEASE_REQ,
+};
+
+struct gsm_lchan;
+struct gsm_subscriber;
+
+/* One end of a call */
+struct gsm_call {
+ enum gsm_call_type type;
+ enum gsm_call_state state;
+ u_int8_t transaction_id; /* 10.3.2 */
+
+ /* the 'local' channel */
+ struct gsm_lchan *local_lchan;
+ /* the 'remote' channel */
+ struct gsm_lchan *remote_lchan;
+
+ /* the 'remote' subscriber */
+ struct gsm_subscriber *called_subscr;
+};
+
+
+enum gsm_phys_chan_config {
+ GSM_PCHAN_NONE,
+ GSM_PCHAN_CCCH,
+ GSM_PCHAN_CCCH_SDCCH4,
+ GSM_PCHAN_TCH_F,
+ GSM_PCHAN_TCH_H,
+ GSM_PCHAN_SDCCH8_SACCH8C,
+ GSM_PCHAN_UNKNOWN,
+};
+
+enum gsm_chan_t {
+ GSM_LCHAN_NONE,
+ GSM_LCHAN_SDCCH,
+ GSM_LCHAN_TCH_F,
+ GSM_LCHAN_TCH_H,
+ GSM_LCHAN_UNKNOWN,
+};
+
+
+/* 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,
+};
+
+/* Network Management State */
+struct gsm_nm_state {
+ u_int8_t operational;
+ u_int8_t administrative;
+ u_int8_t availability;
+};
+struct gsm_attr {
+ u_int8_t len;
+ u_int8_t data[0];
+};
+
+/*
+ * LOCATION UPDATING REQUEST state
+ *
+ * Our current operation is:
+ * - Get imei/tmsi
+ * - Accept/Reject according to global policy
+ */
+struct gsm_loc_updating_operation {
+ struct timer_list updating_timer;
+ int waiting_for_imsi : 1;
+ int waiting_for_imei : 1;
+};
+
+struct gsm_lchan {
+ /* The TS that we're part of */
+ struct gsm_bts_trx_ts *ts;
+ /* The logical subslot number in the TS */
+ u_int8_t nr;
+ /* The logical channel type */
+ enum gsm_chan_t type;
+ /* If TCH, traffic channel mode */
+ enum gsm_chan_t tch_mode;
+ /* Power levels for MS and BTS */
+ u_int8_t bs_power;
+ u_int8_t ms_power;
+
+ /* To whom we are allocated at the moment */
+ struct gsm_subscriber *subscr;
+
+ /* Timer started to release the channel */
+ struct timer_list release_timer;
+
+ /* local end of a call, if any */
+ struct gsm_call call;
+
+ /* temporary user data, to be removed... and merged into gsm_call */
+ void *user_data;
+
+ /*
+ * Operations that have a state and might be pending
+ */
+ struct gsm_loc_updating_operation *loc_operation;
+
+ /* use count. how many users use this channel */
+ unsigned int use_count;
+};
+
+struct gsm_e1_subslot {
+ /* Number of E1 link */
+ u_int8_t e1_nr;
+ /* Number of E1 TS inside E1 link */
+ u_int8_t e1_ts;
+ /* Sub-slot within the E1 TS, 0xff if full TS */
+ u_int8_t e1_ts_ss;
+};
+
+#define BTS_TRX_F_ACTIVATED 0x0001
+/* One Timeslot in a TRX */
+struct gsm_bts_trx_ts {
+ struct gsm_bts_trx *trx;
+ /* number of this timeslot at the TRX */
+ u_int8_t nr;
+
+ enum gsm_phys_chan_config pchan;
+
+ unsigned int flags;
+ struct gsm_nm_state nm_state;
+ struct gsm_attr *nm_attr;
+
+ /* To which E1 subslot are we connected */
+ struct gsm_e1_subslot e1_link;
+ struct {
+ u_int32_t bound_ip;
+ u_int16_t bound_port;
+ u_int8_t attr_fc;
+ u_int16_t attr_f8;
+ } abis_ip;
+
+ struct gsm_lchan lchan[TS_MAX_LCHAN];
+};
+
+/* One TRX in a BTS */
+struct gsm_bts_trx {
+ struct gsm_bts *bts;
+ /* number of this TRX in the BTS */
+ u_int8_t nr;
+ /* how do we talk RSL with this TRX? */
+ struct e1inp_sign_link *rsl_link;
+ struct gsm_nm_state nm_state;
+ struct gsm_attr *nm_attr;
+ struct {
+ struct gsm_nm_state nm_state;
+ } bb_transc;
+
+ u_int16_t arfcn;
+
+ union {
+ struct {
+ struct {
+ struct gsm_nm_state nm_state;
+ } bbsig;
+ struct {
+ struct gsm_nm_state nm_state;
+ } pa;
+ } bs11;
+ };
+ struct gsm_bts_trx_ts ts[TRX_NR_TS];
+};
+
+enum gsm_bts_type {
+ GSM_BTS_TYPE_UNKNOWN,
+ GSM_BTS_TYPE_BS11,
+ GSM_BTS_TYPE_NANOBTS_900,
+ GSM_BTS_TYPE_NANOBTS_1800,
+};
+
+/**
+ * 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 gsm_subscriber struct? */
+ struct gsm_subscriber *subscr;
+ /* 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 timer_list T3113;
+
+ /* callback to be called in case paging completes */
+ gsm_cbfn *cbfn;
+ void *cbfn_param;
+};
+#define T3113_VALUE 60, 0
+
+/*
+ * 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_paging_request *last_request;
+ struct gsm_bts *bts;
+
+ struct timer_list work_timer;
+
+ /* load */
+ u_int16_t available_slots;
+};
+
+struct gsm_envabtse {
+ struct gsm_nm_state nm_state;
+};
+
+/* One BTS */
+struct gsm_bts {
+ struct gsm_network *network;
+ /* number of ths BTS in network */
+ u_int8_t nr;
+ /* location area code of this BTS */
+ u_int8_t location_area_code;
+ /* Training Sequence Code */
+ u_int8_t tsc;
+ /* Base Station Identification Code (BSIC) */
+ u_int8_t bsic;
+ /* type of BTS */
+ enum gsm_bts_type type;
+ /* how do we talk OML with this TRX? */
+ struct e1inp_sign_link *oml_link;
+
+ /* Abis network management O&M handle */
+ struct abis_nm_h *nmh;
+ struct gsm_nm_state nm_state;
+ struct gsm_attr *nm_attr;
+
+ /* number of this BTS on given E1 link */
+ u_int8_t bts_nr;
+
+ struct gsm48_control_channel_descr chan_desc;
+
+ /* paging state and control */
+ struct gsm_bts_paging_state paging;
+
+ /* CCCH is on C0 */
+ struct gsm_bts_trx *c0;
+
+ struct {
+ struct gsm_nm_state nm_state;
+ } site_mgr;
+
+ /* ip.accesss Unit ID's have Site/BTS/TRX layout */
+ union {
+ struct {
+ u_int16_t site_id;
+ u_int16_t bts_id;
+ } ip_access;
+ struct {
+ struct {
+ struct gsm_nm_state nm_state;
+ } cclk;
+ struct {
+ struct gsm_nm_state nm_state;
+ } rack;
+ struct gsm_envabtse envabtse[4];
+ } bs11;
+ };
+
+ /* transceivers */
+ int num_trx;
+ struct gsm_bts_trx trx[BTS_MAX_TRX+1];
+};
+
+struct gsm_network {
+ /* global parameters */
+ u_int16_t country_code;
+ u_int16_t network_code;
+ char *name_long;
+ char *name_short;
+
+ unsigned int num_bts;
+ /* private lists */
+ struct gsm_bts bts[GSM_MAX_BTS+1];
+};
+
+#define SMS_HDR_SIZE 128
+#define SMS_TEXT_SIZE 256
+struct gsm_sms {
+ u_int64_t id;
+ struct gsm_subscriber *sender;
+ struct gsm_subscriber *receiver;
+
+ unsigned char header[SMS_HDR_SIZE];
+ char text[SMS_TEXT_SIZE];
+};
+
+struct gsm_network *gsm_network_init(unsigned int num_bts, enum gsm_bts_type bts_type,
+ u_int16_t country_code, u_int16_t network_code);
+
+const char *gsm_pchan_name(enum gsm_phys_chan_config c);
+const char *gsm_lchan_name(enum gsm_chan_t c);
+const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
+char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
+
+enum gsm_e1_event {
+ EVT_E1_NONE,
+ EVT_E1_TEI_UP,
+ EVT_E1_TEI_DN,
+};
+
+void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
+ u_int8_t e1_ts, u_int8_t e1_ts_ss);
+enum gsm_bts_type parse_btstype(char *arg);
+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);
+
+static inline int is_ipaccess_bts(struct gsm_bts *bts)
+{
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS_900:
+ case GSM_BTS_TYPE_NANOBTS_1800:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+#endif
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
new file mode 100644
index 000000000..1ca79e2ae
--- /dev/null
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -0,0 +1,58 @@
+#ifndef _GSM_SUBSCR_H
+#define _GSM_SUBSCR_H
+
+#include <sys/types.h>
+#include "gsm_data.h"
+#include "linuxlist.h"
+
+#define GSM_IMEI_LENGTH 17
+#define GSM_IMSI_LENGTH 17
+#define GSM_TMSI_LENGTH 17
+#define GSM_NAME_LENGTH 128
+#define GSM_EXTENSION_LENGTH 128
+
+struct gsm_subscriber {
+ long long unsigned int id;
+ char imsi[GSM_IMSI_LENGTH];
+ char tmsi[GSM_TMSI_LENGTH];
+ u_int16_t lac;
+ char name[GSM_NAME_LENGTH];
+ char extension[GSM_EXTENSION_LENGTH];
+ int authorized;
+
+ /* for internal management */
+ int use_count;
+ struct llist_head entry;
+
+ /* those are properties of the equipment, but they
+ * are applicable to the subscriber at the moment */
+ struct gsm48_classmark1 classmark1;
+ u_int8_t classmark2_len;
+ u_int8_t classmark2[3];
+ u_int8_t classmark3_len;
+ u_int8_t classmark3[14];
+};
+
+enum gsm_subscriber_field {
+ GSM_SUBSCRIBER_IMSI,
+ GSM_SUBSCRIBER_TMSI,
+ GSM_SUBSCRIBER_EXTENSION,
+};
+
+enum gsm_subscriber_update_reason {
+ GSM_SUBSCRIBER_UPDATE_ATTACHED,
+ GSM_SUBSCRIBER_UPDATE_DETACHED,
+};
+
+struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
+struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
+struct gsm_subscriber *subscr_get_by_tmsi(const char *tmsi);
+struct gsm_subscriber *subscr_get_by_imsi(const char *imsi);
+struct gsm_subscriber *subscr_get_by_extension(const char *ext);
+int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
+void subscr_put_channel(struct gsm_lchan *lchan);
+
+/* internal */
+struct gsm_subscriber *subscr_alloc(void);
+
+#endif /* _GSM_SUBSCR_H */
diff --git a/openbsc/include/openbsc/gsm_utils.h b/openbsc/include/openbsc/gsm_utils.h
new file mode 100644
index 000000000..c46837185
--- /dev/null
+++ b/openbsc/include/openbsc/gsm_utils.h
@@ -0,0 +1,33 @@
+/* GSM utility functions, e.g. coding and decoding */
+/*
+ * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef GSM_UTILS_H
+#define GSM_UTILS_H
+
+#include <sys/types.h>
+
+int gsm_7bit_decode(char *decoded, const u_int8_t *user_data, u_int8_t length);
+int gsm_7bit_encode(u_int8_t *result, const char *data);
+
+#endif
diff --git a/openbsc/include/openbsc/ipaccess.h b/openbsc/include/openbsc/ipaccess.h
new file mode 100644
index 000000000..d6ded3551
--- /dev/null
+++ b/openbsc/include/openbsc/ipaccess.h
@@ -0,0 +1,37 @@
+#ifndef _IPACCESS_H
+#define _IPACCESS_H
+
+struct ipaccess_head {
+ u_int8_t zero;
+ u_int8_t len;
+ u_int8_t proto;
+ u_int8_t data[0];
+} __attribute__ ((packed));
+
+enum ipaccess_proto {
+ IPAC_PROTO_RSL = 0x00,
+ IPAC_PROTO_IPACCESS = 0xfe,
+ IPAC_PROTO_OML = 0xff,
+};
+
+enum ipaccess_msgtype {
+ IPAC_MSGT_PING = 0x00,
+ IPAC_MSGT_PONG = 0x01,
+ IPAC_MSGT_ID_GET = 0x04,
+ IPAC_MSGT_ID_RESP = 0x05,
+ IPAC_MSGT_ID_ACK = 0x06,
+};
+
+enum ipaccess_id_tags {
+ IPAC_IDTAG_SERNR = 0x00,
+ IPAC_IDTAG_UNITNAME = 0x01,
+ IPAC_IDTAG_LOCATION1 = 0x02,
+ IPAC_IDTAG_LOCATION2 = 0x03,
+ IPAC_IDTAG_EQUIPVERS = 0x04,
+ IPAC_IDTAG_SWVERSION = 0x05,
+ IPAC_IDTAG_IPADDR = 0x06,
+ IPAC_IDTAG_MACADDR = 0x07,
+ IPAC_IDTAG_UNIT = 0x08,
+};
+
+#endif /* _IPACCESS_H */
diff --git a/openbsc/include/openbsc/linuxlist.h b/openbsc/include/openbsc/linuxlist.h
new file mode 100644
index 000000000..fb99c5ec8
--- /dev/null
+++ b/openbsc/include/openbsc/linuxlist.h
@@ -0,0 +1,360 @@
+#ifndef _LINUX_LLIST_H
+#define _LINUX_LLIST_H
+
+#include <stddef.h>
+
+#ifndef inline
+#define inline __inline__
+#endif
+
+static inline void prefetch(const void *x) {;}
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \
+ (type *)( (char *)__mptr - offsetof(type, member) );})
+
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized llist entries.
+ */
+#define LLIST_POISON1 ((void *) 0x00100100)
+#define LLIST_POISON2 ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked llist implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole llists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct llist_head {
+ struct llist_head *next, *prev;
+};
+
+#define LLIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LLIST_HEAD(name) \
+ struct llist_head name = LLIST_HEAD_INIT(name)
+
+#define INIT_LLIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_add(struct llist_head *_new,
+ struct llist_head *prev,
+ struct llist_head *next)
+{
+ next->prev = _new;
+ _new->next = next;
+ _new->prev = prev;
+ prev->next = _new;
+}
+
+/**
+ * llist_add - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void llist_add(struct llist_head *_new, struct llist_head *head)
+{
+ __llist_add(_new, head, head->next);
+}
+
+/**
+ * llist_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: llist head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head)
+{
+ __llist_add(_new, head->prev, head);
+}
+
+/*
+ * Delete a llist entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal llist manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * llist_del - deletes entry from llist.
+ * @entry: the element to delete from the llist.
+ * Note: llist_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void llist_del(struct llist_head *entry)
+{
+ __llist_del(entry->prev, entry->next);
+ entry->next = (struct llist_head *)LLIST_POISON1;
+ entry->prev = (struct llist_head *)LLIST_POISON2;
+}
+
+/**
+ * llist_del_init - deletes entry from llist and reinitialize it.
+ * @entry: the element to delete from the llist.
+ */
+static inline void llist_del_init(struct llist_head *entry)
+{
+ __llist_del(entry->prev, entry->next);
+ INIT_LLIST_HEAD(entry);
+}
+
+/**
+ * llist_move - delete from one llist and add as another's head
+ * @llist: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void llist_move(struct llist_head *llist, struct llist_head *head)
+{
+ __llist_del(llist->prev, llist->next);
+ llist_add(llist, head);
+}
+
+/**
+ * llist_move_tail - delete from one llist and add as another's tail
+ * @llist: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void llist_move_tail(struct llist_head *llist,
+ struct llist_head *head)
+{
+ __llist_del(llist->prev, llist->next);
+ llist_add_tail(llist, head);
+}
+
+/**
+ * llist_empty - tests whether a llist is empty
+ * @head: the llist to test.
+ */
+static inline int llist_empty(const struct llist_head *head)
+{
+ return head->next == head;
+}
+
+static inline void __llist_splice(struct llist_head *llist,
+ struct llist_head *head)
+{
+ struct llist_head *first = llist->next;
+ struct llist_head *last = llist->prev;
+ struct llist_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * llist_splice - join two llists
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ */
+static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
+{
+ if (!llist_empty(llist))
+ __llist_splice(llist, head);
+}
+
+/**
+ * llist_splice_init - join two llists and reinitialise the emptied llist.
+ * @llist: the new llist to add.
+ * @head: the place to add it in the first llist.
+ *
+ * The llist at @llist is reinitialised
+ */
+static inline void llist_splice_init(struct llist_head *llist,
+ struct llist_head *head)
+{
+ if (!llist_empty(llist)) {
+ __llist_splice(llist, head);
+ INIT_LLIST_HEAD(llist);
+ }
+}
+
+/**
+ * llist_entry - get the struct for this entry
+ * @ptr: the &struct llist_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * llist_for_each - iterate over a llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * __llist_for_each - iterate over a llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ *
+ * This variant differs from llist_for_each() in that it's the
+ * simplest possible llist iteration code, no prefetching is done.
+ * Use this for code that knows the llist to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __llist_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * llist_for_each_prev - iterate over a llist backwards
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+/**
+ * llist_for_each_safe - iterate over a llist safe against removal of llist entry
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @n: another &struct llist_head to use as temporary storage
+ * @head: the head for your llist.
+ */
+#define llist_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * llist_for_each_entry - iterate over llist of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry(pos, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_reverse - iterate backwards over llist of given type.
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_reverse(pos, head, member) \
+ for (pos = llist_entry((head)->prev, typeof(*pos), member), \
+ prefetch(pos->member.prev); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.prev, typeof(*pos), member), \
+ prefetch(pos->member.prev))
+
+/**
+ * llist_for_each_entry_continue - iterate over llist of given type
+ * continuing after existing point
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_continue(pos, head, member) \
+ for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ n = llist_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = llist_entry(n->member.next, typeof(*n), member))
+
+/**
+ * llist_for_each_rcu - iterate over an rcu-protected llist
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_rcu(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+
+#define __llist_for_each_rcu(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+
+/**
+ * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
+ * against removal of llist entry
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @n: another &struct llist_head to use as temporary storage
+ * @head: the head for your llist.
+ */
+#define llist_for_each_safe_rcu(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+
+/**
+ * llist_for_each_entry_rcu - iterate over rcu llist of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your llist.
+ * @member: the name of the llist_struct within the struct.
+ */
+#define llist_for_each_entry_rcu(pos, head, member) \
+ for (pos = llist_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = llist_entry(pos->member.next, typeof(*pos), member), \
+ ({ smp_read_barrier_depends(); 0;}), \
+ prefetch(pos->member.next))
+
+
+/**
+ * llist_for_each_continue_rcu - iterate over an rcu-protected llist
+ * continuing after existing point.
+ * @pos: the &struct llist_head to use as a loop counter.
+ * @head: the head for your llist.
+ */
+#define llist_for_each_continue_rcu(pos, head) \
+ for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
+ (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+
+
+#endif
diff --git a/openbsc/include/openbsc/misdn.h b/openbsc/include/openbsc/misdn.h
new file mode 100644
index 000000000..d3631e794
--- /dev/null
+++ b/openbsc/include/openbsc/misdn.h
@@ -0,0 +1,28 @@
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef MISDN_H
+#define MISDN_H
+
+#include "e1_input.h"
+
+int mi_setup(int cardnr, struct e1inp_line *line, int release_l2);
+int _abis_nm_sendmsg(struct msgb *msg);
+
+#endif
diff --git a/openbsc/include/openbsc/msgb.h b/openbsc/include/openbsc/msgb.h
new file mode 100644
index 000000000..2c31d1587
--- /dev/null
+++ b/openbsc/include/openbsc/msgb.h
@@ -0,0 +1,111 @@
+#ifndef _MSGB_H
+#define _MSGB_H
+
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/linuxlist.h>
+
+struct bts_link;
+
+struct msgb {
+ struct llist_head list;
+
+ /* ptr to the physical E1 link to the BTS(s) */
+ struct gsm_bts_link *bts_link;
+
+ /* Part of which TRX logical channel we were received / transmitted */
+ struct gsm_bts_trx *trx;
+ struct gsm_lchan *lchan;
+
+ unsigned char *l2h;
+ unsigned char *l3h;
+ unsigned char *smsh;
+
+ u_int16_t data_len;
+ u_int16_t len;
+
+ unsigned char *head;
+ unsigned char *tail;
+ unsigned char *data;
+ unsigned char _data[0];
+};
+
+extern struct msgb *msgb_alloc(u_int16_t size);
+extern void msgb_free(struct msgb *m);
+extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
+extern struct msgb *msgb_dequeue(struct llist_head *queue);
+
+#define msgb_l2(m) ((void *)(m->l2h))
+#define msgb_l3(m) ((void *)(m->l3h))
+#define msgb_sms(m) ((void *)(m->smsh))
+
+static inline unsigned int msgb_l2len(const struct msgb *msgb)
+{
+ return msgb->tail - (u_int8_t *)msgb_l2(msgb);
+}
+
+static inline unsigned int msgb_l3len(const struct msgb *msgb)
+{
+ return msgb->tail - (u_int8_t *)msgb_l3(msgb);
+}
+
+static inline unsigned int msgb_headlen(const struct msgb *msgb)
+{
+ return msgb->len - msgb->data_len;
+}
+static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
+{
+ unsigned char *tmp = msgb->tail;
+ msgb->tail += len;
+ msgb->len += len;
+ return tmp;
+}
+static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
+{
+ msgb->data -= len;
+ msgb->len += len;
+ return msgb->data;
+}
+static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
+{
+ msgb->len -= len;
+ return msgb->data += len;
+}
+static inline int msgb_tailroom(const struct msgb *msgb)
+{
+ return (msgb->data + msgb->data_len) - msgb->tail;
+}
+
+/* increase the headroom of an empty msgb, reducing the tailroom */
+static inline void msgb_reserve(struct msgb *msg, int len)
+{
+ msg->data += len;
+ msg->tail += len;
+}
+
+static inline struct msgb *msgb_alloc_headroom(int size, int headroom)
+{
+ struct msgb *msg = msgb_alloc(size);
+ if (msg)
+ msgb_reserve(msg, headroom);
+ return msg;
+}
+
+#endif /* _MSGB_H */
diff --git a/openbsc/include/openbsc/openbscdefines.h b/openbsc/include/openbsc/openbscdefines.h
new file mode 100644
index 000000000..082e5922e
--- /dev/null
+++ b/openbsc/include/openbsc/openbscdefines.h
@@ -0,0 +1,35 @@
+/*
+ * (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#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/openbsc/include/openbsc/paging.h b/openbsc/include/openbsc/paging.h
new file mode 100644
index 000000000..de512d1ae
--- /dev/null
+++ b/openbsc/include/openbsc/paging.h
@@ -0,0 +1,46 @@
+/* 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef PAGING_H
+#define PAGING_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "linuxlist.h"
+#include "gsm_data.h"
+#include "gsm_subscriber.h"
+#include "timer.h"
+
+/* call once for every gsm_bts... */
+void paging_init(struct gsm_bts *bts);
+
+/* schedule paging request */
+void paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr,
+ int type, gsm_cbfn *cbfn, void *data);
+
+/* stop paging requests */
+void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
+ struct gsm_lchan *lchan);
+
+/* update paging load */
+void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);
+
+#endif
diff --git a/openbsc/include/openbsc/rs232.h b/openbsc/include/openbsc/rs232.h
new file mode 100644
index 000000000..61187ca62
--- /dev/null
+++ b/openbsc/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/openbsc/include/openbsc/select.h b/openbsc/include/openbsc/select.h
new file mode 100644
index 000000000..c2af1d787
--- /dev/null
+++ b/openbsc/include/openbsc/select.h
@@ -0,0 +1,22 @@
+#ifndef _BSC_SELECT_H
+#define _BSC_SELECT_H
+
+#include <openbsc/linuxlist.h>
+
+#define BSC_FD_READ 0x0001
+#define BSC_FD_WRITE 0x0002
+#define BSC_FD_EXCEPT 0x0004
+
+struct bsc_fd {
+ struct llist_head list;
+ int fd;
+ unsigned int when;
+ int (*cb)(struct bsc_fd *fd, unsigned int what);
+ void *data;
+ unsigned int priv_nr;
+};
+
+int bsc_register_fd(struct bsc_fd *fd);
+void bsc_unregister_fd(struct bsc_fd *fd);
+int bsc_select_main(int polling);
+#endif /* _BSC_SELECT_H */
diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h
new file mode 100644
index 000000000..4a583f689
--- /dev/null
+++ b/openbsc/include/openbsc/signal.h
@@ -0,0 +1,88 @@
+/* Generic signalling/notification infrastructure */
+/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef OPENBSC_SIGNAL_H
+#define OPENBSC_SIGNAL_H
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+
+
+/*
+ * Signalling subsystems
+ */
+enum signal_subsystems {
+ SS_PAGING,
+ SS_SMS,
+ SS_ABISIP,
+ SS_NM,
+ SS_LCHAN,
+};
+
+/* SS_PAGING signals */
+enum signal_paging {
+ S_PAGING_COMPLETED,
+};
+
+/* SS_ABISIP signals */
+enum signal_abisip {
+ S_ABISIP_BIND_ACK,
+};
+
+/* 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 */
+};
+
+/* 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,
+};
+
+typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data);
+
+struct paging_signal_data {
+ struct gsm_subscriber *subscr;
+ struct gsm_bts *bts;
+
+ /* NULL in case the paging didn't work */
+ struct gsm_lchan *lchan;
+};
+
+/* Management */
+int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
+void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
+
+/* Dispatch */
+void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data);
+
+
+#endif
diff --git a/openbsc/include/openbsc/subchan_demux.h b/openbsc/include/openbsc/subchan_demux.h
new file mode 100644
index 000000000..9661b0481
--- /dev/null
+++ b/openbsc/include/openbsc/subchan_demux.h
@@ -0,0 +1,102 @@
+#ifndef _SUBCH_DEMUX_H
+#define _SUBCH_DEMUX_H
+/* A E1 sub-channel (de)multiplexer with TRAU frame sync */
+
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <sys/types.h>
+#include <openbsc/linuxlist.h>
+
+#define NR_SUBCH 4
+#define TRAU_FRAME_SIZE 40
+#define TRAU_FRAME_BITS (TRAU_FRAME_SIZE*8)
+
+/***********************************************************************/
+/* DEMULTIPLEXER */
+/***********************************************************************/
+
+struct demux_subch {
+ u_int8_t out_bitbuf[TRAU_FRAME_BITS];
+ u_int16_t out_idx; /* next bit to be written in out_bitbuf */
+ /* number of consecutive zeros that we have received (for sync) */
+ unsigned int consecutive_zeros;
+ /* are we in TRAU frame sync or not? */
+ unsigned int in_sync;
+};
+
+struct subch_demux {
+ /* bitmask of currently active subchannels */
+ u_int8_t chan_activ;
+ /* one demux_subch struct for every subchannel */
+ struct demux_subch subch[NR_SUBCH];
+ /* callback to be called once we have received a complete
+ * frame on a given subchannel */
+ int (*out_cb)(struct subch_demux *dmx, int ch, u_int8_t *data, int len,
+ void *);
+ /* user-provided data, transparently passed to out_cb() */
+ void *data;
+};
+
+/* initialize one demultiplexer instance */
+int subch_demux_init(struct subch_demux *dmx);
+
+/* feed 'len' number of muxed bytes into the demultiplexer */
+int subch_demux_in(struct subch_demux *dmx, u_int8_t *data, int len);
+
+/* activate decoding/processing for one subchannel */
+int subch_demux_activate(struct subch_demux *dmx, int subch);
+
+/* deactivate decoding/processing for one subchannel */
+int subch_demux_deactivate(struct subch_demux *dmx, int subch);
+
+/***********************************************************************/
+/* MULTIPLEXER */
+/***********************************************************************/
+
+/* one element in the tx_queue of a muxer sub-channel */
+struct subch_txq_entry {
+ struct llist_head list;
+
+ unsigned int bit_len; /* total number of bits in 'bits' */
+ unsigned int next_bit; /* next bit to be transmitted */
+
+ u_int8_t bits[0]; /* one bit per byte */
+};
+
+struct mux_subch {
+ struct llist_head tx_queue;
+};
+
+/* structure representing one instance of the subchannel muxer */
+struct subch_mux {
+ struct mux_subch subch[NR_SUBCH];
+};
+
+/* initialize a subchannel muxer instance */
+int subchan_mux_init(struct subch_mux *mx);
+
+/* request the output of 'len' multiplexed bytes */
+int subchan_mux_out(struct subch_mux *mx, u_int8_t *data, int len);
+
+/* enqueue some data into one sub-channel of the muxer */
+int subchan_mux_enqueue(struct subch_mux *mx, int s_nr, const u_int8_t *data,
+ int len);
+
+#endif /* _SUBCH_DEMUX_H */
diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h
new file mode 100644
index 000000000..97357d794
--- /dev/null
+++ b/openbsc/include/openbsc/telnet_interface.h
@@ -0,0 +1,52 @@
+/* minimalistic telnet/network interface it might turn into a wire interface */
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef TELNET_INTERFACE_H
+#define TELNET_INTERFACE_H
+
+#include "gsm_data.h"
+#include "linuxlist.h"
+#include "select.h"
+
+#include <vty/vty.h>
+
+#define TELNET_COMMAND_48 1
+#define TELNET_COMMAND_11 2
+
+struct telnet_connection {
+ struct llist_head entry;
+ struct gsm_network *network;
+ struct bsc_fd fd;
+ struct vty *vty;
+
+ int bts;
+
+ int command;
+ char *imsi;
+ char commands[1024];
+ int read;
+};
+
+
+void telnet_init(struct gsm_network *network, int port);
+
+int bsc_vty_init(struct gsm_network *net);
+
+#endif
diff --git a/openbsc/include/openbsc/timer.h b/openbsc/include/openbsc/timer.h
new file mode 100644
index 000000000..ae67a5a1a
--- /dev/null
+++ b/openbsc/include/openbsc/timer.h
@@ -0,0 +1,71 @@
+/*
+ * (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <sys/time.h>
+
+#include "linuxlist.h"
+
+/**
+ * Timer management:
+ * - Create a struct timer_list
+ * - Fill out timeout and use add_timer or
+ * use schedule_timer to schedule a timer in
+ * x seconds and microseconds from now...
+ * - Use del_timer to remove the timer
+ *
+ * Internally:
+ * - We hook into select.c to give a timeval of the
+ * nearest timer. On already passed timers we give
+ * it a 0 to immediately fire after the select
+ * - update_timers will call the callbacks and remove
+ * the timers.
+ *
+ */
+struct timer_list {
+ struct llist_head entry;
+ struct timeval timeout;
+ int active : 1;
+ int handled : 1;
+ int in_list : 1;
+
+ void (*cb)(void*);
+ void *data;
+};
+
+/**
+ * timer management
+ */
+void bsc_add_timer(struct timer_list *timer);
+void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds);
+void bsc_del_timer(struct timer_list *timer);
+int bsc_timer_pending(struct timer_list *timer);
+
+
+/**
+ * internal timer list management
+ */
+struct timeval *bsc_nearest_timer();
+void bsc_prepare_timers();
+int bsc_update_timers();
+
+#endif
diff --git a/openbsc/include/openbsc/tlv.h b/openbsc/include/openbsc/tlv.h
new file mode 100644
index 000000000..ae88e6ed3
--- /dev/null
+++ b/openbsc/include/openbsc/tlv.h
@@ -0,0 +1,171 @@
+#ifndef _TLV_H
+#define _TLV_H
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <openbsc/msgb.h>
+
+#define LV_GROSS_LEN(x) (x+1)
+#define TLV_GROSS_LEN(x) (x+2)
+#define TLV16_GROSS_LEN(x) ((2*x)+2)
+#define TL16V_GROSS_LEN(x) (x+3)
+
+/* TLV generation */
+
+static inline u_int8_t *lv_put(u_int8_t *buf, u_int8_t len,
+ const u_int8_t *val)
+{
+ *buf++ = len;
+ memcpy(buf, val, len);
+ return buf + len;
+}
+
+static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
+ const u_int8_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ memcpy(buf, val, len);
+ return buf + len;
+}
+
+static inline u_int8_t *tlv16_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
+ const u_int16_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ memcpy(buf, val, len*2);
+ return buf + len*2;
+}
+
+static inline u_int8_t *tl16v_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
+ const u_int8_t *val)
+{
+ *buf++ = tag;
+ *buf++ = len >> 8;
+ *buf++ = len & 0xff;
+ memcpy(buf, val, len);
+ return buf + len*2;
+}
+
+static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
+ return tlv16_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tl16v_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
+ const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
+ return tl16v_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *v_put(u_int8_t *buf, u_int8_t val)
+{
+ *buf++ = val;
+ return buf;
+}
+
+static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
+ u_int8_t val)
+{
+ *buf++ = tag;
+ *buf++ = val;
+ return buf;
+}
+
+static inline u_int8_t *tv16_put(u_int8_t *buf, u_int8_t tag,
+ u_int16_t val)
+{
+ *buf++ = tag;
+ *buf++ = val >> 8;
+ *buf++ = val & 0xff;
+ return buf;
+}
+
+static inline u_int8_t *msgb_lv_put(struct msgb *msg, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
+ return lv_put(buf, len, val);
+}
+
+static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
+ return tlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 2);
+ return tv_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_v_put(struct msgb *msg, u_int8_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 1);
+ return v_put(buf, val);
+}
+
+static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
+{
+ u_int8_t *buf = msgb_put(msg, 3);
+ return tv16_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
+{
+ u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
+ return tlv_put(buf, tag, len, val);
+}
+
+static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t val)
+{
+ u_int8_t *buf = msgb_push(msg, 2);
+ return tv_put(buf, tag, val);
+}
+
+static inline u_int8_t *msgb_tv16_push(struct msgb *msg, u_int8_t tag, u_int16_t val)
+{
+ u_int8_t *buf = msgb_push(msg, 3);
+ return tv16_put(buf, tag, val);
+}
+
+/* TLV parsing */
+
+struct tlv_p_entry {
+ u_int16_t len;
+ const u_int8_t *val;
+};
+
+enum tlv_type {
+ TLV_TYPE_FIXED,
+ TLV_TYPE_T,
+ TLV_TYPE_TV,
+ TLV_TYPE_TLV,
+ TLV_TYPE_TL16V,
+};
+
+struct tlv_def {
+ enum tlv_type type;
+ u_int8_t fixed_len;
+};
+
+struct tlv_definition {
+ struct tlv_def def[0xff];
+};
+
+struct tlv_parsed {
+ struct tlv_p_entry lv[0xff];
+};
+
+int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
+ const u_int8_t *buf, int buf_len, u_int8_t lv_tag, u_int8_t lv_tag2);
+
+#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
+#define TLVP_LEN(x, y) (x)->lv[y].len
+#define TLVP_VAL(x, y) (x)->lv[y].val
+
+#endif /* _TLV_H */
diff --git a/openbsc/include/openbsc/trau_frame.h b/openbsc/include/openbsc/trau_frame.h
new file mode 100644
index 000000000..5923d4ac1
--- /dev/null
+++ b/openbsc/include/openbsc/trau_frame.h
@@ -0,0 +1,65 @@
+#ifndef _TRAU_FRAME_H
+#define _TRAU_FRAME_H
+/* TRAU frame handling according to GSM TS 08.60 */
+
+/* (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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <sys/types.h>
+
+/* 21 for FR/EFR, 25 for AMR, 15 for OM, 15 for data, 13 for E-data, 21 idle */
+#define MAX_C_BITS 25
+/* 260 for FR/EFR, 256 for AMR, 264 for OM, 288 for E-data */
+#define MAX_D_BITS 288
+/* for all speech frames */
+#define MAX_T_BITS 4
+/* for OM */
+#define MAX_S_BITS 6
+/* for E-data */
+#define MAX_M_BITS 2
+
+struct decoded_trau_frame {
+ u_int8_t c_bits[MAX_C_BITS];
+ u_int8_t d_bits[MAX_D_BITS];
+ u_int8_t t_bits[MAX_T_BITS];
+ u_int8_t s_bits[MAX_S_BITS];
+ u_int8_t m_bits[MAX_M_BITS];
+};
+
+#define TRAU_FT_FR_UP 0x02 /* 0 0 0 1 0 - 3.5.1.1.1 */
+#define TRAU_FT_FR_DOWN 0x1c /* 1 1 1 0 0 - 3.5.1.1.1 */
+#define TRAU_FT_EFR 0x1a /* 1 1 0 1 0 - 3.5.1.1.1 */
+#define TRAU_FT_AMR 0x06 /* 0 0 1 1 0 - 3.5.1.2 */
+#define TRAU_FT_OM_UP 0x07 /* 0 0 1 0 1 - 3.5.2 */
+#define TRAU_FT_OM_DOWN 0x1b /* 1 1 0 1 1 - 3.5.2 */
+#define TRAU_FT_DATA_UP 0x08 /* 0 1 0 0 0 - 3.5.3 */
+#define TRAU_FT_DATA_DOWN 0x16 /* 1 0 1 1 0 - 3.5.3 */
+#define TRAU_FT_D145_SYNC 0x14 /* 1 0 1 0 0 - 3.5.3 */
+#define TRAU_FT_EDATA 0x1f /* 1 1 1 1 1 - 3.5.4 */
+#define TRAU_FT_IDLE_UP 0x10 /* 1 0 0 0 0 - 3.5.5 */
+#define TRAU_FT_IDLE_DOWN 0x0e /* 0 1 1 1 0 - 3.5.5 */
+
+
+int decode_trau_frame(struct decoded_trau_frame *fr, const u_int8_t *trau_bits);
+int encode_trau_frame(u_int8_t *trau_bits, const struct decoded_trau_frame *fr);
+int trau_frame_up2down(struct decoded_trau_frame *fr);
+u_int8_t *trau_idle_frame(void);
+
+
+#endif /* _TRAU_FRAME_H */
diff --git a/openbsc/include/openbsc/trau_mux.h b/openbsc/include/openbsc/trau_mux.h
new file mode 100644
index 000000000..90535add4
--- /dev/null
+++ b/openbsc/include/openbsc/trau_mux.h
@@ -0,0 +1,49 @@
+/* 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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+/* 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.
+ */
+
+/* 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, u_int32_t callref);
+
+/* we get called by subchan_demux */
+int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
+ const u_int8_t *trau_bits, int num_bits);
+
+/* add a trau receiver */
+int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_t callref);
+
+/* send trau from application */
+int trau_send_lchan(struct gsm_lchan *lchan, struct decoded_trau_frame *tf);
diff --git a/openbsc/include/vty/Makefile.am b/openbsc/include/vty/Makefile.am
new file mode 100644
index 000000000..167476630
--- /dev/null
+++ b/openbsc/include/vty/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = buffer.h command.h vector.h vty.h
diff --git a/openbsc/include/vty/buffer.h b/openbsc/include/vty/buffer.h
new file mode 100644
index 000000000..31519400f
--- /dev/null
+++ b/openbsc/include/vty/buffer.h
@@ -0,0 +1,102 @@
+/*
+ * Buffering to output and input.
+ * Copyright (C) 1998 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_BUFFER_H
+#define _ZEBRA_BUFFER_H
+
+#include <sys/types.h>
+
+/* Create a new buffer. Memory will be allocated in chunks of the given
+ size. If the argument is 0, the library will supply a reasonable
+ default size suitable for buffering socket I/O. */
+struct buffer *buffer_new(size_t);
+
+/* Free all data in the buffer. */
+void buffer_reset(struct buffer *);
+
+/* This function first calls buffer_reset to release all buffered data.
+ Then it frees the struct buffer itself. */
+void buffer_free(struct buffer *);
+
+/* Add the given data to the end of the buffer. */
+extern void buffer_put(struct buffer *, const void *, size_t);
+/* Add a single character to the end of the buffer. */
+extern void buffer_putc(struct buffer *, u_char);
+/* Add a NUL-terminated string to the end of the buffer. */
+extern void buffer_putstr(struct buffer *, const char *);
+
+/* Combine all accumulated (and unflushed) data inside the buffer into a
+ single NUL-terminated string allocated using XMALLOC(MTYPE_TMP). Note
+ that this function does not alter the state of the buffer, so the data
+ is still inside waiting to be flushed. */
+char *buffer_getstr(struct buffer *);
+
+/* Returns 1 if there is no pending data in the buffer. Otherwise returns 0. */
+int buffer_empty(struct buffer *);
+
+typedef enum {
+ /* An I/O error occurred. The buffer should be destroyed and the
+ file descriptor should be closed. */
+ BUFFER_ERROR = -1,
+
+ /* The data was written successfully, and the buffer is now empty
+ (there is no pending data waiting to be flushed). */
+ BUFFER_EMPTY = 0,
+
+ /* There is pending data in the buffer waiting to be flushed. Please
+ try flushing the buffer when select indicates that the file descriptor
+ is writeable. */
+ BUFFER_PENDING = 1
+} buffer_status_t;
+
+/* Try to write this data to the file descriptor. Any data that cannot
+ be written immediately is added to the buffer queue. */
+extern buffer_status_t buffer_write(struct buffer *, int fd,
+ const void *, size_t);
+
+/* This function attempts to flush some (but perhaps not all) of
+ the queued data to the given file descriptor. */
+extern buffer_status_t buffer_flush_available(struct buffer *, int fd);
+
+/* The following 2 functions (buffer_flush_all and buffer_flush_window)
+ are for use in lib/vty.c only. They should not be used elsewhere. */
+
+/* Call buffer_flush_available repeatedly until either all data has been
+ flushed, or an I/O error has been encountered, or the operation would
+ block. */
+extern buffer_status_t buffer_flush_all(struct buffer *, int fd);
+
+/* Attempt to write enough data to the given fd to fill a window of the
+ given width and height (and remove the data written from the buffer).
+
+ If !no_more, then a message saying " --More-- " is appended.
+ If erase is true, then first overwrite the previous " --More-- " message
+ with spaces.
+
+ Any write error (including EAGAIN or EINTR) will cause this function
+ to return -1 (because the logic for handling the erase and more features
+ is too complicated to retry the write later).
+*/
+extern buffer_status_t buffer_flush_window(struct buffer *, int fd, int width,
+ int height, int erase, int no_more);
+
+#endif /* _ZEBRA_BUFFER_H */
diff --git a/openbsc/include/vty/command.h b/openbsc/include/vty/command.h
new file mode 100644
index 000000000..f536f2e02
--- /dev/null
+++ b/openbsc/include/vty/command.h
@@ -0,0 +1,355 @@
+/*
+ * Zebra configuration command interface routine
+ * Copyright (C) 1997, 98 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_COMMAND_H
+#define _ZEBRA_COMMAND_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "vector.h"
+#include "vty.h"
+
+/* Host configuration variable */
+struct host {
+ /* Host name of this router. */
+ char *name;
+
+ /* Password for vty interface. */
+ char *password;
+ char *password_encrypt;
+
+ /* Enable password */
+ char *enable;
+ char *enable_encrypt;
+
+ /* System wide terminal lines. */
+ int lines;
+
+ /* Log filename. */
+ char *logfile;
+
+ /* config file name of this host */
+ char *config;
+
+ /* Flags for services */
+ int advanced;
+ int encrypt;
+
+ /* Banner configuration. */
+ const char *motd;
+ char *motdfile;
+};
+
+/* There are some command levels which called from command node. */
+enum node_type {
+ BTS_NODE,
+ TRX_NODE,
+ TS_NODE,
+ SUBSCR_NODE,
+
+ AUTH_NODE, /* Authentication mode of vty interface. */
+ VIEW_NODE, /* View node. Default mode of vty interface. */
+ AUTH_ENABLE_NODE, /* Authentication mode for change enable. */
+ ENABLE_NODE, /* Enable node. */
+ CONFIG_NODE, /* Config node. Default mode of config file. */
+ SERVICE_NODE, /* Service node. */
+ DEBUG_NODE, /* Debug node. */
+ AAA_NODE, /* AAA node. */
+ KEYCHAIN_NODE, /* Key-chain node. */
+ KEYCHAIN_KEY_NODE, /* Key-chain key node. */
+ INTERFACE_NODE, /* Interface mode node. */
+ ZEBRA_NODE, /* zebra connection node. */
+ TABLE_NODE, /* rtm_table selection node. */
+ RIP_NODE, /* RIP protocol mode node. */
+ RIPNG_NODE, /* RIPng protocol mode node. */
+ BGP_NODE, /* BGP protocol mode which includes BGP4+ */
+ BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
+ BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */
+ BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */
+ BGP_IPV6_NODE, /* BGP IPv6 address family */
+ OSPF_NODE, /* OSPF protocol mode */
+ OSPF6_NODE, /* OSPF protocol for IPv6 mode */
+ ISIS_NODE, /* ISIS protocol mode */
+ MASC_NODE, /* MASC for multicast. */
+ IRDP_NODE, /* ICMP Router Discovery Protocol mode. */
+ IP_NODE, /* Static ip route node. */
+ ACCESS_NODE, /* Access list node. */
+ PREFIX_NODE, /* Prefix list node. */
+ ACCESS_IPV6_NODE, /* Access list node. */
+ PREFIX_IPV6_NODE, /* Prefix list node. */
+ AS_LIST_NODE, /* AS list node. */
+ COMMUNITY_LIST_NODE, /* Community list node. */
+ RMAP_NODE, /* Route map node. */
+ SMUX_NODE, /* SNMP configuration node. */
+ DUMP_NODE, /* Packet dump node. */
+ FORWARDING_NODE, /* IP forwarding node. */
+ VTY_NODE /* Vty node. */
+};
+
+/* Node which has some commands and prompt string and configuration
+ function pointer . */
+struct cmd_node {
+ /* Node index. */
+ enum node_type node;
+
+ /* Prompt character at vty interface. */
+ const char *prompt;
+
+ /* Is this node's configuration goes to vtysh ? */
+ int vtysh;
+
+ /* Node's configuration write function */
+ int (*func) (struct vty *);
+
+ /* Vector of this node's command list. */
+ vector cmd_vector;
+};
+
+enum {
+ CMD_ATTR_DEPRECATED = 1,
+ CMD_ATTR_HIDDEN,
+};
+
+/* Structure of command element. */
+struct cmd_element {
+ const char *string; /* Command specification by string. */
+ int (*func) (struct cmd_element *, struct vty *, int, const char *[]);
+ const char *doc; /* Documentation of this command. */
+ int daemon; /* Daemon to which this command belong. */
+ vector strvec; /* Pointing out each description vector. */
+ unsigned int cmdsize; /* Command index count. */
+ char *config; /* Configuration string */
+ vector subconfig; /* Sub configuration string */
+ u_char attr; /* Command attributes */
+};
+
+/* Command description structure. */
+struct desc {
+ const char *cmd; /* Command string. */
+ const char *str; /* Command's description. */
+};
+
+/* Return value of the commands. */
+#define CMD_SUCCESS 0
+#define CMD_WARNING 1
+#define CMD_ERR_NO_MATCH 2
+#define CMD_ERR_AMBIGUOUS 3
+#define CMD_ERR_INCOMPLETE 4
+#define CMD_ERR_EXEED_ARGC_MAX 5
+#define CMD_ERR_NOTHING_TODO 6
+#define CMD_COMPLETE_FULL_MATCH 7
+#define CMD_COMPLETE_MATCH 8
+#define CMD_COMPLETE_LIST_MATCH 9
+#define CMD_SUCCESS_DAEMON 10
+
+/* Argc max counts. */
+#define CMD_ARGC_MAX 25
+
+/* Turn off these macros when uisng cpp with extract.pl */
+#ifndef VTYSH_EXTRACT_PL
+
+/* helper defines for end-user DEFUN* macros */
+#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
+ struct cmd_element cmdname = \
+ { \
+ .string = cmdstr, \
+ .func = funcname, \
+ .doc = helpstr, \
+ .attr = attrs, \
+ .daemon = dnum, \
+ };
+
+#define DEFUN_CMD_FUNC_DECL(funcname) \
+ static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \
+
+#define DEFUN_CMD_FUNC_TEXT(funcname) \
+ static int funcname \
+ (struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
+
+/* DEFUN for vty command interafce. Little bit hacky ;-). */
+#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_FUNC_DECL(funcname) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
+ DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
+ DEFUN_CMD_FUNC_DECL(funcname) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
+ DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
+
+#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
+
+/* DEFUN_NOSH for commands that vtysh should ignore */
+#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN(funcname, cmdname, cmdstr, helpstr)
+
+/* DEFSH for vtysh. */
+#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) \
+
+/* DEFUN + DEFSH */
+#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_FUNC_DECL(funcname) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \
+ DEFUN_CMD_FUNC_TEXT(funcname)
+
+/* DEFUN + DEFSH with attributes */
+#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \
+ DEFUN_CMD_FUNC_DECL(funcname) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \
+ DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
+
+#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED)
+
+/* ALIAS macro which define existing command's alias. */
+#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
+
+#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
+
+#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0)
+
+#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0)
+
+#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon)
+
+#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon)
+
+#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
+ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon)
+
+#endif /* VTYSH_EXTRACT_PL */
+
+/* Some macroes */
+#define CMD_OPTION(S) ((S[0]) == '[')
+#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
+#define CMD_VARARG(S) ((S[0]) == '.')
+#define CMD_RANGE(S) ((S[0] == '<'))
+
+#define CMD_IPV4(S) ((strcmp ((S), "A.B.C.D") == 0))
+#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
+#define CMD_IPV6(S) ((strcmp ((S), "X:X::X:X") == 0))
+#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
+
+/* Common descriptions. */
+#define SHOW_STR "Show running system information\n"
+#define IP_STR "IP information\n"
+#define IPV6_STR "IPv6 information\n"
+#define NO_STR "Negate a command or set its defaults\n"
+#define CLEAR_STR "Reset functions\n"
+#define RIP_STR "RIP information\n"
+#define BGP_STR "BGP information\n"
+#define OSPF_STR "OSPF information\n"
+#define NEIGHBOR_STR "Specify neighbor router\n"
+#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
+#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
+#define ROUTER_STR "Enable a routing process\n"
+#define AS_STR "AS number\n"
+#define MBGP_STR "MBGP information\n"
+#define MATCH_STR "Match values from routing table\n"
+#define SET_STR "Set values in destination routing protocol\n"
+#define OUT_STR "Filter outgoing routing updates\n"
+#define IN_STR "Filter incoming routing updates\n"
+#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
+#define OSPF6_NUMBER_STR "Specify by number\n"
+#define INTERFACE_STR "Interface infomation\n"
+#define IFNAME_STR "Interface name(e.g. ep0)\n"
+#define IP6_STR "IPv6 Information\n"
+#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
+#define OSPF6_ROUTER_STR "Enable a routing process\n"
+#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
+#define SECONDS_STR "<1-65535> Seconds\n"
+#define ROUTE_STR "Routing Table\n"
+#define PREFIX_LIST_STR "Build a prefix list\n"
+#define OSPF6_DUMP_TYPE_LIST \
+"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
+#define ISIS_STR "IS-IS information\n"
+#define AREA_TAG_STR "[area tag]\n"
+
+#define CONF_BACKUP_EXT ".sav"
+
+/* IPv4 only machine should not accept IPv6 address for peer's IP
+ address. So we replace VTY command string like below. */
+#ifdef HAVE_IPV6
+#define NEIGHBOR_CMD "neighbor (A.B.C.D|X:X::X:X) "
+#define NO_NEIGHBOR_CMD "no neighbor (A.B.C.D|X:X::X:X) "
+#define NEIGHBOR_ADDR_STR "Neighbor address\nIPv6 address\n"
+#define NEIGHBOR_CMD2 "neighbor (A.B.C.D|X:X::X:X|WORD) "
+#define NO_NEIGHBOR_CMD2 "no neighbor (A.B.C.D|X:X::X:X|WORD) "
+#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nNeighbor tag\n"
+#else
+#define NEIGHBOR_CMD "neighbor A.B.C.D "
+#define NO_NEIGHBOR_CMD "no neighbor A.B.C.D "
+#define NEIGHBOR_ADDR_STR "Neighbor address\n"
+#define NEIGHBOR_CMD2 "neighbor (A.B.C.D|WORD) "
+#define NO_NEIGHBOR_CMD2 "no neighbor (A.B.C.D|WORD) "
+#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor tag\n"
+#endif /* HAVE_IPV6 */
+
+/* Prototypes. */
+void install_node(struct cmd_node *, int (*)(struct vty *));
+void install_default(enum node_type);
+void install_element(enum node_type, struct cmd_element *);
+void sort_node();
+
+/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
+ string with a space between each element (allocated using
+ XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */
+char *argv_concat(const char **argv, int argc, int shift);
+
+vector cmd_make_strvec(const char *);
+void cmd_free_strvec(vector);
+vector cmd_describe_command();
+char **cmd_complete_command();
+const char *cmd_prompt(enum node_type);
+int config_from_file(struct vty *, FILE *);
+enum node_type node_parent(enum node_type);
+int cmd_execute_command(vector, struct vty *, struct cmd_element **, int);
+int cmd_execute_command_strict(vector, struct vty *, struct cmd_element **);
+void config_replace_string(struct cmd_element *, char *, ...);
+void cmd_init(int);
+
+/* Export typical functions. */
+extern struct cmd_element config_end_cmd;
+extern struct cmd_element config_exit_cmd;
+extern struct cmd_element config_quit_cmd;
+extern struct cmd_element config_help_cmd;
+extern struct cmd_element config_list_cmd;
+char *host_config_file();
+void host_config_set(char *);
+
+void print_version(const char *);
+
+#endif /* _ZEBRA_COMMAND_H */
diff --git a/openbsc/include/vty/vector.h b/openbsc/include/vty/vector.h
new file mode 100644
index 000000000..00f0079f3
--- /dev/null
+++ b/openbsc/include/vty/vector.h
@@ -0,0 +1,62 @@
+/*
+ * Generic vector interface header.
+ * Copyright (C) 1997, 98 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_VECTOR_H
+#define _ZEBRA_VECTOR_H
+
+/* struct for vector */
+struct _vector {
+ unsigned int active; /* number of active slots */
+ unsigned int alloced; /* number of allocated slot */
+ void **index; /* index to data */
+};
+typedef struct _vector *vector;
+
+#define VECTOR_MIN_SIZE 1
+
+/* (Sometimes) usefull macros. This macro convert index expression to
+ array expression. */
+/* Reference slot at given index, caller must ensure slot is active */
+#define vector_slot(V,I) ((V)->index[(I)])
+/* Number of active slots.
+ * Note that this differs from vector_count() as it the count returned
+ * will include any empty slots
+ */
+#define vector_active(V) ((V)->active)
+
+/* Prototypes. */
+vector vector_init(unsigned int size);
+void vector_ensure(vector v, unsigned int num);
+int vector_empty_slot(vector v);
+int vector_set(vector v, void *val);
+int vector_set_index(vector v, unsigned int i, void *val);
+void vector_unset(vector v, unsigned int i);
+unsigned int vector_count(vector v);
+void vector_only_wrapper_free(vector v);
+void vector_only_index_free(void *index);
+void vector_free(vector v);
+vector vector_copy(vector v);
+
+void *vector_lookup(vector, unsigned int);
+void *vector_lookup_ensure(vector, unsigned int);
+
+#endif /* _ZEBRA_VECTOR_H */
diff --git a/openbsc/include/vty/vty.h b/openbsc/include/vty/vty.h
new file mode 100644
index 000000000..4bb785b9f
--- /dev/null
+++ b/openbsc/include/vty/vty.h
@@ -0,0 +1,150 @@
+#ifndef _VTY_H
+#define _VTY_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* GCC have printf type attribute check. */
+#ifdef __GNUC__
+#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#else
+#define PRINTF_ATTRIBUTE(a,b)
+#endif /* __GNUC__ */
+
+/* Does the I/O error indicate that the operation should be retried later? */
+#define ERRNO_IO_RETRY(EN) \
+ (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
+
+/* Vty read buffer size. */
+#define VTY_READ_BUFSIZ 512
+
+#define VTY_BUFSIZ 512
+#define VTY_MAXHIST 20
+
+/* Vty events */
+enum event {
+ VTY_SERV,
+ VTY_READ,
+ VTY_WRITE,
+ VTY_TIMEOUT_RESET,
+#ifdef VTYSH
+ VTYSH_SERV,
+ VTYSH_READ,
+ VTYSH_WRITE
+#endif /* VTYSH */
+};
+
+struct vty {
+ FILE *file;
+
+ /* private data, specified by creator */
+ void *priv;
+
+ /* File descripter of this vty. */
+ int fd;
+
+ /* Is this vty connect to file or not */
+ enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
+
+ /* Node status of this vty */
+ int node;
+
+ /* Failure count */
+ int fail;
+
+ /* Output buffer. */
+ struct buffer *obuf;
+
+ /* Command input buffer */
+ char *buf;
+
+ /* Command cursor point */
+ int cp;
+
+ /* Command length */
+ int length;
+
+ /* Command max length. */
+ int max;
+
+ /* Histry of command */
+ char *hist[VTY_MAXHIST];
+
+ /* History lookup current point */
+ int hp;
+
+ /* History insert end point */
+ int hindex;
+
+ /* For current referencing point of interface, route-map,
+ access-list etc... */
+ void *index;
+
+ /* For multiple level index treatment such as key chain and key. */
+ void *index_sub;
+
+ /* For escape character. */
+ unsigned char escape;
+
+ /* Current vty status. */
+ enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;
+
+ /* IAC handling: was the last character received the IAC
+ * (interpret-as-command) escape character (and therefore the next
+ * character will be the command code)? Refer to Telnet RFC 854. */
+ unsigned char iac;
+
+ /* IAC SB (option subnegotiation) handling */
+ unsigned char iac_sb_in_progress;
+ /* At the moment, we care only about the NAWS (window size) negotiation,
+ * and that requires just a 5-character buffer (RFC 1073):
+ * <NAWS char> <16-bit width> <16-bit height> */
+#define TELNET_NAWS_SB_LEN 5
+ unsigned char sb_buf[TELNET_NAWS_SB_LEN];
+ /* How many subnegotiation characters have we received? We just drop
+ * those that do not fit in the buffer. */
+ size_t sb_len;
+
+ /* Window width/height. */
+ int width;
+ int height;
+
+ /* Configure lines. */
+ int lines;
+
+ int monitor;
+
+ /* In configure mode. */
+ int config;
+};
+
+/* Small macro to determine newline is newline only or linefeed needed. */
+#define VTY_NEWLINE ((vty->type == VTY_TERM) ? "\r\n" : "\n")
+
+static inline char *vty_newline(struct vty *vty)
+{
+ return VTY_NEWLINE;
+}
+
+/* Prototypes. */
+void vty_init (void);
+void vty_init_vtysh (void);
+void vty_reset (void);
+struct vty *vty_new (void);
+struct vty *vty_create (int vty_sock, void *priv);
+int vty_out (struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3);
+int vty_out_newline(struct vty *);
+int vty_read(struct vty *vty);
+void vty_read_config (char *, char *);
+void vty_time_print (struct vty *, int);
+void vty_close (struct vty *);
+char *vty_get_cwd (void);
+void vty_log (const char *level, const char *proto, const char *fmt, va_list);
+int vty_config_lock (struct vty *);
+int vty_config_unlock (struct vty *);
+int vty_shell (struct vty *);
+int vty_shell_serv (struct vty *);
+void vty_hello (struct vty *);
+
+
+#endif