Compare commits

..

35 Commits

Author SHA1 Message Date
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
225 changed files with 24730 additions and 34533 deletions

12
openbsc/.gitignore vendored
View File

@@ -3,12 +3,8 @@
.deps
Makefile
Makefile.in
bscconfig.h
bscconfig.h.in
openbsc.pc
bsc_hack
bsc_msc_ip
bsc_mgcp
*.*~
*.sw?
@@ -23,9 +19,6 @@ install-sh
missing
stamp-h1
# git-version-gen magic
.tarball-version
.version
# apps and app data
@@ -33,12 +26,7 @@ hlr.sqlite3
bs11_config
ipaccess-config
ipaccess-find
ipaccess-firmware
ipaccess-proxy
isdnsync
bsc_nat
osmo-sgsn
osmo-gbproxy
#tests
tests/channel/channel_test

View File

@@ -3,5 +3,3 @@ Holger Freyther <zecke@selfish.org>
Jan Luebbe <jluebbe@debian.org>
Stefan Schmidt <stefan@datenfreihafen.org>
Daniel Willmann <daniel@totalueberwachung.de>
Andreas Eversberg <Andreas.Eversberg@versatel.de>
Sylvain Munaut <246tnt@gmail.com>

View File

@@ -6,8 +6,5 @@ SUBDIRS = include src tests
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = openbsc.pc
BUILT_SOURCES = $(top_srcdir)/.version
$(top_srcdir)/.version:
echo $(VERSION) > $@-t && mv $@-t $@
dist-hook:
echo $(VERSION) > $(distdir)/.tarball-version
#dist-hook:
# rm -rf `find $(distdir) -name .svn`

View File

@@ -1,32 +1,18 @@
About OpenBSC
=============
OpenBSC is a minimalistic implementation of the GSM Network, with
particular emphasis on the functionality typically provided by the BSC,
MSC, HLR, VLR and SMSC.
OpenBSC is a minimalistic implementation of the GSM Network, with particular
emphasis on the functionality typically provided by the BSC, MSC, HLR, VLR.
Its currently supported interfaces towards the BTS are:
Its only current interface is a mISDN based E1 interface utilizing the A-bis
protocol between BSC and BTS. In other words, you can connect an existing
GSM Base Transceiver Station (BTS) through E1 to OpenBSC.
* Classic A-bis over E1 using a mISDN based E1 interface. In other
words, you can connect existing GSM Base Transceiver Station (BTS)
through E1 to OpenBSC. So far, we have only tested the Siemens BS-11
Test reports with other BTS are much appreciated!
* A-bis over IP as used by the ip.access nanoBTS product family
You can find the project documentation at http://openbsc.gnumonks.org/
So far, it has only been tested with the Siemens microBTS BS-11. Test reports
with other BTS are appreciated!
This project is still in its early days, and there are lots of areas where it
doesn't behave as per GSM spec.
December 29, 2008
Harald Welte <laforge@gnumonks.org>
libosmocore
===========
Please note that as of March 2010, OpenBSC has a dependency to a library
called "libosmocore". You can obtain that library from
git://git.osmocom.org/libosmocore.git

View File

@@ -1,9 +1,7 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT([openbsc],
m4_esyscmd([./git-version-gen .tarball-version]),
[openbsc-devel@lists.openbsc.org])
AC_INIT
AM_INIT_AUTOMAKE([dist-bzip2])
AM_INIT_AUTOMAKE(openbsc, 0.1onwaves)
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -17,34 +15,6 @@ AC_PROG_RANLIB
dnl checks for libraries
AC_SEARCH_LIBS(crypt, crypt,
[LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])])
AC_SEARCH_LIBS(gtp_new, gtp,
[LIBCRYPT="-lgtp"; AC_SUBST([GPRS_LIBGTP], [1])])
AM_CONDITIONAL(HAVE_LIBGTP, test "x$GPRS_LIBGTP" != "x")
AC_ARG_ENABLE([nat], [AS_HELP_STRING([--enable-nat], [Build the BSC NAT. Requires SCCP])],
[
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2)
osmo_ac_build_nat="yes"
],
[
osmo_ac_build_nat="no"
])
AM_CONDITIONAL(BUILD_NAT, test "x$osmo_ac_build_nat" = "xyes")
AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo BSC])],
[
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2)
osmo_ac_build_bsc="yes"
],
[
osmo_ac_build_bsc="no"
])
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.16)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.1.9)
dnl checks for header files
AC_HEADER_STDC
@@ -69,16 +39,16 @@ AM_CONFIG_HEADER(bscconfig.h)
AC_OUTPUT(
openbsc.pc
include/openbsc/Makefile
include/vty/Makefile
include/sccp/Makefile
include/Makefile
src/Makefile
src/ipaccess/Makefile
src/gprs/Makefile
src/nat/Makefile
src/bsc/Makefile
tests/Makefile
tests/debug/Makefile
tests/timer/Makefile
tests/sms/Makefile
tests/gsm0408/Makefile
tests/db/Makefile
tests/channel/Makefile
tests/bsc-nat/Makefile
tests/sccp/Makefile
Makefile)

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

@@ -1,58 +0,0 @@
#!/usr/bin/env python
"""
demonstrate a unblock bug on the GB Proxy..
"""
bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
bts_ns_unblock = "\x06"
ns_unblock_ack = "\x07"
bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02"
ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00"
bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40"
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket.bind(("0.0.0.0", 0))
socket.setblocking(1)
import sys
port = int(sys.argv[1])
print "Sending data to port: %d" % port
def send_and_receive(packet):
socket.sendto(packet, ("127.0.0.1", port))
try:
data, addr = socket.recvfrom(4096)
except socket.error, e:
print "ERROR", e
import sys
sys.exit(0)
return data
#send stuff once
to_send = [
(bts_ns_reset, ns_reset_ack, "reset ack"),
(bts_ns_unblock, ns_unblock_ack, "unblock ack"),
(bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"),
]
for (out, inp, type) in to_send:
res = send_and_receive(out)
if res != inp:
print "Failed to get the %s" % type
sys.exit(-1)
import time
time.sleep(3)
res = send_and_receive(bts_bvc_reset_8167)
print "Sent all messages... check wireshark for the last response"

View File

@@ -1,78 +0,0 @@
-- Simple LUA script to print the size of BSSGP messages over their type...
do
local ip_bucket = {}
local pdu_types = {}
pdu_types[ 6] = "PAGING"
pdu_types[11] = "SUSPEND"
pdu_types[12] = "SUSPEND-ACK"
pdu_types[32] = "BVC-BLOCK"
pdu_types[33] = "BVC-BLOCK-ACK"
pdu_types[34] = "BVC-RESET"
pdu_types[35] = "BVC-RESET-ACK"
pdu_types[36] = "UNBLOCK"
pdu_types[37] = "UNBLOCK-ACK"
pdu_types[38] = "FLOW-CONTROL-BVC"
pdu_types[39] = "FLOW-CONTROL-BVC-ACK"
pdu_types[40] = "FLOW-CONTROL-MS"
pdu_types[41] = "FLOW-CONTROL-MS-ACK"
pdu_types[44] = "LLC-DISCARDED"
local function init_listener()
-- handle the port as NS over IP
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
-- bssgp filters
local bssgp_pdu_get = Field.new("bssgp.pdu_type")
local udp_length_get = Field.new("udp.length")
local tap = Listener.new("ip", "udp.port == 23000")
function tap.packet(pinfo,tvb,ip)
local pdu = bssgp_pdu_get()
local len = udp_length_get()
-- only handle bssgp, but we also want the IP frame
if not pdu then
return
end
pdu = tostring(pdu)
if tonumber(pdu) == 0 or tonumber(pdu) == 1 then
return
end
local ip_src = tostring(ip.ip_src)
local bssgp_histo = ip_bucket[ip_src]
if not bssgp_histo then
bssgp_histo = {}
ip_bucket[ip_src] = bssgp_histo
end
local key = pdu
local bucket = bssgp_histo[key]
if not bucket then
bucket = {}
bssgp_histo[key] = bucket
end
table.insert(bucket, tostring(len))
print("IP: " .. ip_src .. " PDU: " .. pdu_types[tonumber(pdu)] .. " Length: " .. tostring(len))
end
function tap.draw()
-- well... this will not be called...
-- for ip,bssgp_histo in pairs(dumpers) do
-- print("IP " .. ip)
-- end
end
function tap.reset()
-- well... this will not be called...
end
end
init_listener()
end

View File

@@ -1,46 +0,0 @@
-- Create a file named by_ip/''ip_addess''.cap with all ip traffic of each ip host. (works for tshark only)
-- Dump files are created for both source and destination hosts
do
local dir = "by_tlli"
local dumpers = {}
local function init_listener()
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
local field_tlli = Field.new("bssgp.tlli")
local tap = Listener.new("ip", "udp.port == 23000")
-- we will be called once for every IP Header.
-- If there's more than one IP header in a given packet we'll dump the packet once per every header
function tap.packet(pinfo,tvb,ip)
local tlli = field_tlli()
if not tlli then
return
end
local tlli_str = tostring(tlli)
tlli_dmp = dumpers[tlli_str]
if not tlli_dmp then
local tlli_hex = string.format("0x%x", tonumber(tlli_str))
print("Creating dump for TLLI " .. tlli_hex)
tlli_dmp = Dumper.new_for_current(dir .. "/" .. tlli_hex .. ".pcap")
dumpers[tlli_str] = tlli_dmp
end
tlli_dmp:dump_current()
tlli_dmp:flush()
end
function tap.draw()
for tlli,dumper in pairs(dumpers) do
dumper:flush()
end
end
function tap.reset()
for tlli,dumper in pairs(dumpers) do
dumper:close()
end
dumpers = {}
end
end
init_listener()
end

View File

@@ -1,59 +0,0 @@
-- This script verifies that the N(U) is increasing...
--
do
local nu_state_src = {}
local function init_listener()
-- handle the port as NS over IP
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
-- we want to look here...
local llc_sapi_get = Field.new("llcgprs.sapib")
local llc_nu_get = Field.new("llcgprs.nu")
local bssgp_tlli_get = Field.new("bssgp.tlli")
local tap = Listener.new("ip", "udp.port == 23000")
function tap.packet(pinfo,tvb,ip)
local llc_sapi = llc_sapi_get()
local llc_nu = llc_nu_get()
local bssgp_tlli = bssgp_tlli_get()
if not llc_sapi or not llc_nu or not bssgp_tlli then
return
end
local ip_src = tostring(ip.ip_src)
local bssgp_tlli = tostring(bssgp_tlli)
local llc_nu = tostring(llc_nu)
local llc_sapi = tostring(llc_sapi)
local src_key = ip_src .. "-" .. bssgp_tlli .. "-" .. llc_sapi
local last_nu = nu_state_src[src_key]
if not last_nu then
-- print("Establishing mapping for " .. src_key)
nu_state_src[src_key] = llc_nu
return
end
local function tohex(number)
return string.format("0x%x", tonumber(number))
end
nu_state_src[src_key] = llc_nu
if tonumber(last_nu) + 1 ~= tonumber(llc_nu) then
print("JUMP in N(U) on TLLI " .. tohex(bssgp_tlli) .. " and SAPI: " .. llc_sapi .. " src: " .. ip_src)
print("\t last: " .. last_nu .. " now: " .. llc_nu)
end
end
function tap.draw()
end
function tap.reset()
end
end
init_listener()
end

View File

@@ -10,7 +10,7 @@ rsip_resp = """200 321321332\r\n"""
audit_packet = """AUEP %d 13@mgw MGCP 1.0\r\n"""
crcx_packet = """CRCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n"""
dlcx_packet = """DLCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\n"""
mdcx_packet = """MDCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 258696477 0 IN IP4 172.16.1.107\r\ns=-\r\nc=IN IP4 172.16.1.107\r\nt=0 0\r\nm=audio 6666 RTP/AVP 127\r\na=rtpmap:127 GSM-EFR/8000/1\r\na=ptime:20\r\na=recvonly\r\nm=image 4402 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n"""
mdcx_packet = """MDCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 258696477 0 IN IP4 172.16.1.107\r\ns=-\r\nc=IN IP4 172.16.1.107\r\nt=0 0\r\nm=audio 4400 RTP/AVP 127\r\na=rtpmap:127 GSM-EFR/8000/1\r\na=ptime:20\r\na=recvonly\r\nm=image 4402 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n"""
def hexdump(src, length=8):
"""Recipe is from http://code.activestate.com/recipes/142812/"""
@@ -25,24 +25,15 @@ def hexdump(src, length=8):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(("127.0.0.1", MGCP_CALLAGENT_PORT))
server_socket.setblocking(1)
server_socket.setblocking(0)
last_ci = 1
def send_and_receive(packet):
global last_ci
def send_receive(packet):
server_socket.sendto(packet, ("127.0.0.1", MGCP_GATEWAY_PORT))
try:
data, addr = server_socket.recvfrom(4096)
# attempt to store the CI of the response
list = data.split("\n")
for item in list:
if item.startswith("I: "):
last_ci = int(item[3:])
print hexdump(data), addr
except socket.error, e:
print e
except socket.error:
pass
def generate_tid():
@@ -51,10 +42,13 @@ def generate_tid():
i = 1
while True:
send_and_receive(audit_packet % generate_tid())
send_and_receive(crcx_packet % generate_tid() )
send_and_receive(mdcx_packet % (generate_tid(), last_ci))
send_and_receive(dlcx_packet % (generate_tid(), last_ci))
send_receive(rsip_resp)
send_receive(audit_packet)
send_receive(crcx_packet % generate_tid() )
send_receive(mdcx_packet % (generate_tid(), i))
send_receive(dlcx_packet % (generate_tid(), i))
i = i + 1
time.sleep(3)

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

@@ -31,8 +31,6 @@ GSM 04.08 3.4.13: RR connection release procedure
== Implementation in OpenBSC ==
THIS IS OUTDATED and will be updated...
chan_alloc.c:lchan_auto_release()
* checks if use count still > 0 (abort)
* calls gsm48_send_rr_release()

View File

@@ -1,89 +0,0 @@
Ideas about a handover algorithm
======================================================================
This is mostly based on the results presented in Chapter 8 of "Performance
Enhancements in a Frequency Hopping GSM Network" by Thomas Toftegaard Nielsen
and Joeroen Wigard.
=== Reasons for performing handover ===
Section 2.1.1: Handover used in their CAPACITY simulation:
1) Interference Handover
Average RXLEV is satisfactory high, but average RXQUAL too low indicates
interference to the channel. Handover should be made.
2) Bad Quality
Averaged RXQUAL is lower than a threshold
3) Low Level / Signal Strength
Average RXLEV is lower than a threshold
4) Distance Handover
MS is too far away from a cell (measured by TA)
5) Power budget / Better Cell
RX Level of neighbor cell is at least "HO Margin dB" dB better than the
current serving cell.
=== Ideal parameters for HO algorithm ===
Chapter 8, Section 2.2, Table 24:
Window RXLEV averaging: 10 SACCH frames (no weighting)
Window RXQUAL averaging: 1 SACCH frame (no averaging)
Level Threashold: 1 of the last 1 AV-RXLEV values < -110dBm
Quality Threshold: 3 of the last 4 AV-RXQUAL values >= 5
Interference Threshold: 1 of the last AV-RXLEV > -85 dBm &
3 of the last 4 AV-RXQUAL values >= 5
Power Budget: Level of neighbor cell > 3 dB better
Power Budget Interval: Every 6 SACCH frames (6 seconds ?!?)
Distance Handover: Disabled
Evaluation rule 1: RXLEV of the candidate cell a tleast -104 dBm
Evaluation rule 2: Level of candidate cell > 3dB better own cell
Timer Successful HO: 5 SACCH frames
Timer Unsuccessful HO: 1 SACCH frame
In a non-frequency hopping case, RXQUAL threshold can be decreased to
RXLEV >= 4
When frequency hopping is enabled, the following additional parameters
should be introduced:
* No intra-cell handover
* Use a HO Margin of 2dB
=== Handover Channel Reservation ===
In loaded network, each cell should reserve some channels for handovers,
rather than using all of them for new call establishment. This reduces the
need to drop calls due to failing handovers, at the expense of failing new call
attempts.
=== Dynamic HO Margin ===
The handover margin (hysteresis) should depend on the RXQUAL. Optimal results
were achieved with the following settings:
* RXQUAL <= 4: 9 dB
* RXQUAL == 5: 6 dB
* RXQUAL >= 6: 1 dB
== Actual Handover on a protocol level ==
After the BSC has decided a handover shall be done, it has to
# allocate a channel at the new BTS
# allocate a handover reference
# activate the channel on the BTS side using RSL CHANNEL ACTIVATION,
indicating the HO reference
# BTS responds with CHAN ACT ACK, including GSM frame number
# BSC sends 04.08 HO CMD to MS using old BTS

View File

@@ -1,151 +0,0 @@
#!/bin/sh
# Print a version string.
scriptversion=2010-01-28.01
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
#
# 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 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
# It may be run two ways:
# - from a git repository in which the "git describe" command below
# produces useful output (thus requiring at least one signed tag)
# - from a non-git-repo directory containing a .tarball-version file, which
# presumes this script is invoked like "./git-version-gen .tarball-version".
# In order to use intra-version strings in your project, you will need two
# separate generated version string files:
#
# .tarball-version - present only in a distribution tarball, and not in
# a checked-out repository. Created with contents that were learned at
# the last time autoconf was run, and used by git-version-gen. Must not
# be present in either $(srcdir) or $(builddir) for git-version-gen to
# give accurate answers during normal development with a checked out tree,
# but must be present in a tarball when there is no version control system.
# Therefore, it cannot be used in any dependencies. GNUmakefile has
# hooks to force a reconfigure at distribution time to get the value
# correct, without penalizing normal development with extra reconfigures.
#
# .version - present in a checked-out repository and in a distribution
# tarball. Usable in dependencies, particularly for files that don't
# want to depend on config.h but do want to track version changes.
# Delete this file prior to any autoconf run where you want to rebuild
# files to pick up a version string change; and leave it stale to
# minimize rebuild time after unrelated changes to configure sources.
#
# It is probably wise to add these two files to .gitignore, so that you
# don't accidentally commit either generated file.
#
# Use the following line in your configure.ac, so that $(VERSION) will
# automatically be up-to-date each time configure is run (and note that
# since configure.ac no longer includes a version string, Makefile rules
# should not depend on configure.ac for version updates).
#
# AC_INIT([GNU project],
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
# [bug-project@example])
#
# Then use the following lines in your Makefile.am, so that .version
# will be present for dependencies, and so that .tarball-version will
# exist in distribution tarballs.
#
# BUILT_SOURCES = $(top_srcdir)/.version
# $(top_srcdir)/.version:
# echo $(VERSION) > $@-t && mv $@-t $@
# dist-hook:
# echo $(VERSION) > $(distdir)/.tarball-version
case $# in
1) ;;
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
esac
tarball_version_file=$1
nl='
'
# First see if there is a tarball-only version file.
# then try "git describe", then default.
if test -f $tarball_version_file
then
v=`cat $tarball_version_file` || exit 1
case $v in
*$nl*) v= ;; # reject multi-line output
[0-9]*) ;;
*) v= ;;
esac
test -z "$v" \
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
fi
if test -n "$v"
then
: # use $v
elif test -d ./../.git \
&& v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|| git describe --abbrev=4 HEAD 2>/dev/null` \
&& case $v in
[0-9]*) ;;
v[0-9]*) ;;
*) (exit 1) ;;
esac
then
# Is this a new git that lists number of commits since the last
# tag or the previous older version that did not?
# Newer: v6.10-77-g0f8faeb
# Older: v6.10-g0f8faeb
case $v in
*-*-*) : git describe is okay three part flavor ;;
*-*)
: git describe is older two part flavor
# Recreate the number of commits and rewrite such that the
# result is the same as if we were using the newer version
# of git describe.
vtag=`echo "$v" | sed 's/-.*//'`
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
;;
esac
# Change the first '-' to a '.', so version-comparing tools work properly.
# Remove the "g" in git describe's output string, to save a byte.
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
else
v=UNKNOWN
fi
v=`echo "$v" |sed 's/^v//'`
# Don't declare a version "dirty" merely because a time stamp has changed.
git status > /dev/null 2>&1
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
case "$dirty" in
'') ;;
*) # Append the suffix only if there isn't one already.
case $v in
*-dirty) ;;
*) v="$v-dirty" ;;
esac ;;
esac
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
echo "$v" | tr -d '\012'
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

View File

@@ -1,3 +1,3 @@
SUBDIRS = openbsc
SUBDIRS = openbsc vty sccp
noinst_HEADERS = mISDNif.h compat_af_isdn.h

View File

@@ -1,16 +1,7 @@
noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \
gsm_subscriber.h gsm_04_11.h debug.h signal.h \
misdn.h chan_alloc.h paging.h \
subchan_demux.h trau_frame.h e1_input.h trau_mux.h \
ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \
bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \
silent_call.h mgcp.h meas_rep.h rest_octets.h \
system_information.h handover.h mgcp_internal.h \
vty.h socket.h \
crc24.h gprs_bssgp.h gprs_llc.h gprs_ns.h gprs_gmm.h \
gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \
gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \
osmo_bsc_rf.h osmo_bsc.h network_listen.h bsc_nat_sccp.h
openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h
openbscdir = $(includedir)/openbsc
noinst_HEADERS = abis_nm.h abis_rsl.h debug.h db.h gsm_04_08.h gsm_data.h \
gsm_subscriber.h linuxlist.h msgb.h select.h tlv.h gsm_04_11.h \
timer.h misdn.h chan_alloc.h telnet_interface.h paging.h \
subchan_demux.h trau_frame.h e1_input.h trau_mux.h signal.h \
gsm_utils.h ipaccess.h rs232.h openbscdefines.h rtp_proxy.h \
bsc_rll.h mncc.h talloc.h transaction.h ussd.h gsm_04_80.h \
silent_call.h mgcp.h bssap.h

View File

@@ -24,8 +24,665 @@
#define _NM_H
#include <sys/types.h>
#include <osmocore/tlv.h>
#include <osmocore/protocol/gsm_12_21.h>
#include <openbsc/tlv.h>
/* PRIVATE */
/* generic header in front of every OML message according to TS 08.59 */
struct abis_om_hdr {
u_int8_t mdisc;
u_int8_t placement;
u_int8_t sequence;
u_int8_t length;
u_int8_t data[0];
} __attribute__ ((packed));
#define ABIS_OM_MDISC_FOM 0x80
#define ABIS_OM_MDISC_MMI 0x40
#define ABIS_OM_MDISC_TRAU 0x20
#define ABIS_OM_MDISC_MANUF 0x10
#define ABIS_OM_PLACEMENT_ONLY 0x80
#define ABIS_OM_PLACEMENT_FIRST 0x40
#define ABIS_OM_PLACEMENT_MIDDLE 0x20
#define ABIS_OM_PLACEMENT_LAST 0x10
struct abis_om_obj_inst {
u_int8_t bts_nr;
u_int8_t trx_nr;
u_int8_t ts_nr;
} __attribute__ ((packed));
struct abis_om_fom_hdr {
u_int8_t msg_type;
u_int8_t obj_class;
struct abis_om_obj_inst obj_inst;
u_int8_t data[0];
} __attribute__ ((packed));
#define ABIS_OM_FOM_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_fom_hdr))
/* Section 9.1: Message Types */
enum abis_nm_msgtype {
/* SW Download Management Messages */
NM_MT_LOAD_INIT = 0x01,
NM_MT_LOAD_INIT_ACK,
NM_MT_LOAD_INIT_NACK,
NM_MT_LOAD_SEG,
NM_MT_LOAD_SEG_ACK,
NM_MT_LOAD_ABORT,
NM_MT_LOAD_END,
NM_MT_LOAD_END_ACK,
NM_MT_LOAD_END_NACK,
NM_MT_SW_ACT_REQ, /* BTS->BSC */
NM_MT_SW_ACT_REQ_ACK,
NM_MT_SW_ACT_REQ_NACK,
NM_MT_ACTIVATE_SW, /* BSC->BTS */
NM_MT_ACTIVATE_SW_ACK,
NM_MT_ACTIVATE_SW_NACK,
NM_MT_SW_ACTIVATED_REP, /* 0x10 */
/* A-bis Interface Management Messages */
NM_MT_ESTABLISH_TEI = 0x21,
NM_MT_ESTABLISH_TEI_ACK,
NM_MT_ESTABLISH_TEI_NACK,
NM_MT_CONN_TERR_SIGN,
NM_MT_CONN_TERR_SIGN_ACK,
NM_MT_CONN_TERR_SIGN_NACK,
NM_MT_DISC_TERR_SIGN,
NM_MT_DISC_TERR_SIGN_ACK,
NM_MT_DISC_TERR_SIGN_NACK,
NM_MT_CONN_TERR_TRAF,
NM_MT_CONN_TERR_TRAF_ACK,
NM_MT_CONN_TERR_TRAF_NACK,
NM_MT_DISC_TERR_TRAF,
NM_MT_DISC_TERR_TRAF_ACK,
NM_MT_DISC_TERR_TRAF_NACK,
/* Transmission Management Messages */
NM_MT_CONN_MDROP_LINK = 0x31,
NM_MT_CONN_MDROP_LINK_ACK,
NM_MT_CONN_MDROP_LINK_NACK,
NM_MT_DISC_MDROP_LINK,
NM_MT_DISC_MDROP_LINK_ACK,
NM_MT_DISC_MDROP_LINK_NACK,
/* Air Interface Management Messages */
NM_MT_SET_BTS_ATTR = 0x41,
NM_MT_SET_BTS_ATTR_ACK,
NM_MT_SET_BTS_ATTR_NACK,
NM_MT_SET_RADIO_ATTR,
NM_MT_SET_RADIO_ATTR_ACK,
NM_MT_SET_RADIO_ATTR_NACK,
NM_MT_SET_CHAN_ATTR,
NM_MT_SET_CHAN_ATTR_ACK,
NM_MT_SET_CHAN_ATTR_NACK,
/* Test Management Messages */
NM_MT_PERF_TEST = 0x51,
NM_MT_PERF_TEST_ACK,
NM_MT_PERF_TEST_NACK,
NM_MT_TEST_REP,
NM_MT_SEND_TEST_REP,
NM_MT_SEND_TEST_REP_ACK,
NM_MT_SEND_TEST_REP_NACK,
NM_MT_STOP_TEST,
NM_MT_STOP_TEST_ACK,
NM_MT_STOP_TEST_NACK,
/* State Management and Event Report Messages */
NM_MT_STATECHG_EVENT_REP = 0x61,
NM_MT_FAILURE_EVENT_REP,
NM_MT_STOP_EVENT_REP,
NM_MT_STOP_EVENT_REP_ACK,
NM_MT_STOP_EVENT_REP_NACK,
NM_MT_REST_EVENT_REP,
NM_MT_REST_EVENT_REP_ACK,
NM_MT_REST_EVENT_REP_NACK,
NM_MT_CHG_ADM_STATE,
NM_MT_CHG_ADM_STATE_ACK,
NM_MT_CHG_ADM_STATE_NACK,
NM_MT_CHG_ADM_STATE_REQ,
NM_MT_CHG_ADM_STATE_REQ_ACK,
NM_MT_CHG_ADM_STATE_REQ_NACK,
NM_MT_REP_OUTST_ALARMS = 0x93,
NM_MT_REP_OUTST_ALARMS_ACK,
NM_MT_REP_OUTST_ALARMS_NACK,
/* Equipment Management Messages */
NM_MT_CHANGEOVER = 0x71,
NM_MT_CHANGEOVER_ACK,
NM_MT_CHANGEOVER_NACK,
NM_MT_OPSTART,
NM_MT_OPSTART_ACK,
NM_MT_OPSTART_NACK,
NM_MT_REINIT,
NM_MT_REINIT_ACK,
NM_MT_REINIT_NACK,
NM_MT_SET_SITE_OUT, /* BS11: get alarm ?!? */
NM_MT_SET_SITE_OUT_ACK,
NM_MT_SET_SITE_OUT_NACK,
NM_MT_CHG_HW_CONF = 0x90,
NM_MT_CHG_HW_CONF_ACK,
NM_MT_CHG_HW_CONF_NACK,
/* Measurement Management Messages */
NM_MT_MEAS_RES_REQ = 0x8a,
NM_MT_MEAS_RES_RESP,
NM_MT_STOP_MEAS,
NM_MT_START_MEAS,
/* Other Messages */
NM_MT_GET_ATTR = 0x81,
NM_MT_GET_ATTR_RESP,
NM_MT_GET_ATTR_NACK,
NM_MT_SET_ALARM_THRES,
NM_MT_SET_ALARM_THRES_ACK,
NM_MT_SET_ALARM_THRES_NACK,
};
enum abis_nm_msgtype_bs11 {
NM_MT_BS11_RESET_RESOURCE = 0x74,
NM_MT_BS11_BEGIN_DB_TX = 0xa3,
NM_MT_BS11_BEGIN_DB_TX_ACK,
NM_MT_BS11_BEGIN_DB_TX_NACK,
NM_MT_BS11_END_DB_TX = 0xa6,
NM_MT_BS11_END_DB_TX_ACK,
NM_MT_BS11_END_DB_TX_NACK,
NM_MT_BS11_CREATE_OBJ = 0xa9,
NM_MT_BS11_CREATE_OBJ_ACK,
NM_MT_BS11_CREATE_OBJ_NACK,
NM_MT_BS11_DELETE_OBJ = 0xac,
NM_MT_BS11_DELETE_OBJ_ACK,
NM_MT_BS11_DELETE_OBJ_NACK,
NM_MT_BS11_SET_ATTR = 0xd0,
NM_MT_BS11_SET_ATTR_ACK,
NM_MT_BS11_SET_ATTR_NACK,
NM_MT_BS11_LMT_SESSION = 0xdc,
NM_MT_BS11_GET_STATE = 0xe3,
NM_MT_BS11_GET_STATE_ACK,
NM_MT_BS11_LMT_LOGON = 0xe5,
NM_MT_BS11_LMT_LOGON_ACK,
NM_MT_BS11_RESTART = 0xe7,
NM_MT_BS11_RESTART_ACK,
NM_MT_BS11_DISCONNECT = 0xe9,
NM_MT_BS11_DISCONNECT_ACK,
NM_MT_BS11_LMT_LOGOFF = 0xec,
NM_MT_BS11_LMT_LOGOFF_ACK,
NM_MT_BS11_RECONNECT = 0xf1,
NM_MT_BS11_RECONNECT_ACK,
};
enum abis_nm_msgtype_ipacc {
NM_MT_IPACC_RESTART = 0x87,
NM_MT_IPACC_RESTART_ACK,
NM_MT_IPACC_RSL_CONNECT = 0xe0,
NM_MT_IPACC_RSL_CONNECT_ACK,
NM_MT_IPACC_RSL_CONNECT_NACK,
NM_MT_IPACC_RSL_DISCONNECT = 0xe3,
NM_MT_IPACC_RSL_DISCONNECT_ACK,
NM_MT_IPACC_RSL_DISCONNECT_NACK,
NM_MT_IPACC_CONN_TRAF = 0xe6,
NM_MT_IPACC_CONN_TRAF_ACK,
NM_MT_IPACC_CONN_TRAF_NACK,
NM_MT_IPACC_DEF_BOOT_SW = 0xec,
NM_MT_IPACC_DEF_BOOT_SW_ACK,
MN_MT_IPACC_DEF_BOOT_SW_NACK,
NM_MT_IPACC_SET_NVATTR = 0xef,
NM_MT_IPACC_SET_NVATTR_ACK,
NM_MT_IPACC_SET_NVATTR_NACK,
NM_MT_IPACC_GET_NVATTR = 0xf2,
NM_MT_IPACC_GET_NVATTR_ACK,
NM_MT_IPACC_GET_NVATTR_NACK,
NM_MT_IPACC_SET_ATTR = 0xf5,
NM_MT_IPACC_SET_ATTR_ACK,
NM_MT_IPACC_SET_ATTR_NACK,
};
enum abis_nm_bs11_cell_alloc {
NM_BS11_CANR_GSM = 0x00,
NM_BS11_CANR_DCS1800 = 0x01,
};
/* Section 9.2: Object Class */
enum abis_nm_obj_class {
NM_OC_SITE_MANAGER = 0x00,
NM_OC_BTS,
NM_OC_RADIO_CARRIER,
NM_OC_CHANNEL,
NM_OC_BASEB_TRANSC,
/* RFU: 05-FE */
NM_OC_IPAC_E1_TRUNK = 0x0e,
NM_OC_IPAC_E1_PORT = 0x0f,
NM_OC_IPAC_E1_CHAN = 0x10,
NM_OC_IPAC_CLK_MODULE = 0x22,
NM_OC_BS11_ADJC = 0xa0,
NM_OC_BS11_HANDOVER = 0xa1,
NM_OC_BS11_PWR_CTRL = 0xa2,
NM_OC_BS11_BTSE = 0xa3, /* LMT? */
NM_OC_BS11_RACK = 0xa4,
NM_OC_BS11 = 0xa5, /* 01: ALCO */
NM_OC_BS11_TEST = 0xa6,
NM_OC_BS11_ENVABTSE = 0xa8,
NM_OC_BS11_BPORT = 0xa9,
NM_OC_GPRS_NSE = 0xf0,
NM_OC_GPRS_CELL = 0xf1,
NM_OC_GPRS_NSVC = 0xf2,
NM_OC_NULL = 0xff,
};
/* Section 9.4: Attributes */
enum abis_nm_attr {
NM_ATT_ABIS_CHANNEL = 0x01,
NM_ATT_ADD_INFO,
NM_ATT_ADD_TEXT,
NM_ATT_ADM_STATE,
NM_ATT_ARFCN_LIST,
NM_ATT_AUTON_REPORT,
NM_ATT_AVAIL_STATUS,
NM_ATT_BCCH_ARFCN,
NM_ATT_BSIC,
NM_ATT_BTS_AIR_TIMER,
NM_ATT_CCCH_L_I_P,
NM_ATT_CCCH_L_T,
NM_ATT_CHAN_COMB,
NM_ATT_CONN_FAIL_CRIT,
NM_ATT_DEST,
/* res */
NM_ATT_EVENT_TYPE = 0x11, /* BS11: file data ?!? */
NM_ATT_FILE_ID,
NM_ATT_FILE_VERSION,
NM_ATT_GSM_TIME,
NM_ATT_HSN,
NM_ATT_HW_CONFIG,
NM_ATT_HW_DESC,
NM_ATT_INTAVE_PARAM,
NM_ATT_INTERF_BOUND,
NM_ATT_LIST_REQ_ATTR,
NM_ATT_MAIO,
NM_ATT_MANUF_STATE,
NM_ATT_MANUF_THRESH,
NM_ATT_MANUF_ID,
NM_ATT_MAX_TA,
NM_ATT_MDROP_LINK, /* 0x20 */
NM_ATT_MDROP_NEXT,
NM_ATT_NACK_CAUSES,
NM_ATT_NY1,
NM_ATT_OPER_STATE,
NM_ATT_OVERL_PERIOD,
NM_ATT_PHYS_CONF,
NM_ATT_POWER_CLASS,
NM_ATT_POWER_THRESH,
NM_ATT_PROB_CAUSE,
NM_ATT_RACH_B_THRESH,
NM_ATT_LDAVG_SLOTS,
NM_ATT_RAD_SUBC,
NM_ATT_RF_MAXPOWR_R,
NM_ATT_SITE_INPUTS,
NM_ATT_SITE_OUTPUTS,
NM_ATT_SOURCE, /* 0x30 */
NM_ATT_SPEC_PROB,
NM_ATT_START_TIME,
NM_ATT_T200,
NM_ATT_TEI,
NM_ATT_TEST_DUR,
NM_ATT_TEST_NO,
NM_ATT_TEST_REPORT,
NM_ATT_VSWR_THRESH,
NM_ATT_WINDOW_SIZE,
/* Res */
NM_ATT_BS11_RSSI_OFFS = 0x3d,
NM_ATT_BS11_TXPWR = 0x3e,
NM_ATT_BS11_DIVERSITY = 0x3f,
/* Res */
NM_ATT_TSC = 0x40,
NM_ATT_SW_CONFIG,
NM_ATT_SW_DESCR,
NM_ATT_SEVERITY,
NM_ATT_GET_ARI,
NM_ATT_HW_CONF_CHG,
NM_ATT_OUTST_ALARM,
NM_ATT_FILE_DATA,
NM_ATT_MEAS_RES,
NM_ATT_MEAS_TYPE,
NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c,
NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f,
NM_ATT_BS11_ESN_PCB_SERIAL = 0x55,
NM_ATT_BS11_EXCESSIVE_DISTANCE = 0x58,
NM_ATT_BS11_ALL_TEST_CATG = 0x60,
NM_ATT_BS11_BTSLS_HOPPING,
NM_ATT_BS11_CELL_ALLOC_NR,
NM_ATT_BS11_CELL_GLOBAL_ID,
NM_ATT_BS11_ENA_INTERF_CLASS = 0x66,
NM_ATT_BS11_ENA_INT_INTEC_HANDO = 0x67,
NM_ATT_BS11_ENA_INT_INTRC_HANDO = 0x68,
NM_ATT_BS11_ENA_MS_PWR_CTRL = 0x69,
NM_ATT_BS11_ENA_PWR_BDGT_HO = 0x6a,
NM_ATT_BS11_ENA_PWR_CTRL_RLFW = 0x6b,
NM_ATT_BS11_ENA_RXLEV_HO = 0x6c,
NM_ATT_BS11_ENA_RXQUAL_HO = 0x6d,
NM_ATT_BS11_FACCH_QUAL = 0x6e,
NM_ATT_IPACC_DST_IP = 0x80,
NM_ATT_IPACC_DST_IP_PORT = 0x81,
NM_ATT_IPACC_SSRC = 0x82,
NM_ATT_IPACC_RTP_PAYLD_TYPE = 0x83,
NM_ATT_IPACC_BASEB_ID = 0x84,
NM_ATT_IPACC_STREAM_ID = 0x85,
NM_ATT_IPACC_NV_FLAGS = 0x86,
NM_ATT_IPACC_FREQ_CTRL = 0x87,
NM_ATT_IPACC_PRIM_OML_CFG = 0x88,
NM_ATT_IPACC_SEC_OML_CFG = 0x89,
NM_ATT_IPACC_IP_IF_CFG = 0x8a, /* IP interface */
NM_ATT_IPACC_IP_GW_CFG = 0x8b, /* IP gateway */
NM_ATT_IPACC_IN_SERV_TIME = 0x8c,
NM_ATT_IPACC_TRX_BTS_ASS = 0x8d,
NM_ATT_IPACC_LOCATION = 0x8e, /* string describing location */
NM_ATT_IPACC_PAGING_CFG = 0x8f,
NM_ATT_IPACC_FILE_DATA = 0x90,
NM_ATT_IPACC_UNIT_ID = 0x91, /* Site/BTS/TRX */
NM_ATT_IPACC_PARENT_UNIT_ID = 0x92,
NM_ATT_IPACC_UNIT_NAME = 0x93, /* default: nbts-<mac-as-string> */
NM_ATT_IPACC_SNMP_CFG = 0x94,
NM_ATT_IPACC_PRIM_OML_CFG_LIST = 0x95,
NM_ATT_IPACC_PRIM_OML_FB_TOUT = 0x96,
NM_ATT_IPACC_CUR_SW_CFG = 0x97,
NM_ATT_IPACC_TIMING_BUS = 0x98,
NM_ATT_IPACC_CGI = 0x99,
NM_ATT_IPACC_RAC = 0x9a,
NM_ATT_IPACC_OBJ_VERSION = 0x9b,
NM_ATT_IPACC_GPRS_PAGING_CFG = 0x9c,
NM_ATT_IPACC_NSEI = 0x9d,
NM_ATT_IPACC_BVCI = 0x9e,
NM_ATT_IPACC_NSVCI = 0x9f,
NM_ATT_IPACC_NS_CFG = 0xa0,
NM_ATT_IPACC_BSSGP_CFG = 0xa1,
NM_ATT_IPACC_NS_LINK_CFG = 0xa2,
NM_ATT_IPACC_RLC_CFG = 0xa3,
NM_ATT_IPACC_ALM_THRESH_LIST = 0xa4,
NM_ATT_IPACC_MONIT_VAL_LIST = 0xa5,
NM_ATT_IPACC_TIB_CONTROL = 0xa6,
NM_ATT_IPACC_SUPP_FEATURES = 0xa7,
NM_ATT_IPACC_CODING_SCHEMES = 0xa8,
NM_ATT_IPACC_RLC_CFG_2 = 0xa9,
NM_ATT_IPACC_HEARTB_TOUT = 0xaa,
NM_ATT_IPACC_UPTIME = 0xab,
NM_ATT_IPACC_RLC_CFG_3 = 0xac,
NM_ATT_IPACC_SSL_CFG = 0xad,
NM_ATT_IPACC_SEC_POSSIBLE = 0xae,
NM_ATT_IPACC_IML_SSL_STATE = 0xaf,
NM_ATT_IPACC_REVOC_DATE = 0xb0,
NM_ATT_BS11_RF_RES_IND_PER = 0x8f,
NM_ATT_BS11_RX_LEV_MIN_CELL = 0x90,
NM_ATT_BS11_ABIS_EXT_TIME = 0x91,
NM_ATT_BS11_TIMER_HO_REQUEST = 0x92,
NM_ATT_BS11_TIMER_NCELL = 0x93,
NM_ATT_BS11_TSYNC = 0x94,
NM_ATT_BS11_TTRAU = 0x95,
NM_ATT_BS11_EMRG_CFG_MEMBER = 0x9b,
NM_ATT_BS11_TRX_AREA = 0x9f,
NM_ATT_BS11_BCCH_RECONF = 0xd7,
NM_ATT_BS11_BIT_ERR_THESH = 0xa0,
NM_ATT_BS11_BOOT_SW_VERS = 0xa1,
NM_ATT_BS11_CCLK_ACCURACY = 0xa3,
NM_ATT_BS11_CCLK_TYPE = 0xa4,
NM_ATT_BS11_INP_IMPEDANCE = 0xaa,
NM_ATT_BS11_L1_PROT_TYPE = 0xab,
NM_ATT_BS11_LINE_CFG = 0xac,
NM_ATT_BS11_LI_PORT_1 = 0xad,
NM_ATT_BS11_LI_PORT_2 = 0xae,
NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0,
NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb,
NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc,
NM_ATT_BS11_SW_LOAD_STORED = 0xbd,
NM_ATT_BS11_VENDOR_NAME = 0xc1,
NM_ATT_BS11_HOPPING_MODE = 0xc5,
NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6,
NM_ATT_BS11_LMT_LOGIN_TIME = 0xc7,
NM_ATT_BS11_LMT_USER_ACC_LEV = 0xc8,
NM_ATT_BS11_LMT_USER_NAME = 0xc9,
NM_ATT_BS11_L1_CONTROL_TS = 0xd8,
NM_ATT_BS11_RADIO_MEAS_GRAN = 0xdc, /* in SACCH multiframes */
NM_ATT_BS11_RADIO_MEAS_REP = 0xdd,
NM_ATT_BS11_SH_LAPD_INT_TIMER = 0xe8,
NM_ATT_BS11_BTS_STATE = 0xf0,
NM_ATT_BS11_E1_STATE = 0xf1,
NM_ATT_BS11_PLL = 0xf2,
NM_ATT_BS11_RX_OFFSET = 0xf3,
NM_ATT_BS11_ANT_TYPE = 0xf4,
NM_ATT_BS11_PLL_MODE = 0xfc,
NM_ATT_BS11_PASSWORD = 0xfd,
};
#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE
/* Section 9.4.4: Administrative State */
enum abis_nm_adm_state {
NM_STATE_LOCKED = 0x01,
NM_STATE_UNLOCKED = 0x02,
NM_STATE_SHUTDOWN = 0x03,
NM_STATE_NULL = 0xff,
};
/* Section 9.4.7: Administrative State */
enum abis_nm_avail_state {
NM_AVSTATE_IN_TEST = 1,
NM_AVSTATE_POWER_OFF = 2,
NM_AVSTATE_OFF_LINE = 3,
NM_AVSTATE_DEPENDENCY = 5,
NM_AVSTATE_DEGRADED = 6,
NM_AVSTATE_NOT_INSTALLED= 7,
NM_AVSTATE_OK = 0xff,
};
/* Section 9.4.13: Channel Combination */
enum abis_nm_chan_comb {
NM_CHANC_TCHFull = 0x00, /* TCH/F + TCH/H + SACCH/TF */
NM_CHANC_TCHHalf = 0x01, /* TCH/H(0,1) + FACCH/H(0,1) +
SACCH/TH(0,1) */
NM_CHANC_TCHHalf2 = 0x02, /* TCH/H(0) + FACCH/H(0) + SACCH/TH(0) +
TCH/H(1) */
NM_CHANC_SDCCH = 0x03, /* SDCCH/8 + SACCH/8 */
NM_CHANC_mainBCCH = 0x04, /* FCCH + SCH + BCCH + CCCH */
NM_CHANC_BCCHComb = 0x05, /* FCCH + SCH + BCCH + CCCH + SDCCH/4 +
SACCH/C4 */
NM_CHANC_BCCH = 0x06, /* BCCH + CCCH */
NM_CHANC_BCCH_CBCH = 0x07, /* CHANC_BCCHComb + CBCH */
NM_CHANC_SDCCH_CBCH = 0x08, /* CHANC_SDCCH8 + CBCH */
/* ip.access */
NM_CHANC_IPAC_bPDCH = 0x0b, /* PBCCH + PCCCH + PDTCH/F + PACCH/F +
PTCCH/F */
NM_CHANC_IPAC_cPDCH = 0x0c, /* PBCCH + PDTCH/F + PACCH/F + PTCCH/F */
NM_CHANC_IPAC_PDCH = 0x0d, /* PDTCH/F + PACCH/F + PTCCH/F */
NM_CHANC_IPAC_TCHFull_PDCH = 0x80,
NM_CHANC_IPAC_TCHFull_TCHHalf = 0x81,
};
/* Section 9.4.16: Event Type */
enum abis_nm_event_type {
NM_EVT_COMM_FAIL = 0x00,
NM_EVT_QOS_FAIL = 0x01,
NM_EVT_PROC_FAIL = 0x02,
NM_EVT_EQUIP_FAIL = 0x03,
NM_EVT_ENV_FAIL = 0x04,
};
/* Section: 9.4.63: Perceived Severity */
enum abis_nm_severity {
NM_SEVER_CEASED = 0x00,
NM_SEVER_CRITICAL = 0x01,
NM_SEVER_MAJOR = 0x02,
NM_SEVER_MINOR = 0x03,
NM_SEVER_WARNING = 0x04,
NM_SEVER_INDETERMINATE = 0x05,
};
/* Section 9.4.43: Probable Cause Type */
enum abis_nm_pcause_type {
NM_PCAUSE_T_X721 = 0x01,
NM_PCAUSE_T_GSM = 0x02,
NM_PCAUSE_T_MANUF = 0x03,
};
/* Section 9.4.36: NACK Causes */
enum abis_nm_nack_cause {
/* General Nack Causes */
NM_NACK_INCORR_STRUCT = 0x01,
NM_NACK_MSGTYPE_INVAL = 0x02,
NM_NACK_OBJCLASS_INVAL = 0x05,
NM_NACK_OBJCLASS_NOTSUPP = 0x06,
NM_NACK_BTSNR_UNKN = 0x07,
NM_NACK_TRXNR_UNKN = 0x08,
NM_NACK_OBJINST_UNKN = 0x09,
NM_NACK_ATTRID_INVAL = 0x0c,
NM_NACK_ATTRID_NOTSUPP = 0x0d,
NM_NACK_PARAM_RANGE = 0x0e,
NM_NACK_ATTRLIST_INCONSISTENT = 0x0f,
NM_NACK_SPEC_IMPL_NOTSUPP = 0x10,
NM_NACK_CANT_PERFORM = 0x11,
/* Specific Nack Causes */
NM_NACK_RES_NOTIMPL = 0x19,
NM_NACK_RES_NOTAVAIL = 0x1a,
NM_NACK_FREQ_NOTAVAIL = 0x1b,
NM_NACK_TEST_NOTSUPP = 0x1c,
NM_NACK_CAPACITY_RESTR = 0x1d,
NM_NACK_PHYSCFG_NOTPERFORM = 0x1e,
NM_NACK_TEST_NOTINIT = 0x1f,
NM_NACK_PHYSCFG_NOTRESTORE = 0x20,
NM_NACK_TEST_NOSUCH = 0x21,
NM_NACK_TEST_NOSTOP = 0x22,
NM_NACK_MSGINCONSIST_PHYSCFG = 0x23,
NM_NACK_FILE_INCOMPLETE = 0x25,
NM_NACK_FILE_NOTAVAIL = 0x26,
NM_NACK_FILE_NOTACTIVATE = 0x27,
NM_NACK_REQ_NOT_GRANT = 0x28,
NM_NACK_WAIT = 0x29,
NM_NACK_NOTH_REPORT_EXIST = 0x2a,
NM_NACK_MEAS_NOTSUPP = 0x2b,
NM_NACK_MEAS_NOTSTART = 0x2c,
};
/* Section 9.4.1 */
struct abis_nm_channel {
u_int8_t attrib;
u_int8_t bts_port;
u_int8_t timeslot;
u_int8_t subslot;
} __attribute__ ((packed));
/* Siemens BS-11 specific objects in the SienemsHW (0xA5) object class */
enum abis_bs11_objtype {
BS11_OBJ_ALCO = 0x01,
BS11_OBJ_BBSIG = 0x02, /* obj_class: 0,1 */
BS11_OBJ_TRX1 = 0x03, /* only DEACTIVATE TRX1 */
BS11_OBJ_CCLK = 0x04,
BS11_OBJ_GPSU = 0x06,
BS11_OBJ_LI = 0x07,
BS11_OBJ_PA = 0x09, /* obj_class: 0, 1*/
};
enum abis_bs11_trx_power {
BS11_TRX_POWER_GSM_2W = 0x06,
BS11_TRX_POWER_GSM_250mW= 0x07,
BS11_TRX_POWER_GSM_80mW = 0x08,
BS11_TRX_POWER_GSM_30mW = 0x09,
BS11_TRX_POWER_DCS_3W = 0x0a,
BS11_TRX_POWER_DCS_1W6 = 0x0b,
BS11_TRX_POWER_DCS_500mW= 0x0c,
BS11_TRX_POWER_DCS_160mW= 0x0d,
};
enum abis_bs11_li_pll_mode {
BS11_LI_PLL_LOCKED = 2,
BS11_LI_PLL_STANDALONE = 3,
};
enum abis_bs11_line_cfg {
BS11_LINE_CFG_STAR = 0x00,
BS11_LINE_CFG_MULTIDROP = 0x01,
BS11_LINE_CFG_LOOP = 0x02,
};
enum abis_bs11_phase {
BS11_STATE_SOFTWARE_RQD = 0x01,
BS11_STATE_LOAD_SMU_INTENDED = 0x11,
BS11_STATE_LOAD_SMU_SAFETY = 0x21,
BS11_STATE_LOAD_FAILED = 0x31,
BS11_STATE_LOAD_DIAGNOSTIC = 0x41,
BS11_STATE_WARM_UP = 0x51,
BS11_STATE_WARM_UP_2 = 0x52,
BS11_STATE_WAIT_MIN_CFG = 0x62,
BS11_STATE_MAINTENANCE = 0x72,
BS11_STATE_LOAD_MBCCU = 0x92,
BS11_STATE_WAIT_MIN_CFG_2 = 0xA2,
BS11_STATE_NORMAL = 0x03,
BS11_STATE_ABIS_LOAD = 0x13,
};
enum abis_nm_ipacc_test_no {
NM_IPACC_TESTNO_RLOOP_ANT = 0x01,
NM_IPACC_TESTNO_RLOOP_XCVR = 0x02,
NM_IPACC_TESTNO_FUNC_OBJ = 0x03,
NM_IPACC_TESTNO_CHAN_USAGE = 0x40,
NM_IPACC_TESTNO_BCCH_CHAN_USAGE = 0x41,
NM_IPACC_TESTNO_FREQ_SYNC = 0x42,
NM_IPACC_TESTNO_BCCH_INFO = 0x43,
NM_IPACC_TESTNO_TX_BEACON = 0x44,
NM_IPACC_TESTNO_SYSINFO_MONITOR = 0x45,
NM_IPACC_TESTNO_BCCCH_MONITOR = 0x46,
};
/* first byte after length inside NM_ATT_TEST_REPORT */
enum abis_nm_ipacc_test_res {
NM_IPACC_TESTRES_SUCCESS = 0,
NM_IPACC_TESTRES_TIMEOUT = 1,
NM_IPACC_TESTRES_NO_CHANS = 2,
NM_IPACC_TESTRES_PARTIAL = 3,
NM_IPACC_TESTRES_STOPPED = 4,
};
/* internal IE inside NM_ATT_TEST_REPORT */
enum abis_nm_ipacc_testres_ie {
NM_IPACC_TR_IE_FREQ_ERR_LIST = 3,
NM_IPACC_TR_IE_CHAN_USAGE = 4,
NM_IPACC_TR_IE_BCCH_INFO = 6,
NM_IPACC_TR_IE_RESULT_DETAILS = 8,
NM_IPACC_TR_IE_FREQ_ERR = 18,
};
enum ipac_eie {
NM_IPAC_EIE_ARFCN_WHITE = 0x01,
NM_IPAC_EIE_ARFCH_BLACK = 0x02,
NM_IPAC_EIE_FREQ_ERR_LIST = 0x03,
NM_IPAC_EIE_CHAN_USE_LIST = 0x04,
NM_IPAC_EIE_BCCH_INFO_TYPE = 0x05,
NM_IPAC_EIE_BCCH_INFO = 0x06,
/* FIXME */
};
enum ipac_bcch_info_type {
IPAC_BINF_RXLEV = (1 << 8),
IPAC_BINF_RXQUAL = (1 << 9),
IPAC_BINF_FREQ_ERR_QUAL = (1 << 10),
IPAC_BINF_FRAME_OFFSET = (1 << 11),
IPAC_BINF_FRAME_NR_OFFSET = (1 << 12),
IPAC_BINF_BSIC = (1 << 13),
IPAC_BINF_CGI = (1 << 14),
IPAC_BINF_NEIGH_BA_SI2 = (1 << 15),
IPAC_BINF_NEIGH_BA_SI2bis = (1 << 0),
IPAC_BINF_NEIGH_BA_SI2ter = (1 << 1),
IPAC_BINF_CELL_ALLOC = (1 << 2),
};
struct cell_global_id {
u_int16_t mcc;
@@ -55,10 +712,6 @@ struct ipac_bcch_info {
u_int8_t ca_list_si1[16];
};
extern const struct value_string abis_nm_adm_state_names[];
extern const struct value_string abis_nm_obj_class_names[];
extern const struct tlv_definition nm_att_tlvdef;
/* PUBLIC */
struct msgb;
@@ -73,7 +726,7 @@ struct abis_nm_cfg {
extern int abis_nm_rcvmsg(struct msgb *msg);
int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const u_int8_t *buf, int len);
int abis_nm_tlv_parse(struct tlv_parsed *tp, const u_int8_t *buf, int len);
int abis_nm_rx(struct msgb *msg);
int abis_nm_opstart(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0, u_int8_t i1, u_int8_t i2);
int abis_nm_chg_adm_state(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i0,
@@ -94,7 +747,7 @@ int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg);
int abis_nm_event_reports(struct gsm_bts *bts, int on);
int abis_nm_reset_resource(struct gsm_bts *bts);
int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
u_int8_t win_size, int forced,
gsm_cbfn *cbfn, void *cb_data);
int abis_nm_software_load_status(struct gsm_bts *bts);
@@ -106,7 +759,8 @@ int abis_nm_conn_mdrop_link(struct gsm_bts *bts, u_int8_t e1_port0, u_int8_t ts0
int abis_nm_perform_test(struct gsm_bts *bts, u_int8_t obj_class,
u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
u_int8_t test_nr, u_int8_t auton_report, struct msgb *msg);
u_int8_t test_nr, u_int8_t auton_report,
u_int8_t *phys_config, u_int16_t phys_config_len);
int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan);
@@ -126,13 +780,10 @@ int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts);
int abis_nm_bs11_get_serno(struct gsm_bts *bts);
int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, u_int8_t level);
int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx);
int abis_nm_bs11_logon(struct gsm_bts *bts, u_int8_t level, const char *name, int on);
int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on);
int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on);
int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password);
int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked);
int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts);
int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value);
int abis_nm_bs11_get_cclk(struct gsm_bts *bts);
int abis_nm_bs11_get_state(struct gsm_bts *bts);
int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
@@ -147,15 +798,14 @@ int abis_nm_ipaccess_msg(struct gsm_bts *bts, u_int8_t msg_type,
u_int8_t obj_class, u_int8_t bts_nr,
u_int8_t trx_nr, u_int8_t ts_nr,
u_int8_t *attr, int attr_len);
int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr,
int abis_nm_ipaccess_set_nvattr(struct gsm_bts *bts, u_int8_t *attr,
int attr_len);
int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx);
int abis_nm_ipaccess_restart(struct gsm_bts *bts);
int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, u_int8_t obj_class,
u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
u_int8_t *attr, u_int8_t attr_len);
int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
u_int32_t ip, u_int16_t port, u_int8_t stream);
void abis_nm_ipaccess_cgi(u_int8_t *buf, struct gsm_bts *bts);
int ipac_parse_bcch_info(struct ipac_bcch_info *binf, u_int8_t *buf);
const char *ipacc_testres_name(u_int8_t res);
@@ -165,13 +815,8 @@ enum nm_evt {
EVT_STATECHG_ADM,
};
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst);
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state);
const char *nm_opstate_name(u_int8_t os);
const char *nm_avail_name(u_int8_t avail);
int nm_is_running(struct gsm_nm_state *s);
int abis_nm_vty_init(void);
#endif /* _NM_H */

View File

@@ -23,9 +23,468 @@
#ifndef _RSL_H
#define _RSL_H
#include <osmocore/protocol/gsm_08_58.h>
struct abis_rsl_common_hdr {
u_int8_t msg_discr;
u_int8_t msg_type;
u_int8_t data[0];
} __attribute__ ((packed));
#include <osmocore/msgb.h>
/* Chapter 8.3 */
struct abis_rsl_rll_hdr {
struct abis_rsl_common_hdr c;
u_int8_t ie_chan;
u_int8_t chan_nr;
u_int8_t ie_link_id;
u_int8_t link_id;
u_int8_t data[0];
} __attribute__ ((packed));
/* Chapter 8.3 and 8.4 */
struct abis_rsl_dchan_hdr {
struct abis_rsl_common_hdr c;
u_int8_t ie_chan;
u_int8_t chan_nr;
u_int8_t data[0];
} __attribute__ ((packed));
/* Chapter 9.1 */
#define ABIS_RSL_MDISC_RLL 0x02
#define ABIS_RSL_MDISC_DED_CHAN 0x08
#define ABIS_RSL_MDISC_COM_CHAN 0x0c
#define ABIS_RSL_MDISC_TRX 0x10
#define ABIS_RSL_MDISC_LOC 0x20
#define ABIS_RSL_MDISC_IPACCESS 0x7e
#define ABIS_RSL_MDISC_TRANSP 0x01
#define ABIS_RSL_MDISC_IS_TRANSP(x) (x & 0x01)
/* Chapter 9.1 */
enum abis_rsl_msgtype {
/* Radio Link Layer Management */
RSL_MT_DATA_REQ = 0x01,
RSL_MT_DATA_IND,
RSL_MT_ERROR_IND,
RSL_MT_EST_REQ,
RSL_MT_EST_CONF,
RSL_MT_EST_IND,
RSL_MT_REL_REQ,
RSL_MT_REL_CONF,
RSL_MT_REL_IND,
RSL_MT_UNIT_DATA_REQ,
RSL_MT_UNIT_DATA_IND, /* 0x0b */
/* Common Channel Management / TRX Management */
RSL_MT_BCCH_INFO = 0x11,
RSL_MT_CCCH_LOAD_IND,
RSL_MT_CHAN_RQD,
RSL_MT_DELETE_IND,
RSL_MT_PAGING_CMD,
RSL_MT_IMMEDIATE_ASSIGN_CMD,
RSL_MT_SMS_BC_REQ,
/* empty */
RSL_MT_RF_RES_IND = 0x19,
RSL_MT_SACCH_FILL,
RSL_MT_OVERLOAD,
RSL_MT_ERROR_REPORT,
RSL_MT_SMS_BC_CMD,
RSL_MT_CBCH_LOAD_IND,
RSL_MT_NOT_CMD, /* 0x1f */
/* Dedicate Channel Management */
RSL_MT_CHAN_ACTIV = 0x21,
RSL_MT_CHAN_ACTIV_ACK,
RSL_MT_CHAN_ACTIV_NACK,
RSL_MT_CONN_FAIL,
RSL_MT_DEACTIVATE_SACCH,
RSL_MT_ENCR_CMD,
RSL_MT_HANDO_DET,
RSL_MT_MEAS_RES,
RSL_MT_MODE_MODIFY_REQ,
RSL_MT_MODE_MODIFY_ACK,
RSL_MT_MODE_MODIFY_NACK,
RSL_MT_PHY_CONTEXT_REQ,
RSL_MT_PHY_CONTEXT_CONF,
RSL_MT_RF_CHAN_REL,
RSL_MT_MS_POWER_CONTROL,
RSL_MT_BS_POWER_CONTROL, /* 0x30 */
RSL_MT_PREPROC_CONFIG,
RSL_MT_PREPROC_MEAS_RES,
RSL_MT_RF_CHAN_REL_ACK,
RSL_MT_SACCH_INFO_MODIFY,
RSL_MT_TALKER_DET,
RSL_MT_LISTENER_DET,
RSL_MT_REMOTE_CODEC_CONF_REP,
RSL_MT_RTD_REP,
RSL_MT_PRE_HANDO_NOTIF,
RSL_MT_MR_CODEC_MOD_REQ,
RSL_MT_MR_CODEC_MOD_ACK,
RSL_MT_MR_CODEC_MOD_NACK,
RSL_MT_MR_CODEC_MOD_PER,
RSL_MT_TFO_REP,
RSL_MT_TFO_MOD_REQ, /* 0x3f */
RSL_MT_LOCATION_INFO = 0x41,
/* ip.access specific RSL message types */
RSL_MT_IPAC_DIR_RETR_ENQ = 0x40,
RSL_MT_IPAC_PDCH_ACT = 0x48,
RSL_MT_IPAC_PDCH_ACT_ACK,
RSL_MT_IPAC_PDCH_ACT_NACK,
RSL_MT_IPAC_PDCH_DEACT = 0x4b,
RSL_MT_IPAC_PDCH_DEACT_ACK,
RSL_MT_IPAC_PDCH_DEACT_NACK,
RSL_MT_IPAC_CONNECT_MUX = 0x50,
RSL_MT_IPAC_CONNECT_MUX_ACK,
RSL_MT_IPAC_CONNECT_MUX_NACK,
RSL_MT_IPAC_BIND_MUX = 0x53,
RSL_MT_IPAC_BIND_MUX_ACK,
RSL_MT_IPAC_BIND_MUX_NACK,
RSL_MT_IPAC_DISC_MUX = 0x56,
RSL_MT_IPAC_DISC_MUX_ACK,
RSL_MT_IPAC_DISC_MUX_NACK,
RSL_MT_IPAC_CRCX = 0x70, /* Bind to local BTS RTP port */
RSL_MT_IPAC_CRCX_ACK,
RSL_MT_IPAC_CRCX_NACK,
RSL_MT_IPAC_MDCX = 0x73,
RSL_MT_IPAC_MDCX_ACK,
RSL_MT_IPAC_MDCX_NACK,
RSL_MT_IPAC_DLCX_IND = 0x76,
RSL_MT_IPAC_DLCX = 0x77,
RSL_MT_IPAC_DLCX_ACK,
RSL_MT_IPAC_DLCX_NACK,
};
/* Siemens vendor-specific */
enum abis_rsl_msgtype_siemens {
RSL_MT_SIEMENS_MRPCI = 0x41,
RSL_MT_SIEMENS_INTRAC_HO_COND_IND = 0x42,
RSL_MT_SIEMENS_INTERC_HO_COND_IND = 0x43,
RSL_MT_SIEMENS_FORCED_HO_REQ = 0x44,
RSL_MT_SIEMENS_PREF_AREA_REQ = 0x45,
RSL_MT_SIEMENS_PREF_AREA = 0x46,
RSL_MT_SIEMENS_START_TRACE = 0x47,
RSL_MT_SIEMENS_START_TRACE_ACK = 0x48,
RSL_MT_SIEMENS_STOP_TRACE = 0x49,
RSL_MT_SIEMENS_TRMR = 0x4a,
RSL_MT_SIEMENS_HO_FAIL_IND = 0x4b,
RSL_MT_SIEMENS_STOP_TRACE_ACK = 0x4c,
RSL_MT_SIEMENS_UPLF = 0x4d,
RSL_MT_SIEMENS_UPLB = 0x4e,
RSL_MT_SIEMENS_SET_SYS_INFO_10 = 0x4f,
RSL_MT_SIEMENS_MODIF_COND_IND = 0x50,
};
/* Chapter 9.3 */
enum abis_rsl_ie {
RSL_IE_CHAN_NR = 0x01,
RSL_IE_LINK_IDENT,
RSL_IE_ACT_TYPE,
RSL_IE_BS_POWER,
RSL_IE_CHAN_IDENT,
RSL_IE_CHAN_MODE,
RSL_IE_ENCR_INFO,
RSL_IE_FRAME_NUMBER,
RSL_IE_HANDO_REF,
RSL_IE_L1_INFO,
RSL_IE_L3_INFO,
RSL_IE_MS_IDENTITY,
RSL_IE_MS_POWER,
RSL_IE_PAGING_GROUP,
RSL_IE_PAGING_LOAD,
RSL_IE_PYHS_CONTEXT = 0x10,
RSL_IE_ACCESS_DELAY,
RSL_IE_RACH_LOAD,
RSL_IE_REQ_REFERENCE,
RSL_IE_RELEASE_MODE,
RSL_IE_RESOURCE_INFO,
RSL_IE_RLM_CAUSE,
RSL_IE_STARTNG_TIME,
RSL_IE_TIMING_ADVANCE,
RSL_IE_UPLINK_MEAS,
RSL_IE_CAUSE,
RSL_IE_MEAS_RES_NR,
RSL_IE_MSG_ID,
/* reserved */
RSL_IE_SYSINFO_TYPE = 0x1e,
RSL_IE_MS_POWER_PARAM,
RSL_IE_BS_POWER_PARAM,
RSL_IE_PREPROC_PARAM,
RSL_IE_PREPROC_MEAS,
RSL_IE_IMM_ASS_INFO, /* Phase 1 (3.6.0), later Full below */
RSL_IE_SMSCB_INFO = 0x24,
RSL_IE_MS_TIMING_OFFSET,
RSL_IE_ERR_MSG,
RSL_IE_FULL_BCCH_INFO,
RSL_IE_CHAN_NEEDED,
RSL_IE_CB_CMD_TYPE,
RSL_IE_SMSCB_MSG,
RSL_IE_FULL_IMM_ASS_INFO,
RSL_IE_SACCH_INFO,
RSL_IE_CBCH_LOAD_INFO,
RSL_IE_SMSCB_CHAN_INDICATOR,
RSL_IE_GROUP_CALL_REF,
RSL_IE_CHAN_DESC = 0x30,
RSL_IE_NCH_DRX_INFO,
RSL_IE_CMD_INDICATOR,
RSL_IE_EMLPP_PRIO,
RSL_IE_UIC,
RSL_IE_MAIN_CHAN_REF,
RSL_IE_MR_CONFIG,
RSL_IE_MR_CONTROL,
RSL_IE_SUP_CODEC_TYPES,
RSL_IE_CODEC_CONFIG,
RSL_IE_RTD,
RSL_IE_TFO_STATUS,
RSL_IE_LLP_APDU,
/* Siemens vendor-specific */
RSL_IE_SIEMENS_MRPCI = 0x40,
RSL_IE_SIEMENS_PREF_AREA_TYPE = 0x43,
RSL_IE_SIEMENS_ININ_CELL_HO_PAR = 0x45,
RSL_IE_SIEMENS_TRACE_REF_NR = 0x46,
RSL_IE_SIEMENS_INT_TRACE_IDX = 0x47,
RSL_IE_SIEMENS_L2_HDR_INFO = 0x48,
RSL_IE_SIEMENS_HIGHEST_RATE = 0x4e,
RSL_IE_SIEMENS_SUGGESTED_RATE = 0x4f,
/* ip.access */
RSL_IE_IPAC_SRTP_CONFIG = 0xe0,
RSL_IE_IPAC_PROXY_UDP = 0xe1,
RSL_IE_IPAC_BSCMPL_TOUT = 0xe2,
RSL_IE_IPAC_REMOTE_IP = 0xf0,
RSL_IE_IPAC_REMOTE_PORT = 0xf1,
RSL_IE_IPAC_RTP_PAYLOAD = 0xf2,
RSL_IE_IPAC_LOCAL_PORT = 0xf3,
RSL_IE_IPAC_SPEECH_MODE = 0xf4,
RSL_IE_IPAC_LOCAL_IP = 0xf5,
RSL_IE_IPAC_CONN_STAT = 0xf6,
RSL_IE_IPAC_HO_C_PARMS = 0xf7,
RSL_IE_IPAC_CONN_ID = 0xf8,
RSL_IE_IPAC_RTP_CSD_FMT = 0xf9,
RSL_IE_IPAC_RTP_JIT_BUF = 0xfa,
RSL_IE_IPAC_RTP_COMPR = 0xfb,
RSL_IE_IPAC_RTP_PAYLOAD2= 0xfc,
RSL_IE_IPAC_RTP_MPLEX = 0xfd,
RSL_IE_IPAC_RTP_MPLEX_ID= 0xfe,
};
/* Chapter 9.3.1 */
#define RSL_CHAN_NR_MASK 0xf8
#define RSL_CHAN_Bm_ACCHs 0x08
#define RSL_CHAN_Lm_ACCHs 0x10 /* .. 0x18 */
#define RSL_CHAN_SDCCH4_ACCH 0x20 /* .. 0x38 */
#define RSL_CHAN_SDCCH8_ACCH 0x40 /* ...0x78 */
#define RSL_CHAN_BCCH 0x80
#define RSL_CHAN_RACH 0x88
#define RSL_CHAN_PCH_AGCH 0x90
/* Chapter 9.3.3 */
#define RSL_ACT_TYPE_INITIAL 0x00
#define RSL_ACT_TYPE_REACT 0x80
#define RSL_ACT_INTRA_IMM_ASS 0x00
#define RSL_ACT_INTRA_NORM_ASS 0x01
#define RSL_ACT_INTER_ASYNC 0x02
#define RSL_ACT_INTER_SYNC 0x03
#define RSL_ACT_SECOND_ADD 0x04
#define RSL_ACT_SECOND_MULTI 0x05
/* Chapter 9.3.6 */
struct rsl_ie_chan_mode {
u_int8_t dtx_dtu;
u_int8_t spd_ind;
u_int8_t chan_rt;
u_int8_t chan_rate;
} __attribute__ ((packed));
#define RSL_CMOD_DTXu 0x01 /* uplink */
#define RSL_CMOD_DTXd 0x02 /* downlink */
enum rsl_cmod_spd {
RSL_CMOD_SPD_SPEECH = 0x01,
RSL_CMOD_SPD_DATA = 0x02,
RSL_CMOD_SPD_SIGN = 0x03,
};
#define RSL_CMOD_CRT_SDCCH 0x01
#define RSL_CMOD_CRT_TCH_Bm 0x08 /* full-rate */
#define RSL_CMOD_CRT_TCH_Lm 0x09 /* half-rate */
/* FIXME: More CRT types */
/* Speech */
#define RSL_CMOD_SP_GSM1 0x01
#define RSL_CMOD_SP_GSM2 0x11
#define RSL_CMOD_SP_GSM3 0x21
/* Data */
#define RSL_CMOD_SP_NT_14k5 0x58
#define RSL_CMOD_SP_NT_12k0 0x50
#define RSL_CMOD_SP_NT_6k0 0x51
/* Chapter 9.3.5 */
struct rsl_ie_chan_ident {
/* GSM 04.08 10.5.2.5 */
struct {
u_int8_t iei;
u_int8_t chan_nr; /* enc_chan_nr */
u_int8_t oct3;
u_int8_t oct4;
} chan_desc;
#if 0 /* spec says we need this but Abissim doesn't use it */
struct {
u_int8_t tag;
u_int8_t len;
} mobile_alloc;
#endif
} __attribute__ ((packed));
/* Chapter 9.3.22 */
#define RLL_CAUSE_T200_EXPIRED 0x01
#define RLL_CAUSE_REEST_REQ 0x02
#define RLL_CAUSE_UNSOL_UA_RESP 0x03
#define RLL_CAUSE_UNSOL_DM_RESP 0x04
#define RLL_CAUSE_UNSOL_DM_RESP_MF 0x05
#define RLL_CAUSE_UNSOL_SPRV_RESP 0x06
#define RLL_CAUSE_SEQ_ERR 0x07
#define RLL_CAUSE_UFRM_INC_PARAM 0x08
#define RLL_CAUSE_SFRM_INC_PARAM 0x09
#define RLL_CAUSE_IFRM_INC_MBITS 0x0a
#define RLL_CAUSE_IFRM_INC_LEN 0x0b
#define RLL_CAUSE_FRM_UNIMPL 0x0c
#define RLL_CAUSE_SABM_MF 0x0d
#define RLL_CAUSE_SABM_INFO_NOTALL 0x0e
/* Chapter 9.3.26 */
#define RSL_ERRCLS_NORMAL 0x00
#define RSL_ERRCLS_RESOURCE_UNAVAIL 0x20
#define RSL_ERRCLS_SERVICE_UNAVAIL 0x30
#define RSL_ERRCLS_SERVICE_UNIMPL 0x40
#define RSL_ERRCLS_INVAL_MSG 0x50
#define RSL_ERRCLS_PROTO_ERROR 0x60
#define RSL_ERRCLS_INTERWORKING 0x70
/* normal event */
#define RSL_ERR_RADIO_IF_FAIL 0x00
#define RSL_ERR_RADIO_LINK_FAIL 0x01
#define RSL_ERR_HANDOVER_ACC_FAIL 0x02
#define RSL_ERR_TALKER_ACC_FAIL 0x03
#define RSL_ERR_OM_INTERVENTION 0x07
#define RSL_ERR_NORMAL_UNSPEC 0x0f
#define RSL_ERR_T_MSRFPCI_EXP 0x18
/* resource unavailable */
#define RSL_ERR_EQUIPMENT_FAIL 0x20
#define RSL_ERR_RR_UNAVAIL 0x21
#define RSL_ERR_TERR_CH_FAIL 0x22
#define RSL_ERR_CCCH_OVERLOAD 0x23
#define RSL_ERR_ACCH_OVERLOAD 0x24
#define RSL_ERR_PROCESSOR_OVERLOAD 0x25
#define RSL_ERR_RES_UNAVAIL 0x2f
/* service or option not available */
#define RSL_ERR_TRANSC_UNAVAIL 0x30
#define RSL_ERR_SERV_OPT_UNAVAIL 0x3f
/* service or option not implemented */
#define RSL_ERR_ENCR_UNIMPL 0x40
#define RSL_ERR_SERV_OPT_UNIMPL 0x4f
/* invalid message */
#define RSL_ERR_RCH_ALR_ACTV_ALLOC 0x50
#define RSL_ERR_INVALID_MESSAGE 0x5f
/* protocol error */
#define RSL_ERR_MSG_DISCR 0x60
#define RSL_ERR_MSG_TYPE 0x61
#define RSL_ERR_MSG_SEQ 0x62
#define RSL_ERR_IE_ERROR 0x63
#define RSL_ERR_MAND_IE_ERROR 0x64
#define RSL_ERR_OPT_IE_ERROR 0x65
#define RSL_ERR_IE_NONEXIST 0x66
#define RSL_ERR_IE_LENGTH 0x67
#define RSL_ERR_IE_CONTENT 0x68
#define RSL_ERR_PROTO 0x6f
/* interworking */
#define RSL_ERR_INTERWORKING 0x7f
/* Chapter 9.3.30 */
#define RSL_SYSTEM_INFO_8 0x00
#define RSL_SYSTEM_INFO_1 0x01
#define RSL_SYSTEM_INFO_2 0x02
#define RSL_SYSTEM_INFO_3 0x03
#define RSL_SYSTEM_INFO_4 0x04
#define RSL_SYSTEM_INFO_5 0x05
#define RSL_SYSTEM_INFO_6 0x06
#define RSL_SYSTEM_INFO_7 0x07
#define RSL_SYSTEM_INFO_16 0x08
#define RSL_SYSTEM_INFO_17 0x09
#define RSL_SYSTEM_INFO_2bis 0x0a
#define RSL_SYSTEM_INFO_2ter 0x0b
#define RSL_SYSTEM_INFO_5bis 0x0d
#define RSL_SYSTEM_INFO_5ter 0x0e
#define RSL_SYSTEM_INFO_10 0x0f
#define REL_EXT_MEAS_ORDER 0x47
#define RSL_MEAS_INFO 0x48
#define RSL_SYSTEM_INFO_13 0x28
#define RSL_SYSTEM_INFO_2quater 0x29
#define RSL_SYSTEM_INFO_9 0x2a
#define RSL_SYSTEM_INFO_18 0x2b
#define RSL_SYSTEM_INFO_19 0x2c
#define RSL_SYSTEM_INFO_20 0x2d
/* Chapter 9.3.40 */
#define RSL_CHANNEED_ANY 0x00
#define RSL_CHANNEED_SDCCH 0x01
#define RSL_CHANNEED_TCH_F 0x02
#define RSL_CHANNEED_TCH_ForH 0x03
/* Chapter 3.3.2.3 Brocast control channel */
/* CCCH-CONF, NC is not combined */
#define RSL_BCCH_CCCH_CONF_1_NC 0x00
#define RSL_BCCH_CCCH_CONF_1_C 0x01
#define RSL_BCCH_CCCH_CONF_2_NC 0x02
#define RSL_BCCH_CCCH_CONF_3_NC 0x04
#define RSL_BCCH_CCCH_CONF_4_NC 0x06
/* BS-PA-MFRMS */
#define RSL_BS_PA_MFRMS_2 0x00
#define RSL_BS_PA_MFRMS_3 0x01
#define RSL_BS_PA_MFRMS_4 0x02
#define RSL_BS_PA_MFRMS_5 0x03
#define RSL_BS_PA_MFRMS_6 0x04
#define RSL_BS_PA_MFRMS_7 0x05
#define RSL_BS_PA_MFRMS_8 0x06
#define RSL_BS_PA_MFRMS_9 0x07
/* RSL_IE_IPAC_RTP_PAYLOAD[2] */
enum rsl_ipac_rtp_payload {
RSL_IPAC_RTP_GSM = 1,
RSL_IPAC_RTP_EFR,
RSL_IPAC_RTP_AMR,
RSL_IPAC_RTP_CSD,
RSL_IPAC_RTP_MUX,
};
/* RSL_IE_IPAC_SPEECH_MODE, lower four bits */
enum rsl_ipac_speech_mode_s {
RSL_IPAC_SPEECH_GSM_FR = 0, /* GSM FR (Type 1, FS) */
RSL_IPAC_SPEECH_GSM_EFR = 1, /* GSM EFR (Type 2, FS) */
RSL_IPAC_SPEECH_GSM_AMR_FR = 2, /* GSM AMR/FR (Type 3, FS) */
RSL_IPAC_SPEECH_GSM_HR = 3, /* GSM HR (Type 1, HS) */
RSL_IPAC_SPEECH_GSM_AMR_HR = 5, /* GSM AMR/hr (Type 3, HS) */
RSL_IPAC_SPEECH_AS_RTP = 0xf, /* As specified by RTP Payload IE */
};
/* RSL_IE_IPAC_SPEECH_MODE, upper four bits */
enum rsl_ipac_speech_mode_m {
RSL_IPAC_SPEECH_M_RXTX = 0, /* Send and Receive */
RSL_IPAC_SPEECH_M_RX = 1, /* Receive only */
RSL_IPAC_SPEECH_M_TX = 2, /* Send only */
};
/* RSL_IE_IPAC_RTP_CSD_FMT, lower four bits */
enum rsl_ipac_rtp_csd_format_d {
RSL_IPAC_RTP_CSD_EXT_TRAU = 0,
RSL_IPAC_RTP_CSD_NON_TRAU = 1,
RSL_IPAC_RTP_CSD_TRAU_BTS = 2,
RSL_IPAC_RTP_CSD_IWF_FREE = 3,
};
/* RSL_IE_IPAC_RTP_CSD_FMT, upper four bits */
enum rsl_ipac_rtp_csd_format_ir {
RSL_IPAC_RTP_CSD_IR_8k = 0,
RSL_IPAC_RTP_CSD_IR_16k = 1,
RSL_IPAC_RTP_CSD_IR_32k = 2,
RSL_IPAC_RTP_CSD_IR_64k = 3,
};
#include "msgb.h"
int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type,
const u_int8_t *data, int len);
@@ -38,7 +497,7 @@ int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
u_int8_t bs_power, u_int8_t ms_power,
u_int8_t ta);
int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
u_int8_t ta, u_int8_t ho_ref);
u_int8_t ta);
int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
int rsl_encryption_cmd(struct msgb *msg);
int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
@@ -52,14 +511,35 @@ int rsl_establish_request(struct gsm_lchan *lchan, u_int8_t link_id);
int rsl_relase_request(struct gsm_lchan *lchan, u_int8_t link_id);
/* Siemens vendor-specific RSL extensions */
struct rsl_mrpci {
u_int8_t power_class:3,
vgcs_capable:1,
vbs_capable:1,
gsm_phase:2;
} __attribute__ ((packed));
enum rsl_mrpci_pwrclass {
RSL_MRPCI_PWRC_1 = 0,
RSL_MRPCI_PWRC_2 = 1,
RSL_MRPCI_PWRC_3 = 2,
RSL_MRPCI_PWRC_4 = 3,
RSL_MRPCI_PWRC_5 = 4,
};
enum rsl_mrpci_phase {
RSL_MRPCI_PHASE_1 = 0,
/* reserved */
RSL_MRPCI_PHASE_2 = 2,
RSL_MRPCI_PHASE_2PLUS = 3,
};
int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci);
/* ip.access specfic RSL extensions */
int rsl_ipacc_crcx(struct gsm_lchan *lchan);
int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip,
u_int16_t port, u_int8_t rtp_payload2);
int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan);
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act);
u_int16_t port, u_int16_t conn_id,
u_int8_t rtp_payload2);
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan);
int abis_rsl_rcvmsg(struct msgb *msg);
@@ -67,15 +547,13 @@ unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
int n_pag_blocks);
unsigned int n_pag_blocks(int bs_ccch_sdcch_comb, unsigned int bs_ag_blks_res);
u_int64_t str_to_imsi(const char *imsi_str);
u_int8_t lchan2chan_nr(const struct gsm_lchan *lchan);
int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t reason);
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
u_int8_t lchan2chan_nr(struct gsm_lchan *lchan);
int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id);
/* to be provided by external code */
int abis_rsl_sendmsg(struct msgb *msg);
int rsl_deact_sacch(struct gsm_lchan *lchan);
int rsl_lchan_rll_release(struct gsm_lchan *lchan, u_int8_t link_id);
int rsl_chan_release(struct gsm_lchan *lchan);
/* BCCH related code */
int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
@@ -85,9 +563,5 @@ int rsl_number_of_paging_subchannels(struct gsm_bts *bts);
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
/* SMSCB functionality */
int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
uint8_t cb_command, const uint8_t *data, int len);
#endif /* RSL_MT_H */

View File

@@ -1,10 +0,0 @@
#ifndef _AUTH_H
#define _AUTH_H
struct gsm_auth_tuple;
struct gsm_subscriber;
int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
struct gsm_subscriber *subscr, int key_seq);
#endif /* _AUTH_H */

View File

@@ -1,38 +0,0 @@
/* GSM 08.08 like API for OpenBSC */
#ifndef OPENBSC_BSC_API_H
#define OPENBSC_BSC_API_H
#include "gsm_data.h"
#define BSC_API_CONN_POL_ACCEPT 0
#define BSC_API_CONN_POL_REJECT 1
struct bsc_api {
void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci);
void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint8_t chosen_encr);
void (*cipher_mode_reject)(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint16_t reason);
int (*compl_l3)(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint16_t chosen_channel);
void (*dtap)(struct gsm_subscriber_connection *conn, struct msgb *msg);
void (*assign_compl)(struct gsm_subscriber_connection *conn,
uint16_t rr_cause);
void (*assign_fail)(struct gsm_subscriber_connection *conn,
uint16_t rr_cause);
void (*clear_request)(struct gsm_subscriber_connection *conn,
uint32_t cause);
void (*clear_compl)(struct gsm_subscriber_connection *conn);
};
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id);
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_type, int audio);
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
uint8_t *key, int len);
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
unsigned int mi_len, uint8_t *mi, int chan_type);
int gsm0808_clear(struct gsm_subscriber_connection *conn);
#endif

View File

@@ -1,52 +0,0 @@
/* Routines to talk to the MSC using the IPA Protocol */
/*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef BSC_MSC_H
#define BSC_MSC_H
#include <osmocore/write_queue.h>
#include <osmocore/timer.h>
struct bsc_msc_connection {
struct write_queue write_queue;
int is_connected;
int is_authenticated;
int first_contact;
const char *ip;
int port;
int prio;
void (*connection_loss) (struct bsc_msc_connection *);
void (*connected) (struct bsc_msc_connection *);
struct timer_list reconnect_timer;
struct timer_list timeout_timer;
};
struct bsc_msc_connection *bsc_msc_create(const char *ip, int port, int prio);
int bsc_msc_connect(struct bsc_msc_connection *);
void bsc_msc_schedule_connect(struct bsc_msc_connection *);
void bsc_msc_lost(struct bsc_msc_connection *);
struct msgb *bsc_msc_id_get_resp(const char *token);
#endif

View File

@@ -1,281 +0,0 @@
/*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef BSC_NAT_H
#define BSC_NAT_H
#include "mgcp.h"
#include <sys/types.h>
#include <osmocore/select.h>
#include <osmocore/msgb.h>
#include <osmocore/timer.h>
#include <osmocore/write_queue.h>
#include <osmocore/rate_ctr.h>
#include <osmocore/statistics.h>
#include <regex.h>
#define DIR_BSC 1
#define DIR_MSC 2
#define NAT_IPAC_PROTO_MGCP 0xfc
struct sccp_connections;
struct bsc_nat_parsed;
struct bsc_nat;
enum {
NAT_CON_TYPE_NONE,
NAT_CON_TYPE_LU,
NAT_CON_TYPE_CM_SERV_REQ,
NAT_CON_TYPE_PAG_RESP,
NAT_CON_TYPE_LOCAL_REJECT,
NAT_CON_TYPE_OTHER,
};
/*
* Per BSC data structure
*/
struct bsc_connection {
struct llist_head list_entry;
/* do we know anything about this BSC? */
int authenticated;
/* the fd we use to communicate */
struct write_queue write_queue;
/* the BSS associated */
struct bsc_config *cfg;
/* a timeout node */
struct timer_list id_timeout;
/* pong timeout */
struct timer_list ping_timeout;
struct timer_list pong_timeout;
/* a back pointer */
struct bsc_nat *nat;
};
/**
* Stats per BSC
*/
struct bsc_config_stats {
struct rate_ctr_group *ctrg;
};
enum bsc_cfg_ctr {
BCFG_CTR_SCCP_CONN,
BCFG_CTR_SCCP_CALLS,
BCFG_CTR_NET_RECONN,
BCFG_CTR_DROPPED_SCCP,
BCFG_CTR_DROPPED_CALLS,
};
/**
* One BSC entry in the config
*/
struct bsc_config {
struct llist_head entry;
char *token;
unsigned int lac;
int nr;
char *description;
/* imsi white and blacklist */
char *acc_lst_name;
int forbid_paging;
/* backpointer */
struct bsc_nat *nat;
struct bsc_config_stats stats;
};
/**
* BSCs point of view of endpoints
*/
struct bsc_endpoint {
/* the pending transaction id */
char *transaction_id;
/* the bsc we are talking to */
struct bsc_connection *bsc;
};
/**
* Statistic for the nat.
*/
struct bsc_nat_statistics {
struct {
struct counter *conn;
struct counter *calls;
} sccp;
struct {
struct counter *reconn;
struct counter *auth_fail;
} bsc;
struct {
struct counter *reconn;
} msc;
};
struct bsc_nat_acc_lst {
struct llist_head list;
/* the name of the list */
const char *name;
struct llist_head fltr_list;
};
struct bsc_nat_acc_lst_entry {
struct llist_head list;
/* the filter */
char *imsi_allow;
regex_t imsi_allow_re;
char *imsi_deny;
regex_t imsi_deny_re;
};
/**
* the structure of the "nat" network
*/
struct bsc_nat {
/* active SCCP connections that need patching */
struct llist_head sccp_connections;
/* active BSC connections that need patching */
struct llist_head bsc_connections;
/* access lists */
struct llist_head access_lists;
/* known BSC's */
struct llist_head bsc_configs;
int num_bsc;
int bsc_ip_dscp;
/* MGCP config */
struct mgcp_config *mgcp_cfg;
struct write_queue mgcp_queue;
uint8_t mgcp_msg[4096];
int mgcp_length;
/* msc things */
char *msc_ip;
int msc_port;
struct bsc_msc_connection *msc_con;
char *token;
/* timeouts */
int auth_timeout;
int ping_timeout;
int pong_timeout;
struct bsc_endpoint *bsc_endpoints;
/* filter */
char *acc_lst_name;
/* statistics */
struct bsc_nat_statistics stats;
};
/* create and init the structures */
struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token, unsigned int lac);
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
struct bsc_nat *bsc_nat_alloc(void);
struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
void sccp_connection_destroy(struct sccp_connections *);
void bsc_close_connection(struct bsc_connection *);
const char *bsc_con_type_to_string(int type);
/**
* parse the given message into the above structure
*/
struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
/**
* filter based on IP Access header in both directions
*/
int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
int bsc_nat_vty_init(struct bsc_nat *nat);
struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, int *_lac);
/**
* Content filtering.
*/
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
struct bsc_nat_parsed *, int *con_type);
/**
* SCCP patching and handling
*/
struct sccp_connections *create_sccp_src_ref(struct bsc_connection *bsc, struct bsc_nat_parsed *parsed);
int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *parsed);
void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_connection *);
/**
* MGCP/Audio handling
*/
int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_init(struct sccp_connections *);
void bsc_mgcp_dlcx(struct sccp_connections *);
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
int bsc_mgcp_nat_init(struct bsc_nat *nat);
struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
struct msgb *bsc_mgcp_rewrite(char *input, int length, const char *ip, int port);
void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc);
int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
int bsc_mgcp_extract_ci(const char *resp);
int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
/* IMSI allow/deny handling */
void bsc_parse_reg(void *ctx, regex_t *reg, char **imsi, int argc, const char **argv);
struct bsc_nat_acc_lst *bsc_nat_acc_lst_find(struct bsc_nat *nat, const char *name);
struct bsc_nat_acc_lst *bsc_nat_acc_lst_get(struct bsc_nat *nat, const char *name);
void bsc_nat_acc_lst_delete(struct bsc_nat_acc_lst *lst);
struct bsc_nat_acc_lst_entry *bsc_nat_acc_lst_entry_create(struct bsc_nat_acc_lst *);
int bsc_nat_msc_is_connected(struct bsc_nat *nat);
#endif

View File

@@ -1,92 +0,0 @@
/* NAT utilities using SCCP types */
/*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef BSC_NAT_SCCP_H
#define BSC_NAT_SCCP_H
#include <sys/types.h>
#include <osmocom/sccp/sccp_types.h>
/*
* For the NAT we will need to analyze and later patch
* the received message. This would require us to parse
* the IPA and SCCP header twice. Instead of doing this
* we will have one analyze structure and have the patching
* and filter operate on the same structure.
*/
struct bsc_nat_parsed {
/* ip access prototype */
int ipa_proto;
/* source local reference */
struct sccp_source_reference *src_local_ref;
/* destination local reference */
struct sccp_source_reference *dest_local_ref;
/* called ssn number */
int called_ssn;
/* calling ssn number */
int calling_ssn;
/* sccp message type */
int sccp_type;
/* bssap type, e.g. 0 for BSS Management */
int bssap;
/* the gsm0808 message type */
int gsm_type;
};
/*
* Per SCCP source local reference patch table. It needs to
* be updated on new SCCP connections, connection confirm and reject,
* and on the loss of the BSC connection.
*/
struct sccp_connections {
struct llist_head list_entry;
struct bsc_connection *bsc;
struct bsc_msc_connection *msc_con;
struct sccp_source_reference real_ref;
struct sccp_source_reference patched_ref;
struct sccp_source_reference remote_ref;
int has_remote_ref;
/* status */
int con_type;
int con_local;
/* GSM audio handling. That is 32 * multiplex + ts */
int crcx;
int msc_timeslot;
int bsc_timeslot;
/* timeout handling */
struct timespec creation_time;
};
#endif

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

@@ -0,0 +1,64 @@
/*
* (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2008 by Stefan Schmidt <stefan@datenfreihafen.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef _CALL_HANDLING_H
#define _CALL_HANDLING_H
#include "linuxlist.h"
#include "gsm_subscriber.h"
#include "timer.h"
/*
* State transitions to be seen from the outside
*/
#define CALL_STATE_NULL 0
#define CALL_STATE_SETUP 1
#define CALL_STATE_PROCEED 2
#define CALL_STATE_ALERT 3
#define CALL_STATE_CONNECT 4
#define CALL_STATE_ACTIVE 5
#define CALL_STATE_RELEASE 6
struct call_data {
struct llist_head entry;
void (*state_change_cb)(int oldstate, int newstate, int event, void *data);
void *data;
char *destination_number;
/* Internal */
int state;
char tmsi[GSM_TMSI_LENGTH];
struct timer_list t30x; /* to be added for... */
};
int call_initiate(struct call_data *call, char *tmsi);
void call_abort(struct call_data *call);
/**
* Get notified about new incoming calls. The call_data is owned
* and managed by the internal call handling.
*/
void call_set_callback(void (*cb)(struct call_data *call, void *data), void* data);
void call_proceed(struct call_data *call_data);
void call_connect(struct call_data *call_data);
#endif /* _CALL_HANDLING_H */

View File

@@ -23,7 +23,27 @@
#include "gsm_subscriber.h"
struct gsm_subscriber_connection;
/*
* 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,
@@ -36,31 +56,19 @@ struct gsm_bts_trx_ts *ts_alloc(struct gsm_bts *bts,
/* Regular physical channel (TS) */
void ts_free(struct gsm_bts_trx_ts *ts);
/* Find an allocated channel */
struct gsm_lchan *lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr);
/* Find an allocated channel for a specified subscriber */
struct gsm_subscriber_connection *connection_for_subscr(struct gsm_subscriber *subscr);
struct gsm_lchan *lchan_for_subscr(struct gsm_subscriber *subscr);
/* Allocate a logical channel (SDCCH, TCH, ...) */
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type);
/* Free a logical channel (SDCCH, TCH, ...) */
void lchan_free(struct gsm_lchan *lchan);
void lchan_reset(struct gsm_lchan *lchan);
/* Release the given lchan */
int lchan_release(struct gsm_lchan *lchan, int sach_deact, int reason);
struct load_counter {
unsigned int total;
unsigned int used;
};
struct pchan_load {
struct load_counter pchan[GSM_PCHAN_UNKNOWN];
};
void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts);
void network_chan_load(struct pchan_load *pl, struct gsm_network *net);
int trx_is_usable(struct gsm_bts_trx *trx);
/* internal.. do not use */
int _lchan_release(struct gsm_lchan *lchan);
#endif /* _CHAN_ALLOC_H */

View File

@@ -1,8 +0,0 @@
#ifndef _CRC24_H
#define _CRC24_H
#define INIT_CRC24 0xffffff
u_int32_t crc24_calc(u_int32_t fcs, u_int8_t *cp, unsigned int len);
#endif

View File

@@ -43,20 +43,9 @@ int db_subscriber_alloc_token(struct gsm_subscriber* subscriber, u_int32_t* toke
int db_subscriber_assoc_imei(struct gsm_subscriber* subscriber, char *imei);
int db_sync_equipment(struct gsm_equipment *equip);
/* auth info */
int db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
struct gsm_subscriber *subscr);
int db_sync_authinfo_for_subscr(struct gsm_auth_info *ainfo,
struct gsm_subscriber *subscr);
int db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
struct gsm_subscriber *subscr);
int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
struct gsm_subscriber *subscr);
/* SMS store-and-forward */
int db_sms_store(struct gsm_sms *sms);
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id);
struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id);
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id);
struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
int db_sms_mark_sent(struct gsm_sms *sms);
@@ -64,11 +53,4 @@ int db_sms_mark_sent(struct gsm_sms *sms);
int db_apdu_blob_store(struct gsm_subscriber *subscr,
u_int8_t apdu_id_flags, u_int8_t len,
u_int8_t *apdu);
/* Statistics counter storage */
struct counter;
int db_store_counter(struct counter *ctr);
struct rate_ctr_group;
int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
#endif /* _DB_H */

View File

@@ -1,70 +1,45 @@
#ifndef _DEBUG_H
#define _DEBUG_H
#include <stdio.h>
#include <osmocore/linuxlist.h>
#define DEBUG
#include <osmocore/logging.h>
/* Debug Areas of the code */
enum {
DRLL,
DCC,
DMM,
DRR,
DRSL,
DNM,
DMNCC,
DSMS,
DPAG,
DMEAS,
DMI,
DMIB,
DMUX,
DINP,
DSCCP,
DMSC,
DMGCP,
DHO,
DDB,
DREF,
DGPRS,
DNS,
DBSSGP,
DLLC,
DSNDCP,
DNAT,
Debug_LastEntry,
};
#define DRLL 0x0001
#define DCC 0x0002
#define DMM 0x0004
#define DRR 0x0008
#define DRSL 0x0010
#define DNM 0x0020
/* context */
#define BSC_CTX_LCHAN 0
#define BSC_CTX_SUBSCR 1
#define BSC_CTX_BTS 2
#define BSC_CTX_SCCP 3
#define BSC_CTX_NSVC 4
#define BSC_CTX_BVC 5
#define DMNCC 0x0080
#define DSMS 0x0100
#define DPAG 0x0200
#define DMEAS 0x0400
/* target */
#define DMI 0x1000
#define DMIB 0x2000
#define DMUX 0x4000
#define DINP 0x8000
enum {
//DEBUG_FILTER_ALL = 1 << 0,
LOG_FILTER_IMSI = 1 << 1,
LOG_FILTER_NSVC = 1 << 2,
LOG_FILTER_BVC = 1 << 3,
};
#define DSCCP 0x10000
#define DMSC 0x20000
/* we don't need a header dependency for this... */
struct gprs_nsvc;
struct bssgp_bvc_ctx;
#define DMGCP 0x40000
void log_set_imsi_filter(struct log_target *target, const char *imsi);
void log_set_nsvc_filter(struct log_target *target,
struct gprs_nsvc *nsvc);
void log_set_bvc_filter(struct log_target *target,
struct bssgp_bvc_ctx *bctx);
#ifdef DEBUG
#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args)
#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args)
#else
#define DEBUGP(xss, fmt, args...)
#define DEBUGPC(ss, fmt, args...)
#endif
extern const struct log_info log_info;
#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
char *hexdump(const unsigned char *buf, int len);
void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
void debug_parse_category_mask(const char* mask);
void debug_use_color(int use_color);
void debug_timestamp(int enable);
extern unsigned int debug_mask;
#endif /* _DEBUG_H */

View File

@@ -4,10 +4,10 @@
#include <stdlib.h>
#include <netinet/in.h>
#include <osmocore/linuxlist.h>
#include <openbsc/linuxlist.h>
#include <openbsc/gsm_data.h>
#include <osmocore/msgb.h>
#include <osmocore/select.h>
#include <openbsc/msgb.h>
#include <openbsc/select.h>
#include <openbsc/subchan_demux.h>
#define NUM_E1_TS 32

View File

@@ -1,39 +0,0 @@
#ifndef _GB_PROXY_H
#define _GB_PROXY_H
#include <sys/types.h>
#include <osmocore/msgb.h>
#include <openbsc/gprs_ns.h>
#include <osmocom/vty/command.h>
struct gbproxy_config {
/* parsed from config file */
u_int16_t nsip_sgsn_nsei;
/* misc */
struct gprs_ns_inst *nsi;
};
extern struct gbproxy_config gbcfg;
extern struct cmd_element show_gbproxy_cmd;
/* gb_proxy_vty .c */
int gbproxy_vty_init(void);
int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
/* gb_proxy.c */
/* Main input function for Gb proxy */
int gbprox_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
int gbprox_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data);
/* Reset all persistent NS-VC's */
int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
#endif

View File

@@ -1,232 +0,0 @@
#ifndef _GPRS_BSSGP_H
#define _GPRS_BSSGP_H
#include <stdint.h>
/* Section 5.4.1 */
#define BVCI_SIGNALLING 0x0000
#define BVCI_PTM 0x0001
/* Section 11.3.26 / Table 11.27 */
enum bssgp_pdu_type {
/* PDUs between RL and BSSGP SAPs */
BSSGP_PDUT_DL_UNITDATA = 0x00,
BSSGP_PDUT_UL_UNITDATA = 0x01,
BSSGP_PDUT_RA_CAPABILITY = 0x02,
BSSGP_PDUT_PTM_UNITDATA = 0x03,
/* PDUs between GMM SAPs */
BSSGP_PDUT_PAGING_PS = 0x06,
BSSGP_PDUT_PAGING_CS = 0x07,
BSSGP_PDUT_RA_CAPA_UDPATE = 0x08,
BSSGP_PDUT_RA_CAPA_UPDATE_ACK = 0x09,
BSSGP_PDUT_RADIO_STATUS = 0x0a,
BSSGP_PDUT_SUSPEND = 0x0b,
BSSGP_PDUT_SUSPEND_ACK = 0x0c,
BSSGP_PDUT_SUSPEND_NACK = 0x0d,
BSSGP_PDUT_RESUME = 0x0e,
BSSGP_PDUT_RESUME_ACK = 0x0f,
BSSGP_PDUT_RESUME_NACK = 0x10,
/* PDus between NM SAPs */
BSSGP_PDUT_BVC_BLOCK = 0x20,
BSSGP_PDUT_BVC_BLOCK_ACK = 0x21,
BSSGP_PDUT_BVC_RESET = 0x22,
BSSGP_PDUT_BVC_RESET_ACK = 0x23,
BSSGP_PDUT_BVC_UNBLOCK = 0x24,
BSSGP_PDUT_BVC_UNBLOCK_ACK = 0x25,
BSSGP_PDUT_FLOW_CONTROL_BVC = 0x26,
BSSGP_PDUT_FLOW_CONTROL_BVC_ACK = 0x27,
BSSGP_PDUT_FLOW_CONTROL_MS = 0x28,
BSSGP_PDUT_FLOW_CONTROL_MS_ACK = 0x29,
BSSGP_PDUT_FLUSH_LL = 0x2a,
BSSGP_PDUT_FLUSH_LL_ACK = 0x2b,
BSSGP_PDUT_LLC_DISCARD = 0x2c,
BSSGP_PDUT_SGSN_INVOKE_TRACE = 0x40,
BSSGP_PDUT_STATUS = 0x41,
/* PDUs between PFM SAP's */
BSSGP_PDUT_DOWNLOAD_BSS_PFC = 0x50,
BSSGP_PDUT_CREATE_BSS_PFC = 0x51,
BSSGP_PDUT_CREATE_BSS_PFC_ACK = 0x52,
BSSGP_PDUT_CREATE_BSS_PFC_NACK = 0x53,
BSSGP_PDUT_MODIFY_BSS_PFC = 0x54,
BSSGP_PDUT_MODIFY_BSS_PFC_ACK = 0x55,
BSSGP_PDUT_DELETE_BSS_PFC = 0x56,
BSSGP_PDUT_DELETE_BSS_PFC_ACK = 0x57,
};
/* Section 10.2.1 and 10.2.2 */
struct bssgp_ud_hdr {
uint8_t pdu_type;
uint32_t tlli;
uint8_t qos_profile[3];
uint8_t data[0]; /* TLV's */
} __attribute__((packed));
struct bssgp_normal_hdr {
uint8_t pdu_type;
uint8_t data[0]; /* TLV's */
};
enum bssgp_iei_type {
BSSGP_IE_ALIGNMENT = 0x00,
BSSGP_IE_BMAX_DEFAULT_MS = 0x01,
BSSGP_IE_BSS_AREA_ID = 0x02,
BSSGP_IE_BUCKET_LEAK_RATE = 0x03,
BSSGP_IE_BVCI = 0x04,
BSSGP_IE_BVC_BUCKET_SIZE = 0x05,
BSSGP_IE_BVC_MEASUREMENT = 0x06,
BSSGP_IE_CAUSE = 0x07,
BSSGP_IE_CELL_ID = 0x08,
BSSGP_IE_CHAN_NEEDED = 0x09,
BSSGP_IE_DRX_PARAMS = 0x0a,
BSSGP_IE_EMLPP_PRIO = 0x0b,
BSSGP_IE_FLUSH_ACTION = 0x0c,
BSSGP_IE_IMSI = 0x0d,
BSSGP_IE_LLC_PDU = 0x0e,
BSSGP_IE_LLC_FRAMES_DISCARDED = 0x0f,
BSSGP_IE_LOCATION_AREA = 0x10,
BSSGP_IE_MOBILE_ID = 0x11,
BSSGP_IE_MS_BUCKET_SIZE = 0x12,
BSSGP_IE_MS_RADIO_ACCESS_CAP = 0x13,
BSSGP_IE_OMC_ID = 0x14,
BSSGP_IE_PDU_IN_ERROR = 0x15,
BSSGP_IE_PDU_LIFETIME = 0x16,
BSSGP_IE_PRIORITY = 0x17,
BSSGP_IE_QOS_PROFILE = 0x18,
BSSGP_IE_RADIO_CAUSE = 0x19,
BSSGP_IE_RA_CAP_UPD_CAUSE = 0x1a,
BSSGP_IE_ROUTEING_AREA = 0x1b,
BSSGP_IE_R_DEFAULT_MS = 0x1c,
BSSGP_IE_SUSPEND_REF_NR = 0x1d,
BSSGP_IE_TAG = 0x1e,
BSSGP_IE_TLLI = 0x1f,
BSSGP_IE_TMSI = 0x20,
BSSGP_IE_TRACE_REFERENC = 0x21,
BSSGP_IE_TRACE_TYPE = 0x22,
BSSGP_IE_TRANSACTION_ID = 0x23,
BSSGP_IE_TRIGGER_ID = 0x24,
BSSGP_IE_NUM_OCT_AFF = 0x25,
BSSGP_IE_LSA_ID_LIST = 0x26,
BSSGP_IE_LSA_INFORMATION = 0x27,
BSSGP_IE_PACKET_FLOW_ID = 0x28,
BSSGP_IE_PACKET_FLOW_TIMER = 0x29,
BSSGP_IE_AGG_BSS_QOS_PROFILE = 0x3a,
BSSGP_IE_FEATURE_BITMAP = 0x3b,
BSSGP_IE_BUCKET_FULL_RATIO = 0x3c,
BSSGP_IE_SERVICE_UTRAN_CCO = 0x3d,
};
/* Section 11.3.8 / Table 11.10: Cause coding */
enum gprs_bssgp_cause {
BSSGP_CAUSE_PROC_OVERLOAD = 0x00,
BSSGP_CAUSE_EQUIP_FAIL = 0x01,
BSSGP_CAUSE_TRASIT_NET_FAIL = 0x02,
BSSGP_CAUSE_CAPA_GREATER_0KPBS = 0x03,
BSSGP_CAUSE_UNKNOWN_MS = 0x04,
BSSGP_CAUSE_UNKNOWN_BVCI = 0x05,
BSSGP_CAUSE_CELL_TRAF_CONG = 0x06,
BSSGP_CAUSE_SGSN_CONG = 0x07,
BSSGP_CAUSE_OML_INTERV = 0x08,
BSSGP_CAUSE_BVCI_BLOCKED = 0x09,
BSSGP_CAUSE_PFC_CREATE_FAIL = 0x0a,
BSSGP_CAUSE_SEM_INCORR_PDU = 0x20,
BSSGP_CAUSE_INV_MAND_INF = 0x21,
BSSGP_CAUSE_MISSING_MAND_IE = 0x22,
BSSGP_CAUSE_MISSING_COND_IE = 0x23,
BSSGP_CAUSE_UNEXP_COND_IE = 0x24,
BSSGP_CAUSE_COND_IE_ERR = 0x25,
BSSGP_CAUSE_PDU_INCOMP_STATE = 0x26,
BSSGP_CAUSE_PROTO_ERR_UNSPEC = 0x27,
BSSGP_CAUSE_PDU_INCOMP_FEAT = 0x28,
};
/* Our implementation */
/* gprs_bssgp_util.c */
extern struct gprs_ns_inst *bssgp_nsi;
struct msgb *bssgp_msgb_alloc(void);
const char *bssgp_cause_str(enum gprs_bssgp_cause cause);
/* Transmit a simple response such as BLOCK/UNBLOCK/RESET ACK/NACK */
int bssgp_tx_simple_bvci(uint8_t pdu_type, uint16_t nsei,
uint16_t bvci, uint16_t ns_bvci);
/* Chapter 10.4.14: Status */
int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg);
/* gprs_bssgp.c */
#define BVC_S_BLOCKED 0x0001
/* The per-BTS context that we keep on the SGSN side of the BSSGP link */
struct bssgp_bvc_ctx {
struct llist_head list;
/* parsed RA ID and Cell ID of the remote BTS */
struct gprs_ra_id ra_id;
uint16_t cell_id;
/* NSEI and BVCI of underlying Gb link. Together they
* uniquely identify a link to a BTS (5.4.4) */
uint16_t bvci;
uint16_t nsei;
uint32_t state;
struct rate_ctr_group *ctrg;
/* we might want to add this as a shortcut later, avoiding the NSVC
* lookup for every packet, similar to a routing cache */
//struct gprs_nsvc *nsvc;
};
extern struct llist_head bssgp_bvc_ctxts;
/* Find a BTS Context based on parsed RA ID and Cell ID */
struct bssgp_bvc_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid);
/* Find a BTS context based on BVCI+NSEI tuple */
struct bssgp_bvc_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei);
#include <osmocore/tlv.h>
/* BSSGP-UL-UNITDATA.ind */
int gprs_bssgp_rcvmsg(struct msgb *msg);
/* BSSGP-DL-UNITDATA.req */
struct sgsn_mm_ctx;
int gprs_bssgp_tx_dl_ud(struct msgb *msg, struct sgsn_mm_ctx *mmctx);
uint16_t bssgp_parse_cell_id(struct gprs_ra_id *raid, const uint8_t *buf);
/* Wrapper around TLV parser to parse BSSGP IEs */
static inline int bssgp_tlv_parse(struct tlv_parsed *tp, uint8_t *buf, int len)
{
return tlv_parse(tp, &tvlv_att_def, buf, len, 0, 0);
}
enum bssgp_paging_mode {
BSSGP_PAGING_PS,
BSSGP_PAGING_CS,
};
enum bssgp_paging_scope {
BSSGP_PAGING_BSS_AREA, /* all cells in BSS */
BSSGP_PAGING_LOCATION_AREA, /* all cells in LA */
BSSGP_PAGING_ROUTEING_AREA, /* all cells in RA */
BSSGP_PAGING_BVCI, /* one cell */
};
struct bssgp_paging_info {
enum bssgp_paging_mode mode;
enum bssgp_paging_scope scope;
struct gprs_ra_id raid;
uint16_t bvci;
const char *imsi;
uint32_t *ptmsi;
uint16_t drx_params;
uint8_t qos[3];
};
/* Send a single GMM-PAGING.req to a given NSEI/NS-BVCI */
int gprs_bssgp_tx_paging(uint16_t nsei, uint16_t ns_bvci,
struct bssgp_paging_info *pinfo);
/* gprs_bssgp_vty.c */
int gprs_bssgp_vty_init(void);
#endif /* _GPRS_BSSGP_H */

View File

@@ -1,18 +0,0 @@
#ifndef _GPRS_GMM_H
#define _GPRS_GMM_H
#include <osmocore/msgb.h>
#include <openbsc/gprs_sgsn.h>
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
int gsm0408_gprs_rcvmsg(struct msgb *msg, struct gprs_llc_llme *llme);
int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
uint8_t suspend_ref);
#endif /* _GPRS_GMM_H */

View File

@@ -1,162 +0,0 @@
#ifndef _GPRS_LLC_H
#define _GPRS_LLC_H
#include <stdint.h>
#include <openbsc/gprs_sgsn.h>
/* Section 4.7 LLC Layer Structure */
enum gprs_llc_sapi {
GPRS_SAPI_GMM = 1,
GPRS_SAPI_TOM2 = 2,
GPRS_SAPI_SNDCP3 = 3,
GPRS_SAPI_SNDCP5 = 5,
GPRS_SAPI_SMS = 7,
GPRS_SAPI_TOM8 = 8,
GPRS_SAPI_SNDCP9 = 9,
GPRS_SAPI_SNDCP11 = 11,
};
/* Section 6.4 Commands and Responses */
enum gprs_llc_u_cmd {
GPRS_LLC_U_DM_RESP = 0x01,
GPRS_LLC_U_DISC_CMD = 0x04,
GPRS_LLC_U_UA_RESP = 0x06,
GPRS_LLC_U_SABM_CMD = 0x07,
GPRS_LLC_U_FRMR_RESP = 0x08,
GPRS_LLC_U_XID = 0x0b,
GPRS_LLC_U_NULL_CMD = 0x00,
};
/* TS 04.64 Section 7.1.2 Table 7: LLC layer primitives (GMM/SNDCP/SMS/TOM) */
/* TS 04.65 Section 5.1.2 Table 2: Service primitives used by SNDCP */
enum gprs_llc_primitive {
/* GMM <-> LLME */
LLGMM_ASSIGN_REQ, /* GMM tells us new TLLI: TLLI old, TLLI new, Kc, CiphAlg */
LLGMM_RESET_REQ, /* GMM tells us to perform XID negotiation: TLLI */
LLGMM_RESET_CNF, /* LLC informs GMM that XID has completed: TLLI */
LLGMM_SUSPEND_REQ, /* GMM tells us MS has suspended: TLLI, Page */
LLGMM_RESUME_REQ, /* GMM tells us MS has resumed: TLLI */
LLGMM_PAGE_IND, /* LLC asks GMM to page MS: TLLI */
LLGMM_IOV_REQ, /* GMM tells us to perform XID: TLLI */
LLGMM_STATUS_IND, /* LLC informs GMM about error: TLLI, Cause */
/* LLE <-> (GMM/SNDCP/SMS/TOM) */
LL_RESET_IND, /* TLLI */
LL_ESTABLISH_REQ, /* TLLI, XID Req */
LL_ESTABLISH_IND, /* TLLI, XID Req, N201-I, N201-U */
LL_ESTABLISH_RESP, /* TLLI, XID Negotiated */
LL_ESTABLISH_CONF, /* TLLI, XID Neg, N201-i, N201-U */
LL_RELEASE_REQ, /* TLLI, Local */
LL_RELEASE_IND, /* TLLI, Cause */
LL_RELEASE_CONF, /* TLLI */
LL_XID_REQ, /* TLLI, XID Requested */
LL_XID_IND, /* TLLI, XID Req, N201-I, N201-U */
LL_XID_RESP, /* TLLI, XID Negotiated */
LL_XID_CONF, /* TLLI, XID Neg, N201-I, N201-U */
LL_DATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
LL_DATA_IND, /* TLLI, SN-PDU */
LL_DATA_CONF, /* TLLI, Ref */
LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
LL_UNITDATA_IND, /* TLLI, SN-PDU */
LL_STATUS_IND, /* TLLI, Cause */
};
/* Section 4.5.2 Logical Link States + Annex C.2 */
enum gprs_llc_lle_state {
GPRS_LLES_UNASSIGNED = 1, /* No TLLI yet */
GPRS_LLES_ASSIGNED_ADM = 2, /* TLLI assigned */
GPRS_LLES_LOCAL_EST = 3, /* Local Establishment */
GPRS_LLES_REMOTE_EST = 4, /* Remote Establishment */
GPRS_LLES_ABM = 5,
GPRS_LLES_LOCAL_REL = 6, /* Local Release */
GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
};
enum gprs_llc_llme_state {
GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */
};
/* Section 8.9.9 LLC layer parameter default values */
struct gprs_llc_params {
uint16_t iov_i_exp;
uint16_t t200_201;
uint16_t n200;
uint16_t n201_u;
uint16_t n201_i;
uint16_t mD;
uint16_t mU;
uint16_t kD;
uint16_t kU;
};
/* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
struct gprs_llc_lle {
struct llist_head list;
uint32_t sapi;
struct gprs_llc_llme *llme;
enum gprs_llc_lle_state state;
struct timer_list t200;
struct timer_list t201; /* wait for acknowledgement */
uint16_t v_sent;
uint16_t v_ack;
uint16_t v_recv;
uint16_t vu_send;
uint16_t vu_recv;
/* Overflow Counter for ABM */
uint32_t oc_i_send;
uint32_t oc_i_recv;
/* Overflow Counter for unconfirmed transfer */
uint32_t oc_ui_send;
uint32_t oc_ui_recv;
unsigned int retrans_ctr;
struct gprs_llc_params params;
};
#define NUM_SAPIS 16
struct gprs_llc_llme {
struct llist_head list;
enum gprs_llc_llme_state state;
uint32_t tlli;
uint32_t old_tlli;
/* Crypto parameters */
enum gprs_ciph_algo algo;
uint8_t kc[8];
/* over which BSSGP BTS ctx do we need to transmit */
uint16_t bvci;
uint16_t nsei;
struct gprs_llc_lle lle[NUM_SAPIS];
};
extern struct llist_head gprs_llc_llmes;
/* BSSGP-UL-UNITDATA.ind */
int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv);
/* LL-UNITDATA.req */
int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
void *mmctx);
/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
int gprs_llgmm_assign(struct gprs_llc_llme *llme,
uint32_t old_tlli, uint32_t new_tlli,
enum gprs_ciph_algo alg, const uint8_t *kc);
int gprs_llc_init(const char *cipher_plugin_path);
int gprs_llc_vty_init(void);
#endif

View File

@@ -1,232 +0,0 @@
#ifndef _GPRS_NS_H
#define _GPRS_NS_H
#include <stdint.h>
/* GPRS Networks Service (NS) messages on the Gb interface
* 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05)
* 3GPP TS 48.016 version 6.5.0 Release 6 / ETSI TS 148 016 V6.5.0 (2005-11) */
struct gprs_ns_hdr {
uint8_t pdu_type;
uint8_t data[0];
} __attribute__((packed));
/* TS 08.16, Section 10.3.7, Table 14 */
enum ns_pdu_type {
NS_PDUT_UNITDATA = 0x00,
NS_PDUT_RESET = 0x02,
NS_PDUT_RESET_ACK = 0x03,
NS_PDUT_BLOCK = 0x04,
NS_PDUT_BLOCK_ACK = 0x05,
NS_PDUT_UNBLOCK = 0x06,
NS_PDUT_UNBLOCK_ACK = 0x07,
NS_PDUT_STATUS = 0x08,
NS_PDUT_ALIVE = 0x0a,
NS_PDUT_ALIVE_ACK = 0x0b,
/* TS 48.016 Section 10.3.7, Table 10.3.7.1 */
SNS_PDUT_ACK = 0x0c,
SNS_PDUT_ADD = 0x0d,
SNS_PDUT_CHANGE_WEIGHT = 0x0e,
SNS_PDUT_CONFIG = 0x0f,
SNS_PDUT_CONFIG_ACK = 0x10,
SNS_PDUT_DELETE = 0x11,
SNS_PDUT_SIZE = 0x12,
SNS_PDUT_SIZE_ACK = 0x13,
};
/* TS 08.16, Section 10.3, Table 12 */
enum ns_ctrl_ie {
NS_IE_CAUSE = 0x00,
NS_IE_VCI = 0x01,
NS_IE_PDU = 0x02,
NS_IE_BVCI = 0x03,
NS_IE_NSEI = 0x04,
/* TS 48.016 Section 10.3, Table 10.3.1 */
NS_IE_IPv4_LIST = 0x05,
NS_IE_IPv6_LIST = 0x06,
NS_IE_MAX_NR_NSVC = 0x07,
NS_IE_IPv4_EP_NR = 0x08,
NS_IE_IPv6_EP_NR = 0x09,
NS_IE_RESET_FLAG = 0x0a,
NS_IE_IP_ADDR = 0x0b,
};
/* TS 08.16, Section 10.3.2, Table 13 */
enum ns_cause {
NS_CAUSE_TRANSIT_FAIL = 0x00,
NS_CAUSE_OM_INTERVENTION = 0x01,
NS_CAUSE_EQUIP_FAIL = 0x02,
NS_CAUSE_NSVC_BLOCKED = 0x03,
NS_CAUSE_NSVC_UNKNOWN = 0x04,
NS_CAUSE_BVCI_UNKNOWN = 0x05,
NS_CAUSE_SEM_INCORR_PDU = 0x08,
NS_CAUSE_PDU_INCOMP_PSTATE = 0x0a,
NS_CAUSE_PROTO_ERR_UNSPEC = 0x0b,
NS_CAUSE_INVAL_ESSENT_IE = 0x0c,
NS_CAUSE_MISSING_ESSENT_IE = 0x0d,
/* TS 48.016 Section 10.3.2, Table 10.3.2.1 */
NS_CAUSE_INVAL_NR_IPv4_EP = 0x0e,
NS_CAUSE_INVAL_NR_IPv6_EP = 0x0f,
NS_CAUSE_INVAL_NR_NS_VC = 0x10,
NS_CAUSE_INVAL_WEIGH = 0x11,
NS_CAUSE_UNKN_IP_EP = 0x12,
NS_CAUSE_UNKN_IP_ADDR = 0x13,
NS_CAUSE_UNKN_IP_TEST_FAILED = 0x14,
};
/* Our Implementation */
#include <netinet/in.h>
#include <osmocore/linuxlist.h>
#include <osmocore/msgb.h>
#include <osmocore/timer.h>
#include <osmocore/select.h>
#define NS_TIMERS_COUNT 7
#define NS_TIMERS "(tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries)"
#define NS_TIMERS_HELP \
"(un)blocking Timer (Tns-block) timeout\n" \
"(un)blocking Timer (Tns-block) number of retries\n" \
"Reset Timer (Tns-reset) timeout\n" \
"Reset Timer (Tns-reset) number of retries\n" \
"Test Timer (Tns-test) timeout\n" \
enum ns_timeout {
NS_TOUT_TNS_BLOCK,
NS_TOUT_TNS_BLOCK_RETRIES,
NS_TOUT_TNS_RESET,
NS_TOUT_TNS_RESET_RETRIES,
NS_TOUT_TNS_TEST,
NS_TOUT_TNS_ALIVE,
NS_TOUT_TNS_ALIVE_RETRIES,
};
#define NSE_S_BLOCKED 0x0001
#define NSE_S_ALIVE 0x0002
enum gprs_ns_ll {
GPRS_NS_LL_UDP,
GPRS_NS_LL_E1,
GPRS_NS_LL_FR_GRE,
};
enum gprs_ns_evt {
GPRS_NS_EVT_UNIT_DATA,
};
struct gprs_nsvc;
typedef int gprs_ns_cb_t(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
struct msgb *msg, uint16_t bvci);
/* An instance of the NS protocol stack */
struct gprs_ns_inst {
/* callback to the user for incoming UNIT DATA IND */
gprs_ns_cb_t *cb;
/* linked lists of all NSVC in this instance */
struct llist_head gprs_nsvcs;
/* a NSVC object that's needed to deal with packets for unknown NSVC */
struct gprs_nsvc *unknown_nsvc;
uint16_t timeout[NS_TIMERS_COUNT];
/* NS-over-IP specific bits */
struct {
struct bsc_fd fd;
uint32_t local_ip;
uint16_t local_port;
} nsip;
/* NS-over-FR-over-GRE-over-IP specific bits */
struct {
struct bsc_fd fd;
uint32_t local_ip;
int enabled:1;
} frgre;
};
enum nsvc_timer_mode {
/* standard timers */
NSVC_TIMER_TNS_TEST,
NSVC_TIMER_TNS_ALIVE,
NSVC_TIMER_TNS_RESET,
_NSVC_TIMER_NR,
};
struct gprs_nsvc {
struct llist_head list;
struct gprs_ns_inst *nsi;
uint16_t nsei; /* end-to-end significance */
uint16_t nsvci; /* uniquely identifies NS-VC at SGSN */
uint32_t state;
uint32_t remote_state;
struct timer_list timer;
enum nsvc_timer_mode timer_mode;
int alive_retries;
unsigned int remote_end_is_sgsn:1;
unsigned int persistent:1;
struct rate_ctr_group *ctrg;
/* which link-layer are we based on? */
enum gprs_ns_ll ll;
union {
struct {
struct sockaddr_in bts_addr;
} ip;
struct {
struct sockaddr_in bts_addr;
} frgre;
};
};
/* Create a new NS protocol instance */
struct gprs_ns_inst *gprs_ns_instantiate(gprs_ns_cb_t *cb);
/* Destroy a NS protocol instance */
void gprs_ns_destroy(struct gprs_ns_inst *nsi);
/* Listen for incoming GPRS packets via NS/UDP */
int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi);
struct sockaddr_in;
/* main function for higher layers (BSSGP) to send NS messages */
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause);
int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc);
/* Listen for incoming GPRS packets via NS/FR/GRE */
int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi);
/* Establish a connection (from the BSS) to the SGSN */
struct gprs_nsvc *nsip_connect(struct gprs_ns_inst *nsi,
struct sockaddr_in *dest, uint16_t nsei,
uint16_t nsvci);
struct gprs_nsvc *nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci);
void nsvc_delete(struct gprs_nsvc *nsvc);
struct gprs_nsvc *nsvc_by_nsei(struct gprs_ns_inst *nsi, uint16_t nsei);
struct gprs_nsvc *nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci);
/* Initiate a RESET procedure (including timer start, ...)*/
void gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause);
/* Add NS-specific VTY stuff */
int gprs_ns_vty_init(struct gprs_ns_inst *nsi);
#define NS_ALLOC_SIZE 2048
#define NS_ALLOC_HEADROOM 20
static inline struct msgb *gprs_ns_msgb_alloc(void)
{
return msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, "GPRS/NS");
}
#endif

View File

@@ -1,6 +0,0 @@
#ifndef _GPRS_NS_FRGRE_H
#define _GPRS_NS_FRGRE_H
int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
#endif

View File

@@ -1,205 +0,0 @@
#ifndef _GPRS_SGSN_H
#define _GPRS_SGSN_H
#include <stdint.h>
#include <netinet/in.h>
#include <osmocore/gsm48.h>
#include <osmocom/crypt/gprs_cipher.h>
#define GSM_IMSI_LENGTH 17
#define GSM_IMEI_LENGTH 17
#define GSM_EXTENSION_LENGTH 15
struct gprs_llc_lle;
/* TS 04.08 4.1.3.3 GMM mobility management states on the network side */
enum gprs_mm_state {
GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
};
enum gprs_mm_ctr {
GMM_CTR_PKTS_SIG_IN,
GMM_CTR_PKTS_SIG_OUT,
GMM_CTR_PKTS_UDATA_IN,
GMM_CTR_PKTS_UDATA_OUT,
GMM_CTR_BYTES_UDATA_IN,
GMM_CTR_BYTES_UDATA_OUT,
GMM_CTR_PDP_CTX_ACT,
GMM_CTR_SUSPEND,
GMM_CTR_PAGING_PS,
GMM_CTR_PAGING_CS,
GMM_CTR_RA_UPDATE,
};
enum gprs_pdp_ctx {
PDP_CTR_PKTS_UDATA_IN,
PDP_CTR_PKTS_UDATA_OUT,
PDP_CTR_BYTES_UDATA_IN,
PDP_CTR_BYTES_UDATA_OUT,
};
enum gprs_t3350_mode {
GMM_T3350_MODE_ATT,
GMM_T3350_MODE_RAU,
GMM_T3350_MODE_PTMSI_REALL,
};
#define MS_RADIO_ACCESS_CAPA
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
struct sgsn_mm_ctx {
struct llist_head list;
char imsi[GSM_IMSI_LENGTH];
enum gprs_mm_state mm_state;
uint32_t p_tmsi;
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
uint32_t p_tmsi_sig;
char imei[GSM_IMEI_LENGTH];
/* Opt: Software Version Numbber / TS 23.195 */
char msisdn[GSM_EXTENSION_LENGTH];
struct gprs_ra_id ra;
uint16_t cell_id;
uint32_t cell_id_age;
uint16_t sac; /* Iu: Service Area Code */
uint32_t sac_age;/* Iu: Service Area Code age */
/* VLR number */
uint32_t new_sgsn_addr;
/* Authentication Triplets */
/* Kc */
/* Iu: CK, IK, KSI */
/* CKSN */
enum gprs_ciph_algo ciph_algo;
struct {
uint8_t buf[14]; /* 10.5.5.12a */
uint8_t len;
} ms_radio_access_capa;
struct {
uint8_t buf[4]; /* 10.5.5.12 */
uint8_t len;
} ms_network_capa;
uint16_t drx_parms;
int mnrg; /* MS reported to HLR? */
int ngaf; /* MS reported to MSC/VLR? */
int ppf; /* paging for GPRS + non-GPRS? */
/* SMS Parameters */
int recovery;
uint8_t radio_prio_sms;
struct llist_head pdp_list;
/* Additional bits not present in the GSM TS */
struct gprs_llc_llme *llme;
uint32_t tlli;
uint32_t tlli_new;
uint16_t nsei;
uint16_t bvci;
struct rate_ctr_group *ctrg;
struct timer_list timer;
unsigned int T; /* Txxxx number */
unsigned int num_T_exp; /* number of consecutive T expirations */
enum gprs_t3350_mode t3350_mode;
uint8_t t3370_id_type;
};
/* look-up a SGSN MM context based on TLLI + RAI */
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
const struct gprs_ra_id *raid);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
/* Allocate a new SGSN MM context */
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc(uint32_t tlli,
const struct gprs_ra_id *raid);
enum pdp_ctx_state {
PDP_STATE_NONE,
PDP_STATE_CR_REQ,
PDP_STATE_CR_CONF,
};
enum pdp_type {
PDP_TYPE_NONE,
PDP_TYPE_ETSI_PPP,
PDP_TYPE_IANA_IPv4,
PDP_TYPE_IANA_IPv6,
};
struct sgsn_pdp_ctx {
struct llist_head list; /* list_head for mmctx->pdp_list */
struct llist_head g_list; /* list_head for global list */
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
struct rate_ctr_group *ctrg;
//unsigned int id;
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
enum pdp_ctx_state state;
enum pdp_type type;
uint32_t address;
char *apn_subscribed;
//char *apn_used;
uint16_t nsapi; /* SNDCP */
uint16_t sapi; /* LLC */
uint8_t ti; /* transaction identifier */
int vplmn_allowed;
uint32_t qos_profile_subscr;
//uint32_t qos_profile_req;
//uint32_t qos_profile_neg;
uint8_t radio_prio;
uint32_t tx_npdu_nr;
uint32_t rx_npdu_nr;
uint32_t tx_gtp_snd;
uint32_t rx_gtp_snu;
//uint32_t charging_id;
int reordering_reqd;
};
/* look up PDP context by MM context and NSAPI */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
uint8_t nsapi);
/* look up PDP context by MM context and transaction ID */
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
uint8_t tid);
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
uint8_t nsapi);
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
struct sgsn_ggsn_ctx {
struct llist_head list;
uint32_t id;
unsigned int gtp_version;
struct in_addr remote_addr;
struct gsn_t *gsn;
};
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
struct apn_ctx {
struct llist_head list;
struct sgsn_ggsn_ctx *ggsn;
char *name;
char *description;
};
extern struct llist_head sgsn_mm_ctxts;
extern struct llist_head sgsn_ggsn_ctxts;
extern struct llist_head sgsn_apn_ctxts;
extern struct llist_head sgsn_pdp_ctxts;
uint32_t sgsn_alloc_ptmsi(void);
#endif /* _GPRS_SGSN_H */

View File

@@ -1,47 +1,765 @@
#ifndef _GSM_04_08_H
#define _GSM_04_08_H
#include <openbsc/meas_rep.h>
/* GSM TS 04.08 definitions */
struct gsm_lchan;
struct gsm48_classmark1 {
u_int8_t spare:1,
rev_level:2,
es_ind:1,
a5_1:1,
pwr_lev:3;
} __attribute__ ((packed));
/* Chapter 10.5.2.5 */
struct gsm48_chan_desc {
u_int8_t chan_nr;
union {
struct {
u_int8_t maio_high:4,
h:1,
tsc:3;
u_int8_t hsn:6,
maio_low:2;
} h1;
struct {
u_int8_t arfcn_high:2,
spare:2,
h:1,
tsc:3;
u_int8_t arfcn_low;
} h0;
};
} __attribute__ ((packed));
/* Chapter 10.5.2.21aa */
struct gsm48_multi_rate_conf {
u_int8_t smod : 2,
spare: 1,
icmi : 1,
nscb : 1,
ver : 3;
u_int8_t m4_75 : 1,
m5_15 : 1,
m5_90 : 1,
m6_70 : 1,
m7_40 : 1,
m7_95 : 1,
m10_2 : 1,
m12_2 : 1;
} __attribute__((packed));
/* Chapter 10.5.2.30 */
struct gsm48_req_ref {
u_int8_t ra;
u_int8_t t3_high:3,
t1_:5;
u_int8_t t2:5,
t3_low:3;
} __attribute__ ((packed));
/*
* Chapter 9.1.5/9.1.6
*
* For 9.1.6 the chan_desc has the meaning of 10.5.2.5a
*/
struct gsm48_chan_mode_modify {
struct gsm48_chan_desc chan_desc;
u_int8_t mode;
} __attribute__ ((packed));
enum gsm48_chan_mode {
GSM48_CMODE_SIGN = 0x00,
GSM48_CMODE_SPEECH_V1 = 0x01,
GSM48_CMODE_SPEECH_EFR = 0x21,
GSM48_CMODE_SPEECH_AMR = 0x41,
GSM48_CMODE_DATA_14k5 = 0x0f,
GSM48_CMODE_DATA_12k0 = 0x03,
GSM48_CMODE_DATA_6k0 = 0x0b,
GSM48_CMODE_DATA_3k6 = 0x23,
};
/* Chapter 9.1.2 */
struct gsm48_ass_cmd {
/* Semantic is from 10.5.2.5a */
struct gsm48_chan_desc chan_desc;
u_int8_t power_command;
u_int8_t data[0];
} __attribute__((packed));
/* Chapter 9.1.18 */
struct gsm48_imm_ass {
u_int8_t l2_plen;
u_int8_t proto_discr;
u_int8_t msg_type;
u_int8_t page_mode;
struct gsm48_chan_desc chan_desc;
struct gsm48_req_ref req_ref;
u_int8_t timing_advance;
u_int8_t mob_alloc_len;
u_int8_t mob_alloc[0];
} __attribute__ ((packed));
/* Chapter 10.5.1.3 */
struct gsm48_loc_area_id {
u_int8_t digits[3]; /* BCD! */
u_int16_t lac;
} __attribute__ ((packed));
/* Section 9.2.2 */
struct gsm48_auth_req {
u_int8_t key_seq:4,
spare:4;
u_int8_t rand[16];
} __attribute__ ((packed));
/* Section 9.2.15 */
struct gsm48_loc_upd_req {
u_int8_t type:4,
key_seq:4;
struct gsm48_loc_area_id lai;
struct gsm48_classmark1 classmark1;
u_int8_t mi_len;
u_int8_t mi[0];
} __attribute__ ((packed));
/* Section 10.1 */
struct gsm48_hdr {
u_int8_t proto_discr;
u_int8_t msg_type;
u_int8_t data[0];
} __attribute__ ((packed));
/* Section 9.1.3x System information Type header */
struct gsm48_system_information_type_header {
u_int8_t l2_plen;
u_int8_t rr_protocol_discriminator :4,
skip_indicator:4;
u_int8_t system_information;
} __attribute__ ((packed));
struct gsm48_rach_control {
u_int8_t re :1,
cell_bar :1,
tx_integer :4,
max_trans :2;
u_int8_t t2;
u_int8_t t3;
} __attribute__ ((packed));
/* Section 10.5.2.4 Cell Selection Parameters */
struct gsm48_cell_sel_par {
u_int8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */
cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */
u_int8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */
neci:1,
acs:1;
} __attribute__ ((packed));
/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */
struct gsm48_control_channel_descr {
u_int8_t ccch_conf :3,
bs_ag_blks_res :3,
att :1,
spare1 :1;
u_int8_t bs_pa_mfrms : 3,
spare2 :5;
u_int8_t t3212;
} __attribute__ ((packed));
/* Section 9.2.9 CM service request */
struct gsm48_service_request {
u_int8_t cm_service_type : 4,
cipher_key_seq : 4;
/* length + 3 bytes */
u_int32_t classmark;
u_int8_t mi_len;
u_int8_t mi[0];
/* optional priority level */
} __attribute__ ((packed));
/* Section 9.1.31 System information Type 1 */
struct gsm48_system_information_type_1 {
struct gsm48_system_information_type_header header;
u_int8_t cell_channel_description[16];
struct gsm48_rach_control rach_control;
u_int8_t s1_reset;
} __attribute__ ((packed));
/* Section 9.1.32 System information Type 2 */
struct gsm48_system_information_type_2 {
struct gsm48_system_information_type_header header;
u_int8_t bcch_frequency_list[16];
u_int8_t ncc_permitted;
struct gsm48_rach_control rach_control;
} __attribute__ ((packed));
/* Section 9.1.35 System information Type 3 */
struct gsm48_system_information_type_3 {
struct gsm48_system_information_type_header header;
u_int16_t cell_identity;
struct gsm48_loc_area_id lai;
struct gsm48_control_channel_descr control_channel_desc;
u_int8_t cell_options;
struct gsm48_cell_sel_par cell_sel_par;
struct gsm48_rach_control rach_control;
u_int8_t s3_reset_octets[4];
} __attribute__ ((packed));
/* Section 9.1.36 System information Type 4 */
struct gsm48_system_information_type_4 {
struct gsm48_system_information_type_header header;
struct gsm48_loc_area_id lai;
struct gsm48_cell_sel_par cell_sel_par;
struct gsm48_rach_control rach_control;
/* optional CBCH conditional CBCH... followed by
mandantory SI 4 Reset Octets
*/
u_int8_t data[0];
} __attribute__ ((packed));
/* Section 9.1.37 System information Type 5 */
struct gsm48_system_information_type_5 {
u_int8_t rr_protocol_discriminator :4,
skip_indicator:4;
u_int8_t system_information;
u_int8_t bcch_frequency_list[16];
} __attribute__ ((packed));
/* Section 9.1.40 System information Type 6 */
struct gsm48_system_information_type_6 {
u_int8_t rr_protocol_discriminator :4,
skip_indicator:4;
u_int8_t system_information;
u_int16_t cell_identity;
struct gsm48_loc_area_id lai;
u_int8_t cell_options;
u_int8_t ncc_permitted;
u_int8_t si_6_reset[0];
} __attribute__ ((packed));
/* Section 9.2.12 IMSI Detach Indication */
struct gsm48_imsi_detach_ind {
struct gsm48_classmark1 classmark1;
u_int8_t mi_len;
u_int8_t mi[0];
} __attribute__ ((packed));
/* Section 10.2 + GSM 04.07 12.2.3.1.1 */
#define GSM48_PDISC_GROUP_CC 0x00
#define GSM48_PDISC_BCAST_CC 0x01
#define GSM48_PDISC_PDSS1 0x02
#define GSM48_PDISC_CC 0x03
#define GSM48_PDISC_PDSS2 0x04
#define GSM48_PDISC_MM 0x05
#define GSM48_PDISC_RR 0x06
#define GSM48_PDISC_MM_GPRS 0x08
#define GSM48_PDISC_SMS 0x09
#define GSM48_PDISC_SM_GPRS 0x0a
#define GSM48_PDISC_NC_SS 0x0b
#define GSM48_PDISC_LOC 0x0c
#define GSM48_PDISC_MASK 0x0f
#define GSM48_PDISC_USSD 0x11
/* Section 10.4 */
#define GSM48_MT_RR_INIT_REQ 0x3c
#define GSM48_MT_RR_ADD_ASS 0x3b
#define GSM48_MT_RR_IMM_ASS 0x3f
#define GSM48_MT_RR_IMM_ASS_EXT 0x39
#define GSM48_MT_RR_IMM_ASS_REJ 0x3a
#define GSM48_MT_RR_CIPH_M_CMD 0x35
#define GSM48_MT_RR_CIPH_M_COMPL 0x32
#define GSM48_MT_RR_CFG_CHG_CMD 0x30
#define GSM48_MT_RR_CFG_CHG_ACK 0x31
#define GSM48_MT_RR_CFG_CHG_REJ 0x33
#define GSM48_MT_RR_ASS_CMD 0x2e
#define GSM48_MT_RR_ASS_COMPL 0x29
#define GSM48_MT_RR_ASS_FAIL 0x2f
#define GSM48_MT_RR_HANDO_CMD 0x2b
#define GSM48_MT_RR_HANDO_COMPL 0x2c
#define GSM48_MT_RR_HANDO_FAIL 0x28
#define GSM48_MT_RR_HANDO_INFO 0x2d
#define GSM48_MT_RR_CELL_CHG_ORDER 0x08
#define GSM48_MT_RR_PDCH_ASS_CMD 0x23
#define GSM48_MT_RR_CHAN_REL 0x0d
#define GSM48_MT_RR_PART_REL 0x0a
#define GSM48_MT_RR_PART_REL_COMP 0x0f
#define GSM48_MT_RR_PAG_REQ_1 0x21
#define GSM48_MT_RR_PAG_REQ_2 0x22
#define GSM48_MT_RR_PAG_REQ_3 0x24
#define GSM48_MT_RR_PAG_RESP 0x27
#define GSM48_MT_RR_NOTIF_NCH 0x20
#define GSM48_MT_RR_NOTIF_FACCH 0x25
#define GSM48_MT_RR_NOTIF_RESP 0x26
#define GSM48_MT_RR_SYSINFO_8 0x18
#define GSM48_MT_RR_SYSINFO_1 0x19
#define GSM48_MT_RR_SYSINFO_2 0x1a
#define GSM48_MT_RR_SYSINFO_3 0x1b
#define GSM48_MT_RR_SYSINFO_4 0x1c
#define GSM48_MT_RR_SYSINFO_5 0x1d
#define GSM48_MT_RR_SYSINFO_6 0x1e
#define GSM48_MT_RR_SYSINFO_7 0x1f
#define GSM48_MT_RR_SYSINFO_2bis 0x02
#define GSM48_MT_RR_SYSINFO_2ter 0x03
#define GSM48_MT_RR_SYSINFO_5bis 0x05
#define GSM48_MT_RR_SYSINFO_5ter 0x06
#define GSM48_MT_RR_SYSINFO_9 0x04
#define GSM48_MT_RR_SYSINFO_13 0x00
#define GSM48_MT_RR_SYSINFO_16 0x3d
#define GSM48_MT_RR_SYSINFO_17 0x3e
#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10
#define GSM48_MT_RR_STATUS 0x12
#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17
#define GSM48_MT_RR_FREQ_REDEF 0x14
#define GSM48_MT_RR_MEAS_REP 0x15
#define GSM48_MT_RR_CLSM_CHG 0x16
#define GSM48_MT_RR_CLSM_ENQ 0x13
#define GSM48_MT_RR_EXT_MEAS_REP 0x36
#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37
#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34
#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08
#define GSM48_MT_RR_UPLINK_RELEASE 0x0e
#define GSM48_MT_RR_UPLINK_FREE 0x0c
#define GSM48_MT_RR_UPLINK_BUSY 0x2a
#define GSM48_MT_RR_TALKER_IND 0x11
#define GSM48_MT_RR_APP_INFO 0x38
/* Table 10.2/3GPP TS 04.08 */
#define GSM48_MT_MM_IMSI_DETACH_IND 0x01
#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02
#define GSM48_MT_MM_LOC_UPD_REJECT 0x04
#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08
#define GSM48_MT_MM_AUTH_REJ 0x11
#define GSM48_MT_MM_AUTH_REQ 0x12
#define GSM48_MT_MM_AUTH_RESP 0x14
#define GSM48_MT_MM_ID_REQ 0x18
#define GSM48_MT_MM_ID_RESP 0x19
#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a
#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b
#define GSM48_MT_MM_CM_SERV_ACC 0x21
#define GSM48_MT_MM_CM_SERV_REJ 0x22
#define GSM48_MT_MM_CM_SERV_ABORT 0x23
#define GSM48_MT_MM_CM_SERV_REQ 0x24
#define GSM48_MT_MM_CM_SERV_PROMPT 0x25
#define GSM48_MT_MM_CM_REEST_REQ 0x28
#define GSM48_MT_MM_ABORT 0x29
#define GSM48_MT_MM_NULL 0x30
#define GSM48_MT_MM_STATUS 0x31
#define GSM48_MT_MM_INFO 0x32
/* Table 10.3/3GPP TS 04.08 */
#define GSM48_MT_CC_ALERTING 0x01
#define GSM48_MT_CC_CALL_CONF 0x08
#define GSM48_MT_CC_CALL_PROC 0x02
#define GSM48_MT_CC_CONNECT 0x07
#define GSM48_MT_CC_CONNECT_ACK 0x0f
#define GSM48_MT_CC_EMERG_SETUP 0x0e
#define GSM48_MT_CC_PROGRESS 0x03
#define GSM48_MT_CC_ESTAB 0x04
#define GSM48_MT_CC_ESTAB_CONF 0x06
#define GSM48_MT_CC_RECALL 0x0b
#define GSM48_MT_CC_START_CC 0x09
#define GSM48_MT_CC_SETUP 0x05
#define GSM48_MT_CC_MODIFY 0x17
#define GSM48_MT_CC_MODIFY_COMPL 0x1f
#define GSM48_MT_CC_MODIFY_REJECT 0x13
#define GSM48_MT_CC_USER_INFO 0x10
#define GSM48_MT_CC_HOLD 0x18
#define GSM48_MT_CC_HOLD_ACK 0x19
#define GSM48_MT_CC_HOLD_REJ 0x1a
#define GSM48_MT_CC_RETR 0x1c
#define GSM48_MT_CC_RETR_ACK 0x1d
#define GSM48_MT_CC_RETR_REJ 0x1e
#define GSM48_MT_CC_DISCONNECT 0x25
#define GSM48_MT_CC_RELEASE 0x2d
#define GSM48_MT_CC_RELEASE_COMPL 0x2a
#define GSM48_MT_CC_CONG_CTRL 0x39
#define GSM48_MT_CC_NOTIFY 0x3e
#define GSM48_MT_CC_STATUS 0x3d
#define GSM48_MT_CC_STATUS_ENQ 0x34
#define GSM48_MT_CC_START_DTMF 0x35
#define GSM48_MT_CC_STOP_DTMF 0x31
#define GSM48_MT_CC_STOP_DTMF_ACK 0x32
#define GSM48_MT_CC_START_DTMF_ACK 0x36
#define GSM48_MT_CC_START_DTMF_REJ 0x37
#define GSM48_MT_CC_FACILITY 0x3a
/* FIXME: Table 10.4 / 10.4a (GPRS) */
/* Section 10.5.2.26, Table 10.5.64 */
#define GSM48_PM_MASK 0x03
#define GSM48_PM_NORMAL 0x00
#define GSM48_PM_EXTENDED 0x01
#define GSM48_PM_REORG 0x02
#define GSM48_PM_SAME 0x03
/* Chapter 10.5.3.5 / Table 10.5.93 */
#define GSM48_LUPD_NORMAL 0x0
#define GSM48_LUPD_PERIODIC 0x1
#define GSM48_LUPD_IMSI_ATT 0x2
#define GSM48_LUPD_RESERVED 0x3
/* Table 10.5.4 */
#define GSM_MI_TYPE_MASK 0x07
#define GSM_MI_TYPE_NONE 0x00
#define GSM_MI_TYPE_IMSI 0x01
#define GSM_MI_TYPE_IMEI 0x02
#define GSM_MI_TYPE_IMEISV 0x03
#define GSM_MI_TYPE_TMSI 0x04
#define GSM_MI_ODD 0x08
#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */
#define GSM48_IE_MOBILE_ID 0x17
#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */
#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */
#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */
#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */
#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */
#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */
#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */
#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */
#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */
#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */
#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */
#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */
#define GSM48_IE_NOTIFY 0x27 /* 10.5.4.20 */
#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */
#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */
#define GSM48_IE_CONN_BCD 0x4c /* 10.5.4.13 */
#define GSM48_IE_CONN_SUB 0x4d /* 10.5.4.14 */
#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */
#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */
#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */
#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */
#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */
#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */
#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */
#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */
#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */
#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */
#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */
#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */
#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */
#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */
#define GSM48_IE_REPEAT_CIR 0xd1 /* 10.5.4.22 */
#define GSM48_IE_REPEAT_SEQ 0xd3 /* 10.5.4.22 */
/* Section 10.5.4.11 / Table 10.5.122 */
#define GSM48_CAUSE_CS_GSM 0x60
/* Section 9.1.2 / Table 9.3 */
#define GSM48_IE_FRQLIST_AFTER 0x05
#define GSM48_IE_CELL_CH_DESC 0x62
#define GSM48_IE_MSLOT_DESC 0x10
#define GSM48_IE_CHANMODE_1 0x63
#define GSM48_IE_CHANMODE_2 0x11
#define GSM48_IE_CHANMODE_3 0x13
#define GSM48_IE_CHANMODE_4 0x14
#define GSM48_IE_CHANMODE_5 0x15
#define GSM48_IE_CHANMODE_6 0x16
#define GSM48_IE_CHANMODE_7 0x17
#define GSM48_IE_CHANMODE_8 0x18
#define GSM48_IE_CHANDESC_2 0x64
/* FIXME */
/* Section 10.5.4.23 / Table 10.5.130 */
enum gsm48_signal_val {
GSM48_SIGNAL_DIALTONE = 0x00,
GSM48_SIGNAL_RINGBACK = 0x01,
GSM48_SIGNAL_INTERCEPT = 0x02,
GSM48_SIGNAL_NET_CONG = 0x03,
GSM48_SIGNAL_BUSY = 0x04,
GSM48_SIGNAL_CONFIRM = 0x05,
GSM48_SIGNAL_ANSWER = 0x06,
GSM48_SIGNAL_CALL_WAIT = 0x07,
GSM48_SIGNAL_OFF_HOOK = 0x08,
GSM48_SIGNAL_OFF = 0x3f,
GSM48_SIGNAL_ALERT_OFF = 0x4f,
};
enum gsm48_cause_loc {
GSM48_CAUSE_LOC_USER = 0x00,
GSM48_CAUSE_LOC_PRN_S_LU = 0x01,
GSM48_CAUSE_LOC_PUN_S_LU = 0x02,
GSM48_CAUSE_LOC_TRANS_NET = 0x03,
GSM48_CAUSE_LOC_PUN_S_RU = 0x04,
GSM48_CAUSE_LOC_PRN_S_RU = 0x05,
/* not defined */
GSM48_CAUSE_LOC_INN_NET = 0x07,
GSM48_CAUSE_LOC_NET_BEYOND = 0x0a,
};
/* Section 10.5.2.31 RR Cause / Table 10.5.70 */
enum gsm48_rr_cause {
GSM48_RR_CAUSE_NORMAL = 0x00,
GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01,
GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02,
GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03,
GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04,
GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05,
GSM48_RR_CAUSE_HNDOVER_IMP = 0x06,
GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07,
GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08,
GSM48_RR_CAUSE_CALL_CLEARED = 0x41,
GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f,
GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60,
GSM48_RR_CAUSE_MSG_TYPE_N = 0x61,
GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62,
GSM48_RR_CAUSE_COND_IE_ERROR = 0x64,
GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65,
GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f,
};
/* Section 10.5.4.11 CC Cause / Table 10.5.123 */
enum gsm48_cc_cause {
GSM48_CC_CAUSE_UNASSIGNED_NR = 1,
GSM48_CC_CAUSE_NO_ROUTE = 3,
GSM48_CC_CAUSE_CHAN_UNACCEPT = 6,
GSM48_CC_CAUSE_OP_DET_BARRING = 8,
GSM48_CC_CAUSE_NORM_CALL_CLEAR = 16,
GSM48_CC_CAUSE_USER_BUSY = 17,
GSM48_CC_CAUSE_USER_NOTRESPOND = 18,
GSM48_CC_CAUSE_USER_ALERTING_NA = 19,
GSM48_CC_CAUSE_CALL_REJECTED = 21,
GSM48_CC_CAUSE_NUMBER_CHANGED = 22,
GSM48_CC_CAUSE_PRE_EMPTION = 25,
GSM48_CC_CAUSE_NONSE_USER_CLR = 26,
GSM48_CC_CAUSE_DEST_OOO = 27,
GSM48_CC_CAUSE_INV_NR_FORMAT = 28,
GSM48_CC_CAUSE_FACILITY_REJ = 29,
GSM48_CC_CAUSE_RESP_STATUS_INQ = 30,
GSM48_CC_CAUSE_NORMAL_UNSPEC = 31,
GSM48_CC_CAUSE_NO_CIRCUIT_CHAN = 34,
GSM48_CC_CAUSE_NETWORK_OOO = 38,
GSM48_CC_CAUSE_TEMP_FAILURE = 41,
GSM48_CC_CAUSE_SWITCH_CONG = 42,
GSM48_CC_CAUSE_ACC_INF_DISCARD = 43,
GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL = 44,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL = 47,
GSM48_CC_CAUSE_QOS_UNAVAIL = 49,
GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC= 50,
GSM48_CC_CAUSE_INC_BARRED_CUG = 55,
GSM48_CC_CAUSE_BEARER_CAP_UNAUTH= 57,
GSM48_CC_CAUSE_BEARER_CA_UNAVAIL= 58,
GSM48_CC_CAUSE_SERV_OPT_UNAVAIL = 63,
GSM48_CC_CAUSE_BEARERSERV_UNIMPL= 65,
GSM48_CC_CAUSE_ACM_GE_ACM_MAX = 68,
GSM48_CC_CAUSE_REQ_FAC_NOTIMPL = 69,
GSM48_CC_CAUSE_RESTR_BCAP_AVAIL = 70,
GSM48_CC_CAUSE_SERV_OPT_UNIMPL = 79,
GSM48_CC_CAUSE_INVAL_TRANS_ID = 81,
GSM48_CC_CAUSE_USER_NOT_IN_CUG = 87,
GSM48_CC_CAUSE_INCOMPAT_DEST = 88,
GSM48_CC_CAUSE_INVAL_TRANS_NET = 91,
GSM48_CC_CAUSE_SEMANTIC_INCORR = 95,
GSM48_CC_CAUSE_INVAL_MAND_INF = 96,
GSM48_CC_CAUSE_MSGTYPE_NOTEXIST = 97,
GSM48_CC_CAUSE_MSGTYPE_INCOMPAT = 98,
GSM48_CC_CAUSE_IE_NOTEXIST = 99,
GSM48_CC_CAUSE_COND_IE_ERR = 100,
GSM48_CC_CAUSE_MSG_INCOMP_STATE = 101,
GSM48_CC_CAUSE_RECOVERY_TIMER = 102,
GSM48_CC_CAUSE_PROTO_ERR = 111,
GSM48_CC_CAUSE_INTERWORKING = 127,
};
/* Annex G, GSM specific cause values for mobility management */
enum gsm48_reject_value {
GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2,
GSM48_REJECT_ILLEGAL_MS = 3,
GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4,
GSM48_REJECT_IMEI_NOT_ACCEPTED = 5,
GSM48_REJECT_ILLEGAL_ME = 6,
GSM48_REJECT_PLMN_NOT_ALLOWED = 11,
GSM48_REJECT_LOC_NOT_ALLOWED = 12,
GSM48_REJECT_ROAMING_NOT_ALLOWED = 13,
GSM48_REJECT_NETWORK_FAILURE = 17,
GSM48_REJECT_CONGESTION = 22,
GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32,
GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33,
GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34,
GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38,
GSM48_REJECT_INCORRECT_MESSAGE = 95,
GSM48_REJECT_INVALID_MANDANTORY_INF = 96,
GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97,
GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98,
GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99,
GSM48_REJECT_CONDTIONAL_IE_ERROR = 100,
GSM48_REJECT_MSG_NOT_COMPATIBLE = 101,
GSM48_REJECT_PROTOCOL_ERROR = 111,
/* according to G.6 Additional cause codes for GMM */
GSM48_REJECT_GPRS_NOT_ALLOWED = 7,
GSM48_REJECT_SERVICES_NOT_ALLOWED = 8,
GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9,
GSM48_REJECT_IMPLICITLY_DETACHED = 10,
GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14,
GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16,
};
/* extracted from a L3 measurement report IE */
struct gsm_meas_rep_cell {
u_int8_t rxlev;
u_int8_t bcch_freq; /* fixme: translate to ARFCN */
u_int8_t bsic;
};
struct gsm_meas_rep {
unsigned int flags;
u_int8_t rxlev_full;
u_int8_t rxqual_full;
u_int8_t rxlev_sub;
u_int8_t rxqual_sub;
int num_cell;
struct gsm_meas_rep_cell cell[6];
};
#define MEAS_REP_F_DTX 0x01
#define MEAS_REP_F_VALID 0x02
#define MEAS_REP_F_BA1 0x04
void gsm48_parse_meas_rep(struct gsm_meas_rep *rep, const u_int8_t *data,
int len);
enum chreq_type {
CHREQ_T_EMERG_CALL,
CHREQ_T_CALL_REEST_TCH_F,
CHREQ_T_CALL_REEST_TCH_H,
CHREQ_T_CALL_REEST_TCH_H_DBL,
CHREQ_T_SDCCH,
CHREQ_T_TCH_F,
CHREQ_T_VOICE_CALL_TCH_H,
CHREQ_T_DATA_CALL_TCH_H,
CHREQ_T_LOCATION_UPD,
CHREQ_T_PAG_R_ANY_NECI0,
CHREQ_T_PAG_R_ANY_NECI1,
CHREQ_T_PAG_R_TCH_F,
CHREQ_T_PAG_R_TCH_FH,
};
/* Chapter 11.3 */
#define GSM48_T301 180, 0
#define GSM48_T303 30, 0
#define GSM48_T305 30, 0
#define GSM48_T306 30, 0
#define GSM48_T308 10, 0
#define GSM48_T310 180, 0
#define GSM48_T313 30, 0
#define GSM48_T323 30, 0
#define GSM48_T331 30, 0
#define GSM48_T333 30, 0
#define GSM48_T334 25, 0 /* min 15 */
#define GSM48_T338 30, 0
/* Chapter 5.1.2.2 */
#define GSM_CSTATE_NULL 0
#define GSM_CSTATE_INITIATED 1
#define GSM_CSTATE_MO_CALL_PROC 3
#define GSM_CSTATE_CALL_DELIVERED 4
#define GSM_CSTATE_CALL_PRESENT 6
#define GSM_CSTATE_CALL_RECEIVED 7
#define GSM_CSTATE_CONNECT_REQUEST 8
#define GSM_CSTATE_MO_TERM_CALL_CONF 9
#define GSM_CSTATE_ACTIVE 10
#define GSM_CSTATE_DISCONNECT_REQ 12
#define GSM_CSTATE_DISCONNECT_IND 12
#define GSM_CSTATE_RELEASE_REQ 19
#define GSM_CSTATE_MO_ORIG_MODIFY 26
#define GSM_CSTATE_MO_TERM_MODIFY 27
#define GSM_CSTATE_CONNECT_IND 28
#define SBIT(a) (1 << a)
#define ALL_STATES 0xffffffff
/* Table 10.5.3/3GPP TS 04.08: Location Area Identification information element */
#define GSM_LAC_RESERVED_DETACHED 0x0
#define GSM_LAC_RESERVED_ALL_BTS 0xfffe
/* GSM 04.08 Bearer Capability: Information Transfer Capability */
enum gsm48_bcap_itcap {
GSM48_BCAP_ITCAP_SPEECH = 0,
GSM48_BCAP_ITCAP_UNR_DIG_INF = 1,
GSM48_BCAP_ITCAP_3k1_AUDIO = 2,
GSM48_BCAP_ITCAP_FAX_G3 = 3,
GSM48_BCAP_ITCAP_OTHER = 5,
GSM48_BCAP_ITCAP_RESERVED = 7,
};
/* GSM 04.08 Bearer Capability: Transfer Mode */
enum gsm48_bcap_tmod {
GSM48_BCAP_TMOD_CIRCUIT = 0,
GSM48_BCAP_TMOD_PACKET = 1,
};
/* GSM 04.08 Bearer Capability: Coding Standard */
enum gsm48_bcap_coding {
GSM48_BCAP_CODING_GSM_STD = 0,
};
/* GSM 04.08 Bearer Capability: Radio Channel Requirements */
enum gsm48_bcap_rrq {
GSM48_BCAP_RRQ_FR_ONLY = 1,
GSM48_BCAP_RRQ_DUAL_HR = 2,
GSM48_BCAP_RRQ_DUAL_FR = 3,
};
#define GSM48_TMSI_LEN 5
#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2)
#define GSM48_MI_SIZE 32
#include <osmocore/protocol/gsm_04_08.h>
#include <osmocore/gsm48.h>
struct msgb;
struct gsm_bts;
struct gsm_subscriber;
struct gsm_network;
struct gsm_trans;
struct gsm_subscriber_connection;
#define GSM48_ALLOC_SIZE 1024
#define GSM48_ALLOC_HEADROOM 128
static inline struct msgb *gsm48_msgb_alloc(void)
{
return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
"GSM 04.08");
}
/* config options controlling the behaviour of the lower leves */
void gsm0408_allow_everyone(int allow);
void gsm0408_clear_request(struct gsm_subscriber_connection *conn, uint32_t cause);
int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg);
void gsm0408_set_reject_cause(int cause);
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id);
int gsm0408_new_conn(struct gsm_subscriber_connection *conn);
void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc,
u_int16_t mnc, u_int16_t lac);
enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn);
int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, u_int8_t *rand, int key_seq);
int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn);
int gsm48_tx_mm_info(struct gsm_lchan *lchan);
int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand);
int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan);
struct msgb *gsm48_msgb_alloc(void);
int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans);
int gsm48_generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi);
int gsm48_generate_mid_from_imsi(u_int8_t *buf, const char* imsi);
int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len);
int gsm48_send_rr_release(struct gsm_lchan *lchan);
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, u_int8_t apdu_id,
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
u_int8_t apdu_len, const u_int8_t *apdu);
int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, u_int8_t power_class);
int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
u_int8_t power_command, u_int8_t ho_ref);
int gsm48_send_rr_ass_cmd(struct gsm_lchan *lchan, u_int8_t power_class);
int bsc_upqueue(struct gsm_network *net);
@@ -53,18 +771,13 @@ int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len,
int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv,
int h_len);
extern const char *gsm0408_cc_msg_names[];
int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv);
int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type);
int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, u_int8_t *mi_type);
int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, struct msgb *msg, struct gsm_subscriber *subscr);
int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type);
int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr);
int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode);
int gsm48_rx_rr_modif_ack(struct msgb *msg);
int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg);
struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value);
struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);
void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
const struct gsm_lchan *lchan);
#endif

View File

@@ -1,383 +0,0 @@
#ifndef _GSM48_GPRS_H
#define _GSM48_GPRS_H
#include <stdint.h>
#include <osmocore/protocol/gsm_04_08.h>
/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */
#define GSM48_MT_GMM_ATTACH_REQ 0x01
#define GSM48_MT_GMM_ATTACH_ACK 0x02
#define GSM48_MT_GMM_ATTACH_COMPL 0x03
#define GSM48_MT_GMM_ATTACH_REJ 0x04
#define GSM48_MT_GMM_DETACH_REQ 0x05
#define GSM48_MT_GMM_DETACH_ACK 0x06
#define GSM48_MT_GMM_RA_UPD_REQ 0x08
#define GSM48_MT_GMM_RA_UPD_ACK 0x09
#define GSM48_MT_GMM_RA_UPD_COMPL 0x0a
#define GSM48_MT_GMM_RA_UPD_REJ 0x0b
#define GSM48_MT_GMM_PTMSI_REALL_CMD 0x10
#define GSM48_MT_GMM_PTMSI_REALL_COMPL 0x11
#define GSM48_MT_GMM_AUTH_CIPH_REQ 0x12
#define GSM48_MT_GMM_AUTH_CIPH_RESP 0x13
#define GSM48_MT_GMM_AUTH_CIPH_REJ 0x14
#define GSM48_MT_GMM_ID_REQ 0x15
#define GSM48_MT_GMM_ID_RESP 0x16
#define GSM48_MT_GMM_STATUS 0x20
#define GSM48_MT_GMM_INFO 0x21
/* Table 10.4a, GPRS Session Management (GSM) */
#define GSM48_MT_GSM_ACT_PDP_REQ 0x41
#define GSM48_MT_GSM_ACT_PDP_ACK 0x42
#define GSM48_MT_GSM_ACT_PDP_REJ 0x43
#define GSM48_MT_GSM_REQ_PDP_ACT 0x44
#define GSM48_MT_GSM_REQ_PDP_ACT_REJ 0x45
#define GSM48_MT_GSM_DEACT_PDP_REQ 0x46
#define GSM48_MT_GSM_DEACT_PDP_ACK 0x47
#define GSM48_MT_GSM_ACT_AA_PDP_REQ 0x50
#define GSM48_MT_GSM_ACT_AA_PDP_ACK 0x51
#define GSM48_MT_GSM_ACT_AA_PDP_REJ 0x52
#define GSM48_MT_GSM_DEACT_AA_PDP_REQ 0x53
#define GSM48_MT_GSM_DEACT_AA_PDP_ACK 0x54
#define GSM48_MT_GSM_STATUS 0x55
/* Chapter 10.5.5.2 / Table 10.5.135 */
#define GPRS_ATT_T_ATTACH 1
#define GPRS_ATT_T_ATT_WHILE_IMSI 2
#define GPRS_ATT_T_COMBINED 3
/* Chapter 10.5.5.5 / Table 10.5.138 */
#define GPRS_DET_T_MO_GPRS 1
#define GPRS_DET_T_MO_IMSI 2
#define GPRS_DET_T_MO_COMBINED 3
/* Network to MS direction */
#define GPRS_DET_T_MT_REATT_REQ 1
#define GPRS_DET_T_MT_REATT_NOTREQ 2
#define GPRS_DET_T_MT_IMSI 3
/* Chapter 10.5.5.18 / Table 105.150 */
#define GPRS_UPD_T_RA 0
#define GPRS_UPD_T_RA_LA 1
#define GPRS_UPD_T_RA_LA_IMSI_ATT 2
#define GPRS_UPD_T_PERIODIC 3
enum gsm48_gprs_ie_mm {
GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */
GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */
GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */
GSM48_IE_GMM_AUTH_RAND = 0x21, /* 10.5.3.1 */
GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */
GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */
GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */
GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */
GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */
GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */
GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */
};
enum gsm48_gprs_ie_sm {
GSM48_IE_GSM_APN = 0x28, /* 10.5.6.1 */
GSM48_IE_GSM_PROTO_CONF_OPT = 0x27, /* 10.5.6.3 */
GSM48_IE_GSM_PDP_ADDR = 0x2b, /* 10.5.6.4 */
GSM48_IE_GSM_AA_TMR = 0x29, /* 10.5.7.3 */
GSM48_IE_GSM_NAME_FULL = 0x43, /* 10.5.3.5a */
GSM48_IE_GSM_NAME_SHORT = 0x45, /* 10.5.3.5a */
GSM48_IE_GSM_TIMEZONE = 0x46, /* 10.5.3.8 */
GSM48_IE_GSM_UTC_AND_TZ = 0x47, /* 10.5.3.9 */
GSM48_IE_GSM_LSA_ID = 0x48, /* 10.5.3.11 */
/* Fake IEs that are not present on the Layer3 air interface,
* but which we use to simplify internal APIs */
OSMO_IE_GSM_REQ_QOS = 0xfd,
OSMO_IE_GSM_REQ_PDP_ADDR = 0xfe,
};
/* Chapter 9.4.15 / Table 9.4.15 */
struct gsm48_ra_upd_ack {
uint8_t force_stby:4, /* 10.5.5.7 */
upd_result:4; /* 10.5.5.17 */
uint8_t ra_upd_timer; /* 10.5.7.3 */
struct gsm48_ra_id ra_id; /* 10.5.5.15 */
uint8_t data[0];
} __attribute__((packed));
/* Chapter 10.5.7.3 */
enum gsm48_gprs_tmr_unit {
GPRS_TMR_2SECONDS = 0 << 5,
GPRS_TMR_MINUTE = 1 << 5,
GPRS_TMR_6MINUTE = 2 << 5,
GPRS_TMR_DEACTIVATED = 3 << 5,
};
/* Chapter 9.4.2 / Table 9.4.2 */
struct gsm48_attach_ack {
uint8_t att_result:4, /* 10.5.5.7 */
force_stby:4; /* 10.5.5.1 */
uint8_t ra_upd_timer; /* 10.5.7.3 */
uint8_t radio_prio; /* 10.5.7.2 */
struct gsm48_ra_id ra_id; /* 10.5.5.15 */
uint8_t data[0];
} __attribute__((packed));
/* Chapter 9.4.9 / Table 9.4.9 */
struct gsm48_auth_ciph_req {
uint8_t ciph_alg:4, /* 10.5.5.3 */
imeisv_req:4; /* 10.5.5.10 */
uint8_t force_stby:4, /* 10.5.5.7 */
ac_ref_nr:4; /* 10.5.5.19 */
uint8_t data[0];
} __attribute__((packed));
/* optional: TV RAND, TV CKSN */
struct gsm48_auth_ciph_resp {
uint8_t ac_ref_nr:4,
spare:4;
uint8_t data[0];
} __attribute__((packed));
/* Chapter 9.5.1 / Table 9.5.1 */
struct gsm48_act_pdp_ctx_req {
uint8_t req_nsapi;
uint8_t req_llc_sapi;
uint8_t data[0];
} __attribute__((packed));
/* Chapter 10.5.5.14 / Table 10.5.147 */
enum gsm48_gmm_cause {
GMM_CAUSE_IMSI_UNKNOWN = 0x02,
GMM_CAUSE_ILLEGAL_MS = 0x03,
GMM_CAUSE_ILLEGAL_ME = 0x06,
GMM_CAUSE_GPRS_NOTALLOWED = 0x07,
GMM_CAUSE_GPRS_OTHER_NOTALLOWED = 0x08,
GMM_CAUSE_MS_ID_NOT_DERIVED = 0x09,
GMM_CAUSE_IMPL_DETACHED = 0x0a,
GMM_CAUSE_PLMN_NOTALLOWED = 0x0b,
GMM_CAUSE_LA_NOTALLOWED = 0x0c,
GMM_CAUSE_ROAMING_NOTALLOWED = 0x0d,
GMM_CAUSE_NO_GPRS_PLMN = 0x0e,
GMM_CAUSE_MSC_TEMP_NOTREACH = 0x10,
GMM_CAUSE_NET_FAIL = 0x11,
GMM_CAUSE_CONGESTION = 0x16,
GMM_CAUSE_SEM_INCORR_MSG = 0x5f,
GMM_CAUSE_INV_MAND_INFO = 0x60,
GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61,
GMM_CAUSE_MSGT_INCOMP_P_STATE = 0x62,
GMM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63,
GMM_CAUSE_COND_IE_ERR = 0x64,
GMM_CAUSE_MSG_INCOMP_P_STATE = 0x65,
GMM_CAUSE_PROTO_ERR_UNSPEC = 0x6f,
};
/* Chapter 10.4.6.6 / Table 10.5.157 */
enum gsm48_gsm_cause {
GSM_CAUSE_INSUFF_RSRC = 0x1a,
GSM_CAUSE_MISSING_APN = 0x1b,
GSM_CAUSE_UNKNOWN_PDP = 0x1c,
GSM_CAUSE_AUTH_FAILED = 0x1d,
GSM_CAUSE_ACT_REJ_GGSN = 0x1e,
GSM_CAUSE_ACT_REJ_UNSPEC = 0x1f,
GSM_CAUSE_SERV_OPT_NOTSUPP = 0x20,
GSM_CAUSE_REQ_SERV_OPT_NOTSUB = 0x21,
GSM_CAUSE_SERV_OPT_TEMP_OOO = 0x22,
GSM_CAUSE_NSAPI_IN_USE = 0x23,
GSM_CAUSE_DEACT_REGULAR = 0x24,
GSM_CAUSE_QOS_NOT_ACCEPTED = 0x25,
GSM_CAUSE_NET_FAIL = 0x26,
GSM_CAUSE_REACT_RQD = 0x27,
GSM_CAUSE_FEATURE_NOTSUPP = 0x28,
GSM_CAUSE_INVALID_TRANS_ID = 0x51,
GSM_CAUSE_SEM_INCORR_MSG = 0x5f,
GSM_CAUSE_INV_MAND_INFO = 0x60,
GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61,
GSM_CAUSE_MSGT_INCOMP_P_STATE = 0x62,
GSM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63,
GSM_CAUSE_COND_IE_ERR = 0x64,
GSM_CAUSE_MSG_INCOMP_P_STATE = 0x65,
GSM_CAUSE_PROTO_ERR_UNSPEC = 0x6f,
};
/* Section 6.1.2.2: Session management states on the network side */
enum gsm48_pdp_state {
PDP_S_INACTIVE,
PDP_S_ACTIVE_PENDING,
PDP_S_ACTIVE,
PDP_S_INACTIVE_PENDING,
PDP_S_MODIFY_PENDING,
};
/* Table 10.5.155/3GPP TS 24.008 */
enum gsm48_pdp_type_org {
PDP_TYPE_ORG_ETSI = 0x00,
PDP_TYPE_ORG_IETF = 0x01,
};
enum gsm48_pdp_type_nr {
PDP_TYPE_N_ETSI_RESERVED = 0x00,
PDP_TYPE_N_ETSI_PPP = 0x01,
PDP_TYPE_N_IETF_IPv4 = 0x21,
PDP_TYPE_N_IETF_IPv6 = 0x57,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_reliab_class {
GSM48_QOS_RC_LLC_ACK_RLC_ACK_DATA_PROT = 2,
GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT = 3,
GSM48_QOS_RC_LLC_UN_RLC_UN_PROT_DATA = 4,
GSM48_QOS_RC_LLC_UN_RLC_UN_DATA_UN = 5,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_preced_class {
GSM48_QOS_PC_HIGH = 1,
GSM48_QOS_PC_NORMAL = 2,
GSM48_QOS_PC_LOW = 3,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_peak_tput {
GSM48_QOS_PEAK_TPUT_1000bps = 1,
GSM48_QOS_PEAK_TPUT_2000bps = 2,
GSM48_QOS_PEAK_TPUT_4000bps = 3,
GSM48_QOS_PEAK_TPUT_8000bps = 4,
GSM48_QOS_PEAK_TPUT_16000bps = 5,
GSM48_QOS_PEAK_TPUT_32000bps = 6,
GSM48_QOS_PEAK_TPUT_64000bps = 7,
GSM48_QOS_PEAK_TPUT_128000bps = 8,
GSM48_QOS_PEAK_TPUT_256000bps = 9,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_mean_tput {
GSM48_QOS_MEAN_TPUT_100bph = 1,
GSM48_QOS_MEAN_TPUT_200bph = 2,
GSM48_QOS_MEAN_TPUT_500bph = 3,
GSM48_QOS_MEAN_TPUT_1000bph = 4,
GSM48_QOS_MEAN_TPUT_2000bph = 5,
GSM48_QOS_MEAN_TPUT_5000bph = 6,
GSM48_QOS_MEAN_TPUT_10000bph = 7,
GSM48_QOS_MEAN_TPUT_20000bph = 8,
GSM48_QOS_MEAN_TPUT_50000bph = 9,
GSM48_QOS_MEAN_TPUT_100kbph = 10,
GSM48_QOS_MEAN_TPUT_200kbph = 11,
GSM48_QOS_MEAN_TPUT_500kbph = 0xc,
GSM48_QOS_MEAN_TPUT_1Mbph = 0xd,
GSM48_QOS_MEAN_TPUT_2Mbph = 0xe,
GSM48_QOS_MEAN_TPUT_5Mbph = 0xf,
GSM48_QOS_MEAN_TPUT_10Mbph = 0x10,
GSM48_QOS_MEAN_TPUT_20Mbph = 0x11,
GSM48_QOS_MEAN_TPUT_50Mbph = 0x12,
GSM48_QOS_MEAN_TPUT_BEST_EFFORT = 0x1f,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_err_sdu {
GSM48_QOS_ERRSDU_NODETECT = 1,
GSM48_QOS_ERRSDU_YES = 2,
GSM48_QOS_ERRSDU_NO = 3,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_deliv_order {
GSM48_QOS_DO_ORDERED = 1,
GSM48_QOS_DO_UNORDERED = 2,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_traf_class {
GSM48_QOS_TC_CONVERSATIONAL = 1,
GSM48_QOS_TC_STREAMING = 2,
GSM48_QOS_TC_INTERACTIVE = 3,
GSM48_QOS_TC_BACKGROUND = 4,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_max_sdu_size {
/* values below in 10 octet granularity */
GSM48_QOS_MAXSDU_1502 = 0x97,
GSM48_QOS_MAXSDU_1510 = 0x98,
GSM48_QOS_MAXSDU_1520 = 0x99,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_max_bitrate {
GSM48_QOS_MBRATE_1k = 0x01,
GSM48_QOS_MBRATE_63k = 0x3f,
GSM48_QOS_MBRATE_64k = 0x40,
GSM48_QOS_MBRATE_568k = 0x7f,
GSM48_QOS_MBRATE_576k = 0x80,
GSM48_QOS_MBRATE_8640k = 0xfe,
GSM48_QOS_MBRATE_0k = 0xff,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_resid_ber {
GSM48_QOS_RBER_5e_2 = 0x01,
GSM48_QOS_RBER_1e_2 = 0x02,
GSM48_QOS_RBER_5e_3 = 0x03,
GSM48_QOS_RBER_4e_3 = 0x04,
GSM48_QOS_RBER_1e_3 = 0x05,
GSM48_QOS_RBER_1e_4 = 0x06,
GSM48_QOS_RBER_1e_5 = 0x07,
GSM48_QOS_RBER_1e_6 = 0x08,
GSM48_QOS_RBER_6e_8 = 0x09,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
enum gsm48_qos_sdu_err {
GSM48_QOS_SERR_1e_2 = 0x01,
GSM48_QOS_SERR_7e_2 = 0x02,
GSM48_QOS_SERR_1e_3 = 0x03,
GSM48_QOS_SERR_1e_4 = 0x04,
GSM48_QOS_SERR_1e_5 = 0x05,
GSM48_QOS_SERR_1e_6 = 0x06,
GSM48_QOS_SERR_1e_1 = 0x07,
};
/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
struct gsm48_qos {
/* octet 3 */
uint8_t reliab_class:3;
uint8_t delay_class:3;
uint8_t spare:2;
/* octet 4 */
uint8_t preced_class:3;
uint8_t spare2:1;
uint8_t peak_tput:4;
/* octet 5 */
uint8_t mean_tput:5;
uint8_t spare3:3;
/* octet 6 */
uint8_t deliv_err_sdu:3;
uint8_t deliv_order:2;
uint8_t traf_class:3;
/* octet 7 */
uint8_t max_sdu_size;
/* octet 8 */
uint8_t max_bitrate_up;
/* octet 9 */
uint8_t max_bitrate_down;
/* octet 10 */
uint8_t sdu_err_ratio:4;
uint8_t resid_ber:4;
/* octet 11 */
uint8_t handling_prio:2;
uint8_t xfer_delay:6;
/* octet 12 */
uint8_t guar_bitrate_up;
/* octet 13 */
uint8_t guar_bitrate_down;
/* octet 14 */
uint8_t src_stats_desc:4;
uint8_t sig_ind:1;
uint8_t spare5:3;
/* octet 15 */
uint8_t max_bitrate_down_ext;
/* octet 16 */
uint8_t guar_bitrate_down_ext;
};
int gprs_tlli_type(uint32_t tlli);
#endif /* _GSM48_GPRS_H */

View File

@@ -1,9 +1,187 @@
#ifndef _GSM_04_11_H
#define _GSM_04_11_H
#include <osmocore/protocol/gsm_04_11.h>
/* GSM TS 04.11 definitions */
#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
/* Chapter 5.2.3: SMC-CS states at the network side */
enum gsm411_cp_state {
GSM411_CPS_IDLE = 0,
GSM411_CPS_MM_CONN_PENDING = 1, /* only MT ! */
GSM411_CPS_WAIT_CP_ACK = 2,
GSM411_CPS_MM_ESTABLISHED = 3,
};
/* Chapter 6.2.2: SMR states at the network side */
enum gsm411_rp_state {
GSM411_RPS_IDLE = 0,
GSM411_RPS_WAIT_FOR_RP_ACK = 1,
GSM411_RPS_WAIT_TO_TX_RP_ACK = 3,
};
/* Chapter 8.1.2 (refers to GSM 04.07 Chapter 11.2.3.1.1 */
#define GSM411_PDISC_SMS 0x09
/* Chapter 8.1.3 */
#define GSM411_MT_CP_DATA 0x01
#define GSM411_MT_CP_ACK 0x04
#define GSM411_MT_CP_ERROR 0x10
enum gsm411_cp_ie {
GSM411_CP_IE_USER_DATA = 0x01, /* 8.1.4.1 */
GSM411_CP_IE_CAUSE = 0x02, /* 8.1.4.2. */
};
/* Section 8.1.4.2 / Table 8.2 */
enum gsm411_cp_cause {
GSM411_CP_CAUSE_NET_FAIL = 17,
GSM411_CP_CAUSE_CONGESTION = 22,
GSM411_CP_CAUSE_INV_TRANS_ID = 81,
GSM411_CP_CAUSE_SEMANT_INC_MSG = 95,
GSM411_CP_CAUSE_INV_MAND_INF = 96,
GSM411_CP_CAUSE_MSGTYPE_NOTEXIST= 97,
GSM411_CP_CAUSE_MSG_INCOMP_STATE= 98,
GSM411_CP_CAUSE_IE_NOTEXIST = 99,
GSM411_CP_CAUSE_PROTOCOL_ERR = 111,
};
/* Chapter 8.2.2 */
#define GSM411_MT_RP_DATA_MO 0x00
#define GSM411_MT_RP_DATA_MT 0x01
#define GSM411_MT_RP_ACK_MO 0x02
#define GSM411_MT_RP_ACK_MT 0x03
#define GSM411_MT_RP_ERROR_MO 0x04
#define GSM411_MT_RP_ERROR_MT 0x05
#define GSM411_MT_RP_SMMA_MO 0x06
enum gsm411_rp_ie {
GSM411_IE_RP_USER_DATA = 0x41, /* 8.2.5.3 */
GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */
};
/* Chapter 8.2.5.4 Table 8.4 */
enum gsm411_rp_cause {
/* valid only for MO */
GSM411_RP_CAUSE_MO_NUM_UNASSIGNED = 1,
GSM411_RP_CAUSE_MO_OP_DET_BARR = 8,
GSM411_RP_CAUSE_MO_CALL_BARRED = 10,
GSM411_RP_CAUSE_MO_SMS_REJECTED = 21,
GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER = 27,
GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR = 28,
GSM411_RP_CAUSE_MO_FACILITY_REJ = 29,
GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR = 30,
GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER = 38,
GSM411_RP_CAUSE_MO_TEMP_FAIL = 41,
GSM411_RP_CAUSE_MO_CONGESTION = 42,
GSM411_RP_CAUSE_MO_RES_UNAVAIL = 47,
GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR = 50,
GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL = 69,
GSM411_RP_CAUSE_MO_INTERWORKING = 127,
/* valid only for MT */
GSM411_RP_CAUSE_MT_MEM_EXCEEDED = 22,
/* valid for both directions */
GSM411_RP_CAUSE_INV_TRANS_REF = 81,
GSM411_RP_CAUSE_SEMANT_INC_MSG = 95,
GSM411_RP_CAUSE_INV_MAND_INF = 96,
GSM411_RP_CAUSE_MSGTYPE_NOTEXIST = 97,
GSM411_RP_CAUSE_MSG_INCOMP_STATE = 98,
GSM411_RP_CAUSE_IE_NOTEXIST = 99,
GSM411_RP_CAUSE_PROTOCOL_ERR = 111,
};
/* Chapter 10: Timers */
#define GSM411_TMR_TR1M 40, 0 /* 35 < x < 45 seconds */
#define GSM411_TMR_TRAM 30, 0 /* 25 < x < 35 seconds */
#define GSM411_TMR_TR2M 15, 0 /* 12 < x < 20 seconds */
#define GSM411_TMR_TC1A 30, 0
/* Chapter 8.2.1 */
struct gsm411_rp_hdr {
u_int8_t len;
u_int8_t msg_type;
u_int8_t msg_ref;
u_int8_t data[0];
} __attribute__ ((packed));
/* our own enum, not related to on-air protocol */
enum sms_alphabet {
DCS_NONE,
DCS_7BIT_DEFAULT,
DCS_UCS2,
DCS_8BIT_DATA,
};
/* GSM 03.40 / Chapter 9.2.3.1: TP-Message-Type-Indicator */
#define GSM340_SMS_DELIVER_SC2MS 0x00
#define GSM340_SMS_DELIVER_REP_MS2SC 0x00
#define GSM340_SMS_STATUS_REP_SC2MS 0x02
#define GSM340_SMS_COMMAND_MS2SC 0x02
#define GSM340_SMS_SUBMIT_MS2SC 0x01
#define GSM340_SMS_SUBMIT_REP_SC2MS 0x01
#define GSM340_SMS_RESSERVED 0x03
/* GSM 03.40 / Chapter 9.2.3.2: TP-More-Messages-to-Send */
#define GSM340_TP_MMS_MORE 0
#define GSM340_TP_MMS_NO_MORE 1
/* GSM 03.40 / Chapter 9.2.3.3: TP-Validity-Period-Format */
#define GSM340_TP_VPF_NONE 0
#define GSM340_TP_VPF_RELATIVE 2
#define GSM340_TP_VPF_ENHANCED 1
#define GSM340_TP_VPF_ABSOLUTE 3
/* GSM 03.40 / Chapter 9.2.3.4: TP-Status-Report-Indication */
#define GSM340_TP_SRI_NONE 0
#define GSM340_TP_SRI_PRESENT 1
/* GSM 03.40 / Chapter 9.2.3.5: TP-Status-Report-Request */
#define GSM340_TP_SRR_NONE 0
#define GSM340_TP_SRR_REQUESTED 1
/* GSM 03.40 / Chapter 9.2.3.9: TP-Protocol-Identifier */
/* telematic interworking (001 or 111 in bits 7-5) */
#define GSM340_TP_PID_IMPLICIT 0x00
#define GSM340_TP_PID_TELEX 0x01
#define GSM340_TP_PID_FAX_G3 0x02
#define GSM340_TP_PID_FAX_G4 0x03
#define GSM340_TP_PID_VOICE 0x04
#define GSM430_TP_PID_ERMES 0x05
#define GSM430_TP_PID_NATIONAL_PAGING 0x06
#define GSM430_TP_PID_VIDEOTEX 0x07
#define GSM430_TP_PID_TELETEX_UNSPEC 0x08
#define GSM430_TP_PID_TELETEX_PSPDN 0x09
#define GSM430_TP_PID_TELETEX_CSPDN 0x0a
#define GSM430_TP_PID_TELETEX_PSTN 0x0b
#define GSM430_TP_PID_TELETEX_ISDN 0x0c
#define GSM430_TP_PID_TELETEX_UCI 0x0d
#define GSM430_TP_PID_MSG_HANDLING 0x10
#define GSM430_TP_PID_MSG_X400 0x11
#define GSM430_TP_PID_EMAIL 0x12
#define GSM430_TP_PID_GSM_MS 0x1f
/* if bit 7 = 0 and bit 6 = 1 */
#define GSM430_TP_PID_SMS_TYPE_0 0
#define GSM430_TP_PID_SMS_TYPE_1 1
#define GSM430_TP_PID_SMS_TYPE_2 2
#define GSM430_TP_PID_SMS_TYPE_3 3
#define GSM430_TP_PID_SMS_TYPE_4 4
#define GSM430_TP_PID_SMS_TYPE_5 5
#define GSM430_TP_PID_SMS_TYPE_6 6
#define GSM430_TP_PID_SMS_TYPE_7 7
#define GSM430_TP_PID_RETURN_CALL_MSG 0x1f
#define GSM430_TP_PID_ME_DATA_DNLOAD 0x3d
#define GSM430_TP_PID_ME_DE_PERSONAL 0x3e
#define GSM430_TP_PID_ME_SIM_DNLOAD 0x3f
/* GSM 03.38 Chapter 4: SMS Data Coding Scheme */
#define GSM338_DCS_00_
#define GSM338_DCS_1110_7BIT (0 << 2)
#define GSM338_DCS_1111_7BIT (0 << 2)
#define GSM338_DCS_1111_8BIT_DATA (1 << 2)
#define GSM338_DCS_1111_CLASS0 0
#define GSM338_DCS_1111_CLASS1_ME 1
#define GSM338_DCS_1111_CLASS2_SIM 2
#define GSM338_DCS_1111_CLASS3_TE 3 /* See TS 07.05 */
/* SMS deliver PDU */
struct sms_deliver {
@@ -25,7 +203,9 @@ struct sms_deliver {
struct msgb;
int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id);
int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms);
struct gsm_sms *sms_alloc(void);
void sms_free(struct gsm_sms *sms);
@@ -33,5 +213,4 @@ void sms_free(struct gsm_sms *sms);
void _gsm411_sms_trans_free(struct gsm_trans *trans);
int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
struct gsm_sms *sms);
void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
#endif

View File

@@ -1,13 +1,132 @@
#ifndef _GSM_04_80_H
#define _GSM_04_80_H
#include <osmocore/msgb.h>
#include <osmocore/protocol/gsm_04_80.h>
/* GSM TS 04.80 definitions (Supplementary Services Specification, Formats and Coding) */
/* Section 3.4 */
#define GSM0480_MTYPE_RELEASE_COMPLETE 0x2A
#define GSM0480_MTYPE_FACILITY 0x3A
#define GSM0480_MTYPE_REGISTER 0x3B
/* Section 3.5 */
#define GSM0480_IE_FACILITY 0x1C
#define GSM0480_IE_SS_VERSION 0x7F
/* Section 3.6.2 */
#define GSM0480_CTYPE_INVOKE 0xA1
#define GSM0480_CTYPE_RETURN_RESULT 0xA2
#define GSM0480_CTYPE_RETURN_ERROR 0xA3
#define GSM0480_CTYPE_REJECT 0xA4
/* Section 3.6.3 */
#define GSM0480_COMPIDTAG_INVOKE_ID 0x02
#define GSM0480_COMPIDTAG_LINKED_ID 0x80
/* Section 3.6.4 */
#define GSM0480_OPERATION_CODE 0x02
/* Section 3.6.5 */
#define GSM_0480_SEQUENCE_TAG 0x30
#define GSM_0480_SET_TAG 0x31
/* Section 3.6.6 */
#define GSM_0480_ERROR_CODE_TAG 0x02
/* Section 3.6.7 */
/* Table 3.13 */
#define GSM_0480_PROBLEM_CODE_TAG_GENERAL 0x80
#define GSM_0480_PROBLEM_CODE_TAG_INVOKE 0x81
#define GSM_0480_PROBLEM_CODE_TAG_RETURN_RESULT 0x82
#define GSM_0480_PROBLEM_CODE_TAG_RETURN_ERROR 0x83
/* Table 3.14 */
#define GSM_0480_GEN_PROB_CODE_UNRECOGNISED 0x00
#define GSM_0480_GEN_PROB_CODE_MISTYPED 0x01
#define GSM_0480_GEN_PROB_CODE_BAD_STRUCTURE 0x02
/* Table 3.15 */
#define GSM_0480_INVOKE_PROB_CODE_DUPLICATE_INVOKE_ID 0x00
#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_OPERATION 0x01
#define GSM_0480_INVOKE_PROB_CODE_MISTYPED_PARAMETER 0x02
#define GSM_0480_INVOKE_PROB_CODE_RESOURCE_LIMITATION 0x03
#define GSM_0480_INVOKE_PROB_CODE_INITIATING_RELEASE 0x04
#define GSM_0480_INVOKE_PROB_CODE_UNRECOGNISED_LINKED_ID 0x05
#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_RESPONSE 0x06
#define GSM_0480_INVOKE_PROB_CODE_UNEXPECTED_LINKED_OPERATION 0x07
/* Table 3.16 */
#define GSM_0480_RESULT_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00
#define GSM_0480_RESULT_PROB_CODE_RETURN_RESULT_UNEXPECTED 0x01
#define GSM_0480_RESULT_PROB_CODE_MISTYPED_PARAMETER 0x02
/* Table 3.17 */
#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_INVOKE_ID 0x00
#define GSM_0480_ERROR_PROB_CODE_RETURN_ERROR_UNEXPECTED 0x01
#define GSM_0480_ERROR_PROB_CODE_UNRECOGNISED_ERROR 0x02
#define GSM_0480_ERROR_PROB_CODE_UNEXPECTED_ERROR 0x03
#define GSM_0480_ERROR_PROB_CODE_MISTYPED_PARAMETER 0x04
/* Section 4.5 */
#define GSM0480_OP_CODE_REGISTER_SS 0x0A
#define GSM0480_OP_CODE_ERASE_SS 0x0B
#define GSM0480_OP_CODE_ACTIVATE_SS 0x0C
#define GSM0480_OP_CODE_DEACTIVATE_SS 0x0D
#define GSM0480_OP_CODE_INTERROGATE_SS 0x0E
#define GSM0480_OP_CODE_NOTIFY_SS 0x10
#define GSM0480_OP_CODE_REGISTER_PASSWORD 0x11
#define GSM0480_OP_CODE_GET_PASSWORD 0x12
#define GSM0480_OP_CODE_PROCESS_USS_DATA 0x13
#define GSM0480_OP_CODE_FORWARD_CHECK_SS_IND 0x26
#define GSM0480_OP_CODE_PROCESS_USS_REQ 0x3B
#define GSM0480_OP_CODE_USS_REQUEST 0x3C
#define GSM0480_OP_CODE_USS_NOTIFY 0x3D
#define GSM0480_OP_CODE_FORWARD_CUG_INFO 0x78
#define GSM0480_OP_CODE_SPLIT_MPTY 0x79
#define GSM0480_OP_CODE_RETRIEVE_MPTY 0x7A
#define GSM0480_OP_CODE_HOLD_MPTY 0x7B
#define GSM0480_OP_CODE_BUILD_MPTY 0x7C
#define GSM0480_OP_CODE_FORWARD_CHARGE_ADVICE 0x7D
#define GSM0480_ERR_CODE_UNKNOWN_SUBSCRIBER 0x01
#define GSM0480_ERR_CODE_ILLEGAL_SUBSCRIBER 0x09
#define GSM0480_ERR_CODE_BEARER_SERVICE_NOT_PROVISIONED 0x0A
#define GSM0480_ERR_CODE_TELESERVICE_NOT_PROVISIONED 0x0B
#define GSM0480_ERR_CODE_ILLEGAL_EQUIPMENT 0x0C
#define GSM0480_ERR_CODE_CALL_BARRED 0x0D
#define GSM0480_ERR_CODE_ILLEGAL_SS_OPERATION 0x10
#define GSM0480_ERR_CODE_SS_ERROR_STATUS 0x11
#define GSM0480_ERR_CODE_SS_NOT_AVAILABLE 0x12
#define GSM0480_ERR_CODE_SS_SUBSCRIPTION_VIOLATION 0x13
#define GSM0480_ERR_CODE_SS_INCOMPATIBILITY 0x14
#define GSM0480_ERR_CODE_FACILITY_NOT_SUPPORTED 0x15
#define GSM0480_ERR_CODE_ABSENT_SUBSCRIBER 0x1B
#define GSM0480_ERR_CODE_SYSTEM_FAILURE 0x22
#define GSM0480_ERR_CODE_DATA_MISSING 0x23
#define GSM0480_ERR_CODE_UNEXPECTED_DATA_VALUE 0x24
#define GSM0480_ERR_CODE_PW_REGISTRATION_FAILURE 0x25
#define GSM0480_ERR_CODE_NEGATIVE_PW_CHECK 0x26
#define GSM0480_ERR_CODE_NUM_PW_ATTEMPTS_VIOLATION 0x2B
#define GSM0480_ERR_CODE_UNKNOWN_ALPHABET 0x47
#define GSM0480_ERR_CODE_USSD_BUSY 0x48
#define GSM0480_ERR_CODE_MAX_MPTY_PARTICIPANTS 0x7E
#define GSM0480_ERR_CODE_RESOURCES_NOT_AVAILABLE 0x7F
/* ASN.1 type-tags */
#define ASN1_BOOLEAN_TAG 0x01
#define ASN1_INTEGER_TAG 0x02
#define ASN1_BIT_STRING_TAG 0x03
#define ASN1_OCTET_STRING_TAG 0x04
#define ASN1_NULL_TYPE_TAG 0x05
#define ASN1_OBJECT_ID_TAG 0x06
#define ASN1_UTF8_STRING_TAG 0x0C
#define ASN1_PRINTABLE_STRING_TAG 0x13
#define ASN1_IA5_STRING_TAG 0x16
#define ASN1_UNICODE_STRING_TAG 0x1E
#include <openbsc/msgb.h>
#define MAX_LEN_USSD_STRING 31
struct gsm_subscriber_connection;
struct ussd_request {
char text[MAX_LEN_USSD_STRING + 1];
u_int8_t transaction_id;
@@ -16,20 +135,9 @@ struct ussd_request {
int gsm0480_decode_ussd_request(const struct msgb *msg,
struct ussd_request *request);
int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
const struct msgb *in_msg, const char* response_text,
const struct ussd_request *req);
int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
const struct msgb *msg,
const struct ussd_request *request);
struct msgb *gsm0480_create_notifySS(const char *text);
struct msgb *gsm0480_create_unstructuredSS_Notify(int alertLevel, const char *text);
int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id);
int gsm0480_wrap_facility(struct msgb *msg);
int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text);
int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn);
int gsm0480_send_ussd_response(const struct msgb *in_msg, const char* response_text,
const struct ussd_request *req);
int gsm0480_send_ussd_reject(const struct msgb *msg,
const struct ussd_request *request);
#endif

View File

@@ -3,6 +3,21 @@
#include <sys/types.h>
struct value_string {
unsigned int value;
const char *str;
};
const char *get_value_string(const struct value_string *vs, u_int32_t val);
enum gsm_band {
GSM_BAND_400,
GSM_BAND_850,
GSM_BAND_900,
GSM_BAND_1800,
GSM_BAND_1900,
};
enum gsm_phys_chan_config {
GSM_PCHAN_NONE,
GSM_PCHAN_CCCH,
@@ -23,13 +38,6 @@ enum gsm_chan_t {
GSM_LCHAN_UNKNOWN,
};
/* RRLP mode of operation */
enum rrlp_mode {
RRLP_MODE_NONE,
RRLP_MODE_MS_BASED,
RRLP_MODE_MS_PREF,
RRLP_MODE_ASS_PREF,
};
/* Channel Request reason */
enum gsm_chreq_reason_t {
@@ -40,18 +48,13 @@ enum gsm_chreq_reason_t {
GSM_CHREQ_REASON_OTHER,
};
#include <osmocore/timer.h>
#include <openbsc/timer.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/system_information.h>
#include <openbsc/mncc.h>
#include <openbsc/tlv.h>
#include <osmocore/tlv.h>
#include <osmocore/bitvec.h>
#include <osmocore/statistics.h>
#include <osmocore/gsm_utils.h>
#include <osmocore/utils.h>
#include <osmocore/rxlev_stat.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define TRX_NR_TS 8
#define TS_MAX_LCHAN 8
@@ -68,7 +71,6 @@ enum gsm_chreq_reason_t {
enum gsm_hooks {
GSM_HOOK_NM_SWLOAD,
GSM_HOOK_RR_PAGING,
GSM_HOOK_RR_SECURITY,
};
enum gsm_paging_event {
@@ -77,79 +79,54 @@ enum gsm_paging_event {
GSM_PAGING_OOM,
};
enum bts_gprs_mode {
BTS_GPRS_NONE = 0,
BTS_GPRS_GPRS = 1,
BTS_GPRS_EGPRS = 2,
};
/* the data structure stored in msgb->cb for openbsc apps */
struct openbsc_msgb_cb {
unsigned char *bssgph;
unsigned char *llch;
/* Cell Identifier */
unsigned char *bssgp_cell_id;
/* Identifiers of a BTS, equal to 'struct bssgp_bts_ctx' */
u_int16_t nsei;
u_int16_t bvci;
/* Identifier of a MS (inside BTS), equal to 'struct sgsn_mm_ctx' */
u_int32_t tlli;
} __attribute__((packed));
#define OBSC_MSGB_CB(__msgb) ((struct openbsc_msgb_cb *)&((__msgb)->cb[0]))
#define msgb_tlli(__x) OBSC_MSGB_CB(__x)->tlli
#define msgb_nsei(__x) OBSC_MSGB_CB(__x)->nsei
#define msgb_bvci(__x) OBSC_MSGB_CB(__x)->bvci
#define msgb_gmmh(__x) (__x)->l3h
#define msgb_bssgph(__x) OBSC_MSGB_CB(__x)->bssgph
#define msgb_bssgp_len(__x) ((__x)->tail - (uint8_t *)msgb_bssgph(__x))
#define msgb_bcid(__x) OBSC_MSGB_CB(__x)->bssgp_cell_id
#define msgb_llch(__x) OBSC_MSGB_CB(__x)->llch
#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
enum gsm_security_event {
GSM_SECURITY_NOAVAIL,
GSM_SECURITY_AUTH_FAILED,
GSM_SECURITY_SUCCEEDED,
};
struct msgb;
typedef int gsm_cbfn(unsigned int hooknum,
unsigned int event,
struct msgb *msg,
void *data, void *param);
/* Real authentication information containing Ki */
enum gsm_auth_algo {
AUTH_ALGO_NONE,
AUTH_ALGO_XOR,
AUTH_ALGO_COMP128v1,
/* communications link with a BTS */
struct gsm_bts_link {
struct gsm_bts *bts;
};
struct gsm_auth_info {
enum gsm_auth_algo auth_algo;
unsigned int a3a8_ki_len;
u_int8_t a3a8_ki[16];
};
struct gsm_auth_tuple {
int use_count;
int key_seq;
u_int8_t rand[16];
u_int8_t sres[4];
u_int8_t kc[8];
};
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
struct sccp_connection;
struct gsm_lchan;
struct gsm_subscriber;
struct gsm_mncc;
struct rtp_socket;
struct bsc_api;
/* 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 {
@@ -169,44 +146,9 @@ struct gsm_loc_updating_operation {
struct timer_list updating_timer;
unsigned int waiting_for_imsi : 1;
unsigned int waiting_for_imei : 1;
unsigned int key_seq : 4;
};
/*
* AUTHENTICATION/CIPHERING state
*/
struct gsm_security_operation {
struct gsm_auth_tuple atuple;
gsm_cbfn *cb;
void *cb_data;
};
/*
* A dummy to keep a connection up for at least
* a couple of seconds to work around MSC issues.
*/
struct gsm_anchor_operation {
struct timer_list timeout;
};
/* Maximum number of neighbor cells whose average we track */
#define MAX_NEIGH_MEAS 10
/* Maximum size of the averaging window for neighbor cells */
#define MAX_WIN_NEIGH_AVG 10
/* processed neighbor measurements for one cell */
struct neigh_meas_proc {
u_int16_t arfcn;
u_int8_t bsic;
u_int8_t rxlev[MAX_WIN_NEIGH_AVG];
unsigned int rxlev_cnt;
u_int8_t last_seen_nr;
};
#define MAX_A5_KEY_LEN (128/8)
#define A38_XOR_MIN_KEY_LEN 12
#define A38_XOR_MAX_KEY_LEN 16
#define A38_COMP128_KEY_LEN 16
#define RSL_ENC_ALG_A5(x) (x+1)
/* is the data link established? who established it? */
@@ -214,38 +156,6 @@ struct neigh_meas_proc {
#define LCHAN_SAPI_MS 1
#define LCHAN_SAPI_NET 2
/* state of a logical channel */
enum gsm_lchan_state {
LCHAN_S_NONE, /* channel is not active */
LCHAN_S_ACT_REQ, /* channel activatin requested */
LCHAN_S_ACTIVE, /* channel is active and operational */
LCHAN_S_REL_REQ, /* channel release has been requested */
LCHAN_S_REL_ERR, /* channel is in an error state */
LCHAN_S_INACTIVE, /* channel is set inactive */
};
/* the per subscriber data for lchan */
struct gsm_subscriber_connection {
/* To whom we are allocated at the moment */
struct gsm_subscriber *subscr;
/*
* Operations that have a state and might be pending
*/
struct gsm_loc_updating_operation *loc_operation;
struct gsm_security_operation *sec_operation;
struct gsm_anchor_operation *anch_operation;
/* Are we part of a special "silent" call */
int silent_call;
/* back pointers */
int in_release;
struct gsm_lchan *lchan;
struct gsm_lchan *ho_lchan;
struct gsm_bts *bts;
};
struct gsm_lchan {
/* The TS that we're part of */
struct gsm_bts_trx_ts *ts;
@@ -257,8 +167,6 @@ struct gsm_lchan {
enum rsl_cmod_spd rsl_cmode;
/* If TCH, traffic channel mode */
enum gsm48_chan_mode tch_mode;
/* State */
enum gsm_lchan_state state;
/* Power levels for MS and BTS */
u_int8_t bs_power;
u_int8_t ms_power;
@@ -269,42 +177,30 @@ struct gsm_lchan {
u_int8_t key[MAX_A5_KEY_LEN];
} encr;
struct timer_list T3101;
struct timer_list T3111;
struct timer_list error_timer;
/* AMR bits */
struct gsm48_multi_rate_conf mr_conf;
/* To whom we are allocated at the moment */
struct gsm_subscriber *subscr;
struct timer_list T3101;
/* Established data link layer services */
u_int8_t sapis[8];
int sach_deact;
int release_reason;
/* GSM Random Access data */
struct gsm48_req_ref *rqd_ref;
uint8_t rqd_ta;
/*
* Operations that have a state and might be pending
*/
struct gsm_loc_updating_operation *loc_operation;
/* cache of last measurement reports on this lchan */
struct gsm_meas_rep meas_rep[6];
int meas_rep_idx;
/*
* MSC handling...
*/
struct bss_sccp_connection_data *msc_data;
/* table of neighbor cell measurements */
struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS];
struct {
u_int32_t bound_ip;
u_int32_t connect_ip;
u_int16_t bound_port;
u_int16_t connect_port;
u_int16_t conn_id;
u_int8_t rtp_payload;
u_int8_t rtp_payload2;
u_int8_t speech_mode;
struct rtp_socket *rtp_socket;
} abis_ip;
struct gsm_subscriber_connection *conn;
/* use count. how many users use this channel */
unsigned int use_count;
};
struct gsm_e1_subslot {
@@ -316,7 +212,7 @@ struct gsm_e1_subslot {
u_int8_t e1_ts_ss;
};
#define TS_F_PDCH_MODE 0x1000
#define BTS_TRX_F_ACTIVATED 0x0001
/* One Timeslot in a TRX */
struct gsm_bts_trx_ts {
struct gsm_bts_trx *trx;
@@ -330,21 +226,15 @@ struct gsm_bts_trx_ts {
struct tlv_parsed nm_attr;
u_int8_t nm_chan_comb;
struct {
/* Parameters below are configured by VTY */
int enabled;
u_int8_t maio;
u_int8_t hsn;
struct bitvec arfcns;
u_int8_t arfcns_data[1024/8];
/* This is the pre-computed MA for channel assignments */
struct bitvec ma;
u_int8_t ma_len; /* part of ma_data that is used */
u_int8_t ma_data[8]; /* 10.5.2.21: max 8 bytes value part */
} hopping;
/* To which E1 subslot are we connected */
struct gsm_e1_subslot e1_link;
struct {
u_int32_t bound_ip;
u_int16_t bound_port;
u_int8_t rtp_payload2;
u_int16_t conn_id;
struct rtp_socket *rtp_socket;
} abis_ip;
struct gsm_lchan lchan[TS_MAX_LCHAN];
};
@@ -357,8 +247,6 @@ struct gsm_bts_trx {
struct gsm_bts *bts;
/* number of this TRX in the BTS */
u_int8_t nr;
/* human readable name / description */
char *description;
/* how do we talk RSL with this TRX? */
struct gsm_e1_subslot rsl_e1_link;
u_int8_t rsl_tei;
@@ -383,16 +271,12 @@ struct gsm_bts_trx {
struct gsm_nm_state nm_state;
} pa;
} bs11;
struct {
unsigned int test_state;
u_int8_t test_nr;
struct rxlev_stats rxlev_stat;
} ipaccess;
};
struct gsm_bts_trx_ts ts[TRX_NR_TS];
};
#define GSM_BTS_SI(bts, i) (void *)(bts->si_buf[i])
/* NM state */
int rf_locked;
};
enum gsm_bts_type {
GSM_BTS_TYPE_UNKNOWN,
@@ -400,26 +284,6 @@ enum gsm_bts_type {
GSM_BTS_TYPE_NANOBTS,
};
struct gsm_bts_model {
struct llist_head list;
enum gsm_bts_type type;
const char *name;
struct tlv_definition nm_att_tlvdef;
struct bitvec features;
uint8_t _features_data[128/8];
};
enum gsm_bts_features {
BTS_FEAT_HSCSD,
BTS_FEAT_GPRS,
BTS_FEAT_EGPRS,
BTS_FEAT_ECSD,
BTS_FEAT_HOPPING,
};
/**
* A pending paging request
*/
@@ -441,6 +305,7 @@ struct gsm_paging_request {
gsm_cbfn *cbfn;
void *cbfn_param;
};
#define T3113_VALUE 60, 0
/*
* This keeps track of the paging status of one BTS. It
@@ -450,6 +315,7 @@ struct gsm_paging_request {
struct gsm_bts_paging_state {
/* pending requests */
struct llist_head pending_requests;
struct gsm_paging_request *last_request;
struct gsm_bts *bts;
struct timer_list work_timer;
@@ -464,14 +330,7 @@ struct gsm_envabtse {
struct gsm_bts_gprs_nsvc {
struct gsm_bts *bts;
/* data read via VTY config file, to configure the BTS
* via OML from BSC */
int id;
u_int16_t nsvci;
u_int16_t local_port; /* on the BTS */
u_int16_t remote_port; /* on the SGSN */
u_int32_t remote_ip; /* on the SGSN */
struct gsm_nm_state nm_state;
};
@@ -483,8 +342,6 @@ struct gsm_bts {
struct gsm_network *network;
/* number of ths BTS in network */
u_int8_t nr;
/* human readable name / description */
char *description;
/* Cell Identity */
u_int16_t cell_identity;
/* location area code of this BTS */
@@ -495,11 +352,11 @@ struct gsm_bts {
u_int8_t bsic;
/* type of BTS */
enum gsm_bts_type type;
struct gsm_bts_model *model;
enum gsm_band band;
/* should the channel allocator allocate channels from high TRX to TRX0,
* rather than starting from TRX0 and go upwards? */
int chan_alloc_reverse;
int cell_barred;
/* maximum Tx power that the MS is permitted to use in this cell */
int ms_max_power;
@@ -516,6 +373,8 @@ struct gsm_bts {
/* number of this BTS on given E1 link */
u_int8_t bts_nr;
struct gsm48_control_channel_descr chan_desc;
/* paging state and control */
struct gsm_bts_paging_state paging;
@@ -526,35 +385,11 @@ struct gsm_bts {
struct gsm_nm_state nm_state;
} site_mgr;
/* parameters from which we build SYSTEM INFORMATION */
struct {
struct gsm48_rach_control rach_control;
u_int8_t ncc_permitted;
struct gsm48_cell_sel_par cell_sel_par;
struct gsm48_cell_options cell_options;
struct gsm48_control_channel_descr chan_desc;
struct bitvec neigh_list;
struct bitvec cell_alloc;
struct {
/* bitmask large enough for all possible ARFCN's */
u_int8_t neigh_list[1024/8];
u_int8_t cell_alloc[1024/8];
} data;
} si_common;
/* do we use static (user-defined) system information messages? (bitmask) */
uint32_t si_mode_static;
/* bitmask of all SI that are present/valid in si_buf */
uint32_t si_valid;
/* buffers where we put the pre-computed SI */
sysinfo_buf_t si_buf[_MAX_SYSINFO_TYPE];
/* ip.accesss Unit ID's have Site/BTS/TRX layout */
union {
struct {
u_int16_t site_id;
u_int16_t bts_id;
u_int32_t flags;
} ip_access;
struct {
struct {
@@ -569,89 +404,33 @@ struct gsm_bts {
/* Not entirely sure how ip.access specific this is */
struct {
enum bts_gprs_mode mode;
struct {
struct gsm_nm_state nm_state;
u_int16_t nsei;
uint8_t timer[7];
} nse;
struct {
struct gsm_nm_state nm_state;
u_int16_t bvci;
uint8_t timer[11];
} cell;
struct gsm_bts_gprs_nsvc nsvc[2];
u_int8_t rac;
} gprs;
/* RACH NM values */
int rach_b_thresh;
int rach_ldavg_slots;
/* transceivers */
int num_trx;
struct llist_head trx_list;
};
/* Some statistics of our network */
struct gsmnet_stats {
struct {
struct counter *total;
struct counter *no_channel;
} chreq;
struct {
struct counter *attempted;
struct counter *no_channel; /* no channel available */
struct counter *timeout; /* T3103 timeout */
struct counter *completed; /* HO COMPL received */
struct counter *failed; /* HO FAIL received */
} handover;
struct {
struct counter *attach;
struct counter *normal;
struct counter *periodic;
struct counter *detach;
} loc_upd_type;
struct {
struct counter *reject;
struct counter *accept;
} loc_upd_resp;
struct {
struct counter *attempted;
struct counter *detached;
struct counter *completed;
struct counter *expired;
} paging;
struct {
struct counter *submitted; /* MO SMS submissions */
struct counter *no_receiver;
struct counter *delivered; /* MT SMS deliveries */
struct counter *rp_err_mem;
struct counter *rp_err_other;
} sms;
struct {
struct counter *dialled; /* total number of dialled calls */
struct counter *alerted; /* we alerted the other end */
struct counter *connected;/* how many calls were accepted */
} call;
struct {
struct counter *rf_fail;
struct counter *rll_err;
} chan;
struct {
struct counter *oml_fail;
struct counter *rsl_fail;
} bts;
};
enum gsm_auth_policy {
GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */
GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */
GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */
};
#define GSM_T3101_DEFAULT 10
#define GSM_T3113_DEFAULT 60
/*
* internal data for audio management
*/
struct gsm_audio_support {
u_int8_t hr : 1,
ver : 7;
};
struct gsm_network {
/* global parameters */
@@ -660,56 +439,21 @@ struct gsm_network {
char *name_long;
char *name_short;
enum gsm_auth_policy auth_policy;
enum gsm48_reject_value reject_cause;
int a5_encryption;
int neci;
int send_mm_info;
struct {
int active;
/* Window RXLEV averaging */
unsigned int win_rxlev_avg; /* number of SACCH frames */
/* Window RXQUAL averaging */
unsigned int win_rxqual_avg; /* number of SACCH frames */
/* Window RXLEV neighbouring cells averaging */
unsigned int win_rxlev_avg_neigh; /* number of SACCH frames */
/* how often should we check for power budget HO */
unsigned int pwr_interval; /* SACCH frames */
/* how much better does a neighbor cell have to be ? */
unsigned int pwr_hysteresis; /* dBm */
/* maximum distacne before we try a handover */
unsigned int max_distance; /* TA values */
} handover;
struct gsmnet_stats stats;
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;
struct llist_head trans_list;
struct bsc_api *bsc_api;
unsigned int num_bts;
struct llist_head bts_list;
/* timer values */
int T3101;
int T3103;
int T3105;
int T3107;
int T3109;
int T3111;
int T3113;
int T3115;
int T3117;
int T3119;
int T3141;
/* Radio Resource Location Protocol (TS 04.31) */
struct {
enum rrlp_mode mode;
} rrlp;
int msc_prio;
};
#define SMS_HDR_SIZE 128
@@ -734,30 +478,20 @@ struct gsm_sms {
char text[SMS_TEXT_SIZE];
};
struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
int (*mncc_recv)(struct gsm_network *, int, void *));
struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
u_int8_t tsc, u_int8_t bsic);
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
/* Get reference to a neighbor cell on a given BCCH ARFCN */
struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
u_int16_t arfcn, u_int8_t bsic);
struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num);
const char *gsm_pchan_name(enum gsm_phys_chan_config c);
enum gsm_phys_chan_config gsm_pchan_parse(const char *name);
const char *gsm_lchant_name(enum gsm_chan_t c);
const char *gsm_lchan_name(enum gsm_chan_t c);
const char *gsm_chreq_name(enum gsm_chreq_reason_t c);
char *gsm_trx_name(struct gsm_bts_trx *trx);
char *gsm_ts_name(struct gsm_bts_trx_ts *ts);
char *gsm_lchan_name(struct gsm_lchan *lchan);
const char *gsm_lchans_name(enum gsm_lchan_state s);
enum gsm_e1_event {
EVT_E1_NONE,
@@ -769,12 +503,13 @@ void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
u_int8_t e1_ts, u_int8_t e1_ts_ss);
enum gsm_bts_type parse_btstype(const char *arg);
const char *btstype2str(enum gsm_bts_type type);
struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr);
struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
struct gsm_bts *start_bts);
char *gsm_band_name(enum gsm_band band);
enum gsm_band gsm_band_parse(const char *mhz);
extern void *tall_bsc_ctx;
extern int ipacc_rtp_direct;
static inline int is_ipaccess_bts(struct gsm_bts *bts)
{
@@ -803,23 +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);
enum rrlp_mode rrlp_mode_parse(const char *arg);
const char *rrlp_mode_name(enum rrlp_mode mode);
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg);
const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
int gsm48_ra_id_by_bts(u_int8_t *buf, struct gsm_bts *bts);
void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
int gsm_bts_has_feature(struct gsm_bts *bts, enum gsm_bts_features feat);
int gsm_bts_model_register(struct gsm_bts_model *model);
struct gsm_subscriber_connection *subscr_con_allocate(struct gsm_lchan *lchan);
void subscr_con_free(struct gsm_subscriber_connection *conn);
#endif

View File

@@ -3,11 +3,11 @@
#include <sys/types.h>
#include "gsm_data.h"
#include <osmocore/linuxlist.h>
#include "linuxlist.h"
#define GSM_IMEI_LENGTH 17
#define GSM_IMSI_LENGTH 17
#define GSM_NAME_LENGTH 160
#define GSM_NAME_LENGTH 128
#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
#define GSM_MIN_EXTEN 20000
@@ -81,13 +81,13 @@ 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_subscriber_connection *conn);
void subscr_put_channel(struct gsm_lchan *lchan);
void subscr_get_channel(struct gsm_subscriber *subscr,
int type, gsm_cbfn *cbfn, void *param);
char *subscr_name(struct gsm_subscriber *subscr);
/* internal */
struct gsm_subscriber *subscr_alloc(void);
extern struct llist_head active_subscribers;

View File

@@ -1,6 +1,8 @@
/* Generic BTS - VTY code tries to allocate this BTS before type is known */
/* (C) 2010 by Daniel Willmann <daniel@totalueberwachung.de>
/* GSM utility functions, e.g. coding and decoding */
/*
* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -20,21 +22,16 @@
*
*/
#ifndef GSM_UTILS_H
#define GSM_UTILS_H
#include <sys/types.h>
#include <openbsc/gsm_data.h>
#include <osmocore/tlv.h>
#include <openbsc/abis_nm.h>
int gsm_7bit_decode(char *decoded, const u_int8_t *user_data, u_int8_t length);
int gsm_7bit_encode(u_int8_t *result, const char *data);
static struct gsm_bts_model model_unknown = {
.type = GSM_BTS_TYPE_UNKNOWN,
.nm_att_tlvdef = {
.def = {
},
},
};
int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm);
int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl);
int bts_model_unknown_init(void)
{
return gsm_bts_model_register(&model_unknown);
}
void generate_backtrace();
#endif

View File

@@ -1,14 +0,0 @@
#ifndef _HANDOVER_H
#define _HANDOVER_H
struct gsm_subscriber_connection;
/* Hand over the specified logical channel to the specified new BTS.
* This is the main entry point for the actual handover algorithm,
* after it has decided it wants to initiate HO to a specific BTS */
int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
/* clear any operation for this connection */
void bsc_clear_handover(struct gsm_subscriber_connection *conn);
#endif /* _HANDOVER_H */

View File

@@ -2,10 +2,6 @@
#define _IPACCESS_H
#include "e1_input.h"
#include <osmocore/linuxlist.h>
#define IPA_TCP_PORT_OML 3002
#define IPA_TCP_PORT_RSL 3003
struct ipaccess_head {
u_int16_t len; /* network byte order */
@@ -48,62 +44,5 @@ int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa);
int ipaccess_rcvmsg_base(struct msgb *msg, struct bsc_fd *bfd);
struct msgb *ipaccess_read_msg(struct bsc_fd *bfd, int *error);
void ipaccess_prepend_header(struct msgb *msg, int proto);
int ipaccess_send_id_ack(int fd);
int ipaccess_send_id_req(int fd);
int ipaccess_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len);
int ipaccess_drop_oml(struct gsm_bts *bts);
int ipaccess_drop_rsl(struct gsm_bts_trx *trx);
/*
* Firmware specific header
*/
struct sdp_firmware {
char magic[4];
char more_magic[2];
u_int16_t more_more_magic;
u_int32_t header_length;
u_int32_t file_length;
char sw_part[20];
char text1[64];
char time[12];
char date[14];
char text2[10];
char version[20];
u_int16_t table_offset;
/* stuff i don't know */
} __attribute__((packed));
struct sdp_header_entry {
u_int16_t something1;
char text1[64];
char time[12];
char date[14];
char text2[10];
char version[20];
u_int32_t length;
u_int32_t addr1;
u_int32_t addr2;
u_int32_t start;
} __attribute__((packed));
struct sdp_header_item {
struct sdp_header_entry header_entry;
struct llist_head entry;
off_t absolute_offset;
};
struct sdp_header {
struct sdp_firmware firmware_info;
/* for more_magic a list of sdp_header_entry_list */
struct llist_head header_list;
/* the entry of the sdp_header */
struct llist_head entry;
};
int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned base_offset, struct llist_head *list);
#endif /* _IPACCESS_H */

View File

@@ -0,0 +1,360 @@
#ifndef _LINUX_LLIST_H
#define _LINUX_LLIST_H
#include <stddef.h>
#ifndef inline
#define inline __inline__
#endif
static inline void prefetch(const void *x) {;}
/**
* container_of - cast a member of a structure out to the containing structure
*
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized llist entries.
*/
#define LLIST_POISON1 ((void *) 0x00100100)
#define LLIST_POISON2 ((void *) 0x00200200)
/*
* Simple doubly linked llist implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole llists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct llist_head {
struct llist_head *next, *prev;
};
#define LLIST_HEAD_INIT(name) { &(name), &(name) }
#define LLIST_HEAD(name) \
struct llist_head name = LLIST_HEAD_INIT(name)
#define INIT_LLIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal llist manipulation where we know
* the prev/next entries already!
*/
static inline void __llist_add(struct llist_head *_new,
struct llist_head *prev,
struct llist_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
/**
* llist_add - add a new entry
* @new: new entry to be added
* @head: llist head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void llist_add(struct llist_head *_new, struct llist_head *head)
{
__llist_add(_new, head, head->next);
}
/**
* llist_add_tail - add a new entry
* @new: new entry to be added
* @head: llist head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head)
{
__llist_add(_new, head->prev, head);
}
/*
* Delete a llist entry by making the prev/next entries
* point to each other.
*
* This is only for internal llist manipulation where we know
* the prev/next entries already!
*/
static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* llist_del - deletes entry from llist.
* @entry: the element to delete from the llist.
* Note: llist_empty on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void llist_del(struct llist_head *entry)
{
__llist_del(entry->prev, entry->next);
entry->next = (struct llist_head *)LLIST_POISON1;
entry->prev = (struct llist_head *)LLIST_POISON2;
}
/**
* llist_del_init - deletes entry from llist and reinitialize it.
* @entry: the element to delete from the llist.
*/
static inline void llist_del_init(struct llist_head *entry)
{
__llist_del(entry->prev, entry->next);
INIT_LLIST_HEAD(entry);
}
/**
* llist_move - delete from one llist and add as another's head
* @llist: the entry to move
* @head: the head that will precede our entry
*/
static inline void llist_move(struct llist_head *llist, struct llist_head *head)
{
__llist_del(llist->prev, llist->next);
llist_add(llist, head);
}
/**
* llist_move_tail - delete from one llist and add as another's tail
* @llist: the entry to move
* @head: the head that will follow our entry
*/
static inline void llist_move_tail(struct llist_head *llist,
struct llist_head *head)
{
__llist_del(llist->prev, llist->next);
llist_add_tail(llist, head);
}
/**
* llist_empty - tests whether a llist is empty
* @head: the llist to test.
*/
static inline int llist_empty(const struct llist_head *head)
{
return head->next == head;
}
static inline void __llist_splice(struct llist_head *llist,
struct llist_head *head)
{
struct llist_head *first = llist->next;
struct llist_head *last = llist->prev;
struct llist_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* llist_splice - join two llists
* @llist: the new llist to add.
* @head: the place to add it in the first llist.
*/
static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
{
if (!llist_empty(llist))
__llist_splice(llist, head);
}
/**
* llist_splice_init - join two llists and reinitialise the emptied llist.
* @llist: the new llist to add.
* @head: the place to add it in the first llist.
*
* The llist at @llist is reinitialised
*/
static inline void llist_splice_init(struct llist_head *llist,
struct llist_head *head)
{
if (!llist_empty(llist)) {
__llist_splice(llist, head);
INIT_LLIST_HEAD(llist);
}
}
/**
* llist_entry - get the struct for this entry
* @ptr: the &struct llist_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the llist_struct within the struct.
*/
#define llist_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* llist_for_each - iterate over a llist
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*/
#define llist_for_each(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, prefetch(pos->next))
/**
* __llist_for_each - iterate over a llist
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*
* This variant differs from llist_for_each() in that it's the
* simplest possible llist iteration code, no prefetching is done.
* Use this for code that knows the llist to be very short (empty
* or 1 entry) most of the time.
*/
#define __llist_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/**
* llist_for_each_prev - iterate over a llist backwards
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*/
#define llist_for_each_prev(pos, head) \
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
pos = pos->prev, prefetch(pos->prev))
/**
* llist_for_each_safe - iterate over a llist safe against removal of llist entry
* @pos: the &struct llist_head to use as a loop counter.
* @n: another &struct llist_head to use as temporary storage
* @head: the head for your llist.
*/
#define llist_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* llist_for_each_entry - iterate over llist of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your llist.
* @member: the name of the llist_struct within the struct.
*/
#define llist_for_each_entry(pos, head, member) \
for (pos = llist_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = llist_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
/**
* llist_for_each_entry_reverse - iterate backwards over llist of given type.
* @pos: the type * to use as a loop counter.
* @head: the head for your llist.
* @member: the name of the llist_struct within the struct.
*/
#define llist_for_each_entry_reverse(pos, head, member) \
for (pos = llist_entry((head)->prev, typeof(*pos), member), \
prefetch(pos->member.prev); \
&pos->member != (head); \
pos = llist_entry(pos->member.prev, typeof(*pos), member), \
prefetch(pos->member.prev))
/**
* llist_for_each_entry_continue - iterate over llist of given type
* continuing after existing point
* @pos: the type * to use as a loop counter.
* @head: the head for your llist.
* @member: the name of the llist_struct within the struct.
*/
#define llist_for_each_entry_continue(pos, head, member) \
for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = llist_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
/**
* llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your llist.
* @member: the name of the llist_struct within the struct.
*/
#define llist_for_each_entry_safe(pos, n, head, member) \
for (pos = llist_entry((head)->next, typeof(*pos), member), \
n = llist_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = llist_entry(n->member.next, typeof(*n), member))
/**
* llist_for_each_rcu - iterate over an rcu-protected llist
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*/
#define llist_for_each_rcu(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
#define __llist_for_each_rcu(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
/**
* llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
* against removal of llist entry
* @pos: the &struct llist_head to use as a loop counter.
* @n: another &struct llist_head to use as temporary storage
* @head: the head for your llist.
*/
#define llist_for_each_safe_rcu(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
/**
* llist_for_each_entry_rcu - iterate over rcu llist of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your llist.
* @member: the name of the llist_struct within the struct.
*/
#define llist_for_each_entry_rcu(pos, head, member) \
for (pos = llist_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = llist_entry(pos->member.next, typeof(*pos), member), \
({ smp_read_barrier_depends(); 0;}), \
prefetch(pos->member.next))
/**
* llist_for_each_continue_rcu - iterate over an rcu-protected llist
* continuing after existing point.
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*/
#define llist_for_each_continue_rcu(pos, head) \
for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
#endif

View File

@@ -1,85 +0,0 @@
#ifndef _MEAS_REP_H
#define _MEAS_REP_H
#define MRC_F_PROCESSED 0x0001
/* extracted from a L3 measurement report IE */
struct gsm_meas_rep_cell {
u_int8_t rxlev;
u_int8_t bsic;
u_int8_t neigh_idx;
u_int16_t arfcn;
unsigned int flags;
};
/* RX Level and RX Quality */
struct gsm_rx_lev_qual {
u_int8_t rx_lev;
u_int8_t rx_qual;
};
/* unidirectional measumrement report */
struct gsm_meas_rep_unidir {
struct gsm_rx_lev_qual full;
struct gsm_rx_lev_qual sub;
};
#define MEAS_REP_F_UL_DTX 0x01
#define MEAS_REP_F_DL_VALID 0x02
#define MEAS_REP_F_BA1 0x04
#define MEAS_REP_F_DL_DTX 0x08
#define MEAS_REP_F_MS_TO 0x10
#define MEAS_REP_F_MS_L1 0x20
#define MEAS_REP_F_FPC 0x40
/* parsed uplink and downlink measurement result */
struct gsm_meas_rep {
/* back-pointer to the logical channel */
struct gsm_lchan *lchan;
/* number of the measurement report */
u_int8_t nr;
/* flags, see MEAS_REP_F_* */
unsigned int flags;
/* uplink and downlink rxlev, rxqual; full and sub */
struct gsm_meas_rep_unidir ul;
struct gsm_meas_rep_unidir dl;
u_int8_t bs_power;
u_int8_t ms_timing_offset;
struct {
int8_t pwr; /* MS power in dBm */
u_int8_t ta; /* MS timing advance */
} ms_l1;
/* neighbor measurement reports for up to 6 cells */
int num_cell;
struct gsm_meas_rep_cell cell[6];
};
enum meas_rep_field {
MEAS_REP_DL_RXLEV_FULL,
MEAS_REP_DL_RXLEV_SUB,
MEAS_REP_DL_RXQUAL_FULL,
MEAS_REP_DL_RXQUAL_SUB,
MEAS_REP_UL_RXLEV_FULL,
MEAS_REP_UL_RXLEV_SUB,
MEAS_REP_UL_RXQUAL_FULL,
MEAS_REP_UL_RXQUAL_SUB,
};
/* obtain an average over the last 'num' fields in the meas reps */
int get_meas_rep_avg(const struct gsm_lchan *lchan,
enum meas_rep_field field, unsigned int num);
/* Check if N out of M last values for FIELD are >= bd */
int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan,
enum meas_rep_field field,
unsigned int n, unsigned int m, int be);
unsigned int calc_initial_idx(unsigned int array_size,
unsigned int meas_rep_idx,
unsigned int num_values);
#endif /* _MEAS_REP_H */

View File

@@ -1,8 +1,8 @@
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
/*
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* (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
@@ -21,16 +21,6 @@
*
*/
#ifndef OPENBSC_MGCP_H
#define OPENBSC_MGCP_H
#include <osmocore/msgb.h>
#include <arpa/inet.h>
#define RTP_PORT_DEFAULT 4000
#define RTP_PORT_NET_DEFAULT 16000
/**
* Calculate the RTP audio port for the given multiplex
* and the direction. This allows a semi static endpoint
@@ -50,103 +40,7 @@
* network and BTS.
*
*/
static inline int rtp_calculate_port(int multiplex, int base)
int rtp_calculate_port(int multiplex, int base)
{
return base + (multiplex * 2);
}
/*
* Handling of MGCP Endpoints and the MGCP Config
*/
struct mgcp_endpoint;
struct mgcp_config;
#define MGCP_ENDP_CRCX 1
#define MGCP_ENDP_DLCX 2
#define MGCP_ENDP_MDCX 3
/*
* what to do with the msg?
* - continue as usual?
* - reject and send a failure code?
* - defer? do not send anything
*/
#define MGCP_POLICY_CONT 4
#define MGCP_POLICY_REJECT 5
#define MGCP_POLICY_DEFER 6
typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state);
typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
typedef int (*mgcp_reset)(struct mgcp_config *cfg);
#define PORT_ALLOC_STATIC 0
#define PORT_ALLOC_DYNAMIC 1
/**
* This holds information on how to allocate ports
*/
struct mgcp_port_range {
int mode;
/* pre-allocated from a base? */
int base_port;
/* dynamically allocated */
int range_start;
int range_end;
int last_port;
};
struct mgcp_config {
int source_port;
char *local_ip;
char *source_addr;
unsigned int number_endpoints;
char *bts_ip;
char *call_agent_addr;
struct in_addr bts_in;
char *audio_name;
int audio_payload;
int audio_loop;
struct mgcp_port_range bts_ports;
struct mgcp_port_range net_ports;
int endp_dscp;
/* spec handling */
int force_realloc;
mgcp_change change_cb;
mgcp_policy policy_cb;
mgcp_reset reset_cb;
void *data;
struct mgcp_endpoint *endpoints;
unsigned int last_call_id;
};
/* config management */
struct mgcp_config *mgcp_config_alloc(void);
int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg);
int mgcp_vty_init(void);
int mgcp_endpoints_allocate(struct mgcp_config *cfg);
void mgcp_free_endp(struct mgcp_endpoint *endp);
/*
* format helper functions
*/
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg);
struct msgb *mgcp_create_response_with_data(int code, const char *msg, const char *trans, const char *data);
/* adc helper */
static inline int mgcp_timeslot_to_endpoint(int multiplex, int timeslot)
{
if (timeslot == 0)
timeslot = 1;
return timeslot + (31 * multiplex);
}
#endif

View File

@@ -1,109 +0,0 @@
/* MGCP Private Data */
/*
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef OPENBSC_MGCP_DATA_H
#define OPENBSC_MGCP_DATA_H
#include <osmocore/select.h>
#define CI_UNUSED 0
enum mgcp_connection_mode {
MGCP_CONN_NONE = 0,
MGCP_CONN_RECV_ONLY = 1,
MGCP_CONN_SEND_ONLY = 2,
MGCP_CONN_RECV_SEND = MGCP_CONN_RECV_ONLY | MGCP_CONN_SEND_ONLY,
MGCP_CONN_LOOPBACK = 4,
};
struct mgcp_rtp_state {
int initialized;
int patch;
uint32_t orig_ssrc;
uint32_t ssrc;
uint16_t seq_no;
int lost_no;
int seq_offset;
uint32_t last_timestamp;
int32_t timestamp_offset;
};
struct mgcp_rtp_end {
/* statistics */
unsigned int packets;
struct in_addr addr;
/* in network byte order */
int rtp_port, rtcp_port;
int payload_type;
/*
* Each end has a socket...
*/
struct bsc_fd rtp;
struct bsc_fd rtcp;
int local_port;
int local_alloc;
};
struct mgcp_endpoint {
int ci;
char *callid;
char *local_options;
int conn_mode;
int orig_mode;
/* backpointer */
struct mgcp_config *cfg;
/* port status for bts/net */
struct mgcp_rtp_end bts_end;
struct mgcp_rtp_end net_end;
/* sequence bits */
struct mgcp_rtp_state net_state;
struct mgcp_rtp_state bts_state;
/* SSRC/seq/ts patching for loop */
int allow_patch;
};
#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
struct mgcp_msg_ptr {
unsigned int start;
unsigned int length;
};
int mgcp_analyze_header(struct mgcp_config *cfg, struct msgb *msg,
struct mgcp_msg_ptr *ptr, int size,
const char **transaction_id, struct mgcp_endpoint **endp);
int mgcp_send_dummy(struct mgcp_endpoint *endp);
int mgcp_bind_bts_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port);
int mgcp_free_rtp_port(struct mgcp_rtp_end *end);
#endif

View File

@@ -25,8 +25,7 @@
#ifndef _MNCC_H
#define _MNCC_H
#include <osmocore/linuxlist.h>
#include <osmocore/mncc.h>
#include <openbsc/linuxlist.h>
/* One end of a call */
struct gsm_call {
@@ -88,8 +87,7 @@ struct gsm_call {
#define MNCC_FRAME_DROP 0x0202
#define MNCC_LCHAN_MODIFY 0x0203
#define GSM_TCHF_FRAME 0x0300
#define GSM_TCHF_FRAME_EFR 0x0301
#define GSM_TRAU_FRAME 0x0300
#define GSM_MAX_FACILITY 128
#define GSM_MAX_SSVERSION 128
@@ -110,6 +108,61 @@ struct gsm_call {
#define MNCC_F_KEYPAD 0x1000
#define MNCC_F_SIGNAL 0x2000
/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
struct gsm_mncc_bearer_cap {
int transfer; /* Information Transfer Capability */
int mode; /* Transfer Mode */
int coding; /* Coding Standard */
int radio; /* Radio Channel Requirement */
int speech_ctm; /* CTM text telephony indication */
int speech_ver[8]; /* Speech version indication */
};
struct gsm_mncc_number {
int type;
int plan;
int present;
int screen;
char number[33];
};
struct gsm_mncc_cause {
int location;
int coding;
int rec;
int rec_val;
int value;
int diag_len;
char diag[32];
};
struct gsm_mncc_useruser {
int proto;
char info[GSM_MAX_USERUSER + 1]; /* + termination char */
};
struct gsm_mncc_progress {
int coding;
int location;
int descr;
};
struct gsm_mncc_facility {
int len;
char info[GSM_MAX_FACILITY];
};
struct gsm_mncc_ssversion {
int len;
char info[GSM_MAX_SSVERSION];
};
struct gsm_mncc_cccap {
int dtmf;
int pcp;
};
struct gsm_mncc {
/* context based information */
u_int32_t msg_type;
@@ -146,7 +199,7 @@ struct gsm_mncc {
unsigned char lchan_mode;
};
struct gsm_data_frame {
struct gsm_trau_frame {
u_int32_t msg_type;
u_int32_t callref;
unsigned char data[0];

View File

@@ -0,0 +1,115 @@
#ifndef _MSGB_H
#define _MSGB_H
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/linuxlist.h>
struct bts_link;
struct msgb {
struct llist_head list;
/* ptr to the physical E1 link to the BTS(s) */
struct gsm_bts_link *bts_link;
/* Part of which TRX logical channel we were received / transmitted */
struct gsm_bts_trx *trx;
struct gsm_lchan *lchan;
unsigned char *l2h;
unsigned char *l3h;
unsigned char *smsh;
unsigned char *l4h;
u_int16_t data_len;
u_int16_t len;
unsigned char *head;
unsigned char *tail;
unsigned char *data;
unsigned char _data[0];
};
extern struct msgb *msgb_alloc(u_int16_t size, const char *name);
extern void msgb_free(struct msgb *m);
extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
extern struct msgb *msgb_dequeue(struct llist_head *queue);
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)
{
return msgb->tail - (u_int8_t *)msgb_l2(msgb);
}
static inline unsigned int msgb_l3len(const struct msgb *msgb)
{
return msgb->tail - (u_int8_t *)msgb_l3(msgb);
}
static inline unsigned int msgb_headlen(const struct msgb *msgb)
{
return msgb->len - msgb->data_len;
}
static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
{
unsigned char *tmp = msgb->tail;
msgb->tail += len;
msgb->len += len;
return tmp;
}
static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
{
msgb->data -= len;
msgb->len += len;
return msgb->data;
}
static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len)
{
msgb->len -= len;
return msgb->data += len;
}
static inline int msgb_tailroom(const struct msgb *msgb)
{
return (msgb->data + msgb->data_len) - msgb->tail;
}
/* increase the headroom of an empty msgb, reducing the tailroom */
static inline void msgb_reserve(struct msgb *msg, int len)
{
msg->data += len;
msg->tail += len;
}
static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
const char *name)
{
struct msgb *msg = msgb_alloc(size, name);
if (msg)
msgb_reserve(msg, headroom);
return msg;
}
#endif /* _MSGB_H */

View File

@@ -1,16 +0,0 @@
#ifndef _OPENBSC_NWL_H
#define _OPENBSC_NWL_H
#include <stdint.h>
#include <openbsc/gsm_data.h>
void ipac_nwl_init(void);
/* Start a NWL test. It will raise the S_IPAC_TEST_COMPLETE signal. */
int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr,
const uint8_t *phys_conf, unsigned int phys_conf_len);
int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev,
uint16_t max_num_arfcns);
#endif /* _OPENBSC_NWL_H */

View File

@@ -1,10 +0,0 @@
/* OpenBSC BSC code */
#ifndef OSMO_BSC_H
#define OSMO_BSC_H
#include "bsc_api.h"
struct bsc_api *osmo_bsc_api();
#endif

View File

@@ -1,20 +0,0 @@
#ifndef OSMO_BSC_RF
#define OSMO_BSC_RF
#include <osmocore/write_queue.h>
struct gsm_network;
struct osmo_bsc_rf {
struct bsc_fd listen;
struct gsm_network *gsm_network;
};
struct osmo_bsc_rf_conn {
struct write_queue queue;
struct gsm_network *gsm_network;
};
struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net);
#endif

View File

@@ -1,11 +0,0 @@
/* Routines for the MSC handling */
#ifndef OSMO_MSC_H
#define OSMO_MSC_H
#include "bsc_api.h"
struct bsc_api *msc_bsc_api();
void msc_release_connection(struct gsm_subscriber_connection *conn);
#endif

View File

@@ -24,10 +24,10 @@
#include <stdlib.h>
#include <string.h>
#include <osmocore/linuxlist.h>
#include "linuxlist.h"
#include "gsm_data.h"
#include "gsm_subscriber.h"
#include <osmocore/timer.h>
#include "timer.h"
/* call once for every gsm_bts... */
void paging_init(struct gsm_bts *bts);
@@ -38,7 +38,7 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr,
/* stop paging requests */
void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr,
struct gsm_subscriber_connection *conn);
struct gsm_lchan *lchan);
/* update paging load */
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t);

View File

@@ -1,133 +0,0 @@
#ifndef _REST_OCTETS_H
#define _REST_OCTETS_H
#include <sys/types.h>
#include <openbsc/gsm_04_08.h>
/* generate SI1 rest octets */
int rest_octets_si1(u_int8_t *data, u_int8_t *nch_pos);
struct gsm48_si_selection_params {
u_int16_t penalty_time:5,
temp_offs:3,
cell_resel_off:6,
cbq:1,
present:1;
};
struct gsm48_si_power_offset {
u_int8_t power_offset:2,
present:1;
};
struct gsm48_si3_gprs_ind {
u_int8_t si13_position:1,
ra_colour:3,
present:1;
};
struct gsm48_lsa_params {
u_int32_t prio_thr:3,
lsa_offset:3,
mcc:12,
mnc:12;
unsigned int present;
};
struct gsm48_si_ro_info {
struct gsm48_si_selection_params selection_params;
struct gsm48_si_power_offset power_offset;
u_int8_t si2ter_indicator;
u_int8_t early_cm_ctrl;
struct {
u_int8_t where:3,
present:1;
} scheduling;
struct gsm48_si3_gprs_ind gprs_ind;
/* SI 4 specific */
struct gsm48_lsa_params lsa_params;
u_int16_t cell_id;
u_int8_t break_ind; /* do we have SI7 + SI8 ? */
};
/* Generate SI3 Rest Octests (Chapter 10.5.2.34 / Table 10.4.72) */
int rest_octets_si3(u_int8_t *data, const struct gsm48_si_ro_info *si3);
/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
int rest_octets_si4(u_int8_t *data, const struct gsm48_si_ro_info *si4);
enum pbcch_carrier_type {
PBCCH_BCCH,
PBCCH_ARFCN,
PBCCH_MAIO
};
/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */
enum gprs_nmo {
GPRS_NMO_I = 0, /* CS pagin on GPRS paging or traffic channel */
GPRS_NMO_II = 1, /* all paging on CCCH */
GPRS_NMO_III = 2, /* no paging coordination */
};
/* TS 04.60 12.24 */
struct gprs_cell_options {
enum gprs_nmo nmo;
/* T3168: wait for packet uplink assignment message */
u_int32_t t3168; /* in milliseconds */
/* T3192: wait for release of the TBF after reception of the final block */
u_int32_t t3192; /* in milliseconds */
u_int32_t drx_timer_max;/* in seconds */
u_int32_t bs_cv_max;
u_int8_t ext_info_present;
struct {
u_int8_t egprs_supported;
u_int8_t use_egprs_p_ch_req;
u_int8_t bep_period;
u_int8_t pfc_supported;
u_int8_t dtm_supported;
u_int8_t bss_paging_coordination;
} ext_info;
};
/* TS 04.60 Table 12.9.2 */
struct gprs_power_ctrl_pars {
u_int8_t alpha;
u_int8_t t_avg_w;
u_int8_t t_avg_t;
u_int8_t pc_meas_chan;
u_int8_t n_avg_i;
};
struct gsm48_si13_info {
struct gprs_cell_options cell_opts;
struct gprs_power_ctrl_pars pwr_ctrl_pars;
u_int8_t bcch_change_mark;
u_int8_t si_change_field;
u_int8_t pbcch_present;
union {
struct {
u_int8_t rac;
u_int8_t spgc_ccch_sup;
u_int8_t net_ctrl_ord;
u_int8_t prio_acc_thr;
} no_pbcch;
struct {
u_int8_t psi1_rep_per;
u_int8_t pb;
u_int8_t tsc;
u_int8_t tn;
enum pbcch_carrier_type carrier_type;
u_int16_t arfcn;
u_int8_t maio;
} pbcch;
};
};
/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13);
#endif /* _REST_OCTETS_H */

View File

@@ -25,14 +25,8 @@
#include <netinet/in.h>
#include <osmocore/linuxlist.h>
#include <osmocore/select.h>
#define RTP_PT_GSM_FULL 3
#define RTP_PT_GSM_HALF 96
#define RTP_PT_GSM_EFR 97
#define RTP_PT_AMR_FULL 98
#define RTP_PT_AMR_HALF 99
#include <openbsc/linuxlist.h>
#include <openbsc/select.h>
enum rtp_rx_action {
RTP_NONE,
@@ -40,11 +34,6 @@ enum rtp_rx_action {
RTP_RECV_UPSTREAM,
};
enum rtp_tx_action {
RTP_SEND_NONE,
RTP_SEND_DOWNSTREAM,
};
struct rtp_sub_socket {
struct sockaddr_in sin_local;
struct sockaddr_in sin_remote;
@@ -67,25 +56,15 @@ struct rtp_socket {
struct rtp_socket *other_sock;
} proxy;
struct {
struct gsm_network *net;
u_int32_t callref;
void (*recv_cb)(struct msgb *msg);
} receive;
};
enum rtp_tx_action tx_action;
struct {
u_int16_t sequence;
u_int32_t timestamp;
u_int32_t ssrc;
struct timeval last_tv;
} transmit;
};
struct rtp_socket *rtp_socket_create(void);
int rtp_socket_bind(struct rtp_socket *rs, u_int32_t ip);
int rtp_socket_connect(struct rtp_socket *rs, u_int32_t ip, u_int16_t port);
int rtp_socket_proxy(struct rtp_socket *this, struct rtp_socket *other);
int rtp_socket_upstream(struct rtp_socket *this, struct gsm_network *net, u_int32_t callref);
int rtp_socket_free(struct rtp_socket *rs);
int rtp_send_frame(struct rtp_socket *rs, struct gsm_data_frame *frame);
#endif /* _RTP_PROXY_H */

View File

@@ -0,0 +1,22 @@
#ifndef _BSC_SELECT_H
#define _BSC_SELECT_H
#include <openbsc/linuxlist.h>
#define BSC_FD_READ 0x0001
#define BSC_FD_WRITE 0x0002
#define BSC_FD_EXCEPT 0x0004
struct bsc_fd {
struct llist_head list;
int fd;
unsigned int when;
int (*cb)(struct bsc_fd *fd, unsigned int what);
void *data;
unsigned int priv_nr;
};
int bsc_register_fd(struct bsc_fd *fd);
void bsc_unregister_fd(struct bsc_fd *fd);
int bsc_select_main(int polling);
#endif /* _BSC_SELECT_H */

View File

@@ -1,65 +0,0 @@
#ifndef _SGSN_H
#define _SGSN_H
#include <sys/types.h>
#include <osmocore/msgb.h>
#include <openbsc/gprs_ns.h>
#include <openbsc/gprs_sgsn.h>
struct sgsn_config {
/* parsed from config file */
char *gtp_statedir;
struct sockaddr_in gtp_listenaddr;
/* misc */
struct gprs_ns_inst *nsi;
};
struct sgsn_instance {
char *config_file;
struct sgsn_config cfg;
/* File descriptor wrappers for LibGTP */
struct bsc_fd gtp_fd0;
struct bsc_fd gtp_fd1c;
struct bsc_fd gtp_fd1u;
/* Timer for libGTP */
struct timer_list gtp_timer;
/* GSN instance for libgtp */
struct gsn_t *gsn;
};
extern struct sgsn_instance *sgsn;
/* sgsn_vty.c */
int sgsn_vty_init(void);
int sgsn_parse_config(const char *config_file, struct sgsn_config *cfg);
/* sgsn.c */
/* Main input function for Gb proxy */
int sgsn_rcvmsg(struct msgb *msg, struct gprs_nsvc *nsvc, uint16_t ns_bvci);
struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn,
struct sgsn_mm_ctx *mmctx,
uint16_t nsapi,
struct tlv_parsed *tp);
int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx);
/* gprs_sndcp.c */
/* Entry point for the SNSM-ACTIVATE.indication */
int sndcp_sm_activate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Entry point for the SNSM-DEACTIVATE.indication */
int sndcp_sm_deactivate_ind(struct gprs_llc_lle *lle, uint8_t nsapi);
/* Called by SNDCP when it has received/re-assembled a N-PDU */
int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
struct msgb *msg, uint32_t npdu_len, uint8_t *npdu);
int sndcp_unitdata_req(struct msgb *msg, struct gprs_llc_lle *lle, uint8_t nsapi,
void *mmcontext);
#endif

View File

@@ -1,5 +1,5 @@
/* Generic signalling/notification infrastructure */
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
@@ -26,8 +26,8 @@
#include <errno.h>
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
#include <osmocore/signal.h>
/*
* Signalling subsystems
@@ -40,17 +40,11 @@ enum signal_subsystems {
SS_LCHAN,
SS_SUBSCR,
SS_SCALL,
SS_GLOBAL,
SS_CHALLOC,
SS_NS,
SS_IPAC_NWL,
SS_RF,
};
/* SS_PAGING signals */
enum signal_paging {
S_PAGING_SUCCEEDED,
S_PAGING_EXPIRED,
S_PAGING_COMPLETED,
};
/* SS_SMS signals */
@@ -64,7 +58,6 @@ enum signal_sms {
/* SS_ABISIP signals */
enum signal_abisip {
S_ABISIP_CRCX_ACK,
S_ABISIP_MDCX_ACK,
S_ABISIP_DLCX_IND,
};
@@ -74,9 +67,6 @@ enum signal_nm {
S_NM_FAIL_REP, /* GSM 12.21 failure event report */
S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */
S_NM_IPACC_NACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */
S_NM_IPACC_ACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_ACK happened */
S_NM_IPACC_RESTART_ACK, /* nanoBTS has send a restart ack */
S_NM_IPACC_RESTART_NACK,/* nanoBTS has send a restart ack */
S_NM_TEST_REP, /* GSM 12.21 Test Report */
};
@@ -88,25 +78,12 @@ enum signal_lchan {
* signal handler.
*/
S_LCHAN_UNEXPECTED_RELEASE,
S_LCHAN_ACTIVATE_ACK, /* 08.58 Channel Activate ACK */
S_LCHAN_ACTIVATE_NACK, /* 08.58 Channel Activate NACK */
S_LCHAN_HANDOVER_COMPL, /* 04.08 Handover Completed */
S_LCHAN_HANDOVER_FAIL, /* 04.08 Handover Failed */
S_LCHAN_HANDOVER_DETECT, /* 08.58 Handover Detect */
S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */
};
/* SS_CHALLOC signals */
enum signal_challoc {
S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */
S_CHALLOC_FREED, /* lchan has been successfully freed */
};
/* SS_SUBSCR signals */
enum signal_subscr {
S_SUBSCR_ATTACHED,
S_SUBSCR_DETACHED,
S_SUBSCR_IDENTITY, /* we've received some identity information */
};
/* SS_SCALL signals */
@@ -116,68 +93,29 @@ enum signal_scall {
S_SCALL_DETACHED,
};
/* SS_IPAC_NWL signals */
enum signal_ipaccess {
S_IPAC_NWL_COMPLETE,
};
enum signal_global {
S_GLOBAL_SHUTDOWN,
};
/* SS_RF signals */
enum signal_rf {
S_RF_OFF,
S_RF_ON,
S_RF_GRACE,
};
struct gsm_subscriber;
typedef int signal_cbfn(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data);
struct paging_signal_data {
struct gsm_subscriber *subscr;
struct gsm_bts *bts;
/* NULL in case the paging didn't work */
struct gsm_subscriber_connection *conn;
struct gsm_lchan *lchan;
};
struct scall_signal_data {
struct gsm_subscriber *subscr;
struct gsm_subscriber_connection *conn;
struct gsm_lchan *lchan;
void *data;
};
struct ipacc_ack_signal_data {
struct gsm_bts_trx *trx;
u_int8_t msg_type;
};
/* Management */
int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data);
struct nm_nack_signal_data {
struct msgb *msg;
uint8_t mt;
};
/* Dispatch */
void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data);
struct challoc_signal_data {
struct gsm_bts *bts;
struct gsm_lchan *lchan;
enum gsm_chan_t type;
};
struct rf_signal_data {
struct gsm_network *net;
};
enum signal_ns {
S_NS_RESET,
S_NS_BLOCK,
S_NS_UNBLOCK,
S_NS_ALIVE_EXP, /* Tns-alive expired more than N times */
};
struct ns_signal_data {
struct gprs_nsvc *nsvc;
uint8_t cause;
};
#endif

View File

@@ -1,12 +1,7 @@
#ifndef _SILENT_CALL_H
#define _SILENT_CALL_H
struct gsm_subscriber_connection;
extern int gsm_silent_call_start(struct gsm_subscriber *subscr,
void *data, int type);
extern int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data);
extern int gsm_silent_call_stop(struct gsm_subscriber *subscr);
extern int silent_call_rx(struct gsm_subscriber_connection *conn, struct msgb *msg);
extern int silent_call_reroute(struct gsm_subscriber_connection *conn, struct msgb *msg);
#endif /* _SILENT_CALL_H */

View File

@@ -1,14 +0,0 @@
#ifndef _BSC_SOCKET_H
#define _BSC_SOCKET_H
#include <sys/types.h>
#include <osmocore/select.h>
#ifndef IPPROTO_GRE
#define IPPROTO_GRE 47
#endif
int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
int (*cb)(struct bsc_fd *fd, unsigned int what));
#endif /* _BSC_SOCKET_H */

View File

@@ -22,7 +22,7 @@
*/
#include <sys/types.h>
#include <osmocore/linuxlist.h>
#include <openbsc/linuxlist.h>
#define NR_SUBCH 4
#define TRAU_FRAME_SIZE 40

View File

@@ -1,42 +0,0 @@
#ifndef _SYSTEM_INFO_H
#define _SYSTEM_INFO_H
#include <osmocore/utils.h>
#define GSM_MACBLOCK_LEN 23
enum osmo_sysinfo_type {
SYSINFO_TYPE_NONE,
SYSINFO_TYPE_1,
SYSINFO_TYPE_2,
SYSINFO_TYPE_3,
SYSINFO_TYPE_4,
SYSINFO_TYPE_5,
SYSINFO_TYPE_6,
SYSINFO_TYPE_7,
SYSINFO_TYPE_8,
SYSINFO_TYPE_9,
SYSINFO_TYPE_10,
SYSINFO_TYPE_13,
SYSINFO_TYPE_16,
SYSINFO_TYPE_17,
SYSINFO_TYPE_18,
SYSINFO_TYPE_19,
SYSINFO_TYPE_20,
SYSINFO_TYPE_2bis,
SYSINFO_TYPE_2ter,
SYSINFO_TYPE_2quater,
SYSINFO_TYPE_5bis,
SYSINFO_TYPE_5ter,
/* FIXME all the various bis and ter */
_MAX_SYSINFO_TYPE
};
typedef u_int8_t sysinfo_buf_t[GSM_MACBLOCK_LEN];
const struct value_string osmo_sitype_strs[_MAX_SYSINFO_TYPE];
uint8_t gsm_sitype2rsl(enum osmo_sysinfo_type si_type);
const char *gsm_sitype_name(enum osmo_sysinfo_type si_type);
int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
#endif

View File

@@ -0,0 +1,192 @@
#ifndef _TALLOC_H_
#define _TALLOC_H_
/*
Unix SMB/CIFS implementation.
Samba temporary memory allocation functions
Copyright (C) Andrew Tridgell 2004-2005
Copyright (C) Stefan Metzmacher 2006
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
** under the LGPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#define HAVE_VA_COPY
/* this is only needed for compatibility with the old talloc */
typedef void TALLOC_CTX;
/*
this uses a little trick to allow __LINE__ to be stringified
*/
#ifndef __location__
#define __TALLOC_STRING_LINE1__(s) #s
#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s)
#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__)
#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__
#endif
#ifndef TALLOC_DEPRECATED
#define TALLOC_DEPRECATED 0
#endif
#ifndef PRINTF_ATTRIBUTE
#if (__GNUC__ >= 3)
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
* argument. Note that some gcc 2.x versions don't handle this
* properly **/
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
#endif
#endif
/* try to make talloc_set_destructor() and talloc_steal() type safe,
if we have a recent gcc */
#if (__GNUC__ >= 3)
#define _TALLOC_TYPEOF(ptr) __typeof__(ptr)
#define talloc_set_destructor(ptr, function) \
do { \
int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \
_talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \
} while(0)
/* this extremely strange macro is to avoid some braindamaged warning
stupidity in gcc 4.1.x */
#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; })
#else
#define talloc_set_destructor(ptr, function) \
_talloc_set_destructor((ptr), (int (*)(void *))(function))
#define _TALLOC_TYPEOF(ptr) void *
#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr))
#endif
#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr))
#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr))
/* useful macros for creating type checked pointers */
#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type)
#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__)
#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr)))
#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__)
#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type)
#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__)
#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type)
#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type)
#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__)
#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count)
#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx))
#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type)
#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__)
#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__)
#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__)
#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
#if TALLOC_DEPRECATED
#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
#define talloc_p(ctx, type) talloc(ctx, type)
#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count)
#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count)
#define talloc_destroy(ctx) talloc_free(ctx)
#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a))
#endif
#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
/* The following definitions come from talloc.c */
void *_talloc(const void *context, size_t size);
void *talloc_pool(const void *context, size_t size);
void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *));
int talloc_increase_ref_count(const void *ptr);
size_t talloc_reference_count(const void *ptr);
void *_talloc_reference(const void *context, const void *ptr);
int talloc_unlink(const void *context, void *ptr);
const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
void talloc_set_name_const(const void *ptr, const char *name);
void *talloc_named(const void *context, size_t size,
const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
void *talloc_named_const(const void *context, size_t size, const char *name);
const char *talloc_get_name(const void *ptr);
void *talloc_check_name(const void *ptr, const char *name);
void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location);
void *talloc_parent(const void *ptr);
const char *talloc_parent_name(const void *ptr);
void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2);
int talloc_free(void *ptr);
void talloc_free_children(void *ptr);
void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name);
void *_talloc_steal(const void *new_ctx, const void *ptr);
void *_talloc_move(const void *new_ctx, const void *pptr);
size_t talloc_total_size(const void *ptr);
size_t talloc_total_blocks(const void *ptr);
void talloc_report_depth_cb(const void *ptr, int depth, int max_depth,
void (*callback)(const void *ptr,
int depth, int max_depth,
int is_ref,
void *private_data),
void *private_data);
void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f);
void talloc_report_full(const void *ptr, FILE *f);
void talloc_report(const void *ptr, FILE *f);
void talloc_enable_null_tracking(void);
void talloc_disable_null_tracking(void);
void talloc_enable_leak_report(void);
void talloc_enable_leak_report_full(void);
void *_talloc_zero(const void *ctx, size_t size, const char *name);
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name);
void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name);
void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
void *talloc_autofree_context(void);
size_t talloc_get_size(const void *ctx);
void *talloc_find_parent_byname(const void *ctx, const char *name);
void talloc_show_parents(const void *context, FILE *file);
int talloc_is_parent(const void *context, const void *ptr);
char *talloc_strdup(const void *t, const char *p);
char *talloc_strdup_append(char *s, const char *a);
char *talloc_strdup_append_buffer(char *s, const char *a);
char *talloc_strndup(const void *t, const char *p, size_t n);
char *talloc_strndup_append(char *s, const char *a, size_t n);
char *talloc_strndup_append_buffer(char *s, const char *a, size_t n);
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
void talloc_set_abort_fn(void (*abort_fn)(const char *reason));
#endif

View File

@@ -1,5 +1,5 @@
/* Hold the copyright and version string */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
/* minimalistic telnet/network interface it might turn into a wire interface */
/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -18,14 +18,28 @@
*
*/
#include "bscconfig.h"
#ifndef TELNET_INTERFACE_H
#define TELNET_INTERFACE_H
const char *openbsc_copyright =
"Copyright (C) 2008-2010 Harald Welte, Holger Freyther\n"
"Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\n"
"Dieter Spaar, Andreas Eversberg\n\n"
"License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n";
#include "gsm_data.h"
#include "linuxlist.h"
#include "select.h"
#include <vty/vty.h>
#define TELNET_COMMAND_48 1
#define TELNET_COMMAND_11 2
struct telnet_connection {
struct llist_head entry;
struct gsm_network *network;
struct bsc_fd fd;
struct vty *vty;
};
void telnet_init(struct gsm_network *network, int port);
int bsc_vty_init(struct gsm_network *net);
#endif

View File

@@ -0,0 +1,72 @@
/*
* (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef TIMER_H
#define TIMER_H
#include <sys/time.h>
#include "linuxlist.h"
/**
* Timer management:
* - Create a struct timer_list
* - Fill out timeout and use add_timer or
* use schedule_timer to schedule a timer in
* x seconds and microseconds from now...
* - Use del_timer to remove the timer
*
* Internally:
* - We hook into select.c to give a timeval of the
* nearest timer. On already passed timers we give
* it a 0 to immediately fire after the select
* - update_timers will call the callbacks and remove
* the timers.
*
*/
struct timer_list {
struct llist_head entry;
struct timeval timeout;
unsigned int active : 1;
unsigned int handled : 1;
unsigned int in_list : 1;
void (*cb)(void*);
void *data;
};
/**
* timer management
*/
void bsc_add_timer(struct timer_list *timer);
void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds);
void bsc_del_timer(struct timer_list *timer);
int bsc_timer_pending(struct timer_list *timer);
/**
* internal timer list management
*/
struct timeval *bsc_nearest_timer();
void bsc_prepare_timers();
int bsc_update_timers();
int bsc_timer_check(void);
#endif

View File

@@ -0,0 +1,220 @@
#ifndef _TLV_H
#define _TLV_H
#include <sys/types.h>
#include <string.h>
#include <openbsc/msgb.h>
/* Terminology / wording
tag length value (in bits)
V - - 8
LV - 8 N * 8
TLV 8 8 N * 8
TL16V 8 16 N * 8
TLV16 8 8 N * 16
TvLV 8 8/16 N * 8
*/
#define LV_GROSS_LEN(x) (x+1)
#define TLV_GROSS_LEN(x) (x+2)
#define TLV16_GROSS_LEN(x) ((2*x)+2)
#define TL16V_GROSS_LEN(x) (x+3)
#define TVLV_MAX_ONEBYTE 0x7f
static inline u_int16_t TVLV_GROSS_LEN(u_int16_t len)
{
if (len <= TVLV_MAX_ONEBYTE)
return TLV_GROSS_LEN(len);
else
return TL16V_GROSS_LEN(len);
}
/* TLV generation */
static inline u_int8_t *lv_put(u_int8_t *buf, u_int8_t len,
const u_int8_t *val)
{
*buf++ = len;
memcpy(buf, val, len);
return buf + len;
}
static inline u_int8_t *tlv_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
const u_int8_t *val)
{
*buf++ = tag;
*buf++ = len;
memcpy(buf, val, len);
return buf + len;
}
static inline u_int8_t *tlv16_put(u_int8_t *buf, u_int8_t tag, u_int8_t len,
const u_int16_t *val)
{
*buf++ = tag;
*buf++ = len;
memcpy(buf, val, len*2);
return buf + len*2;
}
static inline u_int8_t *tl16v_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
const u_int8_t *val)
{
*buf++ = tag;
*buf++ = len >> 8;
*buf++ = len & 0xff;
memcpy(buf, val, len);
return buf + len*2;
}
static inline u_int8_t *tvlv_put(u_int8_t *buf, u_int8_t tag, u_int16_t len,
const u_int8_t *val)
{
u_int8_t *ret;
if (len <= TVLV_MAX_ONEBYTE) {
ret = tlv_put(buf, tag, len, val);
buf[1] |= 0x80;
} else
ret = tl16v_put(buf, tag, len, val);
return ret;
}
static inline u_int8_t *msgb_tlv16_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int16_t *val)
{
u_int8_t *buf = msgb_put(msg, TLV16_GROSS_LEN(len));
return tlv16_put(buf, tag, len, val);
}
static inline u_int8_t *msgb_tl16v_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
const u_int8_t *val)
{
u_int8_t *buf = msgb_put(msg, TL16V_GROSS_LEN(len));
return tl16v_put(buf, tag, len, val);
}
static inline u_int8_t *msgb_tvlv_put(struct msgb *msg, u_int8_t tag, u_int16_t len,
const u_int8_t *val)
{
u_int8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
return tvlv_put(buf, tag, len, val);
}
static inline u_int8_t *v_put(u_int8_t *buf, u_int8_t val)
{
*buf++ = val;
return buf;
}
static inline u_int8_t *tv_put(u_int8_t *buf, u_int8_t tag,
u_int8_t val)
{
*buf++ = tag;
*buf++ = val;
return buf;
}
static inline u_int8_t *tv16_put(u_int8_t *buf, u_int8_t tag,
u_int16_t val)
{
*buf++ = tag;
*buf++ = val >> 8;
*buf++ = val & 0xff;
return buf;
}
static inline u_int8_t *msgb_lv_put(struct msgb *msg, u_int8_t len, const u_int8_t *val)
{
u_int8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
return lv_put(buf, len, val);
}
static inline u_int8_t *msgb_tlv_put(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
{
u_int8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
return tlv_put(buf, tag, len, val);
}
static inline u_int8_t *msgb_tv_put(struct msgb *msg, u_int8_t tag, u_int8_t val)
{
u_int8_t *buf = msgb_put(msg, 2);
return tv_put(buf, tag, val);
}
static inline u_int8_t *msgb_v_put(struct msgb *msg, u_int8_t val)
{
u_int8_t *buf = msgb_put(msg, 1);
return v_put(buf, val);
}
static inline u_int8_t *msgb_tv16_put(struct msgb *msg, u_int8_t tag, u_int16_t val)
{
u_int8_t *buf = msgb_put(msg, 3);
return tv16_put(buf, tag, val);
}
static inline u_int8_t *msgb_tlv_push(struct msgb *msg, u_int8_t tag, u_int8_t len, const u_int8_t *val)
{
u_int8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
return tlv_put(buf, tag, len, val);
}
static inline u_int8_t *msgb_tv_push(struct msgb *msg, u_int8_t tag, u_int8_t val)
{
u_int8_t *buf = msgb_push(msg, 2);
return tv_put(buf, tag, val);
}
static inline u_int8_t *msgb_tv16_push(struct msgb *msg, u_int8_t tag, u_int16_t val)
{
u_int8_t *buf = msgb_push(msg, 3);
return tv16_put(buf, tag, val);
}
/* TLV parsing */
struct tlv_p_entry {
u_int16_t len;
const u_int8_t *val;
};
enum tlv_type {
TLV_TYPE_FIXED,
TLV_TYPE_T,
TLV_TYPE_TV,
TLV_TYPE_TLV,
TLV_TYPE_TL16V,
TLV_TYPE_TvLV,
};
struct tlv_def {
enum tlv_type type;
u_int8_t fixed_len;
};
struct tlv_definition {
struct tlv_def def[0xff];
};
struct tlv_parsed {
struct tlv_p_entry lv[0xff];
};
extern struct tlv_definition tvlv_att_def;
int tlv_parse_one(u_int8_t *o_tag, u_int16_t *o_len, const u_int8_t **o_val,
const struct tlv_definition *def,
const u_int8_t *buf, int buf_len);
int tlv_parse(struct tlv_parsed *dec, const struct tlv_definition *def,
const u_int8_t *buf, int buf_len, u_int8_t lv_tag, u_int8_t lv_tag2);
#define TLVP_PRESENT(x, y) ((x)->lv[y].val)
#define TLVP_LEN(x, y) (x)->lv[y].len
#define TLVP_VAL(x, y) (x)->lv[y].val
#endif /* _TLV_H */

View File

@@ -3,7 +3,7 @@
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
#include <osmocore/linuxlist.h>
#include <openbsc/linuxlist.h>
#include <openbsc/gsm_04_11.h>
/* One transaction */
@@ -20,15 +20,12 @@ struct gsm_trans {
/* To whom we belong, unique identifier of remote MM entity */
struct gsm_subscriber *subscr;
/* The associated connection we are using to transmit messages */
struct gsm_subscriber_connection *conn;
/* The LCHAN that we're currently using to transmit messages */
struct gsm_lchan *lchan;
/* reference from MNCC or other application */
u_int32_t callref;
/* if traffic channel receive was requested */
int tch_recv;
union {
struct {
@@ -68,5 +65,4 @@ void trans_free(struct gsm_trans *trans);
int trans_assign_trans_id(struct gsm_subscriber *subscr,
u_int8_t protocol, u_int8_t ti_flag);
#endif

View File

@@ -46,4 +46,4 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss,
int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_t callref);
/* send trau from application */
int trau_send_frame(struct gsm_lchan *lchan, struct gsm_data_frame *frame);
int trau_send_lchan(struct gsm_lchan *lchan, struct decoded_trau_frame *tf);

View File

@@ -3,8 +3,8 @@
/* Handler function for mobile-originated USSD messages */
#include <osmocore/msgb.h>
#include <openbsc/msgb.h>
int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg);
int handle_rcv_ussd(struct msgb *msg);
#endif

View File

@@ -1,36 +0,0 @@
#ifndef OPENBSC_VTY_H
#define OPENBSC_VTY_H
#include <osmocom/vty/vty.h>
#include <osmocom/vty/buffer.h>
#include <osmocom/vty/command.h>
struct gsm_network;
struct vty;
void openbsc_vty_print_statistics(struct vty *vty, struct gsm_network *);
struct buffer *vty_argv_to_buffer(int argc, const char *argv[], int base);
extern struct cmd_element cfg_description_cmd;
extern struct cmd_element cfg_no_description_cmd;
extern struct cmd_element ournode_exit_cmd;
extern struct cmd_element ournode_end_cmd;
enum bsc_vty_node {
GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,
BTS_NODE,
TRX_NODE,
TS_NODE,
SUBSCR_NODE,
MGCP_NODE,
GBPROXY_NODE,
SGSN_NODE,
NS_NODE,
BSSGP_NODE,
OML_NODE,
NAT_NODE,
NAT_BSC_NODE,
};
#endif

View File

@@ -0,0 +1 @@
noinst_HEADERS = sccp_types.h sccp.h

146
openbsc/include/sccp/sccp.h Normal file
View File

@@ -0,0 +1,146 @@
/*
* SCCP management code
*
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef SCCP_H
#define SCCP_H
#include <stdlib.h>
#include <sys/socket.h>
#include <openbsc/msgb.h>
#include "sccp_types.h"
struct sccp_system;
enum {
SCCP_CONNECTION_STATE_NONE,
SCCP_CONNECTION_STATE_REQUEST,
SCCP_CONNECTION_STATE_CONFIRM,
SCCP_CONNECTION_STATE_ESTABLISHED,
SCCP_CONNECTION_STATE_RELEASE,
SCCP_CONNECTION_STATE_RELEASE_COMPLETE,
SCCP_CONNECTION_STATE_REFUSED,
SCCP_CONNECTION_STATE_SETUP_ERROR,
};
struct sockaddr_sccp {
sa_family_t sccp_family; /* AF_SCCP in the future??? */
u_int8_t sccp_ssn; /* subssystem number for routing */
/* TODO fill in address indicator... if that is ever needed */
/* not sure about these */
/* u_int8_t sccp_class; */
};
/*
* parsed structure of an address
*/
struct sccp_address {
struct sccp_called_party_address address;
u_int8_t ssn;
u_int8_t poi[2];
};
struct sccp_optional_data {
u_int8_t data_len;
u_int8_t data_start;
};
struct sccp_connection {
/* public */
void *data_ctx;
void (*data_cb)(struct sccp_connection *conn, struct msgb *msg, unsigned int len);
void *state_ctx;
void (*state_cb)(struct sccp_connection *, int old_state);
struct sccp_source_reference source_local_reference;
struct sccp_source_reference destination_local_reference;
int connection_state;
/* private */
/* list of active connections */
struct llist_head list;
struct sccp_system *system;
int incoming;
};
/**
* system functionality to implement on top of any other transport layer:
* call sccp_system_incoming for incoming data (from the network)
* sccp will call outgoing whenever outgoing data exists
*/
int sccp_system_init(int (*outgoing)(struct msgb *data, void *ctx), void *context);
int sccp_system_incoming(struct msgb *data);
/**
* Send data on an existing connection
*/
int sccp_connection_write(struct sccp_connection *connection, struct msgb *data);
int sccp_connection_send_it(struct sccp_connection *connection);
int sccp_connection_close(struct sccp_connection *connection, int cause);
int sccp_connection_free(struct sccp_connection *connection);
/**
* Create a new socket. Set your callbacks and then call bind to open
* the connection.
*/
struct sccp_connection *sccp_connection_socket(void);
/**
* Open the connection and send additional data
*/
int sccp_connection_connect(struct sccp_connection *conn,
const struct sockaddr_sccp *sccp_called,
struct msgb *data);
/**
* mostly for testing purposes only. Set the accept callback.
* TODO: add true routing information... in analogy to socket, bind, accept
*/
int sccp_connection_set_incoming(const struct sockaddr_sccp *sock,
int (*accept_cb)(struct sccp_connection *connection, void *data),
void *user_data);
/**
* Send data in terms of unit data. A fixed address indicator will be used.
*/
int sccp_write(struct msgb *data,
const struct sockaddr_sccp *sock_sender,
const struct sockaddr_sccp *sock_target, int class);
int sccp_set_read(const struct sockaddr_sccp *sock,
int (*read_cb)(struct msgb *msgb, unsigned int, void *user_data),
void *user_data);
/* generic sock addresses */
extern const struct sockaddr_sccp sccp_ssn_bssap;
/* helpers */
u_int32_t sccp_src_ref_to_int(struct sccp_source_reference *ref);
struct sccp_source_reference sccp_src_ref_from_int(u_int32_t);
#endif

View File

@@ -0,0 +1,394 @@
/*
* ITU Q.713 defined types for SCCP
*
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef SCCP_TYPES_H
#define SCCP_TYPES_H
/* Table 1/Q.713 - SCCP message types */
enum sccp_message_types {
SCCP_MSG_TYPE_CR = 1,
SCCP_MSG_TYPE_CC = 2,
SCCP_MSG_TYPE_CREF = 3,
SCCP_MSG_TYPE_RLSD = 4,
SCCP_MSG_TYPE_RLC = 5,
SCCP_MSG_TYPE_DT1 = 6,
SCCP_MSG_TYPE_DT2 = 7,
SCCP_MSG_TYPE_AK = 8,
SCCP_MSG_TYPE_UDT = 9,
SCCP_MSG_TYPE_UDTS = 10,
SCCP_MSG_TYPE_ED = 11,
SCCP_MSG_TYPE_EA = 12,
SCCP_MSG_TYPE_RSR = 13,
SCCP_MSG_TYPE_RSC = 14,
SCCP_MSG_TYPE_ERR = 15,
SCCP_MSG_TYPE_IT = 16,
SCCP_MSG_TYPE_XUDT = 17,
SCCP_MSG_TYPE_XUDTS = 18,
SCCP_MSG_TYPE_LUDT = 19,
SCCP_MSG_TYPE_LUDTS = 20
};
/* Table 2/Q.713 - SCCP parameter name codes */
enum sccp_parameter_name_codes {
SCCP_PNC_END_OF_OPTIONAL = 0,
SCCP_PNC_DESTINATION_LOCAL_REFERENCE = 1,
SCCP_PNC_SOURCE_LOCAL_REFERENCE = 2,
SCCP_PNC_CALLED_PARTY_ADDRESS = 3,
SCCP_PNC_CALLING_PARTY_ADDRESS = 4,
SCCP_PNC_PROTOCOL_CLASS = 5,
SCCP_PNC_SEGMENTING = 6,
SCCP_PNC_RECEIVE_SEQ_NUMBER = 7,
SCCP_PNC_SEQUENCING = 8,
SCCP_PNC_CREDIT = 9,
SCCP_PNC_RELEASE_CAUSE = 10,
SCCP_PNC_RETURN_CAUSE = 11,
SCCP_PNC_RESET_CAUSE = 12,
SCCP_PNC_ERROR_CAUSE = 13,
SCCP_PNC_REFUSAL_CAUSE = 14,
SCCP_PNC_DATA = 15,
SCCP_PNC_SEGMENTATION = 16,
SCCP_PNC_HOP_COUNTER = 17,
SCCP_PNC_IMPORTANCE = 18,
SCCP_PNC_LONG_DATA = 19,
};
/* Figure 3/Q.713 Called/calling party address */
enum {
SCCP_TITLE_IND_NONE = 0,
SCCP_TITLE_IND_NATURE_ONLY = 1,
SCCP_TITLE_IND_TRANSLATION_ONLY = 2,
SCCP_TITLE_IND_TRANS_NUM_ENC = 3,
SCCP_TITLE_IND_TRANS_NUM_ENC_NATURE = 4,
};
enum {
SCCP_CALL_ROUTE_ON_SSN = 1,
SCCP_CALL_ROUTE_ON_GT = 0,
};
struct sccp_called_party_address {
u_int8_t point_code_indicator : 1,
ssn_indicator : 1,
global_title_indicator : 4,
routing_indicator : 1,
reserved : 1;
u_int8_t data[0];
} __attribute__((packed));
/* indicator indicates presence in the above order */
/* Figure 6/Q.713 */
struct sccp_signalling_point_code {
u_int8_t lsb;
u_int8_t msb : 6,
reserved : 2;
} __attribute__((packed));
/* SSN == subsystem number */
enum sccp_subsystem_number {
SCCP_SSN_NOT_KNOWN_OR_USED = 0,
SCCP_SSN_MANAGEMENT = 1,
SCCP_SSN_RESERVED_ITU = 2,
SCCP_SSN_ISDN_USER_PART = 3,
SCCP_SSN_OMAP = 4, /* operation, maint and administration part */
SCCP_SSN_MAP = 5, /* mobile application part */
SCCP_SSN_HLR = 6,
SCCP_SSN_VLR = 7,
SCCP_SSN_MSC = 8,
SCCP_SSN_EIC = 9, /* equipent identifier centre */
SCCP_SSN_AUC = 10, /* authentication centre */
SCCP_SSN_ISDN_SUPPL_SERVICES = 11,
SCCP_SSN_RESERVED_INTL = 12,
SCCP_SSN_ISDN_EDGE_TO_EDGE = 13,
SCCP_SSN_TC_TEST_RESPONDER = 14,
/* From GSM 03.03 8.2 */
SCCP_SSN_BSSAP = 254,
SCCP_SSN_BSSOM = 253,
};
/* Q.713, 3.4.2.3 */
enum {
SCCP_NAI_UNKNOWN = 0,
SCCP_NAI_SUBSCRIBER_NUMBER = 1,
SCCP_NAI_RESERVED_NATIONAL = 2,
SCCP_NAI_NATIONAL_SIGNIFICANT = 3,
SCCP_NAI_INTERNATIONAL = 4,
};
struct sccp_global_title {
u_int8_t nature_of_addr_ind : 7,
odd_even : 1;
u_int8_t data[0];
} __attribute__((packed));
/* Q.713, 3.3 */
struct sccp_source_reference {
u_int8_t octet1;
u_int8_t octet2;
u_int8_t octet3;
} __attribute__((packed));
/* Q.714, 3.6 */
enum sccp_protocol_class {
SCCP_PROTOCOL_CLASS_0 = 0,
SCCP_PROTOCOL_CLASS_1 = 1,
SCCP_PROTOCOL_CLASS_2 = 2,
SCCP_PROTOCOL_CLASS_3 = 3,
};
/* bits 5-8 when class0, class1 is used */
enum sccp_protocol_options {
SCCP_PROTOCOL_NO_SPECIAL = 0,
SCCP_PROTOCOL_RETURN_MESSAGE = 8,
};
enum sccp_release_cause {
SCCP_RELEASE_CAUSE_END_USER_ORIGINATED = 0,
SCCP_RELEASE_CAUSE_END_USER_CONGESTION = 1,
SCCP_RELEASE_CAUSE_END_USER_FAILURE = 2,
SCCP_RELEASE_CAUSE_SCCP_USER_ORIGINATED = 3,
SCCP_RELEASE_CAUSE_REMOTE_PROCEDURE_ERROR = 4,
SCCP_RELEASE_CAUSE_INCONSISTENT_CONN_DATA = 5,
SCCP_RELEASE_CAUSE_ACCESS_FAILURE = 6,
SCCP_RELEASE_CAUSE_ACCESS_CONGESTION = 7,
SCCP_RELEASE_CAUSE_SUBSYSTEM_FAILURE = 8,
SCCP_RELEASE_CAUSE_SUBSYSTEM_CONGESTION = 9,
SCCP_RELEASE_CAUSE_MTP_FAILURE = 10,
SCCP_RELEASE_CAUSE_NETWORK_CONGESTION = 11,
SCCP_RELEASE_CAUSE_EXPIRATION_RESET = 12,
SCCP_RELEASE_CAUSE_EXPIRATION_INACTIVE = 13,
SCCP_RELEASE_CAUSE_RESERVED = 14,
SCCP_RELEASE_CAUSE_UNQUALIFIED = 15,
SCCP_RELEASE_CAUSE_SCCP_FAILURE = 16,
};
enum sccp_return_cause {
SCCP_RETURN_CAUSE_NO_TRANSLATION_NATURE = 0,
SCCP_RETURN_CAUSE_NO_TRANSLATION = 1,
SCCP_RETURN_CAUSE_SUBSYSTEM_CONGESTION = 2,
SCCP_RETURN_CAUSE_SUBSYSTEM_FAILURE = 3,
SCCP_RETURN_CAUSE_UNEQUIPPED_USER = 4,
SCCP_RETURN_CAUSE_MTP_FAILURE = 5,
SCCP_RETURN_CAUSE_NETWORK_CONGESTION = 6,
SCCP_RETURN_CAUSE_UNQUALIFIED = 7,
SCCP_RETURN_CAUSE_ERROR_IN_MSG_TRANSPORT = 8,
SCCP_RETURN_CAUSE_ERROR_IN_LOCAL_PROCESSING = 9,
SCCP_RETURN_CAUSE_DEST_CANNOT_PERFORM_REASSEMBLY = 10,
SCCP_RETURN_CAUSE_SCCP_FAILURE = 11,
SCCP_RETURN_CAUSE_HOP_COUNTER_VIOLATION = 12,
SCCP_RETURN_CAUSE_SEGMENTATION_NOT_SUPPORTED= 13,
SCCP_RETURN_CAUSE_SEGMENTATION_FAOLURE = 14
};
enum sccp_reset_cause {
SCCP_RESET_CAUSE_END_USER_ORIGINATED = 0,
SCCP_RESET_CAUSE_SCCP_USER_ORIGINATED = 1,
SCCP_RESET_CAUSE_MSG_OUT_OF_ORDER_PS = 2,
SCCP_RESET_CAUSE_MSG_OUT_OF_ORDER_PR = 3,
SCCP_RESET_CAUSE_RPC_OUT_OF_WINDOW = 4,
SCCP_RESET_CAUSE_RPC_INCORRECT_PS = 5,
SCCP_RESET_CAUSE_RPC_GENERAL = 6,
SCCP_RESET_CAUSE_REMOTE_END_USER_OPERATIONAL= 7,
SCCP_RESET_CAUSE_NETWORK_OPERATIONAL = 8,
SCCP_RESET_CAUSE_ACCESS_OPERATIONAL = 9,
SCCP_RESET_CAUSE_NETWORK_CONGESTION = 10,
SCCP_RESET_CAUSE_RESERVED = 11,
};
enum sccp_error_cause {
SCCP_ERROR_LRN_MISMATCH_UNASSIGNED = 0, /* local reference number */
SCCP_ERROR_LRN_MISMATCH_INCONSISTENT = 1,
SCCP_ERROR_POINT_CODE_MISMATCH = 2,
SCCP_ERROR_SERVICE_CLASS_MISMATCH = 3,
SCCP_ERROR_UNQUALIFIED = 4,
};
enum sccp_refusal_cause {
SCCP_REFUSAL_END_USER_ORIGINATED = 0,
SCCP_REFUSAL_END_USER_CONGESTION = 1,
SCCP_REFUSAL_END_USER_FAILURE = 2,
SCCP_REFUSAL_SCCP_USER_ORIGINATED = 3,
SCCP_REFUSAL_DESTINATION_ADDRESS_UKNOWN = 4,
SCCP_REFUSAL_DESTINATION_INACCESSIBLE = 5,
SCCP_REFUSAL_NET_QOS_NON_TRANSIENT = 6,
SCCP_REFUSAL_NET_QOS_TRANSIENT = 7,
SCCP_REFUSAL_ACCESS_FAILURE = 8,
SCCP_REFUSAL_ACCESS_CONGESTION = 9,
SCCP_REFUSAL_SUBSYSTEM_FAILURE = 10,
SCCP_REFUSAL_SUBSYTEM_CONGESTION = 11,
SCCP_REFUSAL_EXPIRATION = 12,
SCCP_REFUSAL_INCOMPATIBLE_USER_DATA = 13,
SCCP_REFUSAL_RESERVED = 14,
SCCP_REFUSAL_UNQUALIFIED = 15,
SCCP_REFUSAL_HOP_COUNTER_VIOLATION = 16,
SCCP_REFUSAL_SCCP_FAILURE = 17,
SCCP_REFUSAL_UNEQUIPPED_USER = 18,
};
/*
* messages... as of Q.713 Chapter 4
*/
struct sccp_connection_request {
/* mandantory */
u_int8_t type;
struct sccp_source_reference source_local_reference;
u_int8_t proto_class;
/* variable */
u_int8_t variable_called;
#if VARIABLE
called_party_address
#endif
/* optional */
u_int8_t optional_start;
#if OPTIONAL
credit 3
callingparty var 4-n
data 3-130
hop_counter 3
importance 3
end_of_optional 1
#endif
u_int8_t data[0];
} __attribute__((packed));
struct sccp_connection_confirm {
/* mandantory */
u_int8_t type;
struct sccp_source_reference destination_local_reference;
struct sccp_source_reference source_local_reference;
u_int8_t proto_class;
/* optional */
u_int8_t optional_start;
/* optional */
#if OPTIONAL
credit 3
called party 4
data 3-130
importance 3
end_of_optional 1
#endif
u_int8_t data[0];
} __attribute__((packed));
struct sccp_connection_refused {
/* mandantory */
u_int8_t type;
struct sccp_source_reference destination_local_reference;
u_int8_t cause;
/* optional */
u_int8_t optional_start;
/* optional */
#if OPTIONAL
called party 4
data 3-130
importance 3
end_of_optional 1
#endif
u_int8_t data[0];
} __attribute__((packed));
struct sccp_connection_released {
/* mandantory */
u_int8_t type;
struct sccp_source_reference destination_local_reference;
struct sccp_source_reference source_local_reference;
u_int8_t release_cause;
/* optional */
u_int8_t optional_start;
#if OPTIONAL
data 3-130
importance 3
end_of_optional 1
#endif
u_int8_t data[0];
} __attribute__((packed));
struct sccp_connection_release_complete {
u_int8_t type;
struct sccp_source_reference destination_local_reference;
struct sccp_source_reference source_local_reference;
} __attribute__((packed));
struct sccp_data_form1 {
/* mandantory */
u_int8_t type;
struct sccp_source_reference destination_local_reference;
u_int8_t segmenting;
/* variable */
u_int8_t variable_start;
#if VARIABLE
data 2-256;
#endif
u_int8_t data[0];
} __attribute__((packed));
struct sccp_data_unitdata {
/* mandantory */
u_int8_t type;
u_int8_t proto_class;
/* variable */
u_int8_t variable_called;
u_int8_t variable_calling;
u_int8_t variable_data;
#if VARIABLE
called party address
calling party address
#endif
u_int8_t data[0];
} __attribute__((packed));
struct sccp_data_it {
/* mandantory */
u_int8_t type;
struct sccp_source_reference destination_local_reference;
struct sccp_source_reference source_local_reference;
u_int8_t proto_class;
u_int8_t sequencing[2];
u_int8_t credit;
} __attribute__((packed));
#endif

View File

@@ -0,0 +1 @@
noinst_HEADERS = buffer.h command.h vector.h vty.h

View File

@@ -0,0 +1,102 @@
/*
* Buffering to output and input.
* Copyright (C) 1998 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _ZEBRA_BUFFER_H
#define _ZEBRA_BUFFER_H
#include <sys/types.h>
/* Create a new buffer. Memory will be allocated in chunks of the given
size. If the argument is 0, the library will supply a reasonable
default size suitable for buffering socket I/O. */
struct buffer *buffer_new(size_t);
/* Free all data in the buffer. */
void buffer_reset(struct buffer *);
/* This function first calls buffer_reset to release all buffered data.
Then it frees the struct buffer itself. */
void buffer_free(struct buffer *);
/* Add the given data to the end of the buffer. */
extern void buffer_put(struct buffer *, const void *, size_t);
/* Add a single character to the end of the buffer. */
extern void buffer_putc(struct buffer *, u_char);
/* Add a NUL-terminated string to the end of the buffer. */
extern void buffer_putstr(struct buffer *, const char *);
/* Combine all accumulated (and unflushed) data inside the buffer into a
single NUL-terminated string allocated using XMALLOC(MTYPE_TMP). Note
that this function does not alter the state of the buffer, so the data
is still inside waiting to be flushed. */
char *buffer_getstr(struct buffer *);
/* Returns 1 if there is no pending data in the buffer. Otherwise returns 0. */
int buffer_empty(struct buffer *);
typedef enum {
/* An I/O error occurred. The buffer should be destroyed and the
file descriptor should be closed. */
BUFFER_ERROR = -1,
/* The data was written successfully, and the buffer is now empty
(there is no pending data waiting to be flushed). */
BUFFER_EMPTY = 0,
/* There is pending data in the buffer waiting to be flushed. Please
try flushing the buffer when select indicates that the file descriptor
is writeable. */
BUFFER_PENDING = 1
} buffer_status_t;
/* Try to write this data to the file descriptor. Any data that cannot
be written immediately is added to the buffer queue. */
extern buffer_status_t buffer_write(struct buffer *, int fd,
const void *, size_t);
/* This function attempts to flush some (but perhaps not all) of
the queued data to the given file descriptor. */
extern buffer_status_t buffer_flush_available(struct buffer *, int fd);
/* The following 2 functions (buffer_flush_all and buffer_flush_window)
are for use in lib/vty.c only. They should not be used elsewhere. */
/* Call buffer_flush_available repeatedly until either all data has been
flushed, or an I/O error has been encountered, or the operation would
block. */
extern buffer_status_t buffer_flush_all(struct buffer *, int fd);
/* Attempt to write enough data to the given fd to fill a window of the
given width and height (and remove the data written from the buffer).
If !no_more, then a message saying " --More-- " is appended.
If erase is true, then first overwrite the previous " --More-- " message
with spaces.
Any write error (including EAGAIN or EINTR) will cause this function
to return -1 (because the logic for handling the erase and more features
is too complicated to retry the write later).
*/
extern buffer_status_t buffer_flush_window(struct buffer *, int fd, int width,
int height, int erase, int no_more);
#endif /* _ZEBRA_BUFFER_H */

View File

@@ -0,0 +1,359 @@
/*
* Zebra configuration command interface routine
* Copyright (C) 1997, 98 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _ZEBRA_COMMAND_H
#define _ZEBRA_COMMAND_H
#include <stdio.h>
#include <sys/types.h>
#include "vector.h"
#include "vty.h"
/* Host configuration variable */
struct host {
/* Host name of this router. */
char *name;
/* Password for vty interface. */
char *password;
char *password_encrypt;
/* Enable password */
char *enable;
char *enable_encrypt;
/* System wide terminal lines. */
int lines;
/* Log filename. */
char *logfile;
/* config file name of this host */
char *config;
/* Flags for services */
int advanced;
int encrypt;
/* Banner configuration. */
const char *motd;
char *motdfile;
};
/* There are some command levels which called from command node. */
enum node_type {
AUTH_NODE, /* Authentication mode of vty interface. */
VIEW_NODE, /* View node. Default mode of vty interface. */
AUTH_ENABLE_NODE, /* Authentication mode for change enable. */
ENABLE_NODE, /* Enable node. */
CONFIG_NODE, /* Config node. Default mode of config file. */
SERVICE_NODE, /* Service node. */
DEBUG_NODE, /* Debug node. */
#if 0
AAA_NODE, /* AAA node. */
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */
INTERFACE_NODE, /* Interface mode node. */
ZEBRA_NODE, /* zebra connection node. */
TABLE_NODE, /* rtm_table selection node. */
RIP_NODE, /* RIP protocol mode node. */
RIPNG_NODE, /* RIPng protocol mode node. */
BGP_NODE, /* BGP protocol mode which includes BGP4+ */
BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */
BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */
BGP_IPV6_NODE, /* BGP IPv6 address family */
OSPF_NODE, /* OSPF protocol mode */
OSPF6_NODE, /* OSPF protocol for IPv6 mode */
ISIS_NODE, /* ISIS protocol mode */
MASC_NODE, /* MASC for multicast. */
IRDP_NODE, /* ICMP Router Discovery Protocol mode. */
IP_NODE, /* Static ip route node. */
ACCESS_NODE, /* Access list node. */
PREFIX_NODE, /* Prefix list node. */
ACCESS_IPV6_NODE, /* Access list node. */
PREFIX_IPV6_NODE, /* Prefix list node. */
AS_LIST_NODE, /* AS list node. */
COMMUNITY_LIST_NODE, /* Community list node. */
RMAP_NODE, /* Route map node. */
SMUX_NODE, /* SNMP configuration node. */
DUMP_NODE, /* Packet dump node. */
FORWARDING_NODE, /* IP forwarding node. */
#endif
VTY_NODE, /* Vty node. */
GSMNET_NODE,
BTS_NODE,
TRX_NODE,
TS_NODE,
SUBSCR_NODE,
MGCP_NODE,
};
/* Node which has some commands and prompt string and configuration
function pointer . */
struct cmd_node {
/* Node index. */
enum node_type node;
/* Prompt character at vty interface. */
const char *prompt;
/* Is this node's configuration goes to vtysh ? */
int vtysh;
/* Node's configuration write function */
int (*func) (struct vty *);
/* Vector of this node's command list. */
vector cmd_vector;
};
enum {
CMD_ATTR_DEPRECATED = 1,
CMD_ATTR_HIDDEN,
};
/* Structure of command element. */
struct cmd_element {
const char *string; /* Command specification by string. */
int (*func) (struct cmd_element *, struct vty *, int, const char *[]);
const char *doc; /* Documentation of this command. */
int daemon; /* Daemon to which this command belong. */
vector strvec; /* Pointing out each description vector. */
unsigned int cmdsize; /* Command index count. */
char *config; /* Configuration string */
vector subconfig; /* Sub configuration string */
u_char attr; /* Command attributes */
};
/* Command description structure. */
struct desc {
const char *cmd; /* Command string. */
const char *str; /* Command's description. */
};
/* Return value of the commands. */
#define CMD_SUCCESS 0
#define CMD_WARNING 1
#define CMD_ERR_NO_MATCH 2
#define CMD_ERR_AMBIGUOUS 3
#define CMD_ERR_INCOMPLETE 4
#define CMD_ERR_EXEED_ARGC_MAX 5
#define CMD_ERR_NOTHING_TODO 6
#define CMD_COMPLETE_FULL_MATCH 7
#define CMD_COMPLETE_MATCH 8
#define CMD_COMPLETE_LIST_MATCH 9
#define CMD_SUCCESS_DAEMON 10
/* Argc max counts. */
#define CMD_ARGC_MAX 25
/* Turn off these macros when uisng cpp with extract.pl */
#ifndef VTYSH_EXTRACT_PL
/* helper defines for end-user DEFUN* macros */
#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
struct cmd_element cmdname = \
{ \
.string = cmdstr, \
.func = funcname, \
.doc = helpstr, \
.attr = attrs, \
.daemon = dnum, \
};
#define DEFUN_CMD_FUNC_DECL(funcname) \
static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \
#define DEFUN_CMD_FUNC_TEXT(funcname) \
static int funcname \
(struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
/* DEFUN for vty command interafce. Little bit hacky ;-). */
#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
DEFUN_CMD_FUNC_TEXT(funcname)
#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
DEFUN_CMD_FUNC_TEXT(funcname)
#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
/* DEFUN_NOSH for commands that vtysh should ignore */
#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
DEFUN(funcname, cmdname, cmdstr, helpstr)
/* DEFSH for vtysh. */
#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) \
/* DEFUN + DEFSH */
#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \
DEFUN_CMD_FUNC_TEXT(funcname)
/* DEFUN + DEFSH with attributes */
#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_FUNC_DECL(funcname) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \
DEFUN_CMD_FUNC_TEXT(funcname)
#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED)
/* ALIAS macro which define existing command's alias. */
#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0)
#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0)
#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon)
#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon)
#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon)
#endif /* VTYSH_EXTRACT_PL */
/* Some macroes */
#define CMD_OPTION(S) ((S[0]) == '[')
#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
#define CMD_VARARG(S) ((S[0]) == '.')
#define CMD_RANGE(S) ((S[0] == '<'))
#define CMD_IPV4(S) ((strcmp ((S), "A.B.C.D") == 0))
#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
#define CMD_IPV6(S) ((strcmp ((S), "X:X::X:X") == 0))
#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
/* Common descriptions. */
#define SHOW_STR "Show running system information\n"
#define IP_STR "IP information\n"
#define IPV6_STR "IPv6 information\n"
#define NO_STR "Negate a command or set its defaults\n"
#define CLEAR_STR "Reset functions\n"
#define RIP_STR "RIP information\n"
#define BGP_STR "BGP information\n"
#define OSPF_STR "OSPF information\n"
#define NEIGHBOR_STR "Specify neighbor router\n"
#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
#define ROUTER_STR "Enable a routing process\n"
#define AS_STR "AS number\n"
#define MBGP_STR "MBGP information\n"
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
#define OUT_STR "Filter outgoing routing updates\n"
#define IN_STR "Filter incoming routing updates\n"
#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
#define OSPF6_NUMBER_STR "Specify by number\n"
#define INTERFACE_STR "Interface infomation\n"
#define IFNAME_STR "Interface name(e.g. ep0)\n"
#define IP6_STR "IPv6 Information\n"
#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
#define OSPF6_ROUTER_STR "Enable a routing process\n"
#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
#define SECONDS_STR "<1-65535> Seconds\n"
#define ROUTE_STR "Routing Table\n"
#define PREFIX_LIST_STR "Build a prefix list\n"
#define OSPF6_DUMP_TYPE_LIST \
"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
#define ISIS_STR "IS-IS information\n"
#define AREA_TAG_STR "[area tag]\n"
#define CONF_BACKUP_EXT ".sav"
/* IPv4 only machine should not accept IPv6 address for peer's IP
address. So we replace VTY command string like below. */
#ifdef HAVE_IPV6
#define NEIGHBOR_CMD "neighbor (A.B.C.D|X:X::X:X) "
#define NO_NEIGHBOR_CMD "no neighbor (A.B.C.D|X:X::X:X) "
#define NEIGHBOR_ADDR_STR "Neighbor address\nIPv6 address\n"
#define NEIGHBOR_CMD2 "neighbor (A.B.C.D|X:X::X:X|WORD) "
#define NO_NEIGHBOR_CMD2 "no neighbor (A.B.C.D|X:X::X:X|WORD) "
#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nNeighbor tag\n"
#else
#define NEIGHBOR_CMD "neighbor A.B.C.D "
#define NO_NEIGHBOR_CMD "no neighbor A.B.C.D "
#define NEIGHBOR_ADDR_STR "Neighbor address\n"
#define NEIGHBOR_CMD2 "neighbor (A.B.C.D|WORD) "
#define NO_NEIGHBOR_CMD2 "no neighbor (A.B.C.D|WORD) "
#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor tag\n"
#endif /* HAVE_IPV6 */
/* Prototypes. */
void install_node(struct cmd_node *, int (*)(struct vty *));
void install_default(enum node_type);
void install_element(enum node_type, struct cmd_element *);
void sort_node();
/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
string with a space between each element (allocated using
XMALLOC(MTYPE_TMP)). Returns NULL if shift >= argc. */
char *argv_concat(const char **argv, int argc, int shift);
vector cmd_make_strvec(const char *);
void cmd_free_strvec(vector);
vector cmd_describe_command();
char **cmd_complete_command();
const char *cmd_prompt(enum node_type);
int config_from_file(struct vty *, FILE *);
enum node_type node_parent(enum node_type);
int cmd_execute_command(vector, struct vty *, struct cmd_element **, int);
int cmd_execute_command_strict(vector, struct vty *, struct cmd_element **);
void config_replace_string(struct cmd_element *, char *, ...);
void cmd_init(int);
/* Export typical functions. */
extern struct cmd_element config_end_cmd;
extern struct cmd_element config_exit_cmd;
extern struct cmd_element config_quit_cmd;
extern struct cmd_element config_help_cmd;
extern struct cmd_element config_list_cmd;
char *host_config_file();
void host_config_set(const char *);
void print_version(const char *);
#endif /* _ZEBRA_COMMAND_H */

View File

@@ -0,0 +1,62 @@
/*
* Generic vector interface header.
* Copyright (C) 1997, 98 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _ZEBRA_VECTOR_H
#define _ZEBRA_VECTOR_H
/* struct for vector */
struct _vector {
unsigned int active; /* number of active slots */
unsigned int alloced; /* number of allocated slot */
void **index; /* index to data */
};
typedef struct _vector *vector;
#define VECTOR_MIN_SIZE 1
/* (Sometimes) usefull macros. This macro convert index expression to
array expression. */
/* Reference slot at given index, caller must ensure slot is active */
#define vector_slot(V,I) ((V)->index[(I)])
/* Number of active slots.
* Note that this differs from vector_count() as it the count returned
* will include any empty slots
*/
#define vector_active(V) ((V)->active)
/* Prototypes. */
vector vector_init(unsigned int size);
void vector_ensure(vector v, unsigned int num);
int vector_empty_slot(vector v);
int vector_set(vector v, void *val);
int vector_set_index(vector v, unsigned int i, void *val);
void vector_unset(vector v, unsigned int i);
unsigned int vector_count(vector v);
void vector_only_wrapper_free(vector v);
void vector_only_index_free(void *index);
void vector_free(vector v);
vector vector_copy(vector v);
void *vector_lookup(vector, unsigned int);
void *vector_lookup_ensure(vector, unsigned int);
#endif /* _ZEBRA_VECTOR_H */

151
openbsc/include/vty/vty.h Normal file
View File

@@ -0,0 +1,151 @@
#ifndef _VTY_H
#define _VTY_H
#include <stdio.h>
#include <stdarg.h>
/* GCC have printf type attribute check. */
#ifdef __GNUC__
#define VTY_PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
#else
#define VTY_PRINTF_ATTRIBUTE(a,b)
#endif /* __GNUC__ */
/* Does the I/O error indicate that the operation should be retried later? */
#define ERRNO_IO_RETRY(EN) \
(((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
/* Vty read buffer size. */
#define VTY_READ_BUFSIZ 512
#define VTY_BUFSIZ 512
#define VTY_MAXHIST 20
/* Vty events */
enum event {
VTY_SERV,
VTY_READ,
VTY_WRITE,
VTY_CLOSED,
VTY_TIMEOUT_RESET,
#ifdef VTYSH
VTYSH_SERV,
VTYSH_READ,
VTYSH_WRITE
#endif /* VTYSH */
};
struct vty {
FILE *file;
/* private data, specified by creator */
void *priv;
/* File descripter of this vty. */
int fd;
/* Is this vty connect to file or not */
enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
/* Node status of this vty */
int node;
/* Failure count */
int fail;
/* Output buffer. */
struct buffer *obuf;
/* Command input buffer */
char *buf;
/* Command cursor point */
int cp;
/* Command length */
int length;
/* Command max length. */
int max;
/* Histry of command */
char *hist[VTY_MAXHIST];
/* History lookup current point */
int hp;
/* History insert end point */
int hindex;
/* For current referencing point of interface, route-map,
access-list etc... */
void *index;
/* For multiple level index treatment such as key chain and key. */
void *index_sub;
/* For escape character. */
unsigned char escape;
/* Current vty status. */
enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;
/* IAC handling: was the last character received the IAC
* (interpret-as-command) escape character (and therefore the next
* character will be the command code)? Refer to Telnet RFC 854. */
unsigned char iac;
/* IAC SB (option subnegotiation) handling */
unsigned char iac_sb_in_progress;
/* At the moment, we care only about the NAWS (window size) negotiation,
* and that requires just a 5-character buffer (RFC 1073):
* <NAWS char> <16-bit width> <16-bit height> */
#define TELNET_NAWS_SB_LEN 5
unsigned char sb_buf[TELNET_NAWS_SB_LEN];
/* How many subnegotiation characters have we received? We just drop
* those that do not fit in the buffer. */
size_t sb_len;
/* Window width/height. */
int width;
int height;
/* Configure lines. */
int lines;
int monitor;
/* In configure mode. */
int config;
};
/* Small macro to determine newline is newline only or linefeed needed. */
#define VTY_NEWLINE ((vty->type == VTY_TERM) ? "\r\n" : "\n")
static inline char *vty_newline(struct vty *vty)
{
return VTY_NEWLINE;
}
/* Prototypes. */
void vty_init (void);
int vty_read_config_file(const char *file_name);
void vty_init_vtysh (void);
void vty_reset (void);
struct vty *vty_new (void);
struct vty *vty_create (int vty_sock, void *priv);
int vty_out (struct vty *, const char *, ...) VTY_PRINTF_ATTRIBUTE(2, 3);
int vty_out_newline(struct vty *);
int vty_read(struct vty *vty);
//void vty_time_print (struct vty *, int);
void vty_close (struct vty *);
char *vty_get_cwd (void);
void vty_log (const char *level, const char *proto, const char *fmt, va_list);
int vty_config_lock (struct vty *);
int vty_config_unlock (struct vty *);
int vty_shell (struct vty *);
int vty_shell_serv (struct vty *);
void vty_hello (struct vty *);
void *tall_vty_ctx;
#endif

View File

@@ -1,7 +1,7 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@/
includedir=@includedir@/openbsc-1.0
Name: OpenBSC
Description: OpenBSC base station controller

View File

@@ -1,48 +1,41 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS)
INCLUDES = $(all_includes) -I$(top_srcdir)/include
AM_CFLAGS=-Wall
# build current directory before building gprs
SUBDIRS = . ipaccess gprs
# Conditional modules
if BUILD_NAT
SUBDIRS += nat
endif
if BUILD_BSC
SUBDIRS += bsc
endif
sbin_PROGRAMS = bsc_hack bs11_config isdnsync bsc_mgcp
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libmgcp.a
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config \
isdnsync bsc_mgcp bsc_msc_ip
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a
noinst_HEADERS = vty/cardshell.h
libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \
chan_alloc.c debug.c socket.c abis_nm_vty.c \
msgb.c select.c chan_alloc.c timer.c debug.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 \
input/misdn.c input/ipaccess.c handover_logic.c \
talloc_ctx.c system_information.c rest_octets.c \
rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \
bts_unknown.c bsc_version.c bsc_api.c bsc_vty.c meas_rep.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 telnet_interface.c
libmsc_a_SOURCES = gsm_subscriber.c db.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 \
handover_decision.c auth.c \
osmo_msc.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
libvty_a_SOURCES = common_vty.c
libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
libmgcp_a_SOURCES = mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c
libsccp_a_SOURCES = sccp/sccp.c
bsc_hack_SOURCES = bsc_hack.c bsc_init.c bsc_vty.c vty_interface_layer3.c
bsc_hack_LDADD = libmsc.a libbsc.a libvty.a libmsc.a \
-ldl -ldbi $(LIBCRYPT) $(LIBOSMOVTY_LIBS)
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)
bs11_config_SOURCES = bs11_config.c abis_nm.c gsm_data.c debug.c \
rs232.c bts_siemens_bs11.c
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
ipaccess_find_SOURCES = ipaccess-find.c select.c timer.c
ipaccess_config_SOURCES = ipaccess-config.c
ipaccess_config_LDADD = libbsc.a libmsc.a libbsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
isdnsync_SOURCES = isdnsync.c
bsc_mgcp_SOURCES = mgcp/mgcp_main.c debug.c
bsc_mgcp_LDADD = libvty.a libmgcp.a $(LIBOSMOVTY_LIBS)
bsc_mgcp_SOURCES = bsc_mgcp.c msgb.c talloc.c debug.c select.c timer.c telnet_interface.c
bsc_mgcp_LDADD = libvty.a

988
openbsc/src/abis_nm.c Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -1,198 +0,0 @@
/* VTY interface for A-bis OML (Netowrk Management) */
/* (C) 2009-2010 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 <errno.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <openbsc/gsm_data.h>
#include <osmocore/msgb.h>
#include <osmocore/tlv.h>
#include <osmocore/talloc.h>
#include <openbsc/debug.h>
#include <openbsc/signal.h>
#include <openbsc/abis_nm.h>
#include <openbsc/vty.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include <osmocom/vty/logging.h>
#include <osmocom/vty/telnet_interface.h>
extern struct gsm_network *bsc_gsmnet;
static struct cmd_node oml_node = {
OML_NODE,
"%s(oml)# ",
1,
};
struct oml_node_state {
struct gsm_bts *bts;
uint8_t obj_class;
uint8_t obj_inst[3];
};
static int dummy_config_write(struct vty *v)
{
return CMD_SUCCESS;
}
/* FIXME: auto-generate those strings from the value_string lists */
#define NM_OBJCLASS_VTY "(site-manager|bts|radio-carrier|baseband-transceiver|channel|adjc|handover|power-contorl|btse|rack|test|envabtse|bport|gprs-nse|gprs-cell|gprs-nsvc|siemenshw)"
#define NM_OBJCLASS_VTY_HELP "FIXME"
DEFUN(oml_class_inst, oml_class_inst_cmd,
"bts <0-255> oml class " NM_OBJCLASS_VTY
" instance <0-255> <0-255> <0-255>",
"BTS related commands\n" "BTS Number\n"
"Manipulate the OML managed objects\n"
"Object Class\n" NM_OBJCLASS_VTY_HELP
"Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n")
{
struct gsm_bts *bts;
struct oml_node_state *oms;
int bts_nr = atoi(argv[0]);
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
if (!bts) {
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
if (!oms)
return CMD_WARNING;
oms->bts = bts;
oms->obj_class = get_string_value(abis_nm_obj_class_names, argv[1]);
oms->obj_inst[0] = atoi(argv[2]);
oms->obj_inst[1] = atoi(argv[3]);
oms->obj_inst[2] = atoi(argv[4]);
vty->index = oms;
vty->node = OML_NODE;
return CMD_SUCCESS;
}
DEFUN(oml_classnum_inst, oml_classnum_inst_cmd,
"bts <0-255> oml class <0-255> instance <0-255> <0-255> <0-255>",
"BTS related commands\n" "BTS Number\n"
"Manipulate the OML managed objects\n"
"Object Class\n" "Object Class\n"
"Object Instance\n" "BTS Number\n" "TRX Number\n" "TS Number\n")
{
struct gsm_bts *bts;
struct oml_node_state *oms;
int bts_nr = atoi(argv[0]);
bts = gsm_bts_num(bsc_gsmnet, bts_nr);
if (!bts) {
vty_out(vty, "%% No such BTS (%d)%s", bts_nr, VTY_NEWLINE);
return CMD_WARNING;
}
oms = talloc_zero(tall_bsc_ctx, struct oml_node_state);
if (!oms)
return CMD_WARNING;
oms->bts = bts;
oms->obj_class = atoi(argv[1]);
oms->obj_inst[0] = atoi(argv[2]);
oms->obj_inst[1] = atoi(argv[3]);
oms->obj_inst[2] = atoi(argv[4]);
vty->index = oms;
vty->node = OML_NODE;
return CMD_SUCCESS;
}
DEFUN(oml_attrib_get, oml_attrib_get_cmd,
"attribute get <0-255>",
"OML Attribute Actions\n" "Get a single OML Attribute\n"
"OML Attribute Number\n")
{
struct oml_node_state *oms = vty->index;
/* FIXME */
return CMD_SUCCESS;
}
DEFUN(oml_attrib_set, oml_attrib_set_cmd,
"attribute set <0-255> .HEX",
"OML Attribute Actions\n" "Set a single OML Attribute\n"
"OML Attribute Number\n")
{
struct oml_node_state *oms = vty->index;
/* FIXME */
return CMD_SUCCESS;
}
DEFUN(oml_chg_adm_state, oml_chg_adm_state_cmd,
"change-adm-state (locked|unlocked|shutdown|null)",
"Change the Administrative State\n"
"Locked\n" "Unlocked\n" "Shutdown\n" "NULL\n")
{
struct oml_node_state *oms = vty->index;
enum abis_nm_adm_state state;
state = get_string_value(abis_nm_adm_state_names, argv[0]);
abis_nm_chg_adm_state(oms->bts, oms->obj_class, oms->obj_inst[0],
oms->obj_inst[1], oms->obj_inst[2], state);
return CMD_SUCCESS;
}
DEFUN(oml_opstart, oml_opstart_cmd,
"opstart", "Send an OPSTART message to the object")
{
struct oml_node_state *oms = vty->index;
abis_nm_opstart(oms->bts, oms->obj_class, oms->obj_inst[0],
oms->obj_inst[1], oms->obj_inst[2]);
return CMD_SUCCESS;
}
int abis_nm_vty_init(void)
{
install_element(ENABLE_NODE, &oml_class_inst_cmd);
install_element(ENABLE_NODE, &oml_classnum_inst_cmd);
install_node(&oml_node, dummy_config_write);
install_default(OML_NODE);
install_element(OML_NODE, &ournode_exit_cmd);
install_element(OML_NODE, &oml_attrib_get_cmd);
install_element(OML_NODE, &oml_attrib_set_cmd);
install_element(OML_NODE, &oml_chg_adm_state_cmd);
install_element(OML_NODE, &oml_opstart_cmd);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,128 +0,0 @@
/* Authentication related functions */
/*
* (C) 2010 by Sylvain Munaut <tnt@246tNt.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 <openbsc/db.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <osmocore/comp128.h>
#include <stdlib.h>
static int
_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
{
int i, l = ainfo->a3a8_ki_len;
if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
DEBUGP(DMM, "Invalid XOR key (len=%d) %s",
ainfo->a3a8_ki_len,
hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
return -1;
}
for (i=0; i<4; i++)
atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
for (i=8; i<12; i++)
atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
return 0;
}
static int
_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
{
if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
DEBUGP(DMM, "Invalid COMP128v1 key (len=%d) %s",
ainfo->a3a8_ki_len,
hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
return -1;
}
comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
return 0;
}
/* Return values
* -1 -> Internal error
* 0 -> Not available
* 1 -> Tuple returned, need to do auth, then enable cipher
* 2 -> Tuple returned, need to enable cipher
*/
int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
struct gsm_subscriber *subscr, int key_seq)
{
struct gsm_auth_info ainfo;
int i, rc;
/* Get subscriber info (if any) */
rc = db_get_authinfo_for_subscr(&ainfo, subscr);
if (rc < 0) {
DEBUGP(DMM, "No retrievable Ki for subscriber, skipping auth");
return rc == -ENOENT ? 0 : -1;
}
/* If possible, re-use the last tuple and skip auth */
rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
if ((rc == 0) &&
(atuple->key_seq != GSM_KEY_SEQ_INVAL) &&
(atuple->use_count < 3))
{
atuple->use_count++;
db_sync_lastauthtuple_for_subscr(atuple, subscr);
return 2;
}
/* Generate a new one */
atuple->use_count = 1;
atuple->key_seq = (atuple->key_seq + 1) % 7;
for (i=0; i<sizeof(atuple->rand); i++)
atuple->rand[i] = random() & 0xff;
switch (ainfo.auth_algo) {
case AUTH_ALGO_NONE:
return 0;
case AUTH_ALGO_XOR:
if (_use_xor(&ainfo, atuple))
return 0;
break;
case AUTH_ALGO_COMP128v1:
if (_use_comp128_v1(&ainfo, atuple))
return 0;
break;
default:
DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
ainfo.auth_algo);
return 0;
}
db_sync_lastauthtuple_for_subscr(atuple, subscr);
return 1;
}

View File

@@ -3,7 +3,7 @@
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* All Rights Reserved
*
* This software is based on ideas (but not code) of BS11Config
* This software is based on ideas (but not code) of BS11Config
* (C) 2009 by Dieter Spaar <spaar@mirider.augusta.de>
*
* This program is free software; you can redistribute it and/or modify
@@ -36,10 +36,10 @@
#include <openbsc/gsm_data.h>
#include <openbsc/abis_nm.h>
#include <osmocore/msgb.h>
#include <osmocore/tlv.h>
#include <openbsc/msgb.h>
#include <openbsc/tlv.h>
#include <openbsc/debug.h>
#include <osmocore/select.h>
#include <openbsc/select.h>
#include <openbsc/rs232.h>
/* state of our bs11_config application */
@@ -51,12 +51,12 @@ enum bs11cfg_state {
STATE_QUERY,
};
static enum bs11cfg_state bs11cfg_state = STATE_NONE;
static char *command, *value;
static char *command;
struct timer_list status_timer;
static const u_int8_t obj_li_attr[] = {
static const u_int8_t obj_li_attr[] = {
NM_ATT_BS11_BIT_ERR_THESH, 0x09, 0x00,
NM_ATT_BS11_L1_PROT_TYPE, 0x00,
NM_ATT_BS11_L1_PROT_TYPE, 0x00,
NM_ATT_BS11_LINE_CFG, 0x00,
};
static const u_int8_t obj_bbsig0_attr[] = {
@@ -71,13 +71,6 @@ static const char *trx1_password = "1111111111";
static const u_int8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 };
static struct log_target *stderr_target;
/* dummy function to keep gsm_data.c happy */
struct counter *counter_alloc(const char *name)
{
return NULL;
}
int handle_serial_msg(struct msgb *rx_msg);
@@ -481,7 +474,7 @@ static int handle_state_resp(enum abis_bs11_phase state)
* argument, so our swload_cbfn can distinguish
* a safety load from a regular software */
if (file_is_readable(fname_safety))
rc = abis_nm_software_load(g_bts, 0xff, fname_safety,
rc = abis_nm_software_load(g_bts, fname_safety,
win_size, param_forced,
swload_cbfn, g_bts);
else
@@ -540,21 +533,6 @@ static int handle_state_resp(enum abis_bs11_phase state)
sleep(1);
abis_nm_bs11_factory_logon(g_bts, 0);
command = NULL;
} else if (!strcmp(command, "pll-setvalue")) {
abis_nm_bs11_set_pll(g_bts, atoi(value));
sleep(1);
abis_nm_bs11_factory_logon(g_bts, 0);
command = NULL;
} else if (!strcmp(command, "pll-workvalue")) {
/* To set the work value we need to login as FIELD */
abis_nm_bs11_factory_logon(g_bts, 0);
sleep(1);
abis_nm_bs11_infield_logon(g_bts, 1);
sleep(1);
abis_nm_bs11_set_pll(g_bts, atoi(value));
sleep(1);
abis_nm_bs11_infield_logon(g_bts, 0);
command = NULL;
} else if (!strcmp(command, "oml-tei")) {
abis_nm_bs11_conn_oml_tei(g_bts, 0, 1, 0xff, TEI_OML);
command = NULL;
@@ -649,7 +627,7 @@ int handle_serial_msg(struct msgb *rx_msg)
exit(0);
break;
case NM_MT_BS11_GET_STATE_ACK:
rc = abis_nm_tlv_parse(&tp, g_bts, foh->data, oh->length-sizeof(*foh));
rc = abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
print_state(&tp);
if (TLVP_PRESENT(&tp, NM_ATT_BS11_BTS_STATE) &&
TLVP_LEN(&tp, NM_ATT_BS11_BTS_STATE) >= 1)
@@ -657,7 +635,7 @@ int handle_serial_msg(struct msgb *rx_msg)
break;
case NM_MT_GET_ATTR_RESP:
printf("\n%sATTRIBUTES:\n", obj_name(foh));
abis_nm_tlv_parse(&tp, g_bts, foh->data, oh->length-sizeof(*foh));
abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
rc = print_attr(&tp);
//hexdump(foh->data, oh->length-sizeof(*foh));
break;
@@ -697,8 +675,7 @@ int handle_serial_msg(struct msgb *rx_msg)
}
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_ins)
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
{
return 0;
}
@@ -722,27 +699,25 @@ static void print_help(void)
printf("\t-p --port </dev/ttyXXX>\t\tSpecify serial port\n");
printf("\t-s --software <file>\t\tSpecify Software file\n");
printf("\t-S --safety <file>\t\tSpecify Safety Load file\n");
printf("\t-d --delay <ms>\t\t\tSpecify delay in milliseconds\n");
printf("\t-d --delay <ms>\t\tSpecify delay in milliseconds\n");
printf("\t-D --disconnect\t\t\tDisconnect BTS from BSC\n");
printf("\t-w --win-size <num>\t\tSpecify Window Size\n");
printf("\t-f --forced\t\t\tForce Software Load\n");
printf("\nSupported commands:\n");
printf("\tquery\t\t\tQuery the BS-11 about serial number and configuration\n");
printf("\tdisconnect\t\tDisconnect A-bis link (go into administrative state)\n");
printf("\tresconnect\t\tReconnect A-bis link (go into normal state)\n");
printf("\trestart\t\t\tRestart the BTS\n");
printf("\tsoftware\t\tDownload Software (only in administrative state)\n");
printf("\tcreate-trx1\t\tCreate objects for TRX1 (Danger: Your BS-11 might overheat)\n");
printf("\tdelete-trx1\t\tDelete objects for TRX1\n");
printf("\tpll-e1-locked\t\tSet the PLL to be locked to E1 clock\n");
printf("\tpll-standalone\t\tSet the PLL to be in standalone mode\n");
printf("\tpll-setvalue <value>\tSet the PLL set value\n");
printf("\tpll-workvalue <value>\tSet the PLL work value\n");
printf("\toml-tei\t\t\tSet OML E1 TS and TEI\n");
printf("\tbport0-star\t\tSet BPORT0 line config to star\n");
printf("\tquery\t\tQuery the BS-11 about serial number and configuration\n");
printf("\tdisconnect\tDisconnect A-bis link (go into administrative state)\n");
printf("\tresconnect\tReconnect A-bis link (go into normal state)\n");
printf("\trestart\t\tRestart the BTS\n");
printf("\tsoftware\tDownload Software (only in administrative state)\n");
printf("\tcreate-trx1\tCreate objects for TRX1 (Danger: Your BS-11 might overheat)\n");
printf("\tdelete-trx1\tDelete objects for TRX1\n");
printf("\tpll-e1-locked\tSet the PLL to be locked to E1 clock\n");
printf("\tpll-standalone\tSet the PLL to be in standalone mode\n");
printf("\toml-tei\tSet OML E1 TS and TEI\n");
printf("\tbport0-star\tSet BPORT0 line config to star\n");
printf("\tbport0-multiport\tSet BPORT0 line config to multiport\n");
printf("\tcreate-bport1\t\tCreate BPORT1 object\n");
printf("\tdelete-bport1\t\tDelete BPORT1 object\n");
printf("\tcreate-bport1\tCreate BPORT1 object\n");
printf("\tdelete-bport1\tDelete BPORT1 object\n");
}
static void handle_options(int argc, char **argv)
@@ -779,7 +754,7 @@ static void handle_options(int argc, char **argv)
serial_port = optarg;
break;
case 'b':
log_parse_category_mask(stderr_target, optarg);
debug_parse_category_mask(optarg);
break;
case 's':
fname_software = optarg;
@@ -809,9 +784,6 @@ static void handle_options(int argc, char **argv)
}
if (optind < argc)
command = argv[optind];
if (optind+1 < argc)
value = argv[optind+1];
}
static int num_sigint;
@@ -830,18 +802,12 @@ static void signal_handler(int signal)
}
}
extern int bts_model_bs11_init(void);
int main(int argc, char **argv)
{
struct gsm_network *gsmnet;
int rc;
log_init(&log_info);
stderr_target = log_target_create_stderr();
log_add_target(stderr_target);
log_set_all_filter(stderr_target, 1);
handle_options(argc, argv);
bts_model_bs11_init();
gsmnet = gsm_network_init(1, 1, NULL);
if (!gsmnet) {

View File

@@ -1,13 +0,0 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOSCCP_CFLAGS)
AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS)
bin_PROGRAMS = osmo-bsc
osmo_bsc_SOURCES = osmo_bsc_main.c osmo_bsc_rf.c osmo_bsc_vty.c osmo_bsc_api.c \
$(top_srcdir)/src/debug.c $(top_srcdir)/src/bsc_msc.c \
$(top_srcdir)/src/bsc_init.c
osmo_bsc_LDADD = $(top_builddir)/src/libvty.a \
$(top_builddir)/src/libmgcp.a $(top_builddir)/src/libbsc.a \
$(LIBOSMOSCCP_LIBS)

View File

@@ -1,26 +0,0 @@
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/osmo_bsc.h>
struct bsc_api *osmo_bsc_api()
{
return NULL;
}

View File

@@ -1,188 +0,0 @@
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009-2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/osmo_bsc_rf.h>
#include <osmocom/vty/command.h>
#include <osmocore/talloc.h>
#include <osmocom/sccp/sccp.h>
#define _GNU_SOURCE
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "bscconfig.h"
static struct log_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *config_file = "openbsc.cfg";
static const char *rf_ctl = NULL;
extern void bsc_vty_init(void);
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
static void print_usage()
{
printf("Usage: bsc_msc_ip\n");
}
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(" -T --timestamp. Print a timestamp in the debug output.\n");
printf(" -c --config-file filename The config file to use.\n");
printf(" -l --local=IP. The local address of the MGCP.\n");
printf(" -e --log-level number. Set a global loglevel.\n");
printf(" -r --rf-ctl NAME. A unix domain socket to listen for cmds.\n");
printf(" -t --testmode. A special mode to provoke failures at the MSC.\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'},
{"msc", 1, 0, 'm'},
{"local", 1, 0, 'l'},
{"log-level", 1, 0, 'e'},
{"rf-ctl", 1, 0, 'r'},
{"testmode", 0, 0, 't'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hd:sTc:e:r:t",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_usage();
print_help();
exit(0);
case 's':
log_set_use_color(stderr_target, 0);
break;
case 'd':
log_parse_category_mask(stderr_target, optarg);
break;
case 'c':
config_file = strdup(optarg);
break;
case 'T':
log_set_print_timestamp(stderr_target, 1);
break;
case 'P':
ipacc_rtp_direct = 0;
break;
case 'e':
log_set_log_level(stderr_target, atoi(optarg));
break;
case 'r':
rf_ctl = optarg;
break;
default:
/* ignore */
break;
}
}
}
extern int bts_model_unknown_init(void);
extern int bts_model_bs11_init(void);
extern int bts_model_nanobts_init(void);
extern enum node_type bsc_vty_go_parent(struct vty *vty);
static struct vty_app_info vty_info = {
.name = "OpenBSC Osmo BSC",
.version = PACKAGE_VERSION,
.go_parent_cb = bsc_vty_go_parent,
};
int main(int argc, char **argv)
{
char *msc;
int rc;
log_init(&log_info);
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
stderr_target = log_target_create_stderr();
log_add_target(stderr_target);
bts_model_unknown_init();
bts_model_bs11_init();
bts_model_nanobts_init();
/* enable filters */
log_set_all_filter(stderr_target, 1);
/* This needs to precede handle_options() */
vty_init(&vty_info);
bsc_vty_init();
/* parse options */
handle_options(argc, argv);
/* seed the PRNG */
srand(time(NULL));
/* initialize SCCP */
sccp_set_log_area(DSCCP);
rc = bsc_bootstrap_network(NULL, config_file);
if (rc < 0) {
fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
exit(1);
}
if (rf_ctl) {
struct osmo_bsc_rf *rf;
rf = osmo_bsc_rf_create(rf_ctl, bsc_gsmnet);
if (!rf) {
fprintf(stderr, "Failed to create the RF service.\n");
exit(1);
}
}
while (1) {
bsc_select_main(0);
}
return 0;
}

View File

@@ -1,264 +0,0 @@
/* RF Ctl handling socket */
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/osmo_bsc_rf.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/signal.h>
#include <osmocore/talloc.h>
#include <osmocore/protocol/gsm_12_21.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <unistd.h>
#define RF_CMD_QUERY '?'
#define RF_CMD_OFF '0'
#define RF_CMD_ON '1'
#define RF_CMD_GRACE 'g'
static int lock_each_trx(struct gsm_network *net, int lock)
{
struct gsm_bts *bts;
llist_for_each_entry(bts, &net->bts_list, list) {
struct gsm_bts_trx *trx;
llist_for_each_entry(trx, &bts->trx_list, list) {
gsm_trx_lock_rf(trx, lock);
}
}
return 0;
}
/*
* Send a '1' when one TRX is online, otherwise send 0
*/
static void handle_query(struct osmo_bsc_rf_conn *conn)
{
struct msgb *msg;
struct gsm_bts *bts;
char send = RF_CMD_OFF;
llist_for_each_entry(bts, &conn->gsm_network->bts_list, list) {
struct gsm_bts_trx *trx;
llist_for_each_entry(trx, &bts->trx_list, list) {
if (trx->nm_state.availability == NM_AVSTATE_OK &&
trx->nm_state.operational != NM_STATE_LOCKED) {
send = RF_CMD_ON;
break;
}
}
}
msg = msgb_alloc(10, "RF Query");
if (!msg) {
LOGP(DINP, LOGL_ERROR, "Failed to allocate response msg.\n");
return;
}
msg->l2h = msgb_put(msg, 1);
msg->l2h[0] = send;
if (write_queue_enqueue(&conn->queue, msg) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to enqueue the answer.\n");
msgb_free(msg);
return;
}
return;
}
static void send_signal(struct osmo_bsc_rf_conn *conn, int val)
{
struct rf_signal_data sig;
sig.net = conn->gsm_network;
dispatch_signal(SS_RF, val, &sig);
}
static int rf_read_cmd(struct bsc_fd *fd)
{
struct osmo_bsc_rf_conn *conn = fd->data;
char buf[1];
int rc;
rc = read(fd->fd, buf, sizeof(buf));
if (rc != sizeof(buf)) {
LOGP(DINP, LOGL_ERROR, "Short read %d/%s\n", errno, strerror(errno));
bsc_unregister_fd(fd);
close(fd->fd);
write_queue_clear(&conn->queue);
talloc_free(conn);
return -1;
}
switch (buf[0]) {
case RF_CMD_QUERY:
handle_query(conn);
break;
case RF_CMD_OFF:
lock_each_trx(conn->gsm_network, 1);
send_signal(conn, S_RF_OFF);
break;
case RF_CMD_ON:
lock_each_trx(conn->gsm_network, 0);
send_signal(conn, S_RF_ON);
break;
case RF_CMD_GRACE:
send_signal(conn, S_RF_GRACE);
break;
default:
LOGP(DINP, LOGL_ERROR, "Unknown command %d\n", buf[0]);
break;
}
return 0;
}
static int rf_write_cmd(struct bsc_fd *fd, struct msgb *msg)
{
int rc;
rc = write(fd->fd, msg->data, msg->len);
if (rc != msg->len) {
LOGP(DINP, LOGL_ERROR, "Short write %d/%s\n", errno, strerror(errno));
return -1;
}
return 0;
}
static int rf_ctl_accept(struct bsc_fd *bfd, unsigned int what)
{
struct osmo_bsc_rf_conn *conn;
struct osmo_bsc_rf *rf = bfd->data;
struct sockaddr_un addr;
socklen_t len = sizeof(addr);
int fd;
fd = accept(bfd->fd, (struct sockaddr *) &addr, &len);
if (fd < 0) {
LOGP(DINP, LOGL_ERROR, "Failed to accept. errno: %d/%s\n",
errno, strerror(errno));
return -1;
}
conn = talloc_zero(rf, struct osmo_bsc_rf_conn);
if (!conn) {
LOGP(DINP, LOGL_ERROR, "Failed to allocate mem.\n");
close(fd);
return -1;
}
write_queue_init(&conn->queue, 10);
conn->queue.bfd.data = conn;
conn->queue.bfd.fd = fd;
conn->queue.bfd.when = BSC_FD_READ | BSC_FD_WRITE;
conn->queue.read_cb = rf_read_cmd;
conn->queue.write_cb = rf_write_cmd;
conn->gsm_network = rf->gsm_network;
if (bsc_register_fd(&conn->queue.bfd) != 0) {
close(fd);
talloc_free(conn);
return -1;
}
return 0;
}
struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net)
{
unsigned int namelen;
struct sockaddr_un local;
struct bsc_fd *bfd;
struct osmo_bsc_rf *rf;
int rc;
rf = talloc_zero(NULL, struct osmo_bsc_rf);
if (!rf) {
LOGP(DINP, LOGL_ERROR, "Failed to create osmo_bsc_rf.\n");
return NULL;
}
bfd = &rf->listen;
bfd->fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (bfd->fd < 0) {
LOGP(DINP, LOGL_ERROR, "Can not create socket. %d/%s\n",
errno, strerror(errno));
return NULL;
}
local.sun_family = AF_UNIX;
strncpy(local.sun_path, path, sizeof(local.sun_path));
local.sun_path[sizeof(local.sun_path) - 1] = '\0';
unlink(local.sun_path);
/* we use the same magic that X11 uses in Xtranssock.c for
* calculating the proper length of the sockaddr */
#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
local.sun_len = strlen(local.sun_path);
#endif
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
namelen = SUN_LEN(&local);
#else
namelen = strlen(local.sun_path) +
offsetof(struct sockaddr_un, sun_path);
#endif
rc = bind(bfd->fd, (struct sockaddr *) &local, namelen);
if (rc != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to bind '%s' errno: %d/%s\n",
local.sun_path, errno, strerror(errno));
close(bfd->fd);
talloc_free(rf);
return NULL;
}
if (listen(bfd->fd, 0) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to listen: %d/%s\n", errno, strerror(errno));
close(bfd->fd);
talloc_free(rf);
return NULL;
}
bfd->when = BSC_FD_READ;
bfd->cb = rf_ctl_accept;
bfd->data = rf;
if (bsc_register_fd(bfd) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to register bfd.\n");
close(bfd->fd);
talloc_free(rf);
return NULL;
}
rf->gsm_network = net;
return rf;
}

View File

@@ -1,209 +0,0 @@
/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */
/* (C) 2010 by Holger Hans Peter Freyther
* (C) 2010 by On Waves
* (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 <openbsc/bsc_api.h>
#include <openbsc/bsc_rll.h>
#include <openbsc/gsm_data.h>
#include <openbsc/signal.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/handover.h>
#include <openbsc/debug.h>
#include <osmocore/talloc.h>
static void rll_ind_cb(struct gsm_lchan *, uint8_t, void *, enum bsc_rllr_ind);
static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id);
int bsc_api_init(struct gsm_network *network, struct bsc_api *api)
{
network->bsc_api = api;
return 0;
}
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn,
struct msgb *msg, int link_id)
{
uint8_t sapi = link_id & 0x7;
msg->lchan = conn->lchan;
msg->trx = msg->lchan->ts->trx;
msg->l3h = msg->data;
if (conn->lchan->sapis[sapi] == LCHAN_SAPI_UNUSED) {
OBSC_LINKID_CB(msg) = link_id;
if (rll_establish(msg->lchan, sapi, rll_ind_cb, msg) != 0) {
msgb_free(msg);
send_sapi_reject(conn, link_id);
return -1;
}
return 0;
} else {
return rsl_data_request(msg, link_id);
}
}
/**
* Send a GSM08.08 Assignment Request. Right now this does not contain the
* audio codec type or the allowed rates for the config.
*/
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_type, int audio)
{
struct bsc_api *api;
api = conn->bts->network->bsc_api;
api->assign_fail(conn, 0);
return 0;
}
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group, unsigned int mi_len,
uint8_t *mi, int chan_type)
{
return rsl_paging_cmd(bts, page_group, mi_len, mi, chan_type);
}
/* dequeue messages to layer 4 */
int bsc_upqueue(struct gsm_network *net)
{
struct gsm_mncc *mncc;
struct msgb *msg;
int work = 0;
if (net)
while ((msg = msgb_dequeue(&net->upqueue))) {
mncc = (struct gsm_mncc *)msg->data;
if (net->mncc_recv)
net->mncc_recv(net, mncc->msg_type, mncc);
work = 1; /* work done */
talloc_free(msg);
}
return work;
}
int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id)
{
int rc;
struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
struct gsm_lchan *lchan;
lchan = msg->lchan;
if (lchan->state != LCHAN_S_ACTIVE) {
LOGP(DRSL, LOGL_ERROR, "Got data in non active state. discarding.\n");
return -1;
}
if (lchan->conn) {
api->dtap(lchan->conn, msg);
} else {
rc = BSC_API_CONN_POL_REJECT;
lchan->conn = subscr_con_allocate(msg->lchan);
if (lchan->conn)
rc = api->compl_l3(lchan->conn, msg, 0);
if (rc != BSC_API_CONN_POL_ACCEPT) {
subscr_con_free(lchan->conn);
lchan_release(lchan, 0, 0);
}
}
return 0;
}
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
uint8_t *key, int len)
{
return -1;
}
int gsm0808_clear(struct gsm_subscriber_connection* conn)
{
struct gsm_lchan *lchan;
bsc_clear_handover(conn);
lchan = conn->lchan;
subscr_con_free(conn);
lchan_release(lchan, 1, 0);
return 0;
}
static void send_sapi_reject(struct gsm_subscriber_connection *conn, int link_id)
{
struct bsc_api *api;
if (!conn)
return;
api = conn->bts->network->bsc_api;
if (!api || !api->sapi_n_reject)
return;
api->sapi_n_reject(conn, link_id);
}
static void rll_ind_cb(struct gsm_lchan *lchan, uint8_t link_id, void *_data, enum bsc_rllr_ind rllr_ind)
{
struct msgb *msg = _data;
switch (rllr_ind) {
case BSC_RLLR_IND_EST_CONF:
rsl_data_request(msg, OBSC_LINKID_CB(msg));
break;
case BSC_RLLR_IND_REL_IND:
case BSC_RLLR_IND_ERR_IND:
case BSC_RLLR_IND_TIMEOUT:
send_sapi_reject(lchan->conn, OBSC_LINKID_CB(msg));
msgb_free(msg);
break;
}
}
static int bsc_handle_lchan_signal(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct bsc_api *bsc;
struct gsm_lchan *lchan;
if (subsys != SS_LCHAN || signal != S_LCHAN_UNEXPECTED_RELEASE)
return 0;
lchan = (struct gsm_lchan *)signal_data;
if (!lchan || !lchan->conn)
return 0;
bsc = lchan->ts->trx->bts->network->bsc_api;
if (!bsc || !bsc->clear_request)
return 0;
bsc->clear_request(lchan->conn, 0);
subscr_con_free(lchan->conn);
return 0;
}
static __attribute__((constructor)) void on_dso_load_bsc(void)
{
register_signal_handler(SS_LCHAN, bsc_handle_lchan_signal, NULL);
}

View File

@@ -1,6 +1,6 @@
/* A hackish minimal BSC (+MSC +HLR) implementation */
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
@@ -31,27 +31,16 @@
#include <getopt.h>
#include <openbsc/db.h>
#include <osmocore/select.h>
#include <openbsc/select.h>
#include <openbsc/debug.h>
#include <openbsc/e1_input.h>
#include <osmocore/talloc.h>
#include <openbsc/signal.h>
#include <openbsc/osmo_msc.h>
#include <osmocom/vty/command.h>
#include "../bscconfig.h"
#include <openbsc/talloc.h>
/* MCC and MNC for the Location Area Identifier */
static struct log_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *database_name = "hlr.sqlite3";
static const char *config_file = "openbsc.cfg";
extern const char *openbsc_copyright;
/* timer to store statistics */
#define DB_SYNC_INTERVAL 60, 0
static struct timer_list db_sync_timer;
extern int ipacc_rtp_direct;
extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
const char *cfg_file);
@@ -80,15 +69,12 @@ 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(" -c --config-file filename The config file to use.\n");
printf(" -s --disable-color\n");
printf(" -c --config-file filename The config file to use.\n");
printf(" -l --database db-name The database to use\n");
printf(" -a --authorize-everyone. Authorize every new subscriber. Dangerous!.\n");
printf(" -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
printf(" -p --pcap file The filename of the pcap file\n");
printf(" -T --timestamp Prefix every log line with a timestamp\n");
printf(" -V --version. Print the version of OpenBSC.\n");
printf(" -P --rtp-proxy Enable the RTP Proxy code inside OpenBSC\n");
printf(" -e --log-level number. Set a global loglevel.\n");
}
static void handle_options(int argc, char** argv)
@@ -102,15 +88,14 @@ static void handle_options(int argc, char** argv)
{"disable-color", 0, 0, 's'},
{"database", 1, 0, 'l'},
{"authorize-everyone", 0, 0, 'a'},
{"reject-cause", 1, 0, 'r'},
{"pcap", 1, 0, 'p'},
{"timestamp", 0, 0, 'T'},
{"version", 0, 0, 'V' },
{"rtp-proxy", 0, 0, 'P'},
{"log-level", 1, 0, 'e'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hd:sl:ar:p:TPVc:e:",
c = getopt_long(argc, argv, "hd:sl:ar:p:TPc:",
long_options, &option_index);
if (c == -1)
break;
@@ -121,10 +106,10 @@ static void handle_options(int argc, char** argv)
print_help();
exit(0);
case 's':
log_set_use_color(stderr_target, 0);
debug_use_color(0);
break;
case 'd':
log_parse_category_mask(stderr_target, optarg);
debug_parse_category_mask(optarg);
break;
case 'l':
database_name = strdup(optarg);
@@ -132,22 +117,18 @@ static void handle_options(int argc, char** argv)
case 'c':
config_file = strdup(optarg);
break;
case 'r':
gsm0408_set_reject_cause(atoi(optarg));
break;
case 'p':
create_pcap_file(optarg);
break;
case 'T':
log_set_print_timestamp(stderr_target, 1);
debug_timestamp(1);
break;
case 'P':
ipacc_rtp_direct = 0;
break;
case 'e':
log_set_log_level(stderr_target, atoi(optarg));
break;
case 'V':
print_version(1);
exit(0);
break;
default:
/* ignore */
break;
@@ -155,7 +136,6 @@ static void handle_options(int argc, char** argv)
}
}
extern void *tall_vty_ctx;
static void signal_handler(int signal)
{
fprintf(stdout, "signal %u received\n", signal);
@@ -163,7 +143,6 @@ static void signal_handler(int signal)
switch (signal) {
case SIGINT:
bsc_shutdown_net(bsc_gsmnet);
dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
sleep(3);
exit(0);
break;
@@ -171,76 +150,25 @@ static void signal_handler(int signal)
/* 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(tall_vty_ctx, stderr);
talloc_report_full(tall_bsc_ctx, stderr);
break;
case SIGUSR2:
talloc_report_full(tall_vty_ctx, stderr);
break;
default:
break;
}
}
/* timer handling */
static int _db_store_counter(struct counter *counter, void *data)
{
return db_store_counter(counter);
}
static void db_sync_timer_cb(void *data)
{
/* store counters to database and re-schedule */
counters_for_each(_db_store_counter, NULL);
bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
}
extern int bts_model_unknown_init(void);
extern int bts_model_bs11_init(void);
extern int bts_model_nanobts_init(void);
extern enum node_type bsc_vty_go_parent(struct vty *vty);
static struct vty_app_info vty_info = {
.name = "OpenBSC",
.version = PACKAGE_VERSION,
.go_parent_cb = bsc_vty_go_parent,
};
int main(int argc, char **argv)
{
int rc;
vty_info.copyright = openbsc_copyright;
log_init(&log_info);
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
talloc_ctx_init();
on_dso_load_token();
on_dso_load_rrlp();
on_dso_load_ho_dec();
stderr_target = log_target_create_stderr();
log_add_target(stderr_target);
bts_model_unknown_init();
bts_model_bs11_init();
bts_model_nanobts_init();
/* enable filters */
log_set_all_filter(stderr_target, 1);
/* This needs to precede handle_options() */
vty_init(&vty_info);
bsc_vty_init();
/* parse options */
handle_options(argc, argv);
rc = bsc_bootstrap_network(mncc_recv, config_file);
if (rc < 0)
exit(1);
bsc_api_init(bsc_gsmnet, msc_bsc_api());
/* seed the PRNG */
srand(time(NULL));
@@ -256,20 +184,16 @@ int main(int argc, char **argv)
}
printf("DB: Database prepared.\n");
/* setup the timer */
db_sync_timer.cb = db_sync_timer_cb;
db_sync_timer.data = NULL;
bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
rc = bsc_bootstrap_network(mncc_recv, config_file);
if (rc < 0)
exit(1);
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
signal(SIGPIPE, SIG_IGN);
while (1) {
bsc_upqueue(bsc_gsmnet);
log_reset_context();
bsc_select_main(0);
}
}

View File

@@ -1,6 +1,6 @@
/* A hackish minimal BSC (+MSC +HLR) implementation */
/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
@@ -21,23 +21,23 @@
*/
#include <openbsc/gsm_data.h>
#include <osmocore/gsm_utils.h>
#include <openbsc/gsm_utils.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/abis_nm.h>
#include <openbsc/debug.h>
#include <openbsc/misdn.h>
#include <osmocom/vty/telnet_interface.h>
#include <openbsc/system_information.h>
#include <openbsc/telnet_interface.h>
#include <openbsc/paging.h>
#include <openbsc/signal.h>
#include <openbsc/chan_alloc.h>
#include <osmocore/talloc.h>
#include <openbsc/talloc.h>
/* global pointer to the gsm network data structure */
extern struct gsm_network *bsc_gsmnet;
extern int ipacc_rtp_direct;
static void patch_nm_tables(struct gsm_bts *bts);
static void patch_si_tables(struct gsm_bts *bts);
/* The following definitions are for OM and NM packets that we cannot yet
* generate by code but we just pass on */
@@ -331,7 +331,6 @@ static unsigned char nanobts_attr_bts[] = {
NM_ATT_NY1, 10, /* 10 retransmissions of physical config */
NM_ATT_BCCH_ARFCN, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
NM_ATT_BSIC, HARDCODED_BSIC,
NM_ATT_IPACC_CGI, 0, 7, 0x00, 0xf1, 0x10, 0x00, 0x01, 0x00, 0x00,
};
static unsigned char nanobts_attr_radio[] = {
@@ -339,75 +338,13 @@ static unsigned char nanobts_attr_radio[] = {
NM_ATT_ARFCN_LIST, 0x00, 0x02, HARDCODED_ARFCN >> 8, HARDCODED_ARFCN & 0xff,
};
static unsigned char nanobts_attr_nse[] = {
NM_ATT_IPACC_NSEI, 0, 2, 0x03, 0x9d, /* NSEI 925 */
NM_ATT_IPACC_NS_CFG, 0, 7, 3, /* (un)blocking timer (Tns-block) */
3, /* (un)blocking retries */
3, /* reset timer (Tns-reset) */
3, /* reset retries */
30, /* test timer (Tns-test) */
3, /* alive timer (Tns-alive) */
10, /* alive retrires */
NM_ATT_IPACC_BSSGP_CFG, 0, 11,
3, /* blockimg timer (T1) */
3, /* blocking retries */
3, /* unblocking retries */
3, /* reset timer */
3, /* reset retries */
10, /* suspend timer (T3) in 100ms */
3, /* suspend retries */
10, /* resume timer (T4) in 100ms */
3, /* resume retries */
10, /* capability update timer (T5) */
3, /* capability update retries */
};
static unsigned char nanobts_attr_cell[] = {
NM_ATT_IPACC_RAC, 0, 1, 1, /* routing area code */
NM_ATT_IPACC_GPRS_PAGING_CFG, 0, 2,
5, /* repeat time (50ms) */
3, /* repeat count */
NM_ATT_IPACC_BVCI, 0, 2, 0x03, 0x9d, /* BVCI 925 */
NM_ATT_IPACC_RLC_CFG, 0, 9,
20, /* T3142 */
5, /* T3169 */
5, /* T3191 */
200, /* T3193 */
5, /* T3195 */
10, /* N3101 */
4, /* N3103 */
8, /* N3105 */
15, /* RLC CV countdown */
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
0x00, 250, /* T downlink TBF extension (0..500) */
0x00, 250, /* T uplink TBF extension (0..500) */
2, /* CS2 */
#if 0
/* EDGE model only, breaks older models.
* Should inquire the BTS capabilities */
NM_ATT_IPACC_RLC_CFG_3, 0, 1,
2, /* MCS2 */
#endif
};
static unsigned char nanobts_attr_nsvc0[] = {
NM_ATT_IPACC_NSVCI, 0, 2, 0x03, 0x9d, /* 925 */
NM_ATT_IPACC_NS_LINK_CFG, 0, 8,
0x59, 0xd8, /* remote udp port (23000) */
192, 168, 100, 11, /* remote ip address */
0x59, 0xd8, /* local udp port (23000) */
};
/* Callback function to be called whenever we get a GSM 12.21 state change event */
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst)
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
{
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
struct gsm_bts_trx_ts *ts;
struct gsm_bts_gprs_nsvc *nsvc;
/* This event-driven BTS setup is currently only required on nanoBTS */
@@ -419,15 +356,16 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
switch (obj_class) {
case NM_OC_SITE_MANAGER:
bts = container_of(obj, struct gsm_bts, site_mgr);
if ((new_state->operational == NM_OPSTATE_ENABLED &&
new_state->availability == NM_AVSTATE_OK) ||
(new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OFF_LINE))
if (new_state->operational == 2 &&
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));
@@ -441,8 +379,9 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
case NM_OC_CHANNEL:
ts = obj;
trx = ts->trx;
if (new_state->operational == NM_OPSTATE_DISABLED &&
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);
@@ -456,58 +395,13 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
break;
case NM_OC_RADIO_CARRIER:
trx = obj;
if (new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OK)
if (new_state->operational == 1 &&
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);
break;
case NM_OC_GPRS_NSE:
bts = container_of(obj, struct gsm_bts, gprs.nse);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0xff, 0xff, nanobts_attr_nse,
sizeof(nanobts_attr_nse));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0xff, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
0xff, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_CELL:
bts = container_of(obj, struct gsm_bts, gprs.cell);
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == NM_AVSTATE_DEPENDENCY) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
0, 0xff, nanobts_attr_cell,
sizeof(nanobts_attr_cell));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
0, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
0, 0xff, NM_STATE_UNLOCKED);
}
break;
case NM_OC_GPRS_NSVC:
nsvc = obj;
bts = nsvc->bts;
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
/* We skip NSVC1 since we only use NSVC0 */
if (nsvc->id == 1)
break;
if (new_state->availability == NM_AVSTATE_OFF_LINE) {
abis_nm_ipaccess_set_attr(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
nanobts_attr_nsvc0,
sizeof(nanobts_attr_nsvc0));
abis_nm_opstart(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff);
abis_nm_chg_adm_state(bts, obj_class, bts->bts_nr,
nsvc->id, 0xff,
NM_STATE_UNLOCKED);
}
default:
break;
}
@@ -521,11 +415,10 @@ static int sw_activ_rep(struct msgb *mb)
struct gsm_bts *bts = mb->trx->bts;
struct gsm_bts_trx *trx = gsm_bts_trx_num(bts, foh->obj_inst.trx_nr);
if (!trx)
return -EINVAL;
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);
@@ -544,7 +437,9 @@ static int sw_activ_rep(struct msgb *mb)
* This code is here to make sure that on start
* a TRX remains locked.
*/
int rc_state = trx->nm_state.administrative;
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;
@@ -563,10 +458,10 @@ static int sw_activ_rep(struct msgb *mb)
}
/* Callback function for NACK on the OML NM */
static int oml_msg_nack(struct nm_nack_signal_data *nack)
static int oml_msg_nack(u_int8_t mt)
{
if (nack->mt == NM_MT_SET_BTS_ATTR_NACK) {
LOGP(DNM, LOGL_FATAL, "Failed to set BTS attributes. That is fatal. "
if (mt == NM_MT_SET_BTS_ATTR_NACK) {
fprintf(stderr, "Failed to set BTS attributes. That is fatal. "
"Was the bts type and frequency properly specified?\n");
exit(-1);
}
@@ -578,15 +473,14 @@ static int oml_msg_nack(struct nm_nack_signal_data *nack)
static int nm_sig_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct nm_nack_signal_data *nack;
u_int8_t *msg_type;
switch (signal) {
case S_NM_SW_ACTIV_REP:
return sw_activ_rep(signal_data);
case S_NM_NACK:
nack = signal_data;
return oml_msg_nack(nack);
msg_type = signal_data;
return oml_msg_nack(*msg_type);
default:
break;
}
@@ -670,7 +564,7 @@ static void nm_reconfig_trx(struct gsm_bts_trx *trx)
trx->nominal_power = 23;
break;
default:
LOGP(DNM, LOGL_ERROR, "Unsupported nanoBTS GSM band %s\n",
fprintf(stderr, "Unsupported nanoBTS GSM band %s\n",
gsm_band_name(trx->bts->band));
break;
}
@@ -689,7 +583,6 @@ static void nm_reconfig_bts(struct gsm_bts *bts)
switch (bts->type) {
case GSM_BTS_TYPE_BS11:
patch_nm_tables(bts);
abis_nm_raw_msg(bts, sizeof(msg_1), msg_1); /* set BTS SiteMgr attr*/
abis_nm_set_bts_attr(bts, bs11_attr_bts, sizeof(bs11_attr_bts));
abis_nm_raw_msg(bts, sizeof(msg_3), msg_3); /* set BTS handover attr */
@@ -735,7 +628,7 @@ static void bootstrap_om_bs11(struct gsm_bts *bts)
static void bootstrap_om(struct gsm_bts *bts)
{
LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
fprintf(stdout, "bootstrapping OML for BTS %u\n", bts->nr);
switch (bts->type) {
case GSM_BTS_TYPE_BS11:
@@ -745,13 +638,13 @@ static void bootstrap_om(struct gsm_bts *bts)
bootstrap_om_nanobts(bts);
break;
default:
LOGP(DNM, LOGL_ERROR, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type);
fprintf(stderr, "Unable to bootstrap OML: Unknown BTS type %d\n", bts->type);
}
}
static int shutdown_om(struct gsm_bts *bts)
{
LOGP(DNM, LOGL_NOTICE, "shutting down OML for BTS %u\n", bts->nr);
fprintf(stdout, "shutting down OML for BTS %u\n", bts->nr);
/* stop sending event reports */
abis_nm_event_reports(bts, 0);
@@ -782,90 +675,219 @@ int bsc_shutdown_net(struct gsm_network *net)
return 0;
}
static int generate_and_rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i)
{
struct gsm_bts *bts = trx->bts;
int rc;
struct bcch_info {
u_int8_t type;
u_int8_t len;
const u_int8_t *data;
};
/* Only generate SI if this SI is not in "static" (user-defined) mode */
if (!(bts->si_mode_static & (1 << i))) {
rc = gsm_generate_si(bts, i);
if (rc < 0)
return rc;
}
/*
SYSTEM INFORMATION TYPE 1
Cell channel description
Format-ID bit map 0
CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
RACH Control Parameters
maximum 7 retransmissions
8 slots used to spread transmission
cell not barred for access
call reestablishment not allowed
Access Control Class = 0000
*/
static u_int8_t si1[] = {
/* header */0x55, 0x06, 0x19,
/* ccdesc */0x04 /*0x00*/, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*0x01*/,
/* rach */0xD5, 0x04, 0x00,
/* s1 reset*/0x2B
};
DEBUGP(DRR, "SI%s: %s\n", gsm_sitype_name(i),
hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
/*
SYSTEM INFORMATION TYPE 2
Neighbour Cells Description
EXT-IND: Carries the complete BA
BA-IND = 0
Format-ID bit map 0
CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
NCC permitted (NCC) = FF
RACH Control Parameters
maximum 7 retransmissions
8 slots used to spread transmission
cell not barred for access
call reestablishment not allowed
Access Control Class = 0000
*/
static u_int8_t si2[] = {
/* header */0x59, 0x06, 0x1A,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* ncc */0xFF,
/* rach*/0xD5, 0x04, 0x00
};
switch (i) {
case SYSINFO_TYPE_5:
case SYSINFO_TYPE_5bis:
case SYSINFO_TYPE_5ter:
case SYSINFO_TYPE_6:
rc = rsl_sacch_filling(trx, gsm_sitype2rsl(i),
GSM_BTS_SI(bts, i), rc);
break;
default:
rc = rsl_bcch_info(trx, gsm_sitype2rsl(i),
GSM_BTS_SI(bts, i), rc);
break;
}
/*
SYSTEM INFORMATION TYPE 3
Cell identity = 00001 (1h)
Location area identification
Mobile Country Code (MCC): 001
Mobile Network Code (MNC): 01
Location Area Code (LAC): 00001 (1h)
Control Channel Description
Attach-detach: MSs in the cell are not allowed to apply IMSI attach /detach
0 blocks reserved for access grant
1 channel used for CCCH, with SDCCH
5 multiframes period for PAGING REQUEST
Time-out T3212 = 0
Cell Options BCCH
Power control indicator: not set
MSs shall not use uplink DTX
Radio link timeout = 36
Cell Selection Parameters
Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
max.TX power level MS may use for CCH = 2 <- according to GSM05.05 39dBm (max)
Additional Reselect Parameter Indication (ACS) = only SYSTEM INFO 4: The SI rest octets, if present, shall be used to derive the value of PI and possibly C2 parameters
Half rate support (NECI): New establishment causes are not supported
min.RX signal level for MS = 0
RACH Control Parameters
maximum 7 retransmissions
8 slots used to spread transmission
cell not barred for access
call reestablishment not allowed
Access Control Class = 0000
SI 3 Rest Octets (not present)
*/
static u_int8_t si3[] = {
/* header */0x49, 0x06, 0x1B,
/* cell */0x00, 0x01,
/* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
/* desc */0x01, 0x03, 0x00,
/* option*/0x28,
/* selection*/0x62, 0x00,
/* rach */0xD5, 0x04, 0x00,
/* rest */ 0x2B, 0x2B, 0x2B, 0x2B
};
return rc;
}
/*
SYSTEM INFORMATION TYPE 4
Location area identification
Mobile Country Code (MCC): 001
Mobile Network Code (MNC): 01
Location Area Code (LAC): 00001 (1h)
Cell Selection Parameters
Cell reselect hysteresis = 6 dB RXLEV hysteresis for LA re-selection
max.TX power level MS may use for CCH = 2
Additional Reselect Parameter Indication (ACS) = only SYSTEM INFO 4: The SI rest octets, if present, shall be used to derive the value of PI and possibly C2 parameters
Half rate support (NECI): New establishment causes are not supported
min.RX signal level for MS = 0
RACH Control Parameters
maximum 7 retransmissions
8 slots used to spread transmission
cell not barred for access
call reestablishment not allowed
Access Control Class = 0000
CBCH Channel Description
Type = SDCCH/4[2]
Timeslot Number: 0
Training Sequence Code: 7h
ARFCN: 1
SI Rest Octets (not present)
*/
static u_int8_t si4[] = {
/* header */0x41, 0x06, 0x1C,
/* lai */0x00, 0xF1, 0x10, 0x00, 0x01,
/* sel */0x62, 0x00,
/* rach*/0xD5, 0x04, 0x00,
/* cbch chan desc */ 0x64, 0x30, 0xE0, HARDCODED_ARFCN/*0x01*/,
/* rest octets */ 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B
};
/*
SYSTEM INFORMATION TYPE 5
Neighbour Cells Description
EXT-IND: Carries the complete BA
BA-IND = 0
Format-ID bit map 0
CA-ARFCN Bit 124...001 (Hex): 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*/
static u_int8_t si5[] = {
/* header without l2 len*/0x06, 0x1D,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// SYSTEM INFORMATION TYPE 6
/*
SACCH FILLING
System Info Type: SYSTEM INFORMATION 6
L3 Information (Hex): 06 1E 00 01 xx xx 10 00 01 28 FF
SYSTEM INFORMATION TYPE 6
Cell identity = 00001 (1h)
Location area identification
Mobile Country Code (MCC): 001
Mobile Network Code (MNC): 01
Location Area Code (LAC): 00001 (1h)
Cell Options SACCH
Power control indicator: not set
MSs shall not use uplink DTX on a TCH-F. MS shall not use uplink DTX on TCH-H.
Radio link timeout = 36
NCC permitted (NCC) = FF
*/
static u_int8_t si6[] = {
/* header */0x06, 0x1E,
/* cell id*/ 0x00, 0x01,
/* lai */ 0x00, 0xF1, 0x10, 0x00, 0x01,
/* options */ 0x28,
/* ncc */ 0xFF,
};
static const struct bcch_info bcch_infos[] = {
{
.type = RSL_SYSTEM_INFO_1,
.len = sizeof(si1),
.data = si1,
}, {
.type = RSL_SYSTEM_INFO_2,
.len = sizeof(si2),
.data = si2,
}, {
.type = RSL_SYSTEM_INFO_3,
.len = sizeof(si3),
.data = si3,
}, {
.type = RSL_SYSTEM_INFO_4,
.len = sizeof(si4),
.data = si4,
},
};
static_assert(sizeof(si1) == sizeof(struct gsm48_system_information_type_1), type1)
static_assert(sizeof(si2) == sizeof(struct gsm48_system_information_type_2), type2)
static_assert(sizeof(si3) == sizeof(struct gsm48_system_information_type_3), type3)
static_assert(sizeof(si4) >= sizeof(struct gsm48_system_information_type_4), type4)
static_assert(sizeof(si5) == sizeof(struct gsm48_system_information_type_5), type5)
static_assert(sizeof(si6) >= sizeof(struct gsm48_system_information_type_6), type6)
/* set all system information types */
static int set_system_infos(struct gsm_bts_trx *trx)
{
int i, rc;
struct gsm_bts *bts = trx->bts;
int i;
bts->si_common.cell_sel_par.ms_txpwr_max_ccch =
ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
bts->si_common.cell_sel_par.neci = bts->network->neci;
/* First, we determine which of the SI messages we actually need */
if (trx == bts->c0) {
/* 1...4 are always present on a C0 TRX */
for (i = SYSINFO_TYPE_1; i <= SYSINFO_TYPE_4; i++)
bts->si_valid |= (1 << i);
/* 13 is always present on a C0 TRX of a GPRS BTS */
if (bts->gprs.mode != BTS_GPRS_NONE)
bts->si_valid |= (1 << SYSINFO_TYPE_13);
}
/* 5 and 6 are always present on every TRX */
bts->si_valid |= (1 << SYSINFO_TYPE_5);
bts->si_valid |= (1 << SYSINFO_TYPE_6);
/* Second, we generate and send the selected SI via RSL */
for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) {
if (!(bts->si_valid & (1 << i)))
continue;
rc = generate_and_rsl_si(trx, i);
if (rc < 0)
goto err_out;
if (trx == trx->bts->c0) {
for (i = 0; i < ARRAY_SIZE(bcch_infos); i++) {
rsl_bcch_info(trx, bcch_infos[i].type,
bcch_infos[i].data,
bcch_infos[i].len);
}
}
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_5, si5, sizeof(si5));
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_6, si6, sizeof(si6));
return 0;
err_out:
LOGP(DRR, LOGL_ERROR, "Cannot generate SI %u for BTS %u, most likely "
"a problem with neighbor cell list generation\n",
i, bts->nr);
return rc;
}
static void patch_16(uint8_t *data, const uint16_t val)
{
memcpy(data, &val, sizeof(val));
}
static void patch_32(uint8_t *data, const uint32_t val)
{
memcpy(data, &val, sizeof(val));
}
/*
@@ -890,143 +912,95 @@ static void patch_nm_tables(struct gsm_bts *bts)
bs11_attr_radio[2] |= arfcn_high;
bs11_attr_radio[3] = arfcn_low;
/* patch the RACH attributes */
if (bts->rach_b_thresh != -1) {
nanobts_attr_bts[33] = bts->rach_b_thresh & 0xff;
bs11_attr_bts[33] = bts->rach_b_thresh & 0xff;
}
if (bts->rach_ldavg_slots != -1) {
u_int8_t avg_high = bts->rach_ldavg_slots & 0xff;
u_int8_t avg_low = (bts->rach_ldavg_slots >> 8) & 0x0f;
nanobts_attr_bts[35] = avg_high;
nanobts_attr_bts[36] = avg_low;
bs11_attr_bts[35] = avg_high;
bs11_attr_bts[36] = avg_low;
}
/* patch BSIC */
bs11_attr_bts[1] = bts->bsic;
nanobts_attr_bts[sizeof(nanobts_attr_bts)-11] = bts->bsic;
/* patch CGI */
abis_nm_ipaccess_cgi(nanobts_attr_bts+sizeof(nanobts_attr_bts)-7, bts);
nanobts_attr_bts[sizeof(nanobts_attr_bts)-1] = bts->bsic;
/* patch the power reduction */
bs11_attr_radio[5] = bts->c0->max_power_red / 2;
nanobts_attr_radio[1] = bts->c0->max_power_red / 2;
/* patch NSEI */
nanobts_attr_nse[3] = bts->gprs.nse.nsei >> 8;
nanobts_attr_nse[4] = bts->gprs.nse.nsei & 0xff;
memcpy(nanobts_attr_nse+8, bts->gprs.nse.timer,
ARRAY_SIZE(bts->gprs.nse.timer));
memcpy(nanobts_attr_nse+18, bts->gprs.cell.timer,
ARRAY_SIZE(bts->gprs.cell.timer));
/* patch NSVCI */
nanobts_attr_nsvc0[3] = bts->gprs.nsvc[0].nsvci >> 8;
nanobts_attr_nsvc0[4] = bts->gprs.nsvc[0].nsvci & 0xff;
/* patch IP address as SGSN IP */
patch_16(nanobts_attr_nsvc0 + 8,
htons(bts->gprs.nsvc[0].remote_port));
patch_32(nanobts_attr_nsvc0 + 10,
htonl(bts->gprs.nsvc[0].remote_ip));
patch_16(nanobts_attr_nsvc0 + 14,
htons(bts->gprs.nsvc[0].local_port));
/* patch BVCI */
nanobts_attr_cell[12] = bts->gprs.cell.bvci >> 8;
nanobts_attr_cell[13] = bts->gprs.cell.bvci & 0xff;
/* patch RAC */
nanobts_attr_cell[3] = bts->gprs.rac;
if (bts->gprs.mode == BTS_GPRS_EGPRS) {
/* patch EGPRS coding schemes MCS 1..9 */
nanobts_attr_cell[29] = 0x8f;
nanobts_attr_cell[30] = 0xff;
}
}
/* Produce a MA as specified in 10.5.2.21 */
static int generate_ma_for_ts(struct gsm_bts_trx_ts *ts)
/*
* Patch the various SYSTEM INFORMATION tables to update
* the LAI
*/
static void patch_si_tables(struct gsm_bts *bts)
{
/* we have three bitvecs: the per-timeslot ARFCNs, the cell chan ARFCNs
* and the MA */
struct bitvec *cell_chan = &ts->trx->bts->si_common.cell_alloc;
struct bitvec *ts_arfcn = &ts->hopping.arfcns;
struct bitvec *ma = &ts->hopping.ma;
unsigned int num_cell_arfcns, bitnum, n_chan;
int i;
u_int8_t arfcn_low = bts->c0->arfcn & 0xff;
u_int8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f;
/* re-set the MA to all-zero */
ma->cur_bit = 0;
ts->hopping.ma_len = 0;
memset(ma->data, 0, ma->data_len);
/* covert the raw packet to the struct */
struct gsm48_system_information_type_1 *type_1 =
(struct gsm48_system_information_type_1*)&si1;
struct gsm48_system_information_type_2 *type_2 =
(struct gsm48_system_information_type_2*)&si2;
struct gsm48_system_information_type_3 *type_3 =
(struct gsm48_system_information_type_3*)&si3;
struct gsm48_system_information_type_4 *type_4 =
(struct gsm48_system_information_type_4*)&si4;
struct gsm48_system_information_type_6 *type_6 =
(struct gsm48_system_information_type_6*)&si6;
struct gsm48_loc_area_id lai;
if (!ts->hopping.enabled)
return 0;
gsm0408_generate_lai(&lai, bts->network->country_code,
bts->network->network_code,
bts->location_area_code);
/* count the number of ARFCNs in the cell channel allocation */
num_cell_arfcns = 0;
for (i = 1; i < 1024; i++) {
if (bitvec_get_bit_pos(cell_chan, i))
num_cell_arfcns++;
/* assign the MCC and MNC */
type_3->lai = lai;
type_4->lai = lai;
type_6->lai = lai;
/* set the CI */
type_3->cell_identity = htons(bts->cell_identity);
type_6->cell_identity = htons(bts->cell_identity);
type_4->data[2] &= 0xf0;
type_4->data[2] |= arfcn_high;
type_4->data[3] = arfcn_low;
/* patch Control Channel Description 10.5.2.11 */
type_3->control_channel_desc = bts->chan_desc;
/* patch TSC */
si4[15] &= ~0xe0;
si4[15] |= (bts->tsc & 7) << 5;
/* patch MS max power for CCH */
type_4->cell_sel_par.ms_txpwr_max_ccch =
ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
/* Set NECI to influence channel request */
type_3->cell_sel_par.neci = bts->network->neci;
type_4->cell_sel_par.neci = bts->network->neci;
if (bts->cell_barred) {
type_1->rach_control.cell_bar = 1;
type_2->rach_control.cell_bar = 1;
type_3->rach_control.cell_bar = 1;
type_4->rach_control.cell_bar = 1;
} else {
type_1->rach_control.cell_bar = 0;
type_2->rach_control.cell_bar = 0;
type_3->rach_control.cell_bar = 0;
type_4->rach_control.cell_bar = 0;
}
/* pad it to octet-aligned number of bits */
ts->hopping.ma_len = num_cell_arfcns / 8;
if (num_cell_arfcns % 8)
ts->hopping.ma_len++;
n_chan = 0;
for (i = 1; i < 1024; i++) {
if (!bitvec_get_bit_pos(cell_chan, i))
continue;
/* set the corresponding bit in the MA */
bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
if (bitvec_get_bit_pos(ts_arfcn, i))
bitvec_set_bit_pos(ma, bitnum, 1);
else
bitvec_set_bit_pos(ma, bitnum, 0);
n_chan++;
}
/* ARFCN 0 is special: It is coded last in the bitmask */
if (bitvec_get_bit_pos(cell_chan, 0)) {
n_chan++;
/* set the corresponding bit in the MA */
bitnum = (ts->hopping.ma_len * 8) - 1 - n_chan;
if (bitvec_get_bit_pos(ts_arfcn, 0))
bitvec_set_bit_pos(ma, bitnum, 1);
else
bitvec_set_bit_pos(ma, bitnum, 0);
}
return 0;
}
static void bootstrap_rsl(struct gsm_bts_trx *trx)
{
unsigned int i;
LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) "
"on ARFCN %u using MCC=%u MNC=%u LAC=%u CID=%u BSIC=%u TSC=%u\n",
trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
bsc_gsmnet->network_code, trx->bts->location_area_code,
trx->bts->cell_identity, trx->bts->bsic, trx->bts->tsc);
fprintf(stdout, "bootstrapping RSL for BTS/TRX (%u/%u) "
"using MCC=%u MNC=%u BSIC=%u TSC=%u\n",
trx->bts->nr, trx->nr, bsc_gsmnet->country_code,
bsc_gsmnet->network_code, trx->bts->bsic, trx->bts->tsc);
patch_si_tables(trx->bts);
set_system_infos(trx);
for (i = 0; i < ARRAY_SIZE(trx->ts); i++)
generate_ma_for_ts(&trx->ts[i]);
}
void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
{
int ts_no, lchan_no;
switch (event) {
case EVT_E1_TEI_UP:
switch (type) {
@@ -1041,35 +1015,8 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
}
break;
case EVT_E1_TEI_DN:
LOGP(DMI, LOGL_ERROR, "Lost some E1 TEI link: %d %p\n", type, trx);
if (type == E1INP_SIGN_OML)
counter_inc(trx->bts->network->stats.bts.oml_fail);
else if (type == E1INP_SIGN_RSL)
counter_inc(trx->bts->network->stats.bts.rsl_fail);
/*
* free all allocated channels. change the nm_state so the
* trx and trx_ts becomes unusable and chan_alloc.c can not
* allocate from it.
*/
for (ts_no = 0; ts_no < ARRAY_SIZE(trx->ts); ++ts_no) {
struct gsm_bts_trx_ts *ts = &trx->ts[ts_no];
for (lchan_no = 0; lchan_no < ARRAY_SIZE(ts->lchan); ++lchan_no) {
if (ts->lchan[lchan_no].state != GSM_LCHAN_NONE)
lchan_free(&ts->lchan[lchan_no]);
lchan_reset(&ts->lchan[lchan_no]);
}
ts->nm_state.operational = 0;
ts->nm_state.availability = 0;
}
trx->nm_state.operational = 0;
trx->nm_state.availability = 0;
trx->bb_transc.nm_state.operational = 0;
trx->bb_transc.nm_state.availability = 0;
fprintf(stderr, "Lost some E1 TEI link\n");
/* FIXME: deal with TEI or L1 link loss */
break;
default:
break;
@@ -1078,89 +1025,36 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
static int bootstrap_bts(struct gsm_bts *bts)
{
int i, n;
/* FIXME: What about secondary TRX of a BTS? What about a BTS that has TRX
* in different bands? Why is 'band' a parameter of the BTS and not of the TRX? */
switch (bts->band) {
case GSM_BAND_1800:
if (bts->c0->arfcn < 512 || bts->c0->arfcn > 885) {
LOGP(DNM, LOGL_ERROR, "GSM1800 channel must be between 512-885.\n");
fprintf(stderr, "GSM1800 channel must be between 512-885.\n");
return -EINVAL;
}
break;
case GSM_BAND_1900:
if (bts->c0->arfcn < 512 || bts->c0->arfcn > 810) {
LOGP(DNM, LOGL_ERROR, "GSM1900 channel must be between 512-810.\n");
fprintf(stderr, "GSM1900 channel must be between 512-810.\n");
return -EINVAL;
}
break;
case GSM_BAND_900:
if (bts->c0->arfcn < 1 ||
(bts->c0->arfcn > 124 && bts->c0->arfcn < 955) ||
bts->c0->arfcn > 1023) {
LOGP(DNM, LOGL_ERROR, "GSM900 channel must be between 1-124, 955-1023.\n");
return -EINVAL;
}
break;
case GSM_BAND_850:
if (bts->c0->arfcn < 128 || bts->c0->arfcn > 251) {
LOGP(DNM, LOGL_ERROR, "GSM850 channel must be between 128-251.\n");
if (bts->c0->arfcn < 1 || bts->c0->arfcn > 124) {
fprintf(stderr, "GSM900 channel must be between 1-124.\n");
return -EINVAL;
}
break;
default:
LOGP(DNM, LOGL_ERROR, "Unsupported frequency band.\n");
fprintf(stderr, "Unsupported frequency band.\n");
return -EINVAL;
}
if (bts->network->auth_policy == GSM_AUTH_POLICY_ACCEPT_ALL &&
!bts->si_common.rach_control.cell_bar)
LOGP(DNM, LOGL_ERROR, "\nWARNING: You are running an 'accept-all' "
"network on a BTS that is not barred. This "
"configuration is likely to interfere with production "
"GSM networks and should only be used in a RF "
"shielded environment such as a faraday cage!\n\n");
/* Control Channel Description */
bts->si_common.chan_desc.att = 1;
bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
bts->chan_desc.att = 1;
bts->chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
bts->chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
/* T3212 is set from vty/config */
/* Set ccch config by looking at ts config */
for (n=0, i=0; i<8; i++)
n += bts->c0->ts[i].pchan == GSM_PCHAN_CCCH ? 1 : 0;
switch (n) {
case 0:
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
break;
case 1:
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_NC;
break;
case 2:
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_2_NC;
break;
case 3:
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_3_NC;
break;
case 4:
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_4_NC;
break;
default:
LOGP(DNM, LOGL_ERROR, "Unsupported CCCH timeslot configuration\n");
return -EINVAL;
}
/* some defaults for our system information */
bts->si_common.cell_options.radio_link_timeout = 2; /* 12 */
bts->si_common.cell_options.dtx = 2; /* MS shall not use upplink DTX */
bts->si_common.cell_options.pwrc = 0; /* PWRC not set */
bts->si_common.cell_sel_par.acs = 0;
bts->si_common.ncc_permitted = 0xff;
paging_init(bts);
return 0;
@@ -1169,7 +1063,6 @@ static int bootstrap_bts(struct gsm_bts *bts)
int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
const char *config_file)
{
struct telnet_connection dummy_conn;
struct gsm_bts *bts;
int rc;
@@ -1181,18 +1074,13 @@ int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, int, void *),
bsc_gsmnet->name_long = talloc_strdup(bsc_gsmnet, "OpenBSC");
bsc_gsmnet->name_short = talloc_strdup(bsc_gsmnet, "OpenBSC");
/* our vty command code expects vty->priv to point to a telnet_connection */
dummy_conn.priv = bsc_gsmnet;
rc = vty_read_config_file(config_file, &dummy_conn);
telnet_init(bsc_gsmnet, 4242);
rc = vty_read_config_file(config_file);
if (rc < 0) {
LOGP(DNM, LOGL_FATAL, "Failed to parse the config file: '%s'\n", config_file);
fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
return rc;
}
rc = telnet_init(tall_bsc_ctx, bsc_gsmnet, 4242);
if (rc < 0)
return rc;
register_signal_handler(SS_NM, nm_sig_cb, NULL);
llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) {

1173
openbsc/src/bsc_mgcp.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,270 +0,0 @@
/* Routines to talk to the MSC using the IPA Protocol */
/*
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2010 by On-Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include <openbsc/bsc_msc.h>
#include <openbsc/debug.h>
#include <openbsc/ipaccess.h>
#include <osmocore/write_queue.h>
#include <osmocore/talloc.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static void connection_loss(struct bsc_msc_connection *con)
{
struct bsc_fd *fd;
fd = &con->write_queue.bfd;
close(fd->fd);
fd->fd = -1;
fd->cb = write_queue_bfd_cb;
fd->when = 0;
con->is_connected = 0;
con->first_contact = 0;
con->connection_loss(con);
}
static void msc_con_timeout(void *_con)
{
struct bsc_msc_connection *con = _con;
LOGP(DMSC, LOGL_ERROR, "MSC Connection timeout.\n");
bsc_msc_lost(con);
}
static int bsc_msc_except(struct bsc_fd *bfd)
{
struct write_queue *wrt;
struct bsc_msc_connection *con;
LOGP(DMSC, LOGL_ERROR, "Exception on the BFD. Closing down.\n");
wrt = container_of(bfd, struct write_queue, bfd);
con = container_of(wrt, struct bsc_msc_connection, write_queue);
connection_loss(con);
return 0;
}
/* called in the case of a non blocking connect */
static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
{
int rc;
int val;
struct bsc_msc_connection *con;
struct write_queue *queue;
socklen_t len = sizeof(val);
if ((what & BSC_FD_WRITE) == 0) {
LOGP(DMSC, LOGL_ERROR, "Callback but not writable.\n");
return -1;
}
queue = container_of(fd, struct write_queue, bfd);
con = container_of(queue, struct bsc_msc_connection, write_queue);
/* check the socket state */
rc = getsockopt(fd->fd, SOL_SOCKET, SO_ERROR, &val, &len);
if (rc != 0) {
LOGP(DMSC, LOGL_ERROR, "getsockopt for the MSC socket failed.\n");
goto error;
}
if (val != 0) {
LOGP(DMSC, LOGL_ERROR, "Not connected to the MSC: %d\n", val);
goto error;
}
/* go to full operation */
fd->cb = write_queue_bfd_cb;
fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
con->is_connected = 1;
bsc_del_timer(&con->timeout_timer);
LOGP(DMSC, LOGL_NOTICE, "(Re)Connected to the MSC.\n");
if (con->connected)
con->connected(con);
return 0;
error:
bsc_unregister_fd(fd);
connection_loss(con);
return -1;
}
static void setnonblocking(struct bsc_fd *fd)
{
int flags;
flags = fcntl(fd->fd, F_GETFL);
if (flags < 0) {
perror("fcntl get failed");
close(fd->fd);
fd->fd = -1;
return;
}
flags |= O_NONBLOCK;
flags = fcntl(fd->fd, F_SETFL, flags);
if (flags < 0) {
perror("fcntl get failed");
close(fd->fd);
fd->fd = -1;
return;
}
}
int bsc_msc_connect(struct bsc_msc_connection *con)
{
struct bsc_fd *fd;
struct sockaddr_in sin;
int on = 1, ret;
LOGP(DMSC, LOGL_NOTICE, "Attempting to connect MSC at %s:%d\n", con->ip, con->port);
con->is_connected = 0;
fd = &con->write_queue.bfd;
fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
fd->priv_nr = 1;
if (fd->fd < 0) {
perror("Creating TCP socket failed");
return fd->fd;
}
/* make it non blocking */
setnonblocking(fd);
/* set the socket priority */
ret = setsockopt(fd->fd, IPPROTO_IP, IP_TOS,
&con->prio, sizeof(con->prio));
if (ret != 0)
LOGP(DMSC, LOGL_ERROR, "Failed to set prio to %d. %s\n",
con->prio, strerror(errno));
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(con->port);
inet_aton(con->ip, &sin.sin_addr);
setsockopt(fd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
ret = connect(fd->fd, (struct sockaddr *) &sin, sizeof(sin));
if (ret == -1 && errno == EINPROGRESS) {
LOGP(DMSC, LOGL_ERROR, "MSC Connection in progress\n");
fd->when = BSC_FD_WRITE;
fd->cb = msc_connection_connect;
con->timeout_timer.cb = msc_con_timeout;
con->timeout_timer.data = con;
bsc_schedule_timer(&con->timeout_timer, 20, 0);
} else if (ret < 0) {
perror("Connection failed");
connection_loss(con);
return ret;
} else {
fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
fd->cb = write_queue_bfd_cb;
con->is_connected = 1;
if (con->connected)
con->connected(con);
}
ret = bsc_register_fd(fd);
if (ret < 0) {
perror("Registering the fd failed");
close(fd->fd);
return ret;
}
return ret;
}
struct bsc_msc_connection *bsc_msc_create(const char *ip, int port, int prio)
{
struct bsc_msc_connection *con;
con = talloc_zero(NULL, struct bsc_msc_connection);
if (!con) {
LOGP(DMSC, LOGL_FATAL, "Failed to create the MSC connection.\n");
return NULL;
}
con->ip = ip;
con->port = port;
con->prio = prio;
write_queue_init(&con->write_queue, 100);
con->write_queue.except_cb = bsc_msc_except;
return con;
}
void bsc_msc_lost(struct bsc_msc_connection *con)
{
write_queue_clear(&con->write_queue);
bsc_unregister_fd(&con->write_queue.bfd);
connection_loss(con);
}
static void reconnect_msc(void *_msc)
{
struct bsc_msc_connection *con = _msc;
LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
bsc_msc_connect(con);
}
void bsc_msc_schedule_connect(struct bsc_msc_connection *con)
{
LOGP(DMSC, LOGL_NOTICE, "Attempting to reconnect to the MSC.\n");
con->reconnect_timer.cb = reconnect_msc;
con->reconnect_timer.data = con;
bsc_schedule_timer(&con->reconnect_timer, 5, 0);
}
struct msgb *bsc_msc_id_get_resp(const char *token)
{
struct msgb *msg;
if (!token) {
LOGP(DMSC, LOGL_ERROR, "No token specified.\n");
return NULL;
}
msg = msgb_alloc_headroom(4096, 128, "id resp");
if (!msg) {
LOGP(DMSC, LOGL_ERROR, "Failed to create the message.\n");
return NULL;
}
msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
msgb_l16tv_put(msg, strlen(token) + 1,
IPAC_IDTAG_UNITNAME, (u_int8_t *) token);
return msg;
}

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, 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);
}
}

Some files were not shown because too many files have changed in this diff Show More