mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 13:03:33 +00:00
Compare commits
92 Commits
openbsc/0.
...
on-waves/0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab46372e2a | ||
|
|
ff0a562f9a | ||
|
|
556008d724 | ||
|
|
0094f84f30 | ||
|
|
86069143ff | ||
|
|
44f0be88a3 | ||
|
|
5d88b372d7 | ||
|
|
71c7bf5907 | ||
|
|
869033148c | ||
|
|
bc0f7c0988 | ||
|
|
7d06063cfb | ||
|
|
4e42b637fd | ||
|
|
f44de9942b | ||
|
|
3a110ae60b | ||
|
|
bb84adc465 | ||
|
|
8d123ea3c0 | ||
|
|
88ca894df7 | ||
|
|
42b0d6b494 | ||
|
|
82d8b0457b | ||
|
|
433d6ee1a2 | ||
|
|
203a6eddf8 | ||
|
|
56ef6249e3 | ||
|
|
b2a96b1be7 | ||
|
|
d4c29c1574 | ||
|
|
3d947e6d67 | ||
|
|
b62c9a19cf | ||
|
|
ff5957568f | ||
|
|
7d2e1ca4be | ||
|
|
7ce2e0c8b0 | ||
|
|
78d442420b | ||
|
|
8cd2709ebf | ||
|
|
41a1780102 | ||
|
|
2f84715984 | ||
|
|
7253154fc5 | ||
|
|
6c1c76683f | ||
|
|
a92fe9a4ca | ||
|
|
e83a3f584e | ||
|
|
118ddebc36 | ||
|
|
bb53004d47 | ||
|
|
6af20842cb | ||
|
|
cc41cb07e7 | ||
|
|
d6fb23523a | ||
|
|
2aa0b45cc0 | ||
|
|
619df61ad2 | ||
|
|
893ea65f38 | ||
|
|
64b811f113 | ||
|
|
91fc9bf862 | ||
|
|
111a58dd37 | ||
|
|
d1a2563a74 | ||
|
|
7d3ef919ce | ||
|
|
cba98d87d6 | ||
|
|
5c18ad0829 | ||
|
|
0d9ed87d5c | ||
|
|
ec7be0c969 | ||
|
|
9be3347601 | ||
|
|
3eef7b7d81 | ||
|
|
9de4a6daa9 | ||
|
|
851ace9f33 | ||
|
|
d1dd069b48 | ||
|
|
401db32ca2 | ||
|
|
17e03d21d2 | ||
|
|
26a9bff201 | ||
|
|
80fb260a60 | ||
|
|
55a0716da7 | ||
|
|
c88fb75616 | ||
|
|
d55a4dc326 | ||
|
|
a4e6f2e6e1 | ||
|
|
7f71d99cc3 | ||
|
|
b92167cf80 | ||
|
|
4b6a6dbe7e | ||
|
|
763e8c7766 | ||
|
|
823ff16088 | ||
|
|
6f93c6a1e0 | ||
|
|
f97e48b0de | ||
|
|
761600b0fd | ||
|
|
8549462bc6 | ||
|
|
436e5c6308 | ||
|
|
f8b9d844c1 | ||
|
|
58ec07d580 | ||
|
|
71465c21f4 | ||
|
|
16d0a833f8 | ||
|
|
ea72b62cac | ||
|
|
49a84ec6e9 | ||
|
|
42c636b6c8 | ||
|
|
a0a55f555e | ||
|
|
23ed00e410 | ||
|
|
3fe910b9f1 | ||
|
|
097bdeb77d | ||
|
|
1b85de02e0 | ||
|
|
2281d1835f | ||
|
|
fb4433a129 | ||
|
|
d954dcf9e1 |
12
openbsc/.gitignore
vendored
12
openbsc/.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.3onwaves)
|
||||
|
||||
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
2
openbsc/contrib/README
Normal file
@@ -0,0 +1,2 @@
|
||||
This contains a set of scripts used for the development of the
|
||||
MSC functionality.
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
30
openbsc/contrib/send_handshake.py
Executable file
30
openbsc/contrib/send_handshake.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
# packages
|
||||
ACK ="\x00\x01\xfe\x06"
|
||||
RESET_ACK = "\x00\x13\xfd\x09\x00\x03\x07\x0b\x04\x43\x01\x00\xfe\x04\x43\x5c\x00\xfe\x03\x00\x01\x31"
|
||||
PAGE = "\x00\x20\xfd\x09\x00\x03\x07\x0b\x04\x43\x01\x00\xfe\x04\x43\x5c\x00\xfe\x10\x00\x0e\x52\x08\x08\x29\x42\x08\x05\x03\x12\x23\x42\x1a\x01\x06"
|
||||
|
||||
|
||||
# simple handshake...
|
||||
sys.stdout.write(ACK)
|
||||
sys.stdout.flush()
|
||||
sys.stdin.read(4)
|
||||
|
||||
# wait for some data and send reset ack
|
||||
sys.stdin.read(21)
|
||||
sys.stdout.write(RESET_ACK)
|
||||
sys.stdout.flush()
|
||||
|
||||
sys.stdout.write(RESET_ACK)
|
||||
sys.stdout.flush()
|
||||
|
||||
# page a subscriber
|
||||
sys.stdout.write(PAGE)
|
||||
sys.stdout.flush()
|
||||
|
||||
while True:
|
||||
sys.stdin.read(1)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
@@ -1,3 +1,3 @@
|
||||
SUBDIRS = openbsc
|
||||
SUBDIRS = openbsc vty sccp
|
||||
|
||||
noinst_HEADERS = mISDNif.h compat_af_isdn.h
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
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 meas_rep.h bitvec.h rest_octets.h \
|
||||
system_information.h handover.h bssap.h bsc_msc.h bsc_nat.h
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
@@ -52,6 +511,27 @@ 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 */
|
||||
@@ -59,7 +539,7 @@ 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);
|
||||
int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan);
|
||||
|
||||
int abis_rsl_rcvmsg(struct msgb *msg);
|
||||
|
||||
@@ -68,14 +548,12 @@ unsigned int get_paging_group(u_int64_t imsi, unsigned int bs_cc_chans,
|
||||
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);
|
||||
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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
65
openbsc/include/openbsc/bitvec.h
Normal file
65
openbsc/include/openbsc/bitvec.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef _BITVEC_H
|
||||
#define _BITVEC_H
|
||||
|
||||
/* bit vector utility routines */
|
||||
|
||||
/* (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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* In GSM mac blocks, every bit can be 0 or 1, or L or H. L/H are
|
||||
* defined relative to the 0x2b padding pattern */
|
||||
enum bit_value {
|
||||
ZERO = 0,
|
||||
ONE = 1,
|
||||
L = 2,
|
||||
H = 3,
|
||||
};
|
||||
|
||||
struct bitvec {
|
||||
unsigned int cur_bit; /* curser to the next unused bit */
|
||||
unsigned int data_len; /* length of data array in bytes */
|
||||
u_int8_t *data; /* pointer to data array */
|
||||
};
|
||||
|
||||
/* check if the bit is 0 or 1 for a given position inside a bitvec */
|
||||
enum bit_value bitvec_get_bit_pos(struct bitvec *bv, unsigned int bitnr);
|
||||
|
||||
/* get the Nth set bit inside the bit vector */
|
||||
unsigned int bitvec_get_nth_set_bit(struct bitvec *bv, unsigned int n);
|
||||
|
||||
/* Set a bit at given position */
|
||||
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnum,
|
||||
enum bit_value bit);
|
||||
|
||||
/* Set the next bit in the vector */
|
||||
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit);
|
||||
|
||||
/* Set multiple bits at the current position */
|
||||
int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count);
|
||||
|
||||
/* Add an unsigned integer (of length count bits) to current position */
|
||||
int bitvec_set_uint(struct bitvec *bv, unsigned int in, int count);
|
||||
|
||||
|
||||
/* Pad the bit vector up to a certain bit position */
|
||||
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit);
|
||||
|
||||
#endif /* _BITVEC_H */
|
||||
@@ -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
|
||||
@@ -1,7 +1,7 @@
|
||||
/* 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
|
||||
* (C) 2010 by on-waves.com
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -23,30 +23,8 @@
|
||||
#ifndef BSC_MSC_H
|
||||
#define BSC_MSC_H
|
||||
|
||||
#include <osmocore/write_queue.h>
|
||||
#include <osmocore/timer.h>
|
||||
#include "select.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);
|
||||
int connect_to_msc(struct bsc_fd *fd, const char *ip, int port);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* (C) 2010 by on-waves.com
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -22,260 +22,12 @@
|
||||
#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);
|
||||
#include "msgb.h"
|
||||
|
||||
/**
|
||||
* 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);
|
||||
int bsc_nat_filter_ipa(struct msgb *msg);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
334
openbsc/include/openbsc/bssap.h
Normal file
334
openbsc/include/openbsc/bssap.h
Normal file
@@ -0,0 +1,334 @@
|
||||
/* 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*);
|
||||
void bts_unblock_queue(struct bss_sccp_connection_data*);
|
||||
|
||||
#endif
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -1,70 +1,58 @@
|
||||
#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);
|
||||
#define DHO 0x80000
|
||||
|
||||
extern const struct log_info log_info;
|
||||
#ifdef DEBUG
|
||||
#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args)
|
||||
#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args)
|
||||
#else
|
||||
#define DEBUGP(xss, fmt, args...)
|
||||
#define DEBUGPC(ss, fmt, args...)
|
||||
#endif
|
||||
|
||||
#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1];
|
||||
|
||||
char *hexdump(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;
|
||||
|
||||
/* new logging interface */
|
||||
#define LOGP(ss, level, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ##args)
|
||||
#define LOGPC(ss, level, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ##args)
|
||||
|
||||
/* different levels */
|
||||
#define LOGL_DEBUG 1 /* debugging information */
|
||||
#define LOGL_INFO 3
|
||||
#define LOGL_NOTICE 5 /* abnormal/unexpected condition */
|
||||
#define LOGL_ERROR 7 /* error condition, requires user action */
|
||||
#define LOGL_FATAL 8 /* fatal, program aborted */
|
||||
|
||||
#endif /* _DEBUG_H */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -3,41 +3,770 @@
|
||||
|
||||
#include <openbsc/meas_rep.h>
|
||||
|
||||
#include <osmocore/protocol/gsm_04_08.h>
|
||||
#include <osmocore/gsm48.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 10.5.2.2 */
|
||||
struct gsm48_cell_desc {
|
||||
u_int8_t bcc:3,
|
||||
ncc:3,
|
||||
arfcn_hi:2;
|
||||
u_int8_t arfcn_lo;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Chapter 9.1.15 */
|
||||
struct gsm48_ho_cmd {
|
||||
struct gsm48_cell_desc cell_desc;
|
||||
struct gsm48_chan_desc chan_desc;
|
||||
u_int8_t ho_ref;
|
||||
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));
|
||||
|
||||
struct gsm48_cell_options {
|
||||
u_int8_t radio_link_timeout:4,
|
||||
dtx:2,
|
||||
pwrc:1,
|
||||
spare:1;
|
||||
} __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 rest_octets[0]; /* NCH position on the CCCH */
|
||||
} __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;
|
||||
struct gsm48_cell_options cell_options;
|
||||
struct gsm48_cell_sel_par cell_sel_par;
|
||||
struct gsm48_rach_control rach_control;
|
||||
u_int8_t rest_octets[0];
|
||||
} __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;
|
||||
struct gsm48_cell_options cell_options;
|
||||
u_int8_t ncc_permitted;
|
||||
u_int8_t rest_octets[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Section 9.1.43a System Information type 13 */
|
||||
struct gsm48_system_information_type_13 {
|
||||
struct gsm48_system_information_type_header header;
|
||||
u_int8_t rest_octets[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,
|
||||
};
|
||||
|
||||
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,
|
||||
CHREQ_T_LMU,
|
||||
CHREQ_T_RESERVED_SDCCH,
|
||||
CHREQ_T_RESERVED_IGNORE,
|
||||
};
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
@@ -53,18 +782,15 @@ 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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
@@ -40,18 +55,14 @@ 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 <openbsc/bitvec.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 +79,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 +87,56 @@ 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 gsm_lchan *secondary_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 */
|
||||
int block_gsm;
|
||||
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,24 +156,6 @@ 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 */
|
||||
@@ -204,9 +173,6 @@ struct neigh_meas_proc {
|
||||
};
|
||||
|
||||
#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? */
|
||||
@@ -217,35 +183,10 @@ struct neigh_meas_proc {
|
||||
/* 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;
|
||||
@@ -269,21 +210,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;
|
||||
|
||||
/*
|
||||
* MSC handling...
|
||||
*/
|
||||
struct bss_sccp_connection_data *msc_data;
|
||||
|
||||
|
||||
/* use count. how many users use this channel */
|
||||
unsigned int use_count;
|
||||
|
||||
/* cache of last measurement reports on this lchan */
|
||||
struct gsm_meas_rep meas_rep[6];
|
||||
@@ -298,13 +248,10 @@ struct gsm_lchan {
|
||||
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;
|
||||
};
|
||||
|
||||
struct gsm_e1_subslot {
|
||||
@@ -316,7 +263,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,19 +277,6 @@ 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;
|
||||
|
||||
@@ -357,8 +291,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 +315,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 +328,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
|
||||
*/
|
||||
@@ -450,6 +358,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 +373,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 +385,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,7 +395,6 @@ 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? */
|
||||
@@ -542,13 +441,6 @@ struct gsm_bts {
|
||||
} 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 {
|
||||
@@ -569,24 +461,14 @@ 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;
|
||||
@@ -596,52 +478,44 @@ struct gsm_bts {
|
||||
/* Some statistics of our network */
|
||||
struct gsmnet_stats {
|
||||
struct {
|
||||
struct counter *total;
|
||||
struct counter *no_channel;
|
||||
unsigned long total;
|
||||
unsigned long 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 */
|
||||
unsigned long attempted;
|
||||
unsigned long no_channel; /* no channel available */
|
||||
unsigned long timeout; /* T3103 timeout */
|
||||
unsigned long completed; /* HO COMPL received */
|
||||
unsigned long failed; /* HO FAIL received */
|
||||
} handover;
|
||||
struct {
|
||||
struct counter *attach;
|
||||
struct counter *normal;
|
||||
struct counter *periodic;
|
||||
struct counter *detach;
|
||||
unsigned long attach;
|
||||
unsigned long normal;
|
||||
unsigned long periodic;
|
||||
unsigned long detach;
|
||||
} loc_upd_type;
|
||||
struct {
|
||||
struct counter *reject;
|
||||
struct counter *accept;
|
||||
unsigned long reject;
|
||||
unsigned long accept;
|
||||
} loc_upd_resp;
|
||||
struct {
|
||||
struct counter *attempted;
|
||||
struct counter *detached;
|
||||
struct counter *completed;
|
||||
struct counter *expired;
|
||||
unsigned long attempted;
|
||||
unsigned long detached;
|
||||
unsigned long completed;
|
||||
unsigned long 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;
|
||||
unsigned long submitted; /* MO SMS submissions */
|
||||
unsigned long no_receiver;
|
||||
unsigned long delivered; /* MT SMS deliveries */
|
||||
unsigned long rp_err_mem;
|
||||
unsigned long 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 */
|
||||
unsigned long dialled; /* total number of dialled calls */
|
||||
unsigned long alerted; /* we alerted the other end */
|
||||
unsigned long 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 {
|
||||
@@ -653,6 +527,14 @@ enum gsm_auth_policy {
|
||||
#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 */
|
||||
u_int16_t country_code;
|
||||
@@ -683,11 +565,15 @@ struct gsm_network {
|
||||
|
||||
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;
|
||||
@@ -709,7 +595,10 @@ struct gsm_network {
|
||||
struct {
|
||||
enum rrlp_mode mode;
|
||||
} rrlp;
|
||||
int msc_prio;
|
||||
|
||||
/* a hack for On Waves. It must be signed */
|
||||
int32_t core_country_code;
|
||||
int32_t core_network_code;
|
||||
};
|
||||
|
||||
#define SMS_HDR_SIZE 128
|
||||
@@ -734,13 +623,11 @@ 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);
|
||||
|
||||
@@ -752,12 +639,9 @@ 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,10 +653,12 @@ 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;
|
||||
|
||||
@@ -806,20 +692,8 @@ 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2010 by On-Waves
|
||||
/* GSM utility functions, e.g. coding and decoding */
|
||||
/*
|
||||
* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -18,9 +22,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openbsc/osmo_bsc.h>
|
||||
#ifndef GSM_UTILS_H
|
||||
#define GSM_UTILS_H
|
||||
|
||||
struct bsc_api *osmo_bsc_api()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#include <sys/types.h>
|
||||
|
||||
int gsm_7bit_decode(char *decoded, const u_int8_t *user_data, u_int8_t length);
|
||||
int gsm_7bit_encode(u_int8_t *result, const char *data);
|
||||
|
||||
int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm);
|
||||
int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl);
|
||||
|
||||
/* According to TS 08.05 Chapter 8.1.4 */
|
||||
int rxlev2dbm(u_int8_t rxlev);
|
||||
u_int8_t dbm2rxlev(int dbm);
|
||||
|
||||
void generate_backtrace();
|
||||
#endif
|
||||
@@ -1,14 +1,8 @@
|
||||
#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 */
|
||||
|
||||
@@ -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 */
|
||||
@@ -49,61 +45,5 @@ 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 */
|
||||
|
||||
360
openbsc/include/openbsc/linuxlist.h
Normal file
360
openbsc/include/openbsc/linuxlist.h
Normal 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
|
||||
@@ -7,7 +7,6 @@
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
@@ -110,6 +109,69 @@ 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;
|
||||
};
|
||||
|
||||
enum {
|
||||
GSM_MNCC_BCAP_SPEECH = 0,
|
||||
GSM_MNCC_BCAP_UNR_DIG = 1,
|
||||
GSM_MNCC_BCAP_AUDIO = 2,
|
||||
GSM_MNCC_BCAP_FAX_G3 = 3,
|
||||
GSM_MNCC_BCAP_OTHER_ITC = 5,
|
||||
GSM_MNCC_BCAP_RESERVED = 7,
|
||||
};
|
||||
|
||||
struct gsm_mncc {
|
||||
/* context based information */
|
||||
u_int32_t msg_type;
|
||||
|
||||
115
openbsc/include/openbsc/msgb.h
Normal file
115
openbsc/include/openbsc/msgb.h
Normal 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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -71,7 +71,6 @@ enum gprs_nmo {
|
||||
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 */
|
||||
@@ -80,16 +79,6 @@ struct gprs_cell_options {
|
||||
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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
22
openbsc/include/openbsc/select.h
Normal file
22
openbsc/include/openbsc/select.h
Normal 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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -41,16 +41,11 @@ enum signal_subsystems {
|
||||
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 */
|
||||
@@ -74,9 +69,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 */
|
||||
};
|
||||
|
||||
@@ -96,12 +88,6 @@ enum signal_lchan {
|
||||
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,
|
||||
@@ -116,68 +102,33 @@ 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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
|
||||
@@ -1,42 +1,6 @@
|
||||
#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);
|
||||
int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type);
|
||||
|
||||
#endif
|
||||
|
||||
192
openbsc/include/openbsc/talloc.h
Normal file
192
openbsc/include/openbsc/talloc.h
Normal 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
|
||||
@@ -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
|
||||
72
openbsc/include/openbsc/timer.h
Normal file
72
openbsc/include/openbsc/timer.h
Normal 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
|
||||
221
openbsc/include/openbsc/tlv.h
Normal file
221
openbsc/include/openbsc/tlv.h
Normal file
@@ -0,0 +1,221 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
/* 'val' is still in host byte order! */
|
||||
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 */
|
||||
@@ -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,8 +20,8 @@ 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;
|
||||
@@ -69,4 +69,8 @@ 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);
|
||||
|
||||
/* update all transactions to use a different LCHAN, e.g.
|
||||
* after handover has succeeded */
|
||||
int trans_lchan_change(struct gsm_lchan *lchan_old,
|
||||
struct gsm_lchan *lchan_new);
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
1
openbsc/include/sccp/Makefile.am
Normal file
1
openbsc/include/sccp/Makefile.am
Normal file
@@ -0,0 +1 @@
|
||||
noinst_HEADERS = sccp_types.h sccp.h
|
||||
167
openbsc/include/sccp/sccp.h
Normal file
167
openbsc/include/sccp/sccp.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* SCCP management code
|
||||
*
|
||||
* (C) 2009, 2010 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);
|
||||
|
||||
/**
|
||||
* Below this are helper functions and structs for parsing SCCP messages
|
||||
*/
|
||||
struct sccp_parse_result {
|
||||
struct sccp_address called;
|
||||
struct sccp_address calling;
|
||||
|
||||
/* point to the msg packet */
|
||||
struct sccp_source_reference *source_local_reference;
|
||||
struct sccp_source_reference *destination_local_reference;
|
||||
|
||||
/* data pointer */
|
||||
int data_len;
|
||||
};
|
||||
|
||||
/*
|
||||
* helper functions for the nat code
|
||||
*/
|
||||
int sccp_determine_msg_type(struct msgb *msg);
|
||||
int sccp_parse_header(struct msgb *msg, struct sccp_parse_result *result);
|
||||
|
||||
#endif
|
||||
394
openbsc/include/sccp/sccp_types.h
Normal file
394
openbsc/include/sccp/sccp_types.h
Normal 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
|
||||
1
openbsc/include/vty/Makefile.am
Normal file
1
openbsc/include/vty/Makefile.am
Normal file
@@ -0,0 +1 @@
|
||||
noinst_HEADERS = buffer.h command.h vector.h vty.h
|
||||
102
openbsc/include/vty/buffer.h
Normal file
102
openbsc/include/vty/buffer.h
Normal 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 */
|
||||
359
openbsc/include/vty/command.h
Normal file
359
openbsc/include/vty/command.h
Normal 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 */
|
||||
62
openbsc/include/vty/vector.h
Normal file
62
openbsc/include/vty/vector.h
Normal 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
151
openbsc/include/vty/vty.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -1,48 +1,47 @@
|
||||
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 bsc_nat
|
||||
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 system_information.c bitvec.c rest_octets.c \
|
||||
rtp_proxy.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
|
||||
handover_logic.c handover_decision.c meas_rep.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.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
|
||||
|
||||
bsc_nat_SOURCES = nat/bsc_nat.c nat/bsc_filter.c bsc_msc.c
|
||||
bsc_nat_LDADD = libbsc.a libsccp.a
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
170
openbsc/src/bitvec.c
Normal file
170
openbsc/src/bitvec.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/* bit vector utility routines */
|
||||
|
||||
/* (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 <errno.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openbsc/bitvec.h>
|
||||
|
||||
#define BITNUM_FROM_COMP(byte, bit) ((byte*8)+bit)
|
||||
|
||||
static inline unsigned int bytenum_from_bitnum(unsigned int bitnum)
|
||||
{
|
||||
unsigned int bytenum = bitnum / 8;
|
||||
|
||||
return bytenum;
|
||||
}
|
||||
|
||||
/* convert ZERO/ONE/L/H to a bitmask at given pos in a byte */
|
||||
static u_int8_t bitval2mask(enum bit_value bit, u_int8_t bitnum)
|
||||
{
|
||||
int bitval;
|
||||
|
||||
switch (bit) {
|
||||
case ZERO:
|
||||
bitval = (0 << bitnum);
|
||||
break;
|
||||
case ONE:
|
||||
bitval = (1 << bitnum);
|
||||
break;
|
||||
case L:
|
||||
bitval = ((0x2b ^ (0 << bitnum)) & (1 << bitnum));
|
||||
break;
|
||||
case H:
|
||||
bitval = ((0x2b ^ (1 << bitnum)) & (1 << bitnum));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return bitval;
|
||||
}
|
||||
|
||||
/* check if the bit is 0 or 1 for a given position inside a bitvec */
|
||||
enum bit_value bitvec_get_bit_pos(struct bitvec *bv, unsigned int bitnr)
|
||||
{
|
||||
unsigned int bytenum = bytenum_from_bitnum(bitnr);
|
||||
unsigned int bitnum = 7 - (bitnr % 8);
|
||||
u_int8_t bitval;
|
||||
|
||||
if (bytenum >= bv->data_len)
|
||||
return -EINVAL;
|
||||
|
||||
bitval = bitval2mask(ONE, bitnum);
|
||||
|
||||
if (bv->data[bytenum] & bitval)
|
||||
return ONE;
|
||||
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
/* get the Nth set bit inside the bit vector */
|
||||
unsigned int bitvec_get_nth_set_bit(struct bitvec *bv, unsigned int n)
|
||||
{
|
||||
unsigned int i, k = 0;
|
||||
|
||||
for (i = 0; i < bv->data_len*8; i++) {
|
||||
if (bitvec_get_bit_pos(bv, i) == ONE) {
|
||||
k++;
|
||||
if (k == n)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the bit at a given position inside a bitvec */
|
||||
int bitvec_set_bit_pos(struct bitvec *bv, unsigned int bitnr,
|
||||
enum bit_value bit)
|
||||
{
|
||||
unsigned int bytenum = bytenum_from_bitnum(bitnr);
|
||||
unsigned int bitnum = 7 - (bitnr % 8);
|
||||
u_int8_t bitval;
|
||||
|
||||
if (bytenum >= bv->data_len)
|
||||
return -EINVAL;
|
||||
|
||||
/* first clear the bit */
|
||||
bitval = bitval2mask(ONE, bitnum);
|
||||
bv->data[bytenum] &= ~bitval;
|
||||
|
||||
/* then set it to desired value */
|
||||
bitval = bitval2mask(bit, bitnum);
|
||||
bv->data[bytenum] |= bitval;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the next bit inside a bitvec */
|
||||
int bitvec_set_bit(struct bitvec *bv, enum bit_value bit)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = bitvec_set_bit_pos(bv, bv->cur_bit, bit);
|
||||
if (!rc)
|
||||
bv->cur_bit++;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* set multiple bits (based on array of bitvals) at current pos */
|
||||
int bitvec_set_bits(struct bitvec *bv, enum bit_value *bits, int count)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
rc = bitvec_set_bit(bv, bits[i]);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set multiple bits (based on numeric value) at current pos */
|
||||
int bitvec_set_uint(struct bitvec *bv, unsigned int ui, int num_bits)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
int bit = 0;
|
||||
if (ui & (1 << (num_bits - i - 1)))
|
||||
bit = 1;
|
||||
rc = bitvec_set_bit(bv, bit);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pad all remaining bits up to num_bits */
|
||||
int bitvec_spare_padding(struct bitvec *bv, unsigned int up_to_bit)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = bv->cur_bit; i <= up_to_bit; i++)
|
||||
bitvec_set_bit(bv, L);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/* Osmo BSC VTY Configuration */
|
||||
/* (C) 2009-2010 by Holger Hans Peter Freyther
|
||||
* (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 <osmocom/vty/vty.h>
|
||||
|
||||
int bsc_vty_init_extra(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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/talloc.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/osmo_msc.h>
|
||||
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
#include "../bscconfig.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 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(" -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)
|
||||
@@ -104,13 +90,11 @@ static void handle_options(int argc, char** argv)
|
||||
{"authorize-everyone", 0, 0, 'a'},
|
||||
{"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 +105,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);
|
||||
@@ -136,18 +120,11 @@ static void handle_options(int argc, char** argv)
|
||||
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 +132,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);
|
||||
@@ -171,76 +147,26 @@ 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 +182,17 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,18 +21,17 @@
|
||||
*/
|
||||
|
||||
#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/telnet_interface.h>
|
||||
#include <openbsc/system_information.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;
|
||||
@@ -331,7 +330,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 +337,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 +355,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 +378,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 +394,11 @@ 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 &&
|
||||
if (new_state->operational == 1 &&
|
||||
new_state->availability == NM_AVSTATE_OK)
|
||||
abis_nm_opstart(trx->bts, obj_class, trx->bts->bts_nr,
|
||||
trx->nr, 0xff);
|
||||
break;
|
||||
case NM_OC_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,8 +412,6 @@ 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:
|
||||
@@ -544,7 +433,8 @@ 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;
|
||||
/* Patch ARFCN into radio attribute */
|
||||
nanobts_attr_radio[5] &= 0xf0;
|
||||
nanobts_attr_radio[5] |= trx->arfcn >> 8;
|
||||
@@ -563,9 +453,9 @@ 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) {
|
||||
if (mt == NM_MT_SET_BTS_ATTR_NACK) {
|
||||
LOGP(DNM, LOGL_FATAL, "Failed to set BTS attributes. That is fatal. "
|
||||
"Was the bts type and frequency properly specified?\n");
|
||||
exit(-1);
|
||||
@@ -578,15 +468,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;
|
||||
}
|
||||
@@ -782,92 +671,57 @@ 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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
DEBUGP(DRR, "SI%s: %s\n", gsm_sitype_name(i),
|
||||
hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* set all system information types */
|
||||
static int set_system_infos(struct gsm_bts_trx *trx)
|
||||
{
|
||||
int i, rc;
|
||||
u_int8_t si_tmp[23];
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
|
||||
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 (trx == trx->bts->c0) {
|
||||
for (i = 1; i <= 4; i++) {
|
||||
rc = gsm_generate_si(si_tmp, trx->bts, i);
|
||||
if (rc < 0)
|
||||
goto err_out;
|
||||
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
|
||||
rsl_bcch_info(trx, i, si_tmp, sizeof(si_tmp));
|
||||
}
|
||||
#ifdef GPRS
|
||||
i = 13
|
||||
rc = gsm_generate_si(si_tmp, trx->bts, RSL_SYSTEM_INFO_13);
|
||||
if (rc < 0)
|
||||
goto err_out;
|
||||
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
|
||||
rsl_bcch_info(trx, RSL_SYSTEM_INFO_13, si_tmp, rc);
|
||||
#endif
|
||||
}
|
||||
|
||||
i = 5;
|
||||
rc = gsm_generate_si(si_tmp, trx->bts, RSL_SYSTEM_INFO_5);
|
||||
if (rc < 0)
|
||||
goto err_out;
|
||||
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
|
||||
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_5, si_tmp, rc);
|
||||
|
||||
i = 6;
|
||||
rc = gsm_generate_si(si_tmp, trx->bts, RSL_SYSTEM_INFO_6);
|
||||
if (rc < 0)
|
||||
goto err_out;
|
||||
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
|
||||
rsl_sacch_filling(trx, RSL_SYSTEM_INFO_6, si_tmp, rc);
|
||||
|
||||
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);
|
||||
i, trx->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));
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch the various SYSTEM INFORMATION tables to update
|
||||
* the LAI
|
||||
@@ -890,143 +744,26 @@ 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)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* re-set the MA to all-zero */
|
||||
ma->cur_bit = 0;
|
||||
ts->hopping.ma_len = 0;
|
||||
memset(ma->data, 0, ma->data_len);
|
||||
|
||||
if (!ts->hopping.enabled)
|
||||
return 0;
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
"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);
|
||||
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 +778,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;
|
||||
LOGP(DMI, LOGL_NOTICE, "Lost some E1 TEI link\n");
|
||||
/* FIXME: deal with TEI or L1 link loss */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1078,10 +788,6 @@ 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) {
|
||||
@@ -1096,16 +802,8 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
||||
}
|
||||
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) {
|
||||
LOGP(DNM, LOGL_ERROR, "GSM900 channel must be between 1-124.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
@@ -1124,35 +822,16 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
||||
|
||||
/* Control Channel Description */
|
||||
bts->si_common.chan_desc.att = 1;
|
||||
bts->si_common.chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
|
||||
bts->si_common.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.rach_control.re = 1; /* no re-establishment */
|
||||
bts->si_common.rach_control.tx_integer = 5; /* 8 slots spread */
|
||||
bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
|
||||
bts->si_common.rach_control.t2 = 4; /* no emergency calls */
|
||||
|
||||
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 */
|
||||
@@ -1169,7 +848,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 +859,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);
|
||||
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) {
|
||||
|
||||
1237
openbsc/src/bsc_mgcp.c
Normal file
1237
openbsc/src/bsc_mgcp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/* 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
|
||||
* (C) 2010 by on-waves.com
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -21,138 +21,23 @@
|
||||
*/
|
||||
|
||||
#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)
|
||||
int connect_to_msc(struct bsc_fd *fd, const char *ip, int port)
|
||||
{
|
||||
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);
|
||||
printf("Attempting to connect MSC at %s:%d\n", ip, port);
|
||||
|
||||
con->is_connected = 0;
|
||||
|
||||
fd = &con->write_queue.bfd;
|
||||
fd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
fd->when = BSC_FD_READ;
|
||||
fd->data = NULL;
|
||||
fd->priv_nr = 1;
|
||||
|
||||
if (fd->fd < 0) {
|
||||
@@ -160,41 +45,18 @@ int bsc_msc_connect(struct bsc_msc_connection *con)
|
||||
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);
|
||||
sin.sin_port = htons(port);
|
||||
inet_aton(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) {
|
||||
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);
|
||||
@@ -207,64 +69,4 @@ int bsc_msc_connect(struct bsc_msc_connection *con)
|
||||
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;
|
||||
}
|
||||
|
||||
808
openbsc/src/bsc_msc_ip.c
Normal file
808
openbsc/src/bsc_msc_ip.c
Normal file
@@ -0,0 +1,808 @@
|
||||
/* 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 <openbsc/bsc_msc.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) {
|
||||
struct bss_sccp_connection_data *con_data;
|
||||
|
||||
DEBUGP(DMSC, "Connection established: %p\n", conn);
|
||||
|
||||
/* start the inactivity test timer */
|
||||
con_data = (struct bss_sccp_connection_data *) conn->data_ctx;
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
bts_unblock_queue(msg->lchan->msc_data);
|
||||
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 gsm_lchan *old_chan;
|
||||
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");
|
||||
put_lchan(msg->lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
|
||||
put_lchan(msg->lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
|
||||
DEBUGP(DMSC, "assignment failure invalid: %d\n",
|
||||
msgb_l3len(msg) - sizeof(*gh));
|
||||
put_lchan(msg->lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* swap the channels and release the old */
|
||||
old_chan = msg->lchan->msc_data->lchan;
|
||||
msg->lchan->msc_data->lchan = msg->lchan;
|
||||
msg->lchan->msc_data->secondary_lchan = NULL;
|
||||
old_chan->msc_data = NULL;
|
||||
|
||||
/* give up the old channel to not do a SACCH deactivate */
|
||||
subscr_put(old_chan->subscr);
|
||||
old_chan->subscr = NULL;
|
||||
put_lchan(old_chan);
|
||||
|
||||
/* activate audio on it... */
|
||||
if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && msg->lchan->tch_mode != GSM48_CMODE_SIGN)
|
||||
rsl_ipacc_crcx(msg->lchan);
|
||||
|
||||
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");
|
||||
put_lchan(msg->lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msg->lchan->msc_data->secondary_lchan != msg->lchan) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n");
|
||||
put_lchan(msg->lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (msgb_l3len(msg) - sizeof(*gh) != 1) {
|
||||
DEBUGP(DMSC, "assignment failure invalid: %d\n",
|
||||
msgb_l3len(msg) - sizeof(*gh));
|
||||
put_lchan(msg->lchan);
|
||||
return -1;
|
||||
}
|
||||
|
||||
gsm0808_send_assignment_failure(msg->lchan,
|
||||
GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE, &gh->data[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a GSM04.08 MODIFY ACK. Actually we have to check
|
||||
* the content to see if this was a success or not.
|
||||
*/
|
||||
static int handle_modify_ack(struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* modify RSL */
|
||||
rc = gsm48_rx_rr_modif_ack(msg);
|
||||
if (rc < 0)
|
||||
gsm0808_send_assignment_failure(msg->lchan,
|
||||
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
|
||||
else
|
||||
gsm0808_send_assignment_compl(msg->lchan, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Receive a GSM 04.08 Radio Resource (RR) message */
|
||||
static int gsm0408_rcv_rr(struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
int rc = 0;
|
||||
|
||||
switch (gh->msg_type) {
|
||||
case GSM48_MT_RR_PAG_RESP:
|
||||
rc = handle_paging_response(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_MEAS_REP:
|
||||
/* ignore measurement for now */
|
||||
rc = -1;
|
||||
break;
|
||||
case GSM48_MT_RR_CIPH_M_COMPL:
|
||||
rc = handle_cipher_m_complete(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_ASS_COMPL:
|
||||
rc = handle_ass_compl(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_ASS_FAIL:
|
||||
rc = handle_ass_fail(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
|
||||
rc = handle_modify_ack(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Receive a GSM 04.08 Mobility Management (MM) message */
|
||||
static int gsm0408_rcv_mm(struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
int rc = 0;
|
||||
|
||||
switch (gh->msg_type & 0xbf) {
|
||||
case GSM48_MT_MM_LOC_UPD_REQUEST:
|
||||
case GSM48_MT_MM_CM_REEST_REQ:
|
||||
case GSM48_MT_MM_CM_SERV_REQ:
|
||||
case GSM48_MT_MM_IMSI_DETACH_IND:
|
||||
rc = send_dtap_or_open_connection(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
u_int8_t pdisc = gh->proto_discr & 0x0f;
|
||||
int rc = 0;
|
||||
|
||||
switch (pdisc) {
|
||||
case GSM48_PDISC_RR:
|
||||
rc = gsm0408_rcv_rr(msg);
|
||||
break;
|
||||
case GSM48_PDISC_MM:
|
||||
rc = gsm0408_rcv_mm(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* if we have a sccp connection and didn't handle the message
|
||||
* forward it to the MSC using DTAP
|
||||
*/
|
||||
if (rc == 0 && msg->lchan->msc_data && lchan_get_sccp(msg->lchan)) {
|
||||
struct msgb *dtap = dtap_create_msg(msg, link_id);
|
||||
if (!dtap) {
|
||||
DEBUGP(DMSC, "Creating a DTAP message failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bsc_queue_connection_write(lchan_get_sccp(msg->lchan), dtap);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* handle ipaccess signals */
|
||||
static int handle_abisip_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct gsm_lchan *lchan = signal_data;
|
||||
struct gsm_bts_trx_ts *ts;
|
||||
int rc;
|
||||
|
||||
if (subsys != SS_ABISIP)
|
||||
return 0;
|
||||
|
||||
ts = lchan->ts;
|
||||
|
||||
switch (signal) {
|
||||
case S_ABISIP_CRCX_ACK:
|
||||
/* we can ask it to connect now */
|
||||
if (lchan->msc_data) {
|
||||
DEBUGP(DMSC, "Connecting BTS to port: %d conn: %d\n",
|
||||
lchan->msc_data->rtp_port, lchan->abis_ip.conn_id);
|
||||
|
||||
int rtp_payload = ts->trx->bts->network->rtp_payload;
|
||||
if (rtp_payload == 0)
|
||||
rtp_payload = lchan->abis_ip.rtp_payload2;
|
||||
|
||||
rc = rsl_ipacc_mdcx(lchan, ntohl(local_addr.s_addr),
|
||||
lchan->msc_data->rtp_port,
|
||||
rtp_payload);
|
||||
if (rc < 0) {
|
||||
DEBUGP(DMSC, "Failed to send connect: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case S_ABISIP_DLCX_IND:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_usage()
|
||||
{
|
||||
printf("Usage: bsc_hack\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* SCCP handling
|
||||
*/
|
||||
static int msc_sccp_write_ipa(struct msgb *msg, void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGP(DMSC, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
|
||||
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
|
||||
|
||||
|
||||
DEBUGP(DMI, "MSC TX %s\n", hexdump(msg->l2h, msgb_l2len(msg)));
|
||||
ret = write(msc_connection.fd, msg->data, msg->len);
|
||||
|
||||
if (ret <= 0) {
|
||||
perror("MSC: Failed to send SCCP");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msc_sccp_accept(struct sccp_connection *connection, void *data)
|
||||
{
|
||||
DEBUGP(DMSC, "Rejecting incoming SCCP connection.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
|
||||
{
|
||||
struct bssmap_header *bs;
|
||||
|
||||
DEBUGP(DMSC, "Incoming SCCP message ftom MSC: %s\n", hexdump(msgb->l3h, length));
|
||||
|
||||
if (length < sizeof(*bs)) {
|
||||
DEBUGP(DMSC, "The header is too short.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bs = (struct bssmap_header *) msgb->l3h;
|
||||
if (bs->length < length - sizeof(*bs))
|
||||
return -1;
|
||||
|
||||
switch (bs->type) {
|
||||
case BSSAP_MSG_BSS_MANAGEMENT:
|
||||
msgb->l4h = &msgb->l3h[sizeof(*bs)];
|
||||
bssmap_rcvmsg_udt(bsc_gsmnet, msgb, length - sizeof(*bs));
|
||||
break;
|
||||
default:
|
||||
DEBUGPC(DMSC, "Unimplemented msg type: %d\n", bs->type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* network initialisation
|
||||
*/
|
||||
static void initialize_if_needed(void)
|
||||
{
|
||||
if (!bsc_gsmnet) {
|
||||
int rc;
|
||||
struct msgb *msg;
|
||||
|
||||
fprintf(stderr, "Bootstraping the network. Sending GSM08.08 reset.\n");
|
||||
rc = bsc_bootstrap_network(NULL, config_file);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Bootstrapping the network failed. exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* send a gsm 08.08 reset message from here */
|
||||
msg = bssmap_create_reset();
|
||||
if (!msg) {
|
||||
DEBUGP(DMSC, "Failed to create the reset message.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sccp_write(msg, &sccp_ssn_bssap, &sccp_ssn_bssap, 0);
|
||||
msgb_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* callback with IP access data
|
||||
*/
|
||||
static int ipaccess_a_fd_cb(struct bsc_fd *bfd, unsigned int what)
|
||||
{
|
||||
int error;
|
||||
struct msgb *msg = ipaccess_read_msg(bfd, &error);
|
||||
struct ipaccess_head *hh;
|
||||
|
||||
if (!msg) {
|
||||
if (error == 0) {
|
||||
fprintf(stderr, "The connection to the MSC was lost, exiting\n");
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Failed to parse ip access message: %d\n", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUGP(DMSC, "From MSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
|
||||
|
||||
/* handle base message handling */
|
||||
hh = (struct ipaccess_head *) msg->data;
|
||||
ipaccess_rcvmsg_base(msg, bfd);
|
||||
|
||||
/* initialize the networking. This includes sending a GSM08.08 message */
|
||||
if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_ID_ACK)
|
||||
initialize_if_needed();
|
||||
else if (hh->proto == IPAC_PROTO_SCCP)
|
||||
sccp_system_incoming(msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
msc_connection.cb = ipaccess_a_fd_cb;
|
||||
rc = connect_to_msc(&msc_connection, msc_address, 5000);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Opening the MSC connection failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
signal(SIGINT, &signal_handler);
|
||||
signal(SIGABRT, &signal_handler);
|
||||
signal(SIGUSR1, &signal_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
while (1) {
|
||||
bsc_select_main(0);
|
||||
}
|
||||
}
|
||||
@@ -24,14 +24,13 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include <openbsc/debug.h>
|
||||
#include <osmocore/talloc.h>
|
||||
#include <osmocore/timer.h>
|
||||
#include <osmocore/linuxlist.h>
|
||||
#include <openbsc/talloc.h>
|
||||
#include <openbsc/timer.h>
|
||||
#include <openbsc/linuxlist.h>
|
||||
#include <openbsc/bsc_rll.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/chan_alloc.h>
|
||||
#include <openbsc/abis_rsl.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
struct bsc_rll_req {
|
||||
struct llist_head list;
|
||||
@@ -53,6 +52,7 @@ static LLIST_HEAD(bsc_rll_reqs);
|
||||
static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type)
|
||||
{
|
||||
llist_del(&rllr->list);
|
||||
put_lchan(rllr->lchan);
|
||||
rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type);
|
||||
talloc_free(rllr);
|
||||
}
|
||||
@@ -80,9 +80,11 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi,
|
||||
/* If we are a TCH and not in signalling mode, we need to
|
||||
* indicate that the new RLL connection is to be made on the SACCH */
|
||||
if ((lchan->type == GSM_LCHAN_TCH_F ||
|
||||
lchan->type == GSM_LCHAN_TCH_H) && sapi != 0)
|
||||
lchan->type == GSM_LCHAN_TCH_H) &&
|
||||
lchan->rsl_cmode != RSL_CMOD_SPD_SIGN)
|
||||
link_id |= 0x40;
|
||||
|
||||
use_lchan(lchan);
|
||||
rllr->lchan = lchan;
|
||||
rllr->link_id = link_id;
|
||||
rllr->cb = cb;
|
||||
@@ -114,29 +116,3 @@ void rll_indication(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int rll_lchan_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct challoc_signal_data *challoc;
|
||||
struct bsc_rll_req *rllr, *rllr2;
|
||||
|
||||
if (subsys != SS_CHALLOC || signal != S_CHALLOC_FREED)
|
||||
return 0;
|
||||
|
||||
challoc = (struct challoc_signal_data *) signal_data;
|
||||
|
||||
llist_for_each_entry_safe(rllr, rllr2, &bsc_rll_reqs, list) {
|
||||
if (rllr->lchan == challoc->lchan) {
|
||||
bsc_del_timer(&rllr->timer);
|
||||
complete_rllr(rllr, BSC_RLLR_IND_ERR_IND);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((constructor)) void on_dso_load_rll(void)
|
||||
{
|
||||
register_signal_handler(SS_CHALLOC, rll_lchan_signal, NULL);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user