Compare commits

...

54 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
bb53004d47 Tag on-waves 0.2 release 2010-01-07 15:12:23 +01:00
Holger Hans Peter Freyther
6af20842cb [bssap] Return u_int16_t from the get_*_code methods
The LAI generation wants to have 16bit unsigned, just keep
them like this already. This means the int32_t will be truncated
inside the get_*_code methods which is better than doing it
somewhere else.
2010-01-07 14:53:18 +01:00
Holger Hans Peter Freyther
cc41cb07e7 [bssap] More brown paper... Make variables really signed
-1 is assigned in case the variables are not set. This means
it must be a signed type (as the comment says), now really use
a signed type.
2010-01-07 14:52:35 +01:00
Holger Hans Peter Freyther
d6fb23523a [bssap] Fix brown paper bag... Keep the air id ...*sigh*
We want to use the real number on the Um... Using the core
network code is totally wrong in this scope...
2010-01-07 14:36:20 +01:00
Holger Hans Peter Freyther
2aa0b45cc0 [bssap] Allow to use a different country code too
* Be able to have a country code in the air but use a different
  country code when talking to the core network.
* Now both country and network code can be different on air and
  on the MSC communication.
2010-01-07 03:17:01 +01:00
Holger Hans Peter Freyther
619df61ad2 [rsl] Partial revert of the GSM speech mode for the nanoBTS
This is partially reverting 0603c9d9e5,
it is true that the ip.access Wireshark dissectors differentiate
TCH/H from TCH/F but in my test I'm unable to send RTP on to the
BTS. It might be that the RTP payload provided in the MDCX is not
the one it will accept with the 0x05 mode. More work needs to be
done to understand this, that is the reason it is comitted to the
on-waves's branch instead of master.
2010-01-06 11:44:26 +01:00
Holger Hans Peter Freyther
893ea65f38 [bsc_msc_ip] Turn the MNC hack into a config option
* Make it possible to have a different MNC in the RSL traffic
  than in the core network.
* Introduce the "core network code NUMBER" variable. If it is
  set this network code will be used in traffic with the MSC.
* Use the core_network_code number when sending a packet to
  the MSC
* Regenerate the LAI (this is where I could have a bug) when
  sending packets to the BTS.
* Add size checks.

This is not tested, I might got something wrong.
2010-01-05 13:57:45 +01:00
Holger Hans Peter Freyther
64b811f113 [bsc_mgcp] Set the right remote rtp and rtcp port
* It is the same as local endpoint port
2010-01-05 12:35:16 +01:00
Holger Hans Peter Freyther
91fc9bf862 [bsc_mgcp] Fix writing of the config file...
* Add the new forward audio option
2010-01-05 12:29:36 +01:00
Holger Hans Peter Freyther
111a58dd37 [bsc_mgcp] Print a message which mode is configured 2010-01-05 12:25:25 +01:00
Holger Hans Peter Freyther
d1a2563a74 [bsc_mgcp] Add a new forward only mode to the bsc_mgcp
With forward IP in the config and early bind on we will
simply forward RTP data on the endpoints from BTS to the
forward IP address.

This is implemented by disabling MGCP functionality when
a forward IP address was specified, setting the forward IP
in the endp->remote and assigning a ci != CI_UNUSED.

Early bind will make sure the sockets are created, the BSC FD's
are registered and then the normal dispatch code will
do the forwarding.
2010-01-05 12:21:36 +01:00
Holger Hans Peter Freyther
7d3ef919ce [bssap] Set the right GSM08.08 speech version indicator
* For half rate we also need to set the 3rd bit to one
* See GSM08.08 §3.2.2.51 and then §3.2.2.11
2010-01-05 04:18:16 +01:00
Holger Hans Peter Freyther
cba98d87d6 [misc] Move handover into libmsc.a
Handover is a high level decision, it can span multiple BSCs
and belongs mostly into the MSC domain.
2009-12-22 08:03:55 +01:00
Holger Hans Peter Freyther
5c18ad0829 Merge commit 'origin/master' into on-waves/bsc-master
Conflicts:
	openbsc/include/openbsc/Makefile.am
	openbsc/include/openbsc/gsm_data.h
	openbsc/src/Makefile.am
	openbsc/src/abis_rsl.c
	openbsc/src/chan_alloc.c
	openbsc/src/gsm_04_08.c
	openbsc/src/gsm_data.c
	openbsc/src/vty_interface.c

The biggest problem is the moving of the RTP code into
the RSL layer. This may break quite some things...
2009-12-22 08:02:13 +01:00
Holger Hans Peter Freyther
0d9ed87d5c [bsc_hack] Ignore the sigpipe...
We might read or write on the OML link when the BTS is
reset and will get SIGPIPE interrupt and be gone... Just
ignore the SIGPIPE we will get the "exception" on the next
run of bsc_select and kill the (old) OML link.
2009-12-06 04:32:27 +01:00
Harald Welte
ec7be0c969 move RTP socket information from timeslot to lchan
With ip.access, in case of TCH/H, we have one RTP stream for each half-slot
(lchan), not just one per on-air timeslot.  This is quite different from
a classic BTS where the TRAU frames of the two TCH/H channels would be
part of the same 16k sub-slot in a E1 timeslot.
2009-12-06 04:05:31 +01:00
Harald Welte
9be3347601 RSL: catch inconsistent parameters ofr channel_mode_from_lchan() 2009-12-06 04:03:55 +01:00
Harald Welte
3eef7b7d81 Assign default values for T3101 and T3113
Without those default values, old config files will no longer work
after commit 23975e718f
2009-12-06 04:03:23 +01:00
Holger Hans Peter Freyther
9de4a6daa9 Merge branch 'master' into on-waves/bsc-master
Conflicts:
	openbsc/src/abis_nm.c
	openbsc/src/bsc_init.c
	openbsc/src/vty_interface.c
2009-11-24 19:58:01 +01:00
Holger Hans Peter Freyther
851ace9f33 Merge branch 'master' into on-waves/bsc-master
Conflicts:
	openbsc/include/openbsc/Makefile.am
	openbsc/src/Makefile.am
2009-11-20 18:01:37 +01:00
Holger Hans Peter Freyther
d1dd069b48 [configure] Add onwaves to the version tag 2009-11-20 17:43:40 +01:00
Holger Hans Peter Freyther
401db32ca2 HACK patch the network code..
Report to the MSC with the right code and patch
it on the air...
2009-11-20 17:41:05 +01:00
Holger Hans Peter Freyther
17e03d21d2 [vty] Add option to disable RF on a given TRX.
- Make sure that on runtime the Radio Carrier can be
  locked and unlocked. The vty code calls into the
  Abis NM to lock/unlock the channel and the state is
  stored there.

- Make sure that on start the Radio Carries remains
  offline and we are not starting it. On start the
  radio carrier is either locked or unlocked. This means
  the RSL will not connect until the RF is unlocked. It
  will connect then. To see RSL bringup failures one
  needs to parse the RSL nack message.
2009-11-20 17:40:50 +01:00
Holger Hans Peter Freyther
26a9bff201 [bsc_init] Activate the RC and the RSL link from the Software Activated Callback
On cold start the RSL link will not be brought up. Wait for the
Software to be Activated before starting the RSL link. This is
working reliable on the BTS I have tested with.
2009-11-20 17:40:39 +01:00
Holger Hans Peter Freyther
80fb260a60 [lchan] Release the channel ones its' usecount drops to zero
Remove the timer handling from the LCHAN and release the
channel ones the use count is dropping to zero.

Change code that was sending/using the lchan after the
release and change the send data method to warn in case
the lchan is used after it has been freed.
2009-11-20 17:40:28 +01:00
Holger Hans Peter Freyther
55a0716da7 [bssap] Open a traffic channel for the paging any reason
In the case the MS is requesting a channel with the
paging any channel reason, use a TCH. This allows us
to keep using very early assignment and the SDCCHs are
kept free for location updating requests.
2009-11-20 17:40:00 +01:00
Holger Hans Peter Freyther
c88fb75616 [rsl] Speculative crash fix in the RSL rcv message
The theory is that the BTS is almost dead and sends out
a incomplete message and we crash with that. I have not
been able to completely verify that.
2009-11-20 17:38:47 +01:00
Holger Hans Peter Freyther
d55a4dc326 Merge branch 'on-waves/gsm0808' into on-waves/bsc-master 2009-11-20 17:38:02 +01:00
Holger Hans Peter Freyther
a4e6f2e6e1 [bssap] Support multiple multiplexers in the assignment command
When more than one trunk group is allocated to the BSC the
MSC will start to assign channels from the different multiplexer.

We will map them the following way onto MGCP endpoints

Multiplex 0:
   0	->	1
   1	->      signalling
   2	->	2
   ..	->	..
   16	->	signalling (might be 15)
   30	->	30

Multiplex 1:
   0	->	31
   2	->	32
...

Multiplex 3:
..
2009-11-20 17:35:47 +01:00
Holger Hans Peter Freyther
7f71d99cc3 [bsc] Add a rtp base port to the BSC config too
Stop having a global variable... keep it in the
gsm network or the mgcp
2009-11-20 17:35:47 +01:00
Holger Hans Peter Freyther
b92167cf80 [vty] Write out BSC specific network parameters too 2009-11-20 17:35:47 +01:00
Holger Hans Peter Freyther
4b6a6dbe7e [bssap] Cope with weird channel mapping on the network side
The timeslot of the network maps the following way
	0	->	1
	1	->	n/a
	2	->	2
	...	->      ...
	31	->	31
2009-11-20 17:35:47 +01:00
Holger Hans Peter Freyther
763e8c7766 [ipacc] Add a way to override the rtp payload for MDCX 2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
823ff16088 [bsc] Send the SCCP IT message in a given interval
Send the message every 60 seconds on every SCCP
connection. The 60 seconds were taken from a protocol
trace obtained on the network.
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
6f93c6a1e0 [bsc] Unref the lchan when the MSC is closing the SCCP connection
Currently we are not sending the Inactivity Test message so the
MSC will close the specific sccp connection but we would keep the
lchan open and then end up with resource issues.

Change the code to close the lchan before closing the SCCP connection..
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
f97e48b0de [bssap] Send multirate config for HR AMR with 5.9k
Send a hardcoded multirate config when usin the
AMR codec. This should be more configurable in
the future.
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
761600b0fd [bsc] Add a test_mode function that can be used to inject packages
This method can be called from the main method to inject
a test message into a "fake" network with sccp connection.
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
8549462bc6 [bssap] Attempt to allow selecting the speech mode from config
It is possible to specify a list of possible speech codecs
and we will try to match the assignment command with the
one from the config file. This is not tested yet and we have
one problem. We assume we can modify the channel to hold
the speech value... this will require more work.
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
436e5c6308 [vty] Add configuration for the preferred speech version
Add network configuration option to specify which audio
codecs are supported by the BTS. This allows the BSC to
pick the audio codec in the GSM0808 Assignment Request.
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
f8b9d844c1 [bssap] Pick the A5/0 vs A5/1 setting from the gsm_network
Follow the configuration of the gsm network. If the Cipher
Mode Request does not allow our preferred format we will
reject it. Otherwise send the cipher mode command to the
mobile station. This code is mostly untested.
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
58ec07d580 [bsc] Add BSC specific config option... currently and empty show is implemented
In the future this should give a list of SCCP connections
and their allocated radio resources/users...
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
71465c21f4 [bssap] Implement generating a classmark update message
Generate a classmark update message from a given payload
this might need to be changed to get the version2 and
version3 parameters
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
16d0a833f8 [bssmap] Fix the chosen encryption in assignment complete
Send the RSL value... it is the right value
2009-11-20 17:35:46 +01:00
Holger Hans Peter Freyther
ea72b62cac [bssmap] Unconditionally include the chosen encryption in cipher mode complete 2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
49a84ec6e9 [bssmap] Assignment handling fixes and improvements
- Fix the generation of the assignment failure message
- Parse the permitted indicator of the assignment request message
2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
42c636b6c8 [bssap] Fix generation of the failure message 2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
a0a55f555e [bssap] Only start establish when the link is not yet established
This is fixing a bug when we try to submit a SMS from the MS to
the network. We send the RLS ESTABLISH REQUEST but as the MS
already established this SAPI we waited for the timeout and failed..
2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
23ed00e410 [bssap] Improve log messages... 2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
3fe910b9f1 [bssap] First go at implementing channel assignment... 2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
097bdeb77d [bssap] First go at implementing ASSIGNMENT REQUEST 2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
1b85de02e0 [bssap] Add a "#warning" that cipher mode is not properly handled 2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
2281d1835f [bssap] Start to queue messages to the BTS and to the MSC
For the MSC we need to queue GSM04.08 messages until the
SCCP connection is  confirmed to be open and then can send
the stored messages. The queue is limited to 10 messages
at which point new ones will be dropped. Currently the
only messages we get are measurement indication messages
but it is better to be safe than sorry.

The SCCP messages are sent as soon as the connection
is considered established and then no queueing happens
any more. While replacing sccp_connection_write calls
various memory leaks has been fixed.

For the MS we might have received a DTAP and need to do
an operation that requires a roundtrip and want to send
wait until this has happened. The two scenerios are sending
a SMS to the phone that requires to do something special
for the different SAPI. Currently it is assumed that
only one SAPI=0 -> SAPI=3 change happen during the connection.

For the first SAPI != 0 we will send the rll_ request
and then wait for the timeout or confirmation. In case
of timeout a SAPI "n" reject is sent and in case of
success the queue is getting emptied.
2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
fb4433a129 [bssap] Implement SAPI "N" Reject message
This message will be needed when no RLL connection
on a different SAPI can be established or we don't
want to establish it.
2009-11-20 17:35:45 +01:00
Holger Hans Peter Freyther
d954dcf9e1 [bsc_msc_ip] This is a BSC that connects to real MSC via IP
This is a BSC to be used by on-waves.com to connect to a real
MSC using SCCP over IP.

The following messages and features are currently implemented:
    - IPA identity ack's
    - COMPLETE LAYER3 INFORMATION
    - DTAP
    - PAGING COMMAND
    - CLEAR COMPLETE/CLEAR REQUEST
    - CIPHER MODE COMMAND/ REJECT /COMPLETE

It comes with a tool to create the enum's from the spec and
a very simple test server to do the handshaking.
2009-11-20 17:35:45 +01:00
27 changed files with 2762 additions and 120 deletions

View File

@@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script dnl Process this file with autoconf to produce a configure script
AC_INIT AC_INIT
AM_INIT_AUTOMAKE(openbsc, 0.0alpha1) AM_INIT_AUTOMAKE(openbsc, 0.2onwaves)
dnl kernel style compile messages dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

2
openbsc/contrib/README Normal file
View File

@@ -0,0 +1,2 @@
This contains a set of scripts used for the development of the
MSC functionality.

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python
import sys
# packages
ACK ="\x00\x01\xfe\x06"
RESET_ACK = "\x00\x13\xfd\x09\x00\x03\x07\x0b\x04\x43\x01\x00\xfe\x04\x43\x5c\x00\xfe\x03\x00\x01\x31"
PAGE = "\x00\x20\xfd\x09\x00\x03\x07\x0b\x04\x43\x01\x00\xfe\x04\x43\x5c\x00\xfe\x10\x00\x0e\x52\x08\x08\x29\x42\x08\x05\x03\x12\x23\x42\x1a\x01\x06"
# simple handshake...
sys.stdout.write(ACK)
sys.stdout.flush()
sys.stdin.read(4)
# wait for some data and send reset ack
sys.stdin.read(21)
sys.stdout.write(RESET_ACK)
sys.stdout.flush()
sys.stdout.write(RESET_ACK)
sys.stdout.flush()
# page a subscriber
sys.stdout.write(PAGE)
sys.stdout.flush()
while True:
sys.stdin.read(1)

View File

@@ -5,4 +5,4 @@ noinst_HEADERS = abis_nm.h abis_rsl.h debug.h db.h gsm_04_08.h gsm_data.h \
gsm_utils.h ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \ gsm_utils.h ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \
bsc_rll.h mncc.h talloc.h transaction.h ussd.h gsm_04_80.h \ bsc_rll.h mncc.h talloc.h transaction.h ussd.h gsm_04_80.h \
silent_call.h mgcp.h meas_rep.h bitvec.h rest_octets.h \ silent_call.h mgcp.h meas_rep.h bitvec.h rest_octets.h \
system_information.h handover.h system_information.h handover.h bssap.h

View File

@@ -0,0 +1,333 @@
/* From GSM08.08 */
#ifndef BSSAP_H
#define BSSAP_H
#include <stdlib.h>
#include <openbsc/msgb.h>
#include <openbsc/gsm_data.h>
/*
* this is from GSM 03.03 CGI but is copied in GSM 08.08
* in § 3.2.2.27 for Cell Identifier List
*/
enum CELL_IDENT {
CELL_IDENT_WHOLE_GLOBAL = 0,
CELL_IDENT_LAC_AND_CI = 1,
CELL_IDENT_CI = 2,
CELL_IDENT_NO_CELL = 3,
CELL_IDENT_LAI_AND_LAC = 4,
CELL_IDENT_LAC = 5,
CELL_IDENT_BSS = 6,
CELL_IDENT_UTRAN_PLMN_LAC_RNC = 8,
CELL_IDENT_UTRAN_RNC = 9,
CELL_IDENT_UTRAN_LAC_RNC = 10,
};
/* GSM 08.06 § 6.3 */
enum BSSAP_MSG_TYPE {
BSSAP_MSG_BSS_MANAGEMENT = 0x0,
BSSAP_MSG_DTAP = 0x1,
};
struct bssmap_header {
u_int8_t type;
u_int8_t length;
} __attribute__((packed));
struct dtap_header {
u_int8_t type;
u_int8_t link_id;
u_int8_t length;
} __attribute__((packed));
enum BSS_MAP_MSG_TYPE {
BSS_MAP_MSG_RESERVED_0 = 0,
/* ASSIGNMENT MESSAGES */
BSS_MAP_MSG_ASSIGMENT_RQST = 1,
BSS_MAP_MSG_ASSIGMENT_COMPLETE = 2,
BSS_MAP_MSG_ASSIGMENT_FAILURE = 3,
/* HANDOVER MESSAGES */
BSS_MAP_MSG_HANDOVER_RQST = 16,
BSS_MAP_MSG_HANDOVER_REQUIRED = 17,
BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18,
BSS_MAP_MSG_HANDOVER_CMD = 19,
BSS_MAP_MSG_HANDOVER_COMPLETE = 20,
BSS_MAP_MSG_HANDOVER_SUCCEEDED = 21,
BSS_MAP_MSG_HANDOVER_FAILURE = 22,
BSS_MAP_MSG_HANDOVER_PERFORMED = 23,
BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE = 24,
BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25,
BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT = 26,
BSS_MAP_MSG_HANDOVER_DETECT = 27,
/* RELEASE MESSAGES */
BSS_MAP_MSG_CLEAR_CMD = 32,
BSS_MAP_MSG_CLEAR_COMPLETE = 33,
BSS_MAP_MSG_CLEAR_RQST = 34,
BSS_MAP_MSG_RESERVED_1 = 35,
BSS_MAP_MSG_RESERVED_2 = 36,
BSS_MAP_MSG_SAPI_N_REJECT = 37,
BSS_MAP_MSG_CONFUSION = 38,
/* OTHER CONNECTION RELATED MESSAGES */
BSS_MAP_MSG_SUSPEND = 40,
BSS_MAP_MSG_RESUME = 41,
BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42,
BSS_MAP_MSG_PERFORM_LOCATION_RQST = 43,
BSS_MAP_MSG_LSA_INFORMATION = 44,
BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE = 45,
BSS_MAP_MSG_PERFORM_LOCATION_ABORT = 46,
BSS_MAP_MSG_COMMON_ID = 47,
/* GENERAL MESSAGES */
BSS_MAP_MSG_RESET = 48,
BSS_MAP_MSG_RESET_ACKNOWLEDGE = 49,
BSS_MAP_MSG_OVERLOAD = 50,
BSS_MAP_MSG_RESERVED_3 = 51,
BSS_MAP_MSG_RESET_CIRCUIT = 52,
BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE = 53,
BSS_MAP_MSG_MSC_INVOKE_TRACE = 54,
BSS_MAP_MSG_BSS_INVOKE_TRACE = 55,
BSS_MAP_MSG_CONNECTIONLESS_INFORMATION = 58,
/* TERRESTRIAL RESOURCE MESSAGES */
BSS_MAP_MSG_BLOCK = 64,
BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE = 65,
BSS_MAP_MSG_UNBLOCK = 66,
BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE = 67,
BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK = 68,
BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE = 69,
BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK = 70,
BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71,
BSS_MAP_MSG_UNEQUIPPED_CIRCUIT = 72,
BSS_MAP_MSG_CHANGE_CIRCUIT = 78,
BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE = 79,
/* RADIO RESOURCE MESSAGES */
BSS_MAP_MSG_RESOURCE_RQST = 80,
BSS_MAP_MSG_RESOURCE_INDICATION = 81,
BSS_MAP_MSG_PAGING = 82,
BSS_MAP_MSG_CIPHER_MODE_CMD = 83,
BSS_MAP_MSG_CLASSMARK_UPDATE = 84,
BSS_MAP_MSG_CIPHER_MODE_COMPLETE = 85,
BSS_MAP_MSG_QUEUING_INDICATION = 86,
BSS_MAP_MSG_COMPLETE_LAYER_3 = 87,
BSS_MAP_MSG_CLASSMARK_RQST = 88,
BSS_MAP_MSG_CIPHER_MODE_REJECT = 89,
BSS_MAP_MSG_LOAD_INDICATION = 90,
/* VGCS/VBS */
BSS_MAP_MSG_VGCS_VBS_SETUP = 4,
BSS_MAP_MSG_VGCS_VBS_SETUP_ACK = 5,
BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE = 6,
BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST = 7,
BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT = 28,
BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29,
BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30,
BSS_MAP_MSG_UPLINK_RQST = 31,
BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE = 39,
BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION = 73,
BSS_MAP_MSG_UPLINK_RELEASE_INDICATION = 74,
BSS_MAP_MSG_UPLINK_REJECT_CMD = 75,
BSS_MAP_MSG_UPLINK_RELEASE_CMD = 76,
BSS_MAP_MSG_UPLINK_SEIZED_CMD = 77,
};
enum GSM0808_IE_CODING {
GSM0808_IE_CIRCUIT_IDENTITY_CODE = 1,
GSM0808_IE_RESERVED_0 = 2,
GSM0808_IE_RESOURCE_AVAILABLE = 3,
GSM0808_IE_CAUSE = 4,
GSM0808_IE_CELL_IDENTIFIER = 5,
GSM0808_IE_PRIORITY = 6,
GSM0808_IE_LAYER_3_HEADER_INFORMATION = 7,
GSM0808_IE_IMSI = 8,
GSM0808_IE_TMSI = 9,
GSM0808_IE_ENCRYPTION_INFORMATION = 10,
GSM0808_IE_CHANNEL_TYPE = 11,
GSM0808_IE_PERIODICITY = 12,
GSM0808_IE_EXTENDED_RESOURCE_INDICATOR = 13,
GSM0808_IE_NUMBER_OF_MSS = 14,
GSM0808_IE_RESERVED_1 = 15,
GSM0808_IE_RESERVED_2 = 16,
GSM0808_IE_RESERVED_3 = 17,
GSM0808_IE_CLASSMARK_INFORMATION_T2 = 18,
GSM0808_IE_CLASSMARK_INFORMATION_T3 = 19,
GSM0808_IE_INTERFERENCE_BAND_TO_USE = 20,
GSM0808_IE_RR_CAUSE = 21,
GSM0808_IE_RESERVED_4 = 22,
GSM0808_IE_LAYER_3_INFORMATION = 23,
GSM0808_IE_DLCI = 24,
GSM0808_IE_DOWNLINK_DTX_FLAG = 25,
GSM0808_IE_CELL_IDENTIFIER_LIST = 26,
GSM0808_IE_RESPONSE_RQST = 27,
GSM0808_IE_RESOURCE_INDICATION_METHOD = 28,
GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29,
GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST = 30,
GSM0808_IE_DIAGNOSTIC = 31,
GSM0808_IE_LAYER_3_MESSAGE_CONTENTS = 32,
GSM0808_IE_CHOSEN_CHANNEL = 33,
GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE = 34,
GSM0808_IE_CIPHER_RESPONSE_MODE = 35,
GSM0808_IE_CHANNEL_NEEDED = 36,
GSM0808_IE_TRACE_TYPE = 37,
GSM0808_IE_TRIGGERID = 38,
GSM0808_IE_TRACE_REFERENCE = 39,
GSM0808_IE_TRANSACTIONID = 40,
GSM0808_IE_MOBILE_IDENTITY = 41,
GSM0808_IE_OMCID = 42,
GSM0808_IE_FORWARD_INDICATOR = 43,
GSM0808_IE_CHOSEN_ENCR_ALG = 44,
GSM0808_IE_CIRCUIT_POOL = 45,
GSM0808_IE_CIRCUIT_POOL_LIST = 46,
GSM0808_IE_TIME_INDICATION = 47,
GSM0808_IE_RESOURCE_SITUATION = 48,
GSM0808_IE_CURRENT_CHANNEL_TYPE_1 = 49,
GSM0808_IE_QUEUEING_INDICATOR = 50,
GSM0808_IE_SPEECH_VERSION = 64,
GSM0808_IE_ASSIGNMENT_REQUIREMENT = 51,
GSM0808_IE_TALKER_FLAG = 53,
GSM0808_IE_CONNECTION_RELEASE_RQSTED = 54,
GSM0808_IE_GROUP_CALL_REFERENCE = 55,
GSM0808_IE_EMLPP_PRIORITY = 56,
GSM0808_IE_CONFIG_EVO_INDI = 57,
GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION = 58,
GSM0808_IE_LSA_IDENTIFIER = 59,
GSM0808_IE_LSA_IDENTIFIER_LIST = 60,
GSM0808_IE_LSA_INFORMATION = 61,
GSM0808_IE_LCS_QOS = 62,
GSM0808_IE_LSA_ACCESS_CTRL_SUPPR = 63,
GSM0808_IE_LCS_PRIORITY = 67,
GSM0808_IE_LOCATION_TYPE = 68,
GSM0808_IE_LOCATION_ESTIMATE = 69,
GSM0808_IE_POSITIONING_DATA = 70,
GSM0808_IE_LCS_CAUSE = 71,
GSM0808_IE_LCS_CLIENT_TYPE = 72,
GSM0808_IE_APDU = 73,
GSM0808_IE_NETWORK_ELEMENT_IDENTITY = 74,
GSM0808_IE_GPS_ASSISTANCE_DATA = 75,
GSM0808_IE_DECIPHERING_KEYS = 76,
GSM0808_IE_RETURN_ERROR_RQST = 77,
GSM0808_IE_RETURN_ERROR_CAUSE = 78,
GSM0808_IE_SEGMENTATION = 79,
GSM0808_IE_SERVICE_HANDOVER = 80,
GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS = 81,
GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82,
GSM0808_IE_RESERVED_5 = 65,
GSM0808_IE_RESERVED_6 = 66,
};
enum gsm0808_cause {
GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE = 0,
GSM0808_CAUSE_RADIO_INTERFACE_FAILURE = 1,
GSM0808_CAUSE_UPLINK_QUALITY = 2,
GSM0808_CAUSE_UPLINK_STRENGTH = 3,
GSM0808_CAUSE_DOWNLINK_QUALITY = 4,
GSM0808_CAUSE_DOWNLINK_STRENGTH = 5,
GSM0808_CAUSE_DISTANCE = 6,
GSM0808_CAUSE_O_AND_M_INTERVENTION = 7,
GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION = 8,
GSM0808_CAUSE_CALL_CONTROL = 9,
GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION = 10,
GSM0808_CAUSE_HANDOVER_SUCCESSFUL = 11,
GSM0808_CAUSE_BETTER_CELL = 12,
GSM0808_CAUSE_DIRECTED_RETRY = 13,
GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL = 14,
GSM0808_CAUSE_TRAFFIC = 15,
GSM0808_CAUSE_EQUIPMENT_FAILURE = 32,
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE = 33,
GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE = 34,
GSM0808_CAUSE_CCCH_OVERLOAD = 35,
GSM0808_CAUSE_PROCESSOR_OVERLOAD = 36,
GSM0808_CAUSE_BSS_NOT_EQUIPPED = 37,
GSM0808_CAUSE_MS_NOT_EQUIPPED = 38,
GSM0808_CAUSE_INVALID_CELL = 39,
GSM0808_CAUSE_TRAFFIC_LOAD = 40,
GSM0808_CAUSE_PREEMPTION = 41,
GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE = 48,
GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH = 49,
GSM0808_CAUSE_SWITCH_CIRCUIT_POOL = 50,
GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE = 51,
GSM0808_CAUSE_LSA_NOT_ALLOWED = 52,
GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED = 64,
GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED = 80,
GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS = 81,
GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING = 82,
GSM0808_CAUSE_INCORRECT_VALUE = 83,
GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE = 84,
GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT = 85,
GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC = 96,
};
/* GSM 08.08 3.2.2.11 Channel Type */
enum gsm0808_chan_indicator {
GSM0808_CHAN_SPEECH = 1,
GSM0808_CHAN_DATA = 2,
GSM0808_CHAN_SIGN = 3,
};
enum gsm0808_chan_rate_type_data {
GSM0808_DATA_FULL_BM = 0x8,
GSM0808_DATA_HALF_LM = 0x9,
GSM0808_DATA_FULL_RPREF = 0xa,
GSM0808_DATA_HALF_PREF = 0xb,
GSM0808_DATA_FULL_PREF_NO_CHANGE = 0x1a,
GSM0808_DATA_HALF_PREF_NO_CHANGE = 0x1b,
GSM0808_DATA_MULTI_MASK = 0x20,
GSM0808_DATA_MULTI_MASK_NO_CHANGE = 0x30,
};
enum gsm0808_chan_rate_type_speech {
GSM0808_SPEECH_FULL_BM = 0x8,
GSM0808_SPEECH_HALF_LM = 0x9,
GSM0808_SPEECH_FULL_PREF= 0xa,
GSM0808_SPEECH_HALF_PREF= 0xb,
GSM0808_SPEECH_FULL_PREF_NO_CHANGE = 0x1a,
GSM0808_SPEECH_HALF_PREF_NO_CHANGE = 0x1b,
GSM0808_SPEECH_PERM = 0xf,
GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f,
};
enum gsm0808_permitted_speech {
GSM0808_PERM_FR1 = 0x01,
GSM0808_PERM_FR2 = 0x11,
GSM0808_PERM_FR3 = 0x21,
GSM0808_PERM_HR1 = GSM0808_PERM_FR1 | 0x4,
GSM0808_PERM_HR2 = GSM0808_PERM_FR2 | 0x4,
GSM0808_PERM_HR3 = GSM0808_PERM_FR3 | 0x4,
};
int bssmap_rcvmsg_dt1(struct sccp_connection *conn, struct msgb *msg, unsigned int length);
int bssmap_rcvmsg_udt(struct gsm_network *net, struct msgb *msg, unsigned int length);
struct msgb *bssmap_create_layer3(struct msgb *msg);
struct msgb *bssmap_create_reset(void);
struct msgb *bssmap_create_clear_complete(void);
struct msgb *bssmap_create_cipher_complete(struct msgb *layer3);
struct msgb *bssmap_create_cipher_reject(u_int8_t cause);
struct msgb *bssmap_create_sapi_reject(u_int8_t link_id);
struct msgb *bssmap_create_assignment_completed(struct gsm_lchan *lchan, u_int8_t rr_cause);
struct msgb *bssmap_create_assignment_failure(u_int8_t cause, u_int8_t *rr_cause);
struct msgb *bssmap_create_classmark_update(const u_int8_t *classmark, u_int8_t length);
void gsm0808_send_assignment_failure(struct gsm_lchan *l, u_int8_t cause, u_int8_t *rr_value);
void gsm0808_send_assignment_compl(struct gsm_lchan *l, u_int8_t rr_value);
int dtap_rcvmsg(struct gsm_lchan *lchan, struct msgb *msg, unsigned int length);
struct msgb *dtap_create_msg(struct msgb *msg_l3, u_int8_t link_id);
void bsc_queue_connection_write(struct sccp_connection *conn, struct msgb *msg);
void bsc_free_queued(struct sccp_connection *conn);
void bsc_send_queued(struct sccp_connection *conn);
void bts_queue_send(struct msgb *msg, int link_id);
void bts_send_queued(struct bss_sccp_connection_data*);
void bts_free_queued(struct bss_sccp_connection_data*);
#endif

View File

@@ -23,6 +23,28 @@
#include "gsm_subscriber.h" #include "gsm_subscriber.h"
/*
* Refcounting for the lchan. If the refcount drops to zero
* the channel will send a RSL release request.
*/
#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); \
} 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); \
if (lchan->use_count <= 0) \
_lchan_release(lchan); \
} while(0);
/* Special allocator for C0 of BTS */ /* Special allocator for C0 of BTS */
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts, struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
enum gsm_phys_chan_config pchan); enum gsm_phys_chan_config pchan);
@@ -46,7 +68,7 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
/* Free a logical channel (SDCCH, TCH, ...) */ /* Free a logical channel (SDCCH, TCH, ...) */
void lchan_free(struct gsm_lchan *lchan); void lchan_free(struct gsm_lchan *lchan);
/* Consider releasing the channel */ /* internal.. do not use */
int lchan_auto_release(struct gsm_lchan *lchan); int _lchan_release(struct gsm_lchan *lchan);
#endif /* _CHAN_ALLOC_H */ #endif /* _CHAN_ALLOC_H */

View File

@@ -93,36 +93,49 @@ typedef int gsm_cbfn(unsigned int hooknum,
struct msgb *msg, struct msgb *msg,
void *data, void *param); void *data, void *param);
/*
* Use the channel. As side effect the lchannel recycle timer
* will be started.
*/
#define LCHAN_RELEASE_TIMEOUT 20, 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 */ /* communications link with a BTS */
struct gsm_bts_link { struct gsm_bts_link {
struct gsm_bts *bts; struct gsm_bts *bts;
}; };
struct sccp_connection;
struct gsm_lchan; struct gsm_lchan;
struct gsm_subscriber; struct gsm_subscriber;
struct gsm_mncc; struct gsm_mncc;
struct rtp_socket; struct rtp_socket;
/* BSC/MSC data holding them together */
struct bss_sccp_connection_data {
struct gsm_lchan *lchan;
struct sccp_connection *sccp;
int ciphering_handled : 1;
/* Timers... */
/* for assginment command */
struct timer_list T10;
/* for SCCP ... */
struct timer_list sccp_it;
/* audio handling */
int rtp_port;
/* Queue SCCP and GSM0408 messages */
struct llist_head gsm_queue;
unsigned int gsm_queue_size;
struct llist_head sccp_queue;
unsigned int sccp_queue_size;
};
#define GSM0808_T10_VALUE 6, 0
#define sccp_get_lchan(data_ctx) ((struct bss_sccp_connection_data *)data_ctx)->lchan
#define lchan_get_sccp(lchan) lchan->msc_data->sccp
struct bss_sccp_connection_data *bss_sccp_create_data();
void bss_sccp_free_data(struct bss_sccp_connection_data *);
/* Network Management State */ /* Network Management State */
struct gsm_nm_state { struct gsm_nm_state {
u_int8_t operational; u_int8_t operational;
@@ -201,9 +214,6 @@ struct gsm_lchan {
/* To whom we are allocated at the moment */ /* To whom we are allocated at the moment */
struct gsm_subscriber *subscr; struct gsm_subscriber *subscr;
/* Timer started to release the channel */
struct timer_list release_timer;
struct timer_list T3101; struct timer_list T3101;
/* Established data link layer services */ /* Established data link layer services */
@@ -214,6 +224,12 @@ struct gsm_lchan {
*/ */
struct gsm_loc_updating_operation *loc_operation; struct gsm_loc_updating_operation *loc_operation;
/*
* MSC handling...
*/
struct bss_sccp_connection_data *msc_data;
/* use count. how many users use this channel */ /* use count. how many users use this channel */
unsigned int use_count; unsigned int use_count;
@@ -509,6 +525,14 @@ enum gsm_auth_policy {
#define GSM_T3101_DEFAULT 10 #define GSM_T3101_DEFAULT 10
#define GSM_T3113_DEFAULT 60 #define GSM_T3113_DEFAULT 60
/*
* internal data for audio management
*/
struct gsm_audio_support {
u_int8_t hr : 1,
ver : 7;
};
struct gsm_network { struct gsm_network {
/* global parameters */ /* global parameters */
u_int16_t country_code; u_int16_t country_code;
@@ -539,6 +563,11 @@ struct gsm_network {
struct gsmnet_stats stats; struct gsmnet_stats stats;
struct gsm_audio_support **audio_support;
int audio_length;
int rtp_payload;
int rtp_base_port;
/* layer 4 */ /* layer 4 */
int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg); int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
struct llist_head upqueue; struct llist_head upqueue;
@@ -564,6 +593,10 @@ struct gsm_network {
struct { struct {
enum rrlp_mode mode; enum rrlp_mode mode;
} rrlp; } rrlp;
/* a hack for On Waves. It must be signed */
int32_t core_country_code;
int32_t core_network_code;
}; };
#define SMS_HDR_SIZE 128 #define SMS_HDR_SIZE 128

View File

@@ -81,6 +81,8 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
const char *ext); const char *ext);
struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net, struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
unsigned long long id); unsigned long long id);
struct gsm_subscriber *subscr_get_or_create(struct gsm_network *net,
const char *imsi);
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason); int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason);
void subscr_put_channel(struct gsm_lchan *lchan); void subscr_put_channel(struct gsm_lchan *lchan);
void subscr_get_channel(struct gsm_subscriber *subscr, void subscr_get_channel(struct gsm_subscriber *subscr,

View File

@@ -21,8 +21,6 @@
* *
*/ */
unsigned int rtp_base_port = 4000;
/** /**
* Calculate the RTP audio port for the given multiplex * Calculate the RTP audio port for the given multiplex
* and the direction. This allows a semi static endpoint * and the direction. This allows a semi static endpoint

View File

@@ -37,6 +37,7 @@ struct msgb {
unsigned char *l2h; unsigned char *l2h;
unsigned char *l3h; unsigned char *l3h;
unsigned char *smsh; unsigned char *smsh;
unsigned char *l4h;
u_int16_t data_len; u_int16_t data_len;
u_int16_t len; u_int16_t len;
@@ -55,6 +56,7 @@ extern void msgb_reset(struct msgb *m);
#define msgb_l2(m) ((void *)(m->l2h)) #define msgb_l2(m) ((void *)(m->l2h))
#define msgb_l3(m) ((void *)(m->l3h)) #define msgb_l3(m) ((void *)(m->l3h))
#define msgb_l4(m) ((void *)(m->l4h))
#define msgb_sms(m) ((void *)(m->smsh)) #define msgb_sms(m) ((void *)(m->smsh))
static inline unsigned int msgb_l2len(const struct msgb *msgb) static inline unsigned int msgb_l2len(const struct msgb *msgb)

View File

@@ -2,21 +2,22 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall AM_CFLAGS=-Wall
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \ sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \
isdnsync bsc_mgcp isdnsync bsc_mgcp bsc_msc_ip
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a
noinst_HEADERS = vty/cardshell.h noinst_HEADERS = vty/cardshell.h
libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
msgb.c select.c chan_alloc.c timer.c debug.c handover_logic.c \ msgb.c select.c chan_alloc.c timer.c debug.c \
gsm_subscriber_base.c subchan_demux.c bsc_rll.c transaction.c \ gsm_subscriber_base.c subchan_demux.c bsc_rll.c transaction.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \ trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \ input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \
talloc_ctx.c system_information.c bitvec.c rest_octets.c \ talloc_ctx.c system_information.c bitvec.c rest_octets.c \
handover_decision.c meas_rep.c rtp_proxy.c rtp_proxy.c telnet_interface.c
libmsc_a_SOURCES = gsm_subscriber.c db.c telnet_interface.c \ libmsc_a_SOURCES = gsm_subscriber.c db.c \
mncc.c gsm_04_08.c gsm_04_11.c transaction.c \ mncc.c gsm_04_08.c gsm_04_11.c transaction.c \
token_auth.c rrlp.c gsm_04_80.c ussd.c silent_call.c token_auth.c rrlp.c gsm_04_80.c ussd.c silent_call.c \
handover_logic.c handover_decision.c meas_rep.c
libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
@@ -25,6 +26,9 @@ libsccp_a_SOURCES = sccp/sccp.c
bsc_hack_SOURCES = bsc_hack.c bsc_init.c vty_interface.c vty_interface_layer3.c bsc_hack_SOURCES = bsc_hack.c bsc_init.c vty_interface.c vty_interface_layer3.c
bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libvty.a -ldl -ldbi $(LIBCRYPT) bsc_hack_LDADD = libmsc.a libbsc.a libmsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
bsc_msc_ip_SOURCES = bssap.c bsc_msc_ip.c bsc_init.c vty_interface.c vty_interface_bsc.c
bsc_msc_ip_LDADD = libbsc.a libvty.a libsccp.a
bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c msgb.c debug.c \ bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c msgb.c debug.c \
select.c timer.c rs232.c tlv_parser.c signal.c talloc.c select.c timer.c rs232.c tlv_parser.c signal.c talloc.c

View File

@@ -853,6 +853,10 @@ int rsl_data_request(struct msgb *msg, u_int8_t link_id)
return -EINVAL; return -EINVAL;
} }
if (msg->lchan->use_count <= 0) {
DEBUGP(DRSL, "BUG: Trying to send data on unused lchan\n");
}
/* First push the L3 IE tag and length */ /* First push the L3 IE tag and length */
msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len); msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
@@ -1477,31 +1481,11 @@ static u_int8_t ipa_smod_s_for_lchan(struct gsm_lchan *lchan)
{ {
switch (lchan->tch_mode) { switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1: case GSM48_CMODE_SPEECH_V1:
switch (lchan->type) { return 0x00;
case GSM_LCHAN_TCH_F:
return 0x00;
case GSM_LCHAN_TCH_H:
return 0x03;
default:
break;
}
case GSM48_CMODE_SPEECH_EFR: case GSM48_CMODE_SPEECH_EFR:
switch (lchan->type) { return 0x01;
case GSM_LCHAN_TCH_F:
return 0x01;
/* there's no half-rate EFR */
default:
break;
}
case GSM48_CMODE_SPEECH_AMR: case GSM48_CMODE_SPEECH_AMR:
switch (lchan->type) { return 0x02;
case GSM_LCHAN_TCH_F:
return 0x02;
case GSM_LCHAN_TCH_H:
return 0x05;
default:
break;
}
default: default:
break; break;
} }
@@ -1795,9 +1779,21 @@ static int abis_rsl_rx_ipacc(struct msgb *msg)
/* Entry-point where L2 RSL from BTS enters */ /* Entry-point where L2 RSL from BTS enters */
int abis_rsl_rcvmsg(struct msgb *msg) int abis_rsl_rcvmsg(struct msgb *msg)
{ {
struct abis_rsl_common_hdr *rslh = msgb_l2(msg) ; struct abis_rsl_common_hdr *rslh;
int rc = 0; int rc = 0;
if (!msg) {
DEBUGP(DRSL, "Empty RSL msg?..\n");
return -1;
}
if (msgb_l2len(msg) < sizeof(*rslh)) {
DEBUGP(DRSL, "Truncated RSL message with l2len: %u\n", msgb_l2len(msg));
return -1;
}
rslh = msgb_l2(msg);
switch (rslh->msg_discr & 0xfe) { switch (rslh->msg_discr & 0xfe) {
case ABIS_RSL_MDISC_RLL: case ABIS_RSL_MDISC_RLL:
rc = abis_rsl_rx_rll(msg); rc = abis_rsl_rx_rll(msg);

View File

@@ -356,12 +356,15 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
case NM_OC_SITE_MANAGER: case NM_OC_SITE_MANAGER:
bts = container_of(obj, struct gsm_bts, site_mgr); bts = container_of(obj, struct gsm_bts, site_mgr);
if (new_state->operational == 2 && if (new_state->operational == 2 &&
new_state->availability == NM_AVSTATE_OK) new_state->availability == NM_AVSTATE_OK) {
printf("STARTING SITE MANAGER\n");
abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff); abis_nm_opstart(bts, obj_class, 0xff, 0xff, 0xff);
}
break; break;
case NM_OC_BTS: case NM_OC_BTS:
bts = obj; bts = obj;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) { if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
printf("STARTING BTS...\n");
patch_nm_tables(bts); patch_nm_tables(bts);
abis_nm_set_bts_attr(bts, nanobts_attr_bts, abis_nm_set_bts_attr(bts, nanobts_attr_bts,
sizeof(nanobts_attr_bts)); sizeof(nanobts_attr_bts));
@@ -377,6 +380,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
trx = ts->trx; trx = ts->trx;
if (new_state->operational == 1 && if (new_state->operational == 1 &&
new_state->availability == NM_AVSTATE_DEPENDENCY) { new_state->availability == NM_AVSTATE_DEPENDENCY) {
printf("STARTING OC Channel...\n");
patch_nm_tables(trx->bts); patch_nm_tables(trx->bts);
enum abis_nm_chan_comb ccomb = enum abis_nm_chan_comb ccomb =
abis_nm_chcomb4pchan(ts->pchan); abis_nm_chcomb4pchan(ts->pchan);

View File

@@ -63,7 +63,9 @@ static const char *audio_name = "GSM-EFR/8000";
static int audio_payload = 97; static int audio_payload = 97;
static int audio_loop = 0; static int audio_loop = 0;
static int early_bind = 0; static int early_bind = 0;
static int rtp_base_port = 0;
static char *forward_ip = NULL;
static char *config_file = "mgcp.cfg"; static char *config_file = "mgcp.cfg";
/* used by msgb and mgcp */ /* used by msgb and mgcp */
@@ -909,6 +911,8 @@ static int config_write_mgcp(struct vty *vty)
vty_out(vty, " sdp audio payload name %s%s", audio_name, VTY_NEWLINE); vty_out(vty, " sdp audio payload name %s%s", audio_name, VTY_NEWLINE);
vty_out(vty, " loop %u%s", !!audio_loop, VTY_NEWLINE); vty_out(vty, " loop %u%s", !!audio_loop, VTY_NEWLINE);
vty_out(vty, " endpoints %u%s", number_endpoints, VTY_NEWLINE); vty_out(vty, " endpoints %u%s", number_endpoints, VTY_NEWLINE);
if (forward_ip)
vty_out(vty, " forward audio %s%s", forward_ip, VTY_NEWLINE);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@@ -1055,6 +1059,17 @@ DEFUN(cfg_mgcp_number_endp,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_mgcp_forward,
cfg_mgcp_forward_cmd,
"forward audio IP",
"Forward packets from and to the IP. This disables most of the MGCP feature.")
{
if (forward_ip)
talloc_free(forward_ip);
forward_ip = talloc_strdup(tall_bsc_ctx, argv[0]);
return CMD_SUCCESS;
}
int bsc_vty_init(struct gsm_network *dummy) int bsc_vty_init(struct gsm_network *dummy)
{ {
cmd_init(1); cmd_init(1);
@@ -1076,6 +1091,7 @@ int bsc_vty_init(struct gsm_network *dummy)
install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd); install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
install_element(MGCP_NODE, &cfg_mgcp_loop_cmd); install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd); install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
install_element(MGCP_NODE, &cfg_mgcp_forward_cmd);
return 0; return 0;
} }
@@ -1116,37 +1132,66 @@ int main(int argc, char** argv)
endpoints[i].ci = CI_UNUSED; endpoints[i].ci = CI_UNUSED;
} }
/* initialize the socket */ /*
bfd.when = BSC_FD_READ; * This application supports two modes.
bfd.cb = read_call_agent; * 1.) a true MGCP gateway with support for AUEP, CRCX, MDCX, DLCX
bfd.fd = socket(AF_INET, SOCK_DGRAM, 0); * 2.) plain forwarding of RTP packets on the endpoints.
if (bfd.fd < 0) { * both modes are mutual exclusive
perror("Gateway failed to listen"); */
return -1; if (forward_ip) {
}
setsockopt(bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (!early_bind) {
DEBUGP(DMGCP, "Forwarding requires early bind.\n");
return -1;
}
memset(&addr, 0, sizeof(addr)); /*
addr.sin_family = AF_INET; * Store the forward IP and assign a ci. For early bind
addr.sin_port = htons(source_port); * the sockets will be created after this.
inet_aton(source_addr, &addr.sin_addr); */
for (i = 1; i < number_endpoints; ++i) {
struct mgcp_endpoint *endp = &endpoints[i];
inet_aton(forward_ip, &endp->remote);
endp->ci = CI_UNUSED + 23;
endp->rtp = htons(rtp_calculate_port(ENDPOINT_NUMBER(endp), rtp_base_port));
endp->rtcp = htons(rtp_calculate_port(ENDPOINT_NUMBER(endp), rtp_base_port) + 1);
}
if (bind(bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { DEBUGP(DMGCP, "Configured for Audio Forwarding.\n");
perror("Gateway failed to bind"); } else {
return -1; bfd.when = BSC_FD_READ;
} bfd.cb = read_call_agent;
bfd.fd = socket(AF_INET, SOCK_DGRAM, 0);
if (bfd.fd < 0) {
perror("Gateway failed to listen");
return -1;
}
bfd.data = msgb_alloc(4096, "mgcp-msg"); setsockopt(bfd.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (!bfd.data) {
fprintf(stderr, "Gateway memory error.\n"); memset(&addr, 0, sizeof(addr));
return -1; addr.sin_family = AF_INET;
} addr.sin_port = htons(source_port);
inet_aton(source_addr, &addr.sin_addr);
if (bind(bfd.fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("Gateway failed to bind");
return -1;
}
bfd.data = msgb_alloc(4096, "mgcp-msg");
if (!bfd.data) {
fprintf(stderr, "Gateway memory error.\n");
return -1;
}
if (bsc_register_fd(&bfd) != 0) { if (bsc_register_fd(&bfd) != 0) {
DEBUGP(DMGCP, "Failed to register the fd\n"); DEBUGP(DMGCP, "Failed to register the fd\n");
return -1; return -1;
}
DEBUGP(DMGCP, "Configured for MGCP.\n");
} }
/* initialisation */ /* initialisation */

813
openbsc/src/bsc_msc_ip.c Normal file
View File

@@ -0,0 +1,813 @@
/* A hackish minimal BSC (+MSC +HLR) implementation */
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009 by on-waves.com
* 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 <unistd.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define _GNU_SOURCE
#include <getopt.h>
#include <openbsc/select.h>
#include <openbsc/debug.h>
#include <openbsc/e1_input.h>
#include <openbsc/talloc.h>
#include <openbsc/select.h>
#include <openbsc/ipaccess.h>
#include <openbsc/bssap.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
#include <openbsc/chan_alloc.h>
#include <sccp/sccp.h>
/* SCCP helper */
#define SCCP_IT_TIMER 60
/* MCC and MNC for the Location Area Identifier */
struct gsm_network *bsc_gsmnet = 0;
static const char *config_file = "openbsc.cfg";
static char *msc_address = "127.0.0.1";
static struct bsc_fd msc_connection;
static struct in_addr local_addr;
extern int ipacc_rtp_direct;
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
extern int bsc_shutdown_net(struct gsm_network *net);
struct bss_sccp_connection_data *bss_sccp_create_data()
{
struct bss_sccp_connection_data *data;
data = _talloc_zero(tall_bsc_ctx,
sizeof(struct bss_sccp_connection_data),
"bsc<->msc");
if (!data)
return NULL;
INIT_LLIST_HEAD(&data->sccp_queue);
INIT_LLIST_HEAD(&data->gsm_queue);
return data;
}
void bss_sccp_free_data(struct bss_sccp_connection_data *data)
{
bsc_del_timer(&data->T10);
bsc_del_timer(&data->sccp_it);
bsc_free_queued(data->sccp);
bts_free_queued(data);
talloc_free(data);
}
static void sccp_it_fired(void *_data)
{
struct bss_sccp_connection_data *data =
(struct bss_sccp_connection_data *) _data;
sccp_connection_send_it(data->sccp);
bsc_schedule_timer(&data->sccp_it, SCCP_IT_TIMER, 0);
}
/* GSM subscriber drop-ins */
extern struct llist_head *subscr_bsc_active_subscriber(void);
struct gsm_subscriber *find_subscriber(u_int8_t type, const char *mi_string)
{
struct gsm_subscriber *subscr;
u_int32_t tmsi = GSM_RESERVED_TMSI;
if (type == GSM_MI_TYPE_TMSI) {
tmsi = tmsi_from_string(mi_string);
if (tmsi == GSM_RESERVED_TMSI) {
DEBUGP(DMSC, "The TMSI is the reserved one.\n");
return NULL;
}
}
llist_for_each_entry(subscr, subscr_bsc_active_subscriber(), entry) {
if (type == GSM_MI_TYPE_TMSI && tmsi == subscr->tmsi) {
return subscr_get(subscr);
} else if (type == GSM_MI_TYPE_IMSI && strcmp(mi_string, subscr->imsi) == 0) {
return subscr_get(subscr);
}
}
DEBUGP(DMSC, "No subscriber has been found.\n");
return NULL;
}
/* SCCP handling */
void msc_outgoing_sccp_data(struct sccp_connection *conn, struct msgb *msg, unsigned int len)
{
struct bssmap_header *bs;
if (len < 1) {
DEBUGP(DMSC, "The header is too short.\n");
return;
}
switch (msg->l3h[0]) {
case BSSAP_MSG_BSS_MANAGEMENT:
msg->l4h = &msg->l3h[sizeof(*bs)];
msg->lchan = sccp_get_lchan(conn->data_ctx);
bssmap_rcvmsg_dt1(conn, msg, len - sizeof(*bs));
break;
case BSSAP_MSG_DTAP:
dtap_rcvmsg(sccp_get_lchan(conn->data_ctx), msg, len);
break;
default:
DEBUGPC(DMSC, "Unimplemented msg type: %d\n", msg->l3h[0]);
}
}
void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
{
if (conn->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
DEBUGP(DMSC, "Freeing sccp conn: %p state: %d\n", conn, conn->connection_state);
if (sccp_get_lchan(conn->data_ctx) != NULL) {
struct gsm_lchan *lchan = sccp_get_lchan(conn->data_ctx);
DEBUGP(DMSC, "ERROR: The lchan is still associated\n.");
lchan->msc_data = NULL;
put_lchan(lchan);
}
bss_sccp_free_data((struct bss_sccp_connection_data *)conn->data_ctx);
sccp_connection_free(conn);
return;
} else if (conn->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED) {
DEBUGP(DMSC, "Connection established: %p\n", conn);
bsc_send_queued(conn);
}
}
/*
* General COMPLETE LAYER3 INFORMATION handling for
* PAGING RESPONSE, LOCATION UPDATING REQUEST, CM REESTABLISHMENT REQUEST,
* CM SERVICE REQUEST, IMSI DETACH, IMMEDIATE SETUP.
*
* IMMEDIATE SETUP is coming from GROUP CC that is not yet
* supported...
*/
int open_sccp_connection(struct msgb *layer3)
{
struct bss_sccp_connection_data *con_data;
struct sccp_connection *sccp_connection;
struct msgb *data;
DEBUGP(DMSC, "Opening new layer3 connection\n");
sccp_connection = sccp_connection_socket();
if (!sccp_connection) {
DEBUGP(DMSC, "Failed to allocate memory.\n");
return -ENOMEM;
}
data = bssmap_create_layer3(layer3);
if (!data) {
DEBUGP(DMSC, "Failed to allocate complete layer3.\n");
sccp_connection_free(sccp_connection);
return -ENOMEM;
}
con_data = bss_sccp_create_data();
if (!con_data) {
DEBUGP(DMSC, "Failed to allocate bss<->msc data.\n");
sccp_connection_free(sccp_connection);
msgb_free(data);
return -ENOMEM;
}
/* initialize the bridge */
con_data->lchan = layer3->lchan;
con_data->sccp = sccp_connection;
sccp_connection->state_cb = msc_outgoing_sccp_state;
sccp_connection->data_cb = msc_outgoing_sccp_data;
sccp_connection->data_ctx = con_data;
layer3->lchan->msc_data = con_data;
/* start the inactivity test timer */
con_data->sccp_it.cb = sccp_it_fired;
con_data->sccp_it.data = con_data;
bsc_schedule_timer(&con_data->sccp_it, SCCP_IT_TIMER, 0);
/* FIXME: Use transaction for this */
use_lchan(layer3->lchan);
sccp_connection_connect(sccp_connection, &sccp_ssn_bssap, data);
msgb_free(data);
return 1;
}
/* figure out if this is the inial layer3 message */
static int send_dtap_or_open_connection(struct msgb *msg)
{
if (msg->lchan->msc_data) {
struct msgb *dtap = dtap_create_msg(msg, 0);
if (!dtap) {
DEBUGP(DMSC, "Creating a DTAP message failed.\n");
return -1;
}
bsc_queue_connection_write(lchan_get_sccp(msg->lchan), dtap);
return 1;
} else {
return open_sccp_connection(msg);
}
}
/* Receive a PAGING RESPONSE message from the MS */
static int handle_paging_response(struct msgb *msg)
{
struct gsm_subscriber *subscr;
char mi_string[GSM48_MI_SIZE];
u_int8_t mi_type;
gsm48_paging_extract_mi(msg, mi_string, &mi_type);
DEBUGP(DMSC, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
mi_type, mi_string);
subscr = find_subscriber(mi_type, mi_string);
if (!subscr)
return -EINVAL;
/* force the paging to stop at every bts */
subscr->lac = GSM_LAC_RESERVED_ALL_BTS;
if (gsm48_handle_paging_resp(msg, subscr) != 0) {
DEBUGP(DMSC, "Paging failed.\n");
return -1;
}
/* open a new transaction and SCCP connection */
return send_dtap_or_open_connection(msg);
}
/* Receive a CIPHER MODE COMPLETE from the MS */
static int handle_cipher_m_complete(struct msgb *msg)
{
struct msgb *resp;
DEBUGP(DMSC, "CIPHER MODE COMPLETE from MS, forwarding to MSC\n");
resp = bssmap_create_cipher_complete(msg);
if (!resp) {
DEBUGP(DMSC, "Creating MSC response failed.\n");
return -1;
}
/* handled this message */
bsc_queue_connection_write(lchan_get_sccp(msg->lchan), resp);
return 1;
}
/* Receive a ASSIGNMENT COMPLETE */
static int handle_ass_compl(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
DEBUGP(DMSC, "ASSIGNMENT COMPLETE from MS, forwarding to MSC\n");
if (!msg->lchan->msc_data) {
DEBUGP(DMSC, "No MSC data\n");
return -1;
}
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
DEBUGP(DMSC, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh));
return -1;
}
gsm0808_send_assignment_compl(msg->lchan, gh->data[0]);
return 1;
}
/*
* Receive a ASSIGNMENT FAILURE. If the message is failed
* to be parsed the T10 timer will send the failure.
*/
static int handle_ass_fail(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
DEBUGP(DMSC, "ASSIGNMENT FAILURE from MS, forwarding to MSC\n");
if (!msg->lchan->msc_data) {
DEBUGP(DMSC, "No MSC data\n");
return -1;
}
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
DEBUGP(DMSC, "assignment failure invalid: %d\n",
msgb_l3len(msg) - sizeof(*gh));
return -1;
}
gsm0808_send_assignment_failure(msg->lchan,
GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, &gh->data[0]);
return 1;
}
/*
* Receive a GSM04.08 MODIFY ACK. Actually we have to check
* the content to see if this was a success or not.
*/
static int handle_modify_ack(struct msgb *msg)
{
int rc;
/* modify RSL */
rc = gsm48_rx_rr_modif_ack(msg);
if (rc < 0)
gsm0808_send_assignment_failure(msg->lchan,
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
else
gsm0808_send_assignment_compl(msg->lchan, 0);
return 1;
}
/* Receive a GSM 04.08 Radio Resource (RR) message */
static int gsm0408_rcv_rr(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
int rc = 0;
switch (gh->msg_type) {
case GSM48_MT_RR_PAG_RESP:
rc = handle_paging_response(msg);
break;
case GSM48_MT_RR_MEAS_REP:
/* ignore measurement for now */
rc = -1;
break;
case GSM48_MT_RR_CIPH_M_COMPL:
rc = handle_cipher_m_complete(msg);
break;
case GSM48_MT_RR_ASS_COMPL:
rc = handle_ass_compl(msg);
break;
case GSM48_MT_RR_ASS_FAIL:
rc = handle_ass_fail(msg);
break;
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
rc = handle_modify_ack(msg);
break;
default:
break;
}
return rc;
}
/* Receive a GSM 04.08 Mobility Management (MM) message */
static int gsm0408_rcv_mm(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
int rc = 0;
switch (gh->msg_type & 0xbf) {
case GSM48_MT_MM_LOC_UPD_REQUEST:
case GSM48_MT_MM_CM_REEST_REQ:
case GSM48_MT_MM_CM_SERV_REQ:
case GSM48_MT_MM_IMSI_DETACH_IND:
rc = send_dtap_or_open_connection(msg);
break;
default:
break;
}
return rc;
}
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
{
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t pdisc = gh->proto_discr & 0x0f;
int rc = 0;
switch (pdisc) {
case GSM48_PDISC_RR:
rc = gsm0408_rcv_rr(msg);
break;
case GSM48_PDISC_MM:
rc = gsm0408_rcv_mm(msg);
break;
default:
break;
}
/*
* if we have a sccp connection and didn't handle the message
* forward it to the MSC using DTAP
*/
if (rc == 0 && msg->lchan->msc_data && lchan_get_sccp(msg->lchan)) {
struct msgb *dtap = dtap_create_msg(msg, link_id);
if (!dtap) {
DEBUGP(DMSC, "Creating a DTAP message failed.\n");
return -1;
}
bsc_queue_connection_write(lchan_get_sccp(msg->lchan), dtap);
}
return rc;
}
/* handle ipaccess signals */
static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct gsm_lchan *lchan = signal_data;
struct gsm_bts_trx_ts *ts;
int rc;
if (subsys != SS_ABISIP)
return 0;
ts = lchan->ts;
switch (signal) {
case S_ABISIP_CRCX_ACK:
/* we can ask it to connect now */
if (lchan->msc_data) {
DEBUGP(DMSC, "Connecting BTS to port: %d conn: %d\n",
lchan->msc_data->rtp_port, lchan->abis_ip.conn_id);
int rtp_payload = ts->trx->bts->network->rtp_payload;
if (rtp_payload == 0)
rtp_payload = lchan->abis_ip.rtp_payload2;
rc = rsl_ipacc_mdcx(lchan, ntohl(local_addr.s_addr),
lchan->msc_data->rtp_port,
rtp_payload);
if (rc < 0) {
DEBUGP(DMSC, "Failed to send connect: %d\n", rc);
return rc;
}
}
break;
case S_ABISIP_DLCX_IND:
break;
}
return 0;
}
static void print_usage()
{
printf("Usage: bsc_hack\n");
}
/*
* SCCP handling
*/
static int msc_sccp_write_ipa(struct msgb *msg, void *data)
{
int ret;
DEBUGP(DMSC, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
DEBUGP(DMI, "MSC TX %s\n", hexdump(msg->l2h, msgb_l2len(msg)));
ret = write(msc_connection.fd, msg->data, msg->len);
if (ret <= 0) {
perror("MSC: Failed to send SCCP");
return -1;
}
return 0;
}
static int msc_sccp_accept(struct sccp_connection *connection, void *data)
{
DEBUGP(DMSC, "Rejecting incoming SCCP connection.\n");
return -1;
}
static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
{
struct bssmap_header *bs;
DEBUGP(DMSC, "Incoming SCCP message ftom MSC: %s\n", hexdump(msgb->l3h, length));
if (length < sizeof(*bs)) {
DEBUGP(DMSC, "The header is too short.\n");
return -1;
}
bs = (struct bssmap_header *) msgb->l3h;
if (bs->length < length - sizeof(*bs))
return -1;
switch (bs->type) {
case BSSAP_MSG_BSS_MANAGEMENT:
msgb->l4h = &msgb->l3h[sizeof(*bs)];
bssmap_rcvmsg_udt(bsc_gsmnet, msgb, length - sizeof(*bs));
break;
default:
DEBUGPC(DMSC, "Unimplemented msg type: %d\n", bs->type);
}
return 0;
}
/*
* network initialisation
*/
static void initialize_if_needed(void)
{
if (!bsc_gsmnet) {
int rc;
struct msgb *msg;
fprintf(stderr, "Bootstraping the network. Sending GSM08.08 reset.\n");
rc = bsc_bootstrap_network(NULL, config_file);
if (rc < 0) {
fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
exit(1);
}
/* send a gsm 08.08 reset message from here */
msg = bssmap_create_reset();
if (!msg) {
DEBUGP(DMSC, "Failed to create the reset message.\n");
return;
}
sccp_write(msg, &sccp_ssn_bssap, &sccp_ssn_bssap, 0);
msgb_free(msg);
}
}
/*
* callback with IP access data
*/
static int ipaccess_a_fd_cb(struct bsc_fd *bfd, unsigned int what)
{
int error;
struct msgb *msg = ipaccess_read_msg(bfd, &error);
struct ipaccess_head *hh;
if (!msg) {
if (error == 0) {
fprintf(stderr, "The connection to the MSC was lost, exiting\n");
exit(-2);
}
fprintf(stderr, "Failed to parse ip access message: %d\n", error);
return -1;
}
DEBUGP(DMSC, "From MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
/* handle base message handling */
hh = (struct ipaccess_head *) msg->data;
ipaccess_rcvmsg_base(msg, bfd);
/* initialize the networking. This includes sending a GSM08.08 message */
if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_ID_ACK)
initialize_if_needed();
else if (hh->proto == IPAC_PROTO_SCCP)
sccp_system_incoming(msg);
return 0;
}
/*
* Connect to the MSC
*/
static int connect_to_msc(const char *ip, int port)
{
struct sockaddr_in sin;
int on = 1, ret;
printf("Attempting to connect MSC at %s:%d\n", ip, port);
msc_connection.fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
msc_connection.cb = ipaccess_a_fd_cb;
msc_connection.when = BSC_FD_READ;
msc_connection.data = NULL;
msc_connection.priv_nr = 1;
if (msc_connection.fd < 0) {
perror("Creating TCP socket failed");
return msc_connection.fd;
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
inet_aton(ip, &sin.sin_addr);
setsockopt(msc_connection.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
ret = connect(msc_connection.fd, (struct sockaddr *) &sin, sizeof(sin));
if (ret < 0) {
perror("Connection failed");
return ret;
}
ret = bsc_register_fd(&msc_connection);
if (ret < 0) {
perror("Registering the fd failed");
close(msc_connection.fd);
return ret;
}
return ret;
}
static void print_help()
{
printf(" Some useful help...\n");
printf(" -h --help this text\n");
printf(" -d option --debug=DRLL:DCC:DMM:DRR:DRSL:DNM enable debugging\n");
printf(" -s --disable-color\n");
printf(" -c --config-file filename The config file to use.\n");
printf(" -m --msc=IP. The address of the MSC.\n");
printf(" -l --local=IP. The local address of the MGCP.\n");
}
static void handle_options(int argc, char** argv)
{
while (1) {
int option_index = 0, c;
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"debug", 1, 0, 'd'},
{"config-file", 1, 0, 'c'},
{"disable-color", 0, 0, 's'},
{"timestamp", 0, 0, 'T'},
{"rtp-proxy", 0, 0, 'P'},
{"msc", 1, 0, 'm'},
{"local", 1, 0, 'l'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hd:sTPc:m:l:",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_usage();
print_help();
exit(0);
case 's':
debug_use_color(0);
break;
case 'd':
debug_parse_category_mask(optarg);
break;
case 'c':
config_file = strdup(optarg);
break;
case 'T':
debug_timestamp(1);
break;
case 'P':
ipacc_rtp_direct = 0;
break;
case 'm':
msc_address = strdup(optarg);
break;
case 'l':
inet_aton(optarg, &local_addr);
break;
default:
/* ignore */
break;
}
}
}
static void signal_handler(int signal)
{
fprintf(stdout, "signal %u received\n", signal);
switch (signal) {
case SIGINT:
bsc_shutdown_net(bsc_gsmnet);
sleep(3);
exit(0);
break;
case SIGABRT:
/* in case of abort, we want to obtain a talloc report
* and then return to the caller, who will abort the process */
case SIGUSR1:
talloc_report_full(tall_bsc_ctx, stderr);
break;
default:
break;
}
}
static void test_mode()
{
static const u_int8_t assignment_req[] = { 0x01, 0x0b, 0x03, 0x01, 0x0b, 0x25, 0x01, 0x00, 0x01 };
struct gsm_lchan lchan;
struct sccp_connection conn;
struct bss_sccp_connection_data data;
struct gsm_bts_trx_ts trx_ts;
struct gsm_bts_trx trx;
struct gsm_bts bts;
int rc;
/* initialize */
fprintf(stderr, "Bootstraping the network. Sending GSM08.08 reset.\n");
rc = bsc_bootstrap_network(NULL, config_file);
if (rc < 0) {
fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
exit(1);
}
bts.network = bsc_gsmnet;
trx.bts = &bts;
trx_ts.trx = &trx;
lchan.ts = &trx_ts;
/* create fake data connection */
data.lchan = &lchan;
data.sccp = &conn;
lchan.msc_data = &data;
conn.data_ctx = &data;
struct msgb *msg = msgb_alloc(400, "test-msg");
msg->lchan = &lchan;
msg->l4h = msgb_put(msg, ARRAY_SIZE(assignment_req));
memcpy(msg->l4h, assignment_req, ARRAY_SIZE(assignment_req));
bssmap_rcvmsg_dt1(&conn, msg, ARRAY_SIZE(assignment_req));
}
int main(int argc, char **argv)
{
int rc;
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
/* parse options */
handle_options(argc, argv);
/* seed the PRNG */
srand(time(NULL));
/* initialize sccp */
sccp_system_init(msc_sccp_write_ipa, NULL);
sccp_connection_set_incoming(&sccp_ssn_bssap, msc_sccp_accept, NULL);
sccp_set_read(&sccp_ssn_bssap, msc_sccp_read, NULL);
/* initialize ipaccess handling */
register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
rc = connect_to_msc(msc_address, 5000);
if (rc < 0) {
fprintf(stderr, "Opening the MSC connection failed.\n");
exit(1);
}
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGPIPE, SIG_IGN);
while (1) {
bsc_select_main(0);
}
}

1165
openbsc/src/bssap.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -33,8 +33,6 @@
#include <openbsc/debug.h> #include <openbsc/debug.h>
#include <openbsc/signal.h> #include <openbsc/signal.h>
static void auto_release_channel(void *_lchan);
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts, struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
enum gsm_phys_chan_config pchan) enum gsm_phys_chan_config pchan)
{ {
@@ -223,10 +221,9 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
/* clear multi rate config */ /* clear multi rate config */
memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf)); memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf));
/* Configure the time and start it so it will be closed */ /* clear any msc reference */
lchan->release_timer.cb = auto_release_channel; lchan->msc_data = NULL;
lchan->release_timer.data = lchan;
bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
} }
return lchan; return lchan;
@@ -249,8 +246,6 @@ void lchan_free(struct gsm_lchan *lchan)
lchan->use_count = 0; lchan->use_count = 0;
} }
/* stop the timer */
bsc_del_timer(&lchan->release_timer);
bsc_del_timer(&lchan->T3101); bsc_del_timer(&lchan->T3101);
/* clear cached measuement reports */ /* clear cached measuement reports */
@@ -261,21 +256,23 @@ void lchan_free(struct gsm_lchan *lchan)
} }
for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++) for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++)
lchan->neigh_meas[i].arfcn = 0; lchan->neigh_meas[i].arfcn = 0;
/* FIXME: ts_free() the timeslot, if we're the last logical /* FIXME: ts_free() the timeslot, if we're the last logical
* channel using it */ * channel using it */
} }
/* Consider releasing the channel now */ /* Consider releasing the channel now */
int lchan_auto_release(struct gsm_lchan *lchan) int _lchan_release(struct gsm_lchan *lchan)
{ {
if (lchan->use_count > 0) { if (lchan->use_count > 0) {
DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n");
return 0; return 0;
} }
/* Assume we have GSM04.08 running and send a release */ /* Assume we have GSM04.08 running and send a release */
if (lchan->subscr) { if (lchan->subscr) {
++lchan->use_count;
gsm48_send_rr_release(lchan); gsm48_send_rr_release(lchan);
--lchan->use_count;
} }
/* spoofed? message */ /* spoofed? message */
@@ -288,15 +285,6 @@ int lchan_auto_release(struct gsm_lchan *lchan)
return 1; return 1;
} }
/* Auto release the channel when the use count is zero */
static void auto_release_channel(void *_lchan)
{
struct gsm_lchan *lchan = _lchan;
if (!lchan_auto_release(lchan))
bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
}
struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) {
struct gsm_bts_trx *trx; struct gsm_bts_trx *trx;
int ts_no, lchan_no; int ts_no, lchan_no;

View File

@@ -232,7 +232,6 @@ static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
int rc; int rc;
db_subscriber_alloc_tmsi(lchan->subscr); db_subscriber_alloc_tmsi(lchan->subscr);
release_loc_updating_req(lchan);
rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi); rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi);
if (lchan->ts->trx->bts->network->send_mm_info) { if (lchan->ts->trx->bts->network->send_mm_info) {
/* send MM INFO with network name */ /* send MM INFO with network name */
@@ -244,8 +243,7 @@ static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
* trigger further action like SMS delivery */ * trigger further action like SMS delivery */
subscr_update(lchan->subscr, msg->trx->bts, subscr_update(lchan->subscr, msg->trx->bts,
GSM_SUBSCRIBER_UPDATE_ATTACHED); GSM_SUBSCRIBER_UPDATE_ATTACHED);
/* try to close channel ASAP */ release_loc_updating_req(lchan);
lchan_auto_release(lchan);
return rc; return rc;
} }
@@ -931,9 +929,8 @@ static void loc_upd_rej_cb(void *data)
struct gsm_lchan *lchan = data; struct gsm_lchan *lchan = data;
struct gsm_bts *bts = lchan->ts->trx->bts; struct gsm_bts *bts = lchan->ts->trx->bts;
release_loc_updating_req(lchan);
gsm0408_loc_upd_rej(lchan, bts->network->reject_cause); gsm0408_loc_upd_rej(lchan, bts->network->reject_cause);
lchan_auto_release(lchan); release_loc_updating_req(lchan);
} }
static void schedule_reject(struct gsm_lchan *lchan) static void schedule_reject(struct gsm_lchan *lchan)
@@ -1355,8 +1352,6 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
* imagine an IMSI DETACH happening during an active call! */ * imagine an IMSI DETACH happening during an active call! */
/* subscriber is detached: should we release lchan? */ /* subscriber is detached: should we release lchan? */
lchan_auto_release(msg->lchan);
return 0; return 0;
} }
@@ -2698,7 +2693,6 @@ static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
MNCC_REL_CNF, &rel); MNCC_REL_CNF, &rel);
/* FIXME: in case of multiple calls, we can't simply /* FIXME: in case of multiple calls, we can't simply
* hang up here ! */ * hang up here ! */
lchan_auto_release(msg->lchan);
break; break;
default: default:
rc = mncc_recvmsg(trans->subscr->net, trans, rc = mncc_recvmsg(trans->subscr->net, trans,

View File

@@ -292,8 +292,8 @@ static const enum gsm_chan_t ctype_by_chreq[] = {
[CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H, [CHREQ_T_VOICE_CALL_TCH_H] = GSM_LCHAN_TCH_H,
[CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H, [CHREQ_T_DATA_CALL_TCH_H] = GSM_LCHAN_TCH_H,
[CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH, [CHREQ_T_LOCATION_UPD] = GSM_LCHAN_SDCCH,
[CHREQ_T_PAG_R_ANY_NECI1] = GSM_LCHAN_SDCCH, [CHREQ_T_PAG_R_ANY_NECI1] = GSM_LCHAN_TCH_H,
[CHREQ_T_PAG_R_ANY_NECI0] = GSM_LCHAN_SDCCH, [CHREQ_T_PAG_R_ANY_NECI0] = GSM_LCHAN_TCH_F,
[CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F, [CHREQ_T_PAG_R_TCH_F] = GSM_LCHAN_TCH_F,
[CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F, [CHREQ_T_PAG_R_TCH_FH] = GSM_LCHAN_TCH_F,
[CHREQ_T_LMU] = GSM_LCHAN_SDCCH, [CHREQ_T_LMU] = GSM_LCHAN_SDCCH,

View File

@@ -224,6 +224,9 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
net->mncc_recv = mncc_recv; net->mncc_recv = mncc_recv;
net->core_country_code = -1;
net->core_network_code = -1;
return net; return net;
} }

View File

@@ -32,6 +32,7 @@
#include <openbsc/paging.h> #include <openbsc/paging.h>
#include <openbsc/debug.h> #include <openbsc/debug.h>
#include <openbsc/paging.h> #include <openbsc/paging.h>
#include <openbsc/chan_alloc.h>
LLIST_HEAD(active_subscribers); LLIST_HEAD(active_subscribers);
void *tall_subscr_ctx; void *tall_subscr_ctx;
@@ -89,6 +90,7 @@ static int subscr_paging_cb(unsigned int hooknum, unsigned int event,
request->cbfn(hooknum, event, msg, data, request->param); request->cbfn(hooknum, event, msg, data, request->param);
subscr->in_callback = 0; subscr->in_callback = 0;
subscr_put(request->subscr);
talloc_free(request); talloc_free(request);
return 0; return 0;
} }
@@ -166,7 +168,7 @@ void subscr_get_channel(struct gsm_subscriber *subscr,
} }
memset(request, 0, sizeof(*request)); memset(request, 0, sizeof(*request));
request->subscr = subscr; request->subscr = subscr_get(subscr);
request->channel_type = type; request->channel_type = type;
request->cbfn = cbfn; request->cbfn = cbfn;
request->param = param; request->param = param;
@@ -212,3 +214,22 @@ void subscr_put_channel(struct gsm_lchan *lchan)
subscr_send_paging_request(lchan->subscr); subscr_send_paging_request(lchan->subscr);
} }
struct gsm_subscriber *subscr_get_or_create(struct gsm_network *net,
const char *imsi)
{
struct gsm_subscriber *subscr;
llist_for_each_entry(subscr, subscr_bsc_active_subscriber(), entry) {
if (strcmp(subscr->imsi, imsi) == 0 && subscr->net == net)
return subscr_get(subscr);
}
subscr = subscr_alloc();
if (!subscr)
return NULL;
strcpy(subscr->imsi, imsi);
subscr->net = net;
return subscr;
}

View File

@@ -223,7 +223,6 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
trans_lchan_change(ho->old_lchan, new_lchan); trans_lchan_change(ho->old_lchan, new_lchan);
ho->old_lchan->state = LCHAN_S_INACTIVE; ho->old_lchan->state = LCHAN_S_INACTIVE;
lchan_auto_release(ho->old_lchan);
/* do something to re-route the actual speech frames ! */ /* do something to re-route the actual speech frames ! */

View File

@@ -95,6 +95,7 @@ void msgb_reset(struct msgb *msg)
msg->l2h = NULL; msg->l2h = NULL;
msg->l3h = NULL; msg->l3h = NULL;
msg->smsh = NULL; msg->smsh = NULL;
msg->l4h = NULL;
} }
static __attribute__((constructor)) void on_dso_load_trau_msgb(void) static __attribute__((constructor)) void on_dso_load_trau_msgb(void)

View File

@@ -28,6 +28,7 @@
#include <openbsc/gsm_04_08.h> #include <openbsc/gsm_04_08.h>
#include <openbsc/mncc.h> #include <openbsc/mncc.h>
#include <openbsc/paging.h> #include <openbsc/paging.h>
#include <openbsc/chan_alloc.h>
void *tall_trans_ctx; void *tall_trans_ctx;
@@ -95,14 +96,14 @@ void trans_free(struct gsm_trans *trans)
break; break;
} }
if (trans->lchan)
put_lchan(trans->lchan);
if (!trans->lchan && trans->subscr && trans->subscr->net) { if (!trans->lchan && trans->subscr && trans->subscr->net) {
/* Stop paging on all bts' */ /* Stop paging on all bts' */
paging_request_stop(NULL, trans->subscr, NULL); paging_request_stop(NULL, trans->subscr, NULL);
} }
if (trans->lchan)
put_lchan(trans->lchan);
if (trans->subscr) if (trans->subscr)
subscr_put(trans->subscr); subscr_put(trans->subscr);

View File

@@ -76,6 +76,8 @@ static void net_dump_nmstate(struct vty *vty, struct gsm_nm_state *nms)
static void net_dump_vty(struct vty *vty, struct gsm_network *net) static void net_dump_vty(struct vty *vty, struct gsm_network *net)
{ {
int i;
vty_out(vty, "BSC is on Country Code %u, Network Code %u " vty_out(vty, "BSC is on Country Code %u, Network Code %u "
"and has %u BTS%s", net->country_code, net->network_code, "and has %u BTS%s", net->country_code, net->network_code,
net->num_bts, VTY_NEWLINE); net->num_bts, VTY_NEWLINE);
@@ -97,6 +99,11 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
VTY_NEWLINE); VTY_NEWLINE);
vty_out(vty, " Handover: %s%s", net->handover.active ? "On" : "Off", vty_out(vty, " Handover: %s%s", net->handover.active ? "On" : "Off",
VTY_NEWLINE); VTY_NEWLINE);
vty_out(vty, " Allowed Audio Codecs: ");
for (i = 0; i < net->audio_length; ++i)
vty_out(vty, "hr: %d ver: %d, ",
net->audio_support[i]->hr, net->audio_support[i]->ver);
vty_out(vty, "%s", VTY_NEWLINE);
} }
DEFUN(show_net, show_net_cmd, "show network", DEFUN(show_net, show_net_cmd, "show network",
@@ -287,7 +294,11 @@ static int config_write_net(struct vty *vty)
{ {
vty_out(vty, "network%s", VTY_NEWLINE); vty_out(vty, "network%s", VTY_NEWLINE);
vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE); vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
if (gsmnet->core_country_code > 0)
vty_out(vty, " core network country code %u%s", gsmnet->core_country_code, VTY_NEWLINE);
vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE); vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
if (gsmnet->core_network_code > 0)
vty_out(vty, " core mobile network code %u%s", gsmnet->core_network_code, VTY_NEWLINE);
vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE); vty_out(vty, " short name %s%s", gsmnet->name_short, VTY_NEWLINE);
vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE); vty_out(vty, " long name %s%s", gsmnet->name_long, VTY_NEWLINE);
vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE); vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
@@ -322,6 +333,24 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " timer t3117 %u%s", gsmnet->T3117, VTY_NEWLINE); vty_out(vty, " timer t3117 %u%s", gsmnet->T3117, VTY_NEWLINE);
vty_out(vty, " timer t3119 %u%s", gsmnet->T3119, VTY_NEWLINE); vty_out(vty, " timer t3119 %u%s", gsmnet->T3119, VTY_NEWLINE);
vty_out(vty, " timer t3141 %u%s", gsmnet->T3141, VTY_NEWLINE); vty_out(vty, " timer t3141 %u%s", gsmnet->T3141, VTY_NEWLINE);
vty_out(vty, " ipacc rtp_payload %u%s", gsmnet->rtp_payload, VTY_NEWLINE);
if (gsmnet->audio_length != 0) {
int i;
vty_out(vty, " codec_list ");
for (i = 0; i < gsmnet->audio_length; ++i) {
printf("I... %d %d\n", i, gsmnet->audio_length);
if (i != 0)
vty_out(vty, ", ");
if (gsmnet->audio_support[i]->hr)
vty_out(vty, "hr%.1u", gsmnet->audio_support[i]->ver);
else
vty_out(vty, "fr%.1u", gsmnet->audio_support[i]->ver);
}
vty_out(vty, "%s", VTY_NEWLINE);
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@@ -818,6 +847,16 @@ DEFUN(cfg_net_ncc,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_core_net_ncc,
cfg_core_net_ncc_cmd,
"core network country code <1-999>",
"Set the GSM country code to be used in the MSC connection")
{
gsmnet->core_country_code = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_mnc, DEFUN(cfg_net_mnc,
cfg_net_mnc_cmd, cfg_net_mnc_cmd,
"mobile network code <1-999>", "mobile network code <1-999>",
@@ -828,6 +867,16 @@ DEFUN(cfg_net_mnc,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_core_net_mnc,
cfg_core_net_mnc_cmd,
"core mobile network code <1-999>",
"Set the GSM mobile network code to be used in the MSC connection")
{
gsmnet->core_network_code = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_name_short, DEFUN(cfg_net_name_short,
cfg_net_name_short_cmd, cfg_net_name_short_cmd,
"short name NAME", "short name NAME",
@@ -976,6 +1025,90 @@ DEFUN(cfg_net_ho_max_distance, cfg_net_ho_max_distance_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN(cfg_net_supported_codecs,
cfg_net_supported_codecs_cmd,
"codec_list .LIST",
"Set the three preferred audio codecs.\n"
"Codec List")
{
int saw_fr, saw_hr;
int i;
saw_fr = saw_hr = 0;
/* free the old list... if it exists */
if (gsmnet->audio_support) {
talloc_free(gsmnet->audio_support);
gsmnet->audio_support = NULL;
gsmnet->audio_length = 0;
}
/* create a new array */
gsmnet->audio_support =
talloc_zero_array(gsmnet, struct gsm_audio_support *, argc);
gsmnet->audio_length = argc;
for (i = 0; i < argc; ++i) {
/* check for hrX or frX */
if (strlen(argv[i]) != 3
|| argv[i][1] != 'r'
|| (argv[i][0] != 'h' && argv[i][0] != 'f')
|| argv[i][2] < 0x30
|| argv[i][2] > 0x39)
goto error;
gsmnet->audio_support[i] = talloc_zero(gsmnet->audio_support,
struct gsm_audio_support);
gsmnet->audio_support[i]->ver = atoi(argv[i] + 2);
if (strncmp("hr", argv[i], 2) == 0) {
gsmnet->audio_support[i]->hr = 1;
saw_hr = 1;
} else if (strncmp("fr", argv[i], 2) == 0) {
gsmnet->audio_support[i]->hr = 0;
saw_fr = 1;
}
if (saw_hr && saw_fr) {
vty_out(vty, "Can not have full-rate and half-rate codec.%s",
VTY_NEWLINE);
return CMD_ERR_INCOMPLETE;
}
}
return CMD_SUCCESS;
error:
vty_out(vty, "Codec name must be hrX or frX. Was '%s'%s",
argv[i], VTY_NEWLINE);
return CMD_ERR_INCOMPLETE;
}
DEFUN(cfg_net_ipacc_rtp_payload,
cfg_net_ipacc_rtp_payload_cmd,
"ipacc rtp_payload <0-256>",
"Override the RTP payload to use")
{
gsmnet->rtp_payload = atoi(argv[0]) & 0xff;
return CMD_SUCCESS;
}
DEFUN(cfg_net_rtp_base_port,
cfg_net_rtp_base_port_cmd,
"rtp base <0-65534>",
"Base port to use for MGCP RTP")
{
unsigned int port = atoi(argv[0]);
if (port > 65534) {
vty_out(vty, "%% wrong base port '%s'%s", argv[0], VTY_NEWLINE);
return CMD_WARNING;
}
gsmnet->rtp_base_port = port;
return CMD_SUCCESS;
}
#define DECLARE_TIMER(number) \ #define DECLARE_TIMER(number) \
DEFUN(cfg_net_T##number, \ DEFUN(cfg_net_T##number, \
cfg_net_T##number##_cmd, \ cfg_net_T##number##_cmd, \
@@ -986,7 +1119,7 @@ DEFUN(cfg_net_ho_max_distance, cfg_net_ho_max_distance_cmd,
\ \
if (value < 0 || value > 65535) { \ if (value < 0 || value > 65535) { \
vty_out(vty, "Timer value %s out of range.%s", \ vty_out(vty, "Timer value %s out of range.%s", \
argv[0], VTY_NEWLINE); \ argv[0], VTY_NEWLINE); \
return CMD_WARNING; \ return CMD_WARNING; \
} \ } \
\ \
@@ -1006,7 +1139,6 @@ DECLARE_TIMER(3117)
DECLARE_TIMER(3119) DECLARE_TIMER(3119)
DECLARE_TIMER(3141) DECLARE_TIMER(3141)
/* per-BTS configuration */ /* per-BTS configuration */
DEFUN(cfg_bts, DEFUN(cfg_bts,
cfg_bts_cmd, cfg_bts_cmd,
@@ -1476,7 +1608,9 @@ int bsc_vty_init(struct gsm_network *net)
install_node(&net_node, config_write_net); install_node(&net_node, config_write_net);
install_default(GSMNET_NODE); install_default(GSMNET_NODE);
install_element(GSMNET_NODE, &cfg_net_ncc_cmd); install_element(GSMNET_NODE, &cfg_net_ncc_cmd);
install_element(GSMNET_NODE, &cfg_core_net_ncc_cmd);
install_element(GSMNET_NODE, &cfg_net_mnc_cmd); install_element(GSMNET_NODE, &cfg_net_mnc_cmd);
install_element(GSMNET_NODE, &cfg_core_net_mnc_cmd);
install_element(GSMNET_NODE, &cfg_net_name_short_cmd); install_element(GSMNET_NODE, &cfg_net_name_short_cmd);
install_element(GSMNET_NODE, &cfg_net_name_long_cmd); install_element(GSMNET_NODE, &cfg_net_name_long_cmd);
install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd); install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd);
@@ -1492,6 +1626,9 @@ int bsc_vty_init(struct gsm_network *net)
install_element(GSMNET_NODE, &cfg_net_ho_pwr_interval_cmd); install_element(GSMNET_NODE, &cfg_net_ho_pwr_interval_cmd);
install_element(GSMNET_NODE, &cfg_net_ho_pwr_hysteresis_cmd); install_element(GSMNET_NODE, &cfg_net_ho_pwr_hysteresis_cmd);
install_element(GSMNET_NODE, &cfg_net_ho_max_distance_cmd); install_element(GSMNET_NODE, &cfg_net_ho_max_distance_cmd);
install_element(GSMNET_NODE, &cfg_net_supported_codecs_cmd);
install_element(GSMNET_NODE, &cfg_net_ipacc_rtp_payload_cmd);
install_element(GSMNET_NODE, &cfg_net_rtp_base_port_cmd);
install_element(GSMNET_NODE, &cfg_net_T3101_cmd); install_element(GSMNET_NODE, &cfg_net_T3101_cmd);
install_element(GSMNET_NODE, &cfg_net_T3103_cmd); install_element(GSMNET_NODE, &cfg_net_T3103_cmd);
install_element(GSMNET_NODE, &cfg_net_T3105_cmd); install_element(GSMNET_NODE, &cfg_net_T3105_cmd);

View File

@@ -0,0 +1,48 @@
/* OpenBSC interface to quagga VTY - BSC options */
/* (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 <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <vty/command.h>
#include <vty/buffer.h>
#include <vty/vty.h>
#include <openbsc/gsm_data.h>
static struct gsmnet *gsmnet = NULL;
DEFUN(show_bsc, show_bsc_cmd, "show bsc",
SHOW_STR "Display information about the BSC\n")
{
vty_out(vty, "BSC... not implemented yet%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
int bsc_vty_init_extra(struct gsm_network *net)
{
gsmnet = net;
/* get runtime information */
install_element(VIEW_NODE, &show_bsc_cmd);
return 0;
}

View File

@@ -76,4 +76,5 @@ int main(int argc, char** argv)
void nm_state_event() {} void nm_state_event() {}
void input_event() {} void input_event() {}
void sms_alloc() {} void sms_alloc() {}
void _lchan_release() {}