mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
				synced 2025-11-04 05:53:26 +00:00 
			
		
		
		
	Compare commits
	
		
			35 Commits
		
	
	
		
			1.11.1
			...
			on-waves/0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					851ace9f33 | ||
| 
						 | 
					d1dd069b48 | ||
| 
						 | 
					401db32ca2 | ||
| 
						 | 
					17e03d21d2 | ||
| 
						 | 
					26a9bff201 | ||
| 
						 | 
					80fb260a60 | ||
| 
						 | 
					55a0716da7 | ||
| 
						 | 
					c88fb75616 | ||
| 
						 | 
					d55a4dc326 | ||
| 
						 | 
					a4e6f2e6e1 | ||
| 
						 | 
					7f71d99cc3 | ||
| 
						 | 
					b92167cf80 | ||
| 
						 | 
					4b6a6dbe7e | ||
| 
						 | 
					763e8c7766 | ||
| 
						 | 
					823ff16088 | ||
| 
						 | 
					6f93c6a1e0 | ||
| 
						 | 
					f97e48b0de | ||
| 
						 | 
					761600b0fd | ||
| 
						 | 
					8549462bc6 | ||
| 
						 | 
					436e5c6308 | ||
| 
						 | 
					f8b9d844c1 | ||
| 
						 | 
					58ec07d580 | ||
| 
						 | 
					71465c21f4 | ||
| 
						 | 
					16d0a833f8 | ||
| 
						 | 
					ea72b62cac | ||
| 
						 | 
					49a84ec6e9 | ||
| 
						 | 
					42c636b6c8 | ||
| 
						 | 
					a0a55f555e | ||
| 
						 | 
					23ed00e410 | ||
| 
						 | 
					3fe910b9f1 | ||
| 
						 | 
					097bdeb77d | ||
| 
						 | 
					1b85de02e0 | ||
| 
						 | 
					2281d1835f | ||
| 
						 | 
					fb4433a129 | ||
| 
						 | 
					d954dcf9e1 | 
@@ -1,7 +1,7 @@
 | 
			
		||||
dnl Process this file with autoconf to produce a configure script
 | 
			
		||||
AC_INIT
 | 
			
		||||
 | 
			
		||||
AM_INIT_AUTOMAKE(openbsc, 0.0alpha1)
 | 
			
		||||
AM_INIT_AUTOMAKE(openbsc, 0.1onwaves)
 | 
			
		||||
 | 
			
		||||
dnl kernel style compile messages
 | 
			
		||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								openbsc/contrib/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								openbsc/contrib/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
This contains a set of scripts used for the development of the
 | 
			
		||||
MSC functionality.
 | 
			
		||||
							
								
								
									
										30
									
								
								openbsc/contrib/send_handshake.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										30
									
								
								openbsc/contrib/send_handshake.py
									
									
									
									
									
										Executable 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)
 | 
			
		||||
 | 
			
		||||
@@ -4,4 +4,4 @@ noinst_HEADERS = abis_nm.h abis_rsl.h debug.h db.h gsm_04_08.h gsm_data.h \
 | 
			
		||||
		 subchan_demux.h trau_frame.h e1_input.h trau_mux.h signal.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 \
 | 
			
		||||
		 silent_call.h mgcp.h
 | 
			
		||||
		 silent_call.h mgcp.h bssap.h
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										333
									
								
								openbsc/include/openbsc/bssap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								openbsc/include/openbsc/bssap.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@@ -23,6 +23,28 @@
 | 
			
		||||
 | 
			
		||||
#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 */
 | 
			
		||||
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
 | 
			
		||||
				   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, ...) */
 | 
			
		||||
void lchan_free(struct gsm_lchan *lchan);
 | 
			
		||||
 | 
			
		||||
/* Consider releasing the channel */
 | 
			
		||||
int lchan_auto_release(struct gsm_lchan *lchan);
 | 
			
		||||
/* internal.. do not use */
 | 
			
		||||
int _lchan_release(struct gsm_lchan *lchan);
 | 
			
		||||
 | 
			
		||||
#endif /* _CHAN_ALLOC_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -85,36 +85,49 @@ typedef int gsm_cbfn(unsigned int hooknum,
 | 
			
		||||
		     struct msgb *msg,
 | 
			
		||||
		     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 */
 | 
			
		||||
struct gsm_bts_link {
 | 
			
		||||
	struct gsm_bts *bts;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct sccp_connection;
 | 
			
		||||
struct gsm_lchan;
 | 
			
		||||
struct gsm_subscriber;
 | 
			
		||||
struct gsm_mncc;
 | 
			
		||||
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 */
 | 
			
		||||
struct gsm_nm_state {
 | 
			
		||||
	u_int8_t operational;
 | 
			
		||||
@@ -170,9 +183,6 @@ struct gsm_lchan {
 | 
			
		||||
	/* To whom we are allocated at the moment */
 | 
			
		||||
	struct gsm_subscriber *subscr;
 | 
			
		||||
 | 
			
		||||
	/* Timer started to release the channel */
 | 
			
		||||
	struct timer_list release_timer;
 | 
			
		||||
 | 
			
		||||
	struct timer_list T3101;
 | 
			
		||||
 | 
			
		||||
	/* Established data link layer services */
 | 
			
		||||
@@ -183,6 +193,12 @@ struct gsm_lchan {
 | 
			
		||||
	 */
 | 
			
		||||
	struct gsm_loc_updating_operation *loc_operation;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * MSC handling...
 | 
			
		||||
	 */
 | 
			
		||||
	struct bss_sccp_connection_data *msc_data;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/* use count. how many users use this channel */
 | 
			
		||||
	unsigned int use_count;
 | 
			
		||||
};
 | 
			
		||||
@@ -257,6 +273,9 @@ struct gsm_bts_trx {
 | 
			
		||||
		} bs11;
 | 
			
		||||
	};
 | 
			
		||||
	struct gsm_bts_trx_ts ts[TRX_NR_TS];
 | 
			
		||||
 | 
			
		||||
	/* NM state */
 | 
			
		||||
	int rf_locked;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum gsm_bts_type {
 | 
			
		||||
@@ -405,6 +424,14 @@ enum gsm_auth_policy {
 | 
			
		||||
	GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * internal data for audio management
 | 
			
		||||
 */
 | 
			
		||||
struct gsm_audio_support {
 | 
			
		||||
	u_int8_t hr  : 1,
 | 
			
		||||
		 ver : 7;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct gsm_network {
 | 
			
		||||
	/* global parameters */
 | 
			
		||||
	u_int16_t country_code;
 | 
			
		||||
@@ -415,6 +442,11 @@ struct gsm_network {
 | 
			
		||||
	int a5_encryption;
 | 
			
		||||
	int neci;
 | 
			
		||||
 | 
			
		||||
	struct gsm_audio_support **audio_support;
 | 
			
		||||
	int audio_length;
 | 
			
		||||
	int rtp_payload;
 | 
			
		||||
	int rtp_base_port;
 | 
			
		||||
 | 
			
		||||
	/* layer 4 */
 | 
			
		||||
	int (*mncc_recv) (struct gsm_network *net, int msg_type, void *arg);
 | 
			
		||||
	struct llist_head upqueue;
 | 
			
		||||
@@ -506,4 +538,6 @@ static inline int is_siemens_bts(struct gsm_bts *bts)
 | 
			
		||||
enum gsm_auth_policy gsm_auth_policy_parse(const char *arg);
 | 
			
		||||
const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
 | 
			
		||||
 | 
			
		||||
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,8 @@ struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
 | 
			
		||||
					       const char *ext);
 | 
			
		||||
struct gsm_subscriber *subscr_get_by_id(struct gsm_network *net,
 | 
			
		||||
					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);
 | 
			
		||||
void subscr_put_channel(struct gsm_lchan *lchan);
 | 
			
		||||
void subscr_get_channel(struct gsm_subscriber *subscr,
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,6 @@
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
unsigned int rtp_base_port = 4000;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate the RTP audio port for the given multiplex
 | 
			
		||||
 * and the direction. This allows a semi static endpoint
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ struct msgb {
 | 
			
		||||
	unsigned char *l2h;
 | 
			
		||||
	unsigned char *l3h;
 | 
			
		||||
	unsigned char *smsh;
 | 
			
		||||
	unsigned char *l4h;
 | 
			
		||||
 | 
			
		||||
	u_int16_t data_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_l3(m)	((void *)(m->l3h))
 | 
			
		||||
#define msgb_l4(m)	((void *)(m->l4h))
 | 
			
		||||
#define msgb_sms(m)	((void *)(m->smsh))
 | 
			
		||||
 | 
			
		||||
static inline unsigned int msgb_l2len(const struct msgb *msgb)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include
 | 
			
		||||
AM_CFLAGS=-Wall
 | 
			
		||||
 | 
			
		||||
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_HEADERS = vty/cardshell.h
 | 
			
		||||
 | 
			
		||||
@@ -11,9 +11,9 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.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 \
 | 
			
		||||
		input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \
 | 
			
		||||
		talloc_ctx.c
 | 
			
		||||
		talloc_ctx.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 rtp_proxy.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
 | 
			
		||||
 | 
			
		||||
@@ -24,6 +24,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_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 \
 | 
			
		||||
		      select.c timer.c rs232.c tlv_parser.c signal.c talloc.c
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2699,6 +2699,16 @@ int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, u_int8_t obj_class,
 | 
			
		||||
				     attr, attr_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked)
 | 
			
		||||
{
 | 
			
		||||
	int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
 | 
			
		||||
 | 
			
		||||
	trx->rf_locked = locked;
 | 
			
		||||
	abis_nm_chg_adm_state(trx->bts, NM_OC_RADIO_CARRIER,
 | 
			
		||||
			      trx->bts->bts_nr, trx->nr, 0xff,
 | 
			
		||||
			      new_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *ipacc_testres_names[] = {
 | 
			
		||||
	[NM_IPACC_TESTRES_SUCCESS]	= "SUCCESS",
 | 
			
		||||
	[NM_IPACC_TESTRES_TIMEOUT]	= "TIMEOUT",
 | 
			
		||||
 
 | 
			
		||||
@@ -837,6 +837,10 @@ int rsl_data_request(struct msgb *msg, u_int8_t link_id)
 | 
			
		||||
		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 */
 | 
			
		||||
	msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
 | 
			
		||||
 | 
			
		||||
@@ -1563,9 +1567,21 @@ static int abis_rsl_rx_ipacc(struct msgb *msg)
 | 
			
		||||
/* Entry-point where L2 RSL from BTS enters */
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
	case ABIS_RSL_MDISC_RLL:
 | 
			
		||||
		rc = abis_rsl_rx_rll(msg);
 | 
			
		||||
 
 | 
			
		||||
@@ -357,12 +357,15 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
 | 
			
		||||
	case NM_OC_SITE_MANAGER:
 | 
			
		||||
		bts = container_of(obj, struct gsm_bts, site_mgr);
 | 
			
		||||
		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);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case NM_OC_BTS:
 | 
			
		||||
		bts = obj;
 | 
			
		||||
		if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
 | 
			
		||||
			printf("STARTING BTS...\n");
 | 
			
		||||
			patch_nm_tables(bts);
 | 
			
		||||
			abis_nm_set_bts_attr(bts, nanobts_attr_bts,
 | 
			
		||||
					     sizeof(nanobts_attr_bts));
 | 
			
		||||
@@ -378,6 +381,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
 | 
			
		||||
		trx = ts->trx;
 | 
			
		||||
		if (new_state->operational == 1 &&
 | 
			
		||||
		    new_state->availability == NM_AVSTATE_DEPENDENCY) {
 | 
			
		||||
			printf("STARTING OC Channel...\n");
 | 
			
		||||
			patch_nm_tables(trx->bts);
 | 
			
		||||
			enum abis_nm_chan_comb ccomb =
 | 
			
		||||
						abis_nm_chcomb4pchan(ts->pchan);
 | 
			
		||||
@@ -392,36 +396,11 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
 | 
			
		||||
	case NM_OC_RADIO_CARRIER:
 | 
			
		||||
		trx = obj;
 | 
			
		||||
		if (new_state->operational == 1 &&
 | 
			
		||||
		    new_state->availability == NM_AVSTATE_OFF_LINE) {
 | 
			
		||||
			/* Patch ARFCN into radio attribute */
 | 
			
		||||
			nanobts_attr_radio[5] &= 0xf0;
 | 
			
		||||
			nanobts_attr_radio[5] |= trx->arfcn >> 8;
 | 
			
		||||
			nanobts_attr_radio[6] = trx->arfcn & 0xff;
 | 
			
		||||
			abis_nm_set_radio_attr(trx, nanobts_attr_radio,
 | 
			
		||||
						sizeof(nanobts_attr_radio));
 | 
			
		||||
			abis_nm_chg_adm_state(trx->bts, obj_class,
 | 
			
		||||
					      trx->bts->bts_nr, trx->nr, 0xff,
 | 
			
		||||
					      NM_STATE_UNLOCKED);
 | 
			
		||||
		    new_state->availability == NM_AVSTATE_OK) {
 | 
			
		||||
			printf("STARTING NM Radio Carrier...\n");
 | 
			
		||||
			abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
 | 
			
		||||
					trx->nr, 0xff);
 | 
			
		||||
		}
 | 
			
		||||
		if (new_state->operational == 1 &&
 | 
			
		||||
		    new_state->availability == NM_AVSTATE_OK)
 | 
			
		||||
			abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
 | 
			
		||||
					trx->nr, 0xff);
 | 
			
		||||
		break;
 | 
			
		||||
	case NM_OC_BASEB_TRANSC:
 | 
			
		||||
		trx = container_of(obj, struct gsm_bts_trx, bb_transc);
 | 
			
		||||
		if (new_state->operational == 1 &&
 | 
			
		||||
		    new_state->availability == NM_AVSTATE_DEPENDENCY) {
 | 
			
		||||
			abis_nm_chg_adm_state(trx->bts, obj_class,
 | 
			
		||||
					trx->bts->bts_nr, trx->nr, 0xff,
 | 
			
		||||
					NM_STATE_UNLOCKED);
 | 
			
		||||
			abis_nm_opstart(trx->bts, obj_class,
 | 
			
		||||
					trx->bts->bts_nr, trx->nr, 0xff);
 | 
			
		||||
			/* TRX software is active, tell it to initiate RSL Link */
 | 
			
		||||
			abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
@@ -438,6 +417,42 @@ static int sw_activ_rep(struct msgb *mb)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	switch (foh->obj_class) {
 | 
			
		||||
	case NM_OC_BASEB_TRANSC:
 | 
			
		||||
		printf("Starting baseband\n");
 | 
			
		||||
		abis_nm_chg_adm_state(trx->bts, foh->obj_class,
 | 
			
		||||
				      trx->bts->bts_nr, trx->nr, 0xff,
 | 
			
		||||
				      NM_STATE_UNLOCKED);
 | 
			
		||||
		abis_nm_opstart(trx->bts, foh->obj_class,
 | 
			
		||||
				trx->bts->bts_nr, trx->nr, 0xff);
 | 
			
		||||
		/* TRX software is active, tell it to initiate RSL Link */
 | 
			
		||||
		abis_nm_ipaccess_rsl_connect(trx, 0, 3003, trx->rsl_tei);
 | 
			
		||||
		break;
 | 
			
		||||
	case NM_OC_RADIO_CARRIER: {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Locking the radio carrier will make it go
 | 
			
		||||
		 * offline again and we would come here. The
 | 
			
		||||
		 * framework should determine that there was
 | 
			
		||||
		 * no change and avoid recursion.
 | 
			
		||||
		 *
 | 
			
		||||
		 * This code is here to make sure that on start
 | 
			
		||||
		 * a TRX remains locked.
 | 
			
		||||
		 */
 | 
			
		||||
		int rc_state = trx->rf_locked ?
 | 
			
		||||
					NM_STATE_LOCKED : NM_STATE_UNLOCKED;
 | 
			
		||||
		printf("Starting radio: %d %d\n", rc_state, trx->rf_locked);
 | 
			
		||||
		/* Patch ARFCN into radio attribute */
 | 
			
		||||
		nanobts_attr_radio[5] &= 0xf0;
 | 
			
		||||
		nanobts_attr_radio[5] |= trx->arfcn >> 8;
 | 
			
		||||
		nanobts_attr_radio[6] = trx->arfcn & 0xff;
 | 
			
		||||
		abis_nm_set_radio_attr(trx, nanobts_attr_radio,
 | 
			
		||||
				       sizeof(nanobts_attr_radio));
 | 
			
		||||
		abis_nm_chg_adm_state(trx->bts, foh->obj_class,
 | 
			
		||||
				      trx->bts->bts_nr, trx->nr, 0xff,
 | 
			
		||||
				      rc_state);
 | 
			
		||||
		abis_nm_opstart(trx->bts, foh->obj_class, trx->bts->bts_nr,
 | 
			
		||||
				trx->nr, 0xff);
 | 
			
		||||
		break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,7 @@ static const char *audio_name = "GSM-EFR/8000";
 | 
			
		||||
static int audio_payload = 97;
 | 
			
		||||
static int audio_loop = 0;
 | 
			
		||||
static int early_bind = 0;
 | 
			
		||||
static int rtp_base_port = 0;
 | 
			
		||||
 | 
			
		||||
static char *config_file = "mgcp.cfg";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										813
									
								
								openbsc/src/bsc_msc_ip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										813
									
								
								openbsc/src/bsc_msc_ip.c
									
									
									
									
									
										Normal 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, ts->abis_ip.conn_id);
 | 
			
		||||
 | 
			
		||||
			int rtp_payload = ts->trx->bts->network->rtp_payload;
 | 
			
		||||
			if (rtp_payload == 0)
 | 
			
		||||
				rtp_payload = ts->abis_ip.rtp_payload2;
 | 
			
		||||
 | 
			
		||||
			rc = rsl_ipacc_mdcx(lchan, ntohl(local_addr.s_addr),
 | 
			
		||||
					    lchan->msc_data->rtp_port,
 | 
			
		||||
					    ts->abis_ip.conn_id,
 | 
			
		||||
					    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);
 | 
			
		||||
 | 
			
		||||
	while (1) {
 | 
			
		||||
		bsc_select_main(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1134
									
								
								openbsc/src/bssap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1134
									
								
								openbsc/src/bssap.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -33,8 +33,6 @@
 | 
			
		||||
#include <openbsc/debug.h>
 | 
			
		||||
#include <openbsc/signal.h>
 | 
			
		||||
 | 
			
		||||
static void auto_release_channel(void *_lchan);
 | 
			
		||||
 | 
			
		||||
struct gsm_bts_trx_ts *ts_c0_alloc(struct gsm_bts *bts,
 | 
			
		||||
				   enum gsm_phys_chan_config pchan)
 | 
			
		||||
{
 | 
			
		||||
@@ -218,10 +216,9 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type)
 | 
			
		||||
		/* clear multi rate config */
 | 
			
		||||
		memset(&lchan->mr_conf, 0, sizeof(lchan->mr_conf));
 | 
			
		||||
 | 
			
		||||
		/* Configure the time and start it so it will be closed */
 | 
			
		||||
		lchan->release_timer.cb = auto_release_channel;
 | 
			
		||||
		lchan->release_timer.data = lchan;
 | 
			
		||||
		bsc_schedule_timer(&lchan->release_timer, LCHAN_RELEASE_TIMEOUT);
 | 
			
		||||
		/* clear any msc reference */
 | 
			
		||||
		lchan->msc_data = NULL;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return lchan;
 | 
			
		||||
@@ -242,44 +239,35 @@ void lchan_free(struct gsm_lchan *lchan)
 | 
			
		||||
		lchan->use_count = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* stop the timer */
 | 
			
		||||
	bsc_del_timer(&lchan->release_timer);
 | 
			
		||||
 | 
			
		||||
	/* FIXME: ts_free() the timeslot, if we're the last logical
 | 
			
		||||
	 * channel using it */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 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) {
 | 
			
		||||
		DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Assume we have GSM04.08 running and send a release */
 | 
			
		||||
	if (lchan->subscr) {
 | 
			
		||||
		++lchan->use_count;
 | 
			
		||||
		gsm48_send_rr_release(lchan);
 | 
			
		||||
		--lchan->use_count;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* spoofed? message */
 | 
			
		||||
	if (lchan->use_count < 0) {
 | 
			
		||||
		DEBUGP(DRLL, "Channel count is negative: %d\n", lchan->use_count);
 | 
			
		||||
		DEBUGP(DRLL, "BUG: channel count is negative: %d\n", lchan->use_count);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DEBUGP(DRLL, "Recycling the channel with: %d (%x)\n", lchan->nr, lchan->nr);
 | 
			
		||||
	DEBUGP(DRLL, "Releasing the channel with: %d (%x)\n", lchan->nr, lchan->nr);
 | 
			
		||||
	rsl_release_request(lchan, 0);
 | 
			
		||||
	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_bts_trx *trx;
 | 
			
		||||
	int ts_no, lchan_no; 
 | 
			
		||||
 
 | 
			
		||||
@@ -296,13 +296,13 @@ static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg)
 | 
			
		||||
		int rc;
 | 
			
		||||
 | 
			
		||||
		db_subscriber_alloc_tmsi(lchan->subscr);
 | 
			
		||||
		release_loc_updating_req(lchan);
 | 
			
		||||
		rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi);
 | 
			
		||||
		/* call subscr_update after putting the loc_upd_acc
 | 
			
		||||
		 * in the transmit queue, since S_SUBSCR_ATTACHED might
 | 
			
		||||
		 * trigger further action like SMS delivery */
 | 
			
		||||
		subscr_update(lchan->subscr, msg->trx->bts,
 | 
			
		||||
			      GSM_SUBSCRIBER_UPDATE_ATTACHED);
 | 
			
		||||
		release_loc_updating_req(lchan);
 | 
			
		||||
		return rc;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -972,9 +972,8 @@ static void loc_upd_rej_cb(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct gsm_lchan *lchan = data;
 | 
			
		||||
 | 
			
		||||
	release_loc_updating_req(lchan);
 | 
			
		||||
	gsm0408_loc_upd_rej(lchan, reject_cause);
 | 
			
		||||
	lchan_auto_release(lchan);
 | 
			
		||||
	release_loc_updating_req(lchan);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void schedule_reject(struct gsm_lchan *lchan)
 | 
			
		||||
 
 | 
			
		||||
@@ -282,8 +282,8 @@ static const enum gsm_chan_t ctype_by_chreq[] = {
 | 
			
		||||
	[CHREQ_T_VOICE_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_PAG_R_ANY_NECI1]	= GSM_LCHAN_SDCCH,
 | 
			
		||||
	[CHREQ_T_PAG_R_ANY_NECI0]	= GSM_LCHAN_SDCCH,
 | 
			
		||||
	[CHREQ_T_PAG_R_ANY_NECI1]	= GSM_LCHAN_TCH_H,
 | 
			
		||||
	[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_FH]		= GSM_LCHAN_TCH_F,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
 | 
			
		||||
#include <openbsc/gsm_data.h>
 | 
			
		||||
#include <openbsc/talloc.h>
 | 
			
		||||
#include <openbsc/abis_nm.h>
 | 
			
		||||
 | 
			
		||||
void *tall_bsc_ctx;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@
 | 
			
		||||
#include <openbsc/paging.h>
 | 
			
		||||
#include <openbsc/debug.h>
 | 
			
		||||
#include <openbsc/paging.h>
 | 
			
		||||
#include <openbsc/chan_alloc.h>
 | 
			
		||||
 | 
			
		||||
LLIST_HEAD(active_subscribers);
 | 
			
		||||
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);
 | 
			
		||||
	subscr->in_callback = 0;
 | 
			
		||||
 | 
			
		||||
	subscr_put(request->subscr);
 | 
			
		||||
	talloc_free(request);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -166,7 +168,7 @@ void subscr_get_channel(struct gsm_subscriber *subscr,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(request, 0, sizeof(*request));
 | 
			
		||||
	request->subscr = subscr;
 | 
			
		||||
	request->subscr = subscr_get(subscr);
 | 
			
		||||
	request->channel_type = type;
 | 
			
		||||
	request->cbfn = cbfn;
 | 
			
		||||
	request->param = param;
 | 
			
		||||
@@ -212,3 +214,22 @@ void subscr_put_channel(struct gsm_lchan *lchan)
 | 
			
		||||
		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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -92,6 +92,7 @@ void msgb_reset(struct msgb *msg)
 | 
			
		||||
	msg->l2h = NULL;
 | 
			
		||||
	msg->l3h = NULL;
 | 
			
		||||
	msg->smsh = NULL;
 | 
			
		||||
	msg->l4h = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __attribute__((constructor)) void on_dso_load_trau_msgb(void)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
#include <openbsc/gsm_04_08.h>
 | 
			
		||||
#include <openbsc/mncc.h>
 | 
			
		||||
#include <openbsc/paging.h>
 | 
			
		||||
#include <openbsc/chan_alloc.h>
 | 
			
		||||
 | 
			
		||||
void *tall_trans_ctx;
 | 
			
		||||
 | 
			
		||||
@@ -95,14 +96,14 @@ void trans_free(struct gsm_trans *trans)
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (trans->lchan)
 | 
			
		||||
		put_lchan(trans->lchan);
 | 
			
		||||
 | 
			
		||||
	if (!trans->lchan && trans->subscr && trans->subscr->net) {
 | 
			
		||||
		/* Stop paging on all bts' */
 | 
			
		||||
		paging_request_stop(NULL, trans->subscr, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (trans->lchan)
 | 
			
		||||
		put_lchan(trans->lchan);
 | 
			
		||||
 | 
			
		||||
	if (trans->subscr)
 | 
			
		||||
		subscr_put(trans->subscr);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	vty_out(vty, "BSC is on Country Code %u, Network Code %u "
 | 
			
		||||
		"and has %u BTS%s", net->country_code, net->network_code,
 | 
			
		||||
		net->num_bts, VTY_NEWLINE);
 | 
			
		||||
@@ -89,6 +91,11 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
 | 
			
		||||
		VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, "  NECI (TCH/H): %u%s", net->neci,
 | 
			
		||||
		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",
 | 
			
		||||
@@ -275,6 +282,24 @@ static int config_write_net(struct vty *vty)
 | 
			
		||||
	vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " encryption a5 %u%s", gsmnet->a5_encryption, VTY_NEWLINE);
 | 
			
		||||
	vty_out(vty, " neci %u%s", gsmnet->neci, 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -801,6 +826,90 @@ DEFUN(cfg_net_neci,
 | 
			
		||||
	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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* per-BTS configuration */
 | 
			
		||||
DEFUN(cfg_bts,
 | 
			
		||||
      cfg_bts_cmd,
 | 
			
		||||
@@ -1158,6 +1267,17 @@ DEFUN(cfg_trx_rsl_e1_tei,
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFUN(cfg_trx_rf_locked,
 | 
			
		||||
      cfg_trx_rf_locked_cmd,
 | 
			
		||||
      "rf_locked (0|1)",
 | 
			
		||||
      "Turn off RF of the TRX.\n")
 | 
			
		||||
{
 | 
			
		||||
	int locked = atoi(argv[0]);
 | 
			
		||||
	struct gsm_bts_trx *trx = vty->index;
 | 
			
		||||
 | 
			
		||||
	gsm_trx_lock_rf(trx, locked);
 | 
			
		||||
	return CMD_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* per TS configuration */
 | 
			
		||||
DEFUN(cfg_ts,
 | 
			
		||||
@@ -1241,6 +1361,9 @@ int bsc_vty_init(struct gsm_network *net)
 | 
			
		||||
	install_element(GSMNET_NODE, &cfg_net_auth_policy_cmd);
 | 
			
		||||
	install_element(GSMNET_NODE, &cfg_net_encryption_cmd);
 | 
			
		||||
	install_element(GSMNET_NODE, &cfg_net_neci_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_bts_cmd);
 | 
			
		||||
	install_node(&bts_node, config_write_bts);
 | 
			
		||||
@@ -1268,6 +1391,7 @@ int bsc_vty_init(struct gsm_network *net)
 | 
			
		||||
	install_element(TRX_NODE, &cfg_trx_max_power_red_cmd);
 | 
			
		||||
	install_element(TRX_NODE, &cfg_trx_rsl_e1_cmd);
 | 
			
		||||
	install_element(TRX_NODE, &cfg_trx_rsl_e1_tei_cmd);
 | 
			
		||||
	install_element(TRX_NODE, &cfg_trx_rf_locked_cmd);
 | 
			
		||||
 | 
			
		||||
	install_element(TRX_NODE, &cfg_ts_cmd);
 | 
			
		||||
	install_node(&ts_node, dummy_config_write);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								openbsc/src/vty_interface_bsc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								openbsc/src/vty_interface_bsc.c
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
@@ -76,4 +76,5 @@ int main(int argc, char** argv)
 | 
			
		||||
void nm_state_event() {}
 | 
			
		||||
void input_event() {}
 | 
			
		||||
void sms_alloc() {}
 | 
			
		||||
void _lchan_release() {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user