Compare commits

..

150 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
61e5e7bd8b Bump version..
* ping pong and possible crash fix.
2010-05-03 17:27:07 +08:00
Holger Hans Peter Freyther
f7b06fbe0c bsc: Speculative crash fix.
Make sure the sccp_cc_timeout is stopped when we delete the
associated data. There is one crash report that indicates that
we have a pending timer that is inside freed memory.

A crash could have occured when the connection to the MSC was
lost while have unconfirmed connections.
2010-05-03 16:13:02 +08:00
Holger Hans Peter Freyther
45403b1804 nat/bsc: Send PONG on PING, send PING from the BSC too
We do want to send PING/PONG in both ways to have a heartbeat
on the TCP connection. When switching over to SCTP we can rely
on the builtin heartbeat functionality.
2010-05-03 11:51:07 +08:00
Holger Hans Peter Freyther
6782cea4bf nat: Send a IPA PING down the stream and wait for the pong.
We will send a ping every 20 seconds and if we have no pong
within 5 seconds we will close down the BSC connection and
wait for a reconnect. We will start this after having
authenticated the BSC and we stop the timer when destructing
the BSC connection.
2010-05-02 19:31:14 +08:00
Holger Hans Peter Freyther
ec7ecab66f nat: Allow to only show statistics for a given BSC Cfg. 2010-05-02 19:31:14 +08:00
Holger Hans Peter Freyther
d1287e379b nat: Do not allow a BSC to send auth messages twice. 2010-05-02 19:31:13 +08:00
Holger Hans Peter Freyther
3fb44f3e61 nat: Fix vty output for connected BSCs 2010-05-02 19:31:13 +08:00
Holger Hans Peter Freyther
d48bfe0e93 bssap: Store the link_id in the new msgb->cb.
Work with a new version of libosmocore that gets rid of
additional pointers.
2010-05-01 15:22:40 +08:00
Holger Hans Peter Freyther
41cdaf520d remove any reference to 'struct gsm_bts_link' 2010-05-01 15:19:14 +08:00
Harald Welte
f94418a129 gsm_04_11.c: Use msgb->l4h instead of sms->smsh, as the latter is gone 2010-05-01 15:18:37 +08:00
Holger Hans Peter Freyther
88b299ca24 configure.in: Bump the version due mem leak fixes.
The nat is stable and in testing..
2010-05-01 15:01:45 +08:00
Holger Hans Peter Freyther
58a2758e78 nat: Improve log message and refer to the BSC that was lost. 2010-05-01 10:37:15 +08:00
Holger Hans Peter Freyther
be3fdc2c6e nat: Fix memory leak... in MGCP forwarding
The code needs to be refactored but this is fixing the leak for
now. We used to forward everything to the BSC but now we handle
the DLCX locally and this means we need to clear the patched
message. We should refactor it to not generate the patched msg
until a lot later.
2010-05-01 10:31:53 +08:00
Holger Hans Peter Freyther
6a8d765334 [vty] Free the matched at the end of the routine.
Remove the return from the case labels and cleanup at
the end matched array at the end of the routine.
2010-04-30 13:24:09 +08:00
Holger Hans Peter Freyther
adebbfdfa7 [vty] Plug memory leak on auto completion.
I assume the original code crashed with a double free as we
have a cleanup at the end of the method. Return from the routine
like the case label below. This is fixing a memory leak I am
experimenting.
2010-04-30 13:18:05 +08:00
Holger Hans Peter Freyther
afccfb9380 [vty] Allow to create a buffer in a given context.
Stop using the global vty context for all allocations
and allow to embed the buffer into a given context, and
allocate sub buffers with the context of its parent.
2010-04-30 12:26:52 +08:00
Holger Hans Peter Freyther
0f7a8258f0 [vty] Move some allocations into the context of the vty. 2010-04-30 12:18:32 +08:00
Holger Hans Peter Freyther
2aa7f10939 [vty] Remove FIXME as it appears to do the right thing. 2010-04-30 11:33:34 +08:00
Holger Hans Peter Freyther
37ba5b3e35 nat: Report some more contexts 2010-04-30 11:08:22 +08:00
Holger Hans Peter Freyther
9f63d2b4ad [mgcp] Remove talloc.h header. 2010-04-29 21:03:43 +08:00
Holger Hans Peter Freyther
d21b5de8c0 nat: Do not use \n in the vty code.
When we really need a newline we need to use VTY_NEWLINE.
2010-04-27 15:35:14 +08:00
Holger Hans Peter Freyther
12b63716e2 nat: Add a command to close a given BSC Connection
This can be used to clear stale connections for a given BSC
or to force a reconnect of the BSC.
2010-04-27 13:21:39 +08:00
Holger Hans Peter Freyther
184961ea3e nat: Print the remote reference as well. 2010-04-27 13:11:18 +08:00
Holger Hans Peter Freyther
a9ec86029f Bump the version of OpenBSC. 2010-04-26 16:08:13 +08:00
Holger Hans Peter Freyther
d1b19f3308 [ts] Make the e1inp_ts delay configurable
Currently the nanoBTS bootstrap code requires a high delay
otherwise we are not bringing the device up properly. Changing
the init code turns out harder than it seems like. So this is
a workaround for that to allow a high speed RSL/OML connection
after the bringup.

The line driver can have a default TS delay. It is set to the
current default for the nanoBTS and the BS11. For the ipaccess
case we will set the delay lower for the RSL connection and
inside the ipaccess-config we can set it low right away to
have fast firmware flashing and such.
2010-04-26 16:02:04 +08:00
Holger Hans Peter Freyther
33f531fd12 ipaccess: Restore the original delay for the nanoBTS delay. 2010-04-26 10:33:56 +08:00
Holger Hans Peter Freyther
b051b3b161 bsc_init: Do not use magic numbers for GSM 12.21 states. 2010-04-26 10:32:34 +08:00
Holger Hans Peter Freyther
479a3aa707 bsc_init: Remove printf that sneaked in. 2010-04-26 10:27:42 +08:00
Holger Hans Peter Freyther
fd2a877e25 nat: Release the transaction id earlier, always reset the BSC
In case we can not find the SCCP connection we still want to
free any pending transaction ids and reset the BSC inside the
endpoint. In most cases this should be already done when the
SCCP connection or the whole BSC is gone.
2010-04-24 21:05:18 +08:00
Holger Hans Peter Freyther
53f797305f [mgcp] Possible memleak fix for the allowed reallocation case
When allowing to reallocate an allocated endpoint we will need
to free it first. When freeing we will free the call id and other
ids that we would have leaked otherwise.
2010-04-24 21:02:48 +08:00
Holger Hans Peter Freyther
691b40e834 nat: Attempt to clarify the text inside the log message. 2010-04-24 21:02:01 +08:00
Holger Hans Peter Freyther
e511d54dd0 nat: Allocate a named context to make dumping allocations possible
This is fixing the SIGUSR1 to really report the allocated
memory on stderr.
2010-04-23 21:56:57 +08:00
Holger Hans Peter Freyther
6edf7b9a51 bsc_msc_ip: Add a timeout for waiting for the CC of the network
Start a timeout to wait for the CC of the network and if it does
not come in time we will abort the connection and take down the
allocated lchans.
2010-04-23 18:22:26 +08:00
Holger Hans Peter Freyther
e4045679a8 nat: Only close connections that were fully connected
Remember that we have seen a CC and have a valid destination
local reference now and only send a fake RLC to the MSC when
we had connections in this state.
2010-04-23 14:13:27 +08:00
Holger Hans Peter Freyther
52ae9a461b nat: When having a proper close down, or a short read close the connection
For now close the connection when having a short read. This might
be due a network issue (loss of segment) or similiar. As we are not
handling these issues well, let us close the connection.
2010-04-23 00:23:03 +08:00
Holger Hans Peter Freyther
5bd9493257 nat: Only send DLCX when we have send a CRCX to the BSC on this endpoint 2010-04-22 20:12:13 +08:00
Holger Hans Peter Freyther
c92fd5d9d3 nat: Handle all queueing to the MSC through the same function. 2010-04-22 19:11:37 +08:00
Holger Hans Peter Freyther
01cf14d679 nat: Use show bsc config for showing the configuration. 2010-04-22 13:36:46 +08:00
Holger Hans Peter Freyther
840447e2bf [mgcp] Add a change callback and send a dummy packet on MDCX.
Send a dummy packet to make sure our Gateway will discover us
and can send the ringtone to us.
2010-04-22 13:23:05 +08:00
Holger Hans Peter Freyther
3f7586d571 nat: Use hex for the endpoint names 2010-04-22 13:06:24 +08:00
Holger Hans Peter Freyther
b74a9f13e5 [mgcp] Ignore every dummy packet...
This routine should operate on different packets and the
dummy load is smaller than a legitimate RTP header so it
is unlikely we will filture out genuine traffic.

The reason is the dummy load might be send more than once.
2010-04-22 12:15:38 +08:00
Holger Hans Peter Freyther
bbc2c6e765 nat: Change MGCP DLCX handling and send dummy MDCX to the BTS.
When setting a new MSC timeslot to a SCCP connection check if
any of the existing connections have this timeslot, if so we will
send a DLCX down the stream to make sure it is closed there, when
we will CRCX this new timeslot we will happily reallocate it.

When the SCCP connection goes away, or we get a DLCX from the
network, or the BSC is gone we will send a DLCX message down the
stream as well.

When we receive a CRCX from the network we will forward the CRCX
as usual and send a dummy MDCX after it.

For the DLCX and the dummy MDCX we send a custom MGCP message
that will not provoke an answer. Even if the downstream MGCP GW
will answer we will ignore it due the dummy transaction id that
is not used anywhere else.

This change should make sure that we close the dowstream endpoint
all the time, even when the DLCX arrives after the SCCP connection
is torndown.
2010-04-22 12:13:44 +08:00
Holger Hans Peter Freyther
7e3724ad18 nat: Move the write queue init to the allocation function
This is required for unit tests that want to queue messages
and see if we can provoke a memleak.
2010-04-22 12:13:44 +08:00
Holger Hans Peter Freyther
569dccf947 nat: Clear the queued messages at the end
It is possible that the calls from the loop would queue
more messages for the BSC and then we would have a nice
memory leak... Move it to the bottom.
2010-04-22 12:13:44 +08:00
Holger Hans Peter Freyther
89a378e9aa [mgcp] Protocol extension to not generate answers.
For the NAT we want to send requests in a send and forget
way and we are not interested in seeing the answers, so tell
the gateway to not answer them.
2010-04-22 12:13:44 +08:00
Holger Hans Peter Freyther
4a78c7b250 [mgcp] Print a Deleted endpoint message again. 2010-04-22 12:13:44 +08:00
Holger Hans Peter Freyther
c71013091a [mgcp] Add a dummy send method...
This can be used by higher level code to send one dummy
message from the audio port to the network. This can be
used to make the remote discover the nated port of this
endpoint.
2010-04-21 21:25:13 +08:00
Holger Hans Peter Freyther
4b1cde10fe [sccp] Move from DEBUGP to LOGP in sccp.c 2010-04-21 21:08:58 +08:00
Holger Hans Peter Freyther
0f5a2345d1 [nat] Degrade the message to a plain debug output. 2010-04-21 20:17:18 +08:00
Holger Hans Peter Freyther
ae81ff95ea [nat] Fix the vty option... use the right argument. 2010-04-21 20:07:07 +08:00
Holger Hans Peter Freyther
e5981edf6a [nat] Add option to forbid the paging to the BSC.
This can be done for testing purposes and to allow making
a BTS crash that can not handle paging requests properly.
2010-04-21 19:05:14 +08:00
Holger Hans Peter Freyther
93cc16ae4f [nat] Lookup by BSC Connection otherwise the point of reassigning the is defeated
When sending a MSG to the MSC try to find the to be used "src" reference
by comparing the reference on the BSC and the BSC connection. Only this
tuple needs to be unique.
Actually only when looking at the SRC REF we need to compare the BSC as the
dest reference should be unique but we are just making the check a bit stronger
to make it look symmetric.
2010-04-21 18:56:12 +08:00
Holger Hans Peter Freyther
119a1976f5 [nat] Slightly improve logging..
If we find the connection of a different BSC at least log the
BSCs that had duplicated references. We should also dump the
src ref and such but i am not doing this right now.
2010-04-21 18:49:55 +08:00
Holger Hans Peter Freyther
c53c2ab524 [nat] Ignore paging that is to page by BSS...
We do not want to handle this identity. If we can not page by
lac there is no need to page anything else.
2010-04-21 18:47:24 +08:00
Holger Hans Peter Freyther
32423500f6 [nat] Add unit test to forward Proto Error messages back both ways. 2010-04-21 15:46:38 +08:00
Holger Hans Peter Freyther
c3a6a1dbe5 [sccp] Parse the error message and add a unit test for it. 2010-04-21 15:46:38 +08:00
Holger Hans Peter Freyther
f4f090ee36 [nat] Reword warning when we had a pending transaction and forget about it. 2010-04-21 15:17:45 +08:00
Holger Hans Peter Freyther
2a554bfcc4 [nat] Cope with a bad BSC reassigning in use SRC REF
Some closed source BSC like to assign the SRC REF from a
small static pool and might reuses one we have not yet given
up on.
2010-04-21 10:47:25 +08:00
Holger Hans Peter Freyther
a12dea66ca [ipaccess] Attempt to fix setting unit ids with a multi trx setup
Add a --trx/-t NR option to set the TRX nr to be used when calling
set unit id and NVRAM. This was not tested and might or might not
work.
2010-04-20 22:22:00 +08:00
Holger Hans Peter Freyther
ec59bb04df Versioning for the bsc_msc_ip 2010-04-20 18:10:27 +08:00
Holger Hans Peter Freyther
4417f7f477 [vty] Allow to set the RACH NM attributes on a per BTS basis
Be able to tune the RACH settings of the BTS via the vty interface,
by default they are initialized to -1 which means we will use the
content of the static array (BTS default) and can be changed via
the VTY interface. I have verified the setting on the nanoBTS with
wireshark and I have tested writing the config file.
2010-04-20 18:02:25 +08:00
Holger Hans Peter Freyther
39563af27c [paging] Implement the counting for TCH/H and TCH/F
Add some code to count TCH/H and TCH/F and also handle
the neci bit of the network. Our channel allocator will
allocate a TCH/F if we request a TCH/H but can not allocate it.
2010-04-20 17:15:21 +08:00
Holger Hans Peter Freyther
242faaafd1 [paging] Only page if we have some free channels right now
Only page if we have a load that is acceptable for paging. This
option is off by default, and can be enabled per bts. The idea
is that when we have no resources right now we will not page as
it will only create more RACHs and increase the load.
2010-04-20 17:10:43 +08:00
Holger Hans Peter Freyther
f77c0cd428 Version bump for On-Waves
* Revert RTP_PAYLOAD change as it does not work on AMR
* Change paging to not send it as a bulk...
2010-04-20 14:36:40 +08:00
Holger Hans Peter Freyther
4103a3e5b9 Revert "ipaccess: Send RTP Payload IE for CRCX & MDCX"
This is causing a regression with AMR audio. The nanoBTS
is sending a MDCX NACK with Cause 0x52. Reverting this
commit makes it work again.

This reverts commit b54dda4cef.
2010-04-20 14:08:20 +08:00
Holger Hans Peter Freyther
4aca7f621f [paging] Continuisly send paging commands.
Instead of throwing a huge pile of paging commands to the BTS
we will submit one paging command every half second. This way
we can have different messages between the paging commands.
2010-04-20 12:27:33 +08:00
Holger Hans Peter Freyther
507d536ce8 [paging] When giving credit try to send out paging requests too.
Make sure the paging timer is restarted after giving some credit
and send out paging requests.
2010-04-20 10:59:33 +08:00
Holger Hans Peter Freyther
cb618c7980 [paging] Revert the paging band aid. 2010-04-20 10:54:43 +08:00
Holger Hans Peter Freyther
3c0702d3c5 Increase the minor version as this is a band-aid.. 2010-04-19 22:30:28 +08:00
Holger Hans Peter Freyther
caf24567d1 BAND AID... Reduce the delay timer, reduce number of paging requests we send
This is a band aid and not a proper fix. Reduce the time between two
IPA commands even if it is breaking rugby sized BTSs, limit the paging
commands we send during one iteration through the event loop. This should
prevent us from killing ourselves in a RACH loop.
2010-04-19 22:30:21 +08:00
Holger Hans Peter Freyther
1d34c6ac5a bsc_msc_ip: Crash fix on MO-Call starting with a SDCCH
We do not assing a GSM Subscriber to Mobile Originated calls, when
requesting a SDCCH and then starting call control we will crash here
due trying to copy a NULL subscriber from the lchan to the other.

We do not need to know the IMSI at the BSC so it is okay to not
copy the subscriber around, we could even kill all subscriber handling
in the future.
2010-04-19 22:15:32 +08:00
Holger Hans Peter Freyther
1506f8e465 [paging] When we ran down to 0 available paging slots start a credit timer
It might be that we run down to zero available slots but the BTS
might not send us a load indication. This can happen if we think
we send paging requests and the BTS disagrees and considers them
as errors and does not count the paging message.
When we drop to zero we will start a credit timer to give us extra
credit after six seconds, if we get a CCCH load indication before
we will stop the timer.
2010-04-19 19:41:26 +08:00
Holger Hans Peter Freyther
f044c585e2 Merge remote branch 'origin/master' into on-waves/bsc-master
Conflicts:
	openbsc/include/openbsc/abis_rsl.h
	openbsc/include/openbsc/mgcp.h
	openbsc/src/abis_rsl.c
	openbsc/src/chan_alloc.c
	openbsc/src/handover_logic.c
	openbsc/src/mgcp/mgcp_network.c
	openbsc/src/vty/command.c
	openbsc/src/vty_interface.c
2010-04-19 17:17:59 +08:00
Harald Welte
38e9c82114 RSL: inmplement ip.access paging load indication 'below threshold'
This is an ip.access specific 08.58 oddity.  It reports 0xffff
available paging buffers if the paging load is below the 12.21
CCCH LOAD INDICATION THRESHOLD.

We use 50, since that is what it reports if the threshold == 0.
2010-04-19 10:29:16 +02:00
Harald Welte
39608dc045 GPRS: Fix calculation of 'Extension Length' in GPRS Cell Options
The actual 'Extension Length' field in the 'GPRS Cell Options' IE
is coded the length - 1, not the full length.  Without this fix,
the code has an off-by-one error.
2010-04-18 22:48:46 +02:00
Harald Welte
5fda90816f GPRS: Indicate the SGSN is Release 99 as this is the first with EDGE 2010-04-18 22:48:41 +02:00
Harald Welte
1803818092 update openbsc.cfg examples for new gprs syntax 2010-04-18 21:33:00 +02:00
Harald Welte
439bb828f9 GPRS: Enable EGPRS coding schemes in Cell Attributes if 'gprs mode egprs' 2010-04-18 21:25:56 +02:00
Harald Welte
a06fea020d GPRS: actually enable indicating EDGE capability in SI13 2010-04-18 21:25:56 +02:00
Harald Welte
4511d891dd GPRS: change 'gprs enabled <0-1>' to 'gprs mode (none|gprs|egprs)'
This causes some config file breakage but sounds like a much cleaner
approach than to have two separate config variables for this.
2010-04-18 21:25:56 +02:00
Harald Welte
da0586a838 GPRS: Add Support for the GPRS Cell Option Extension Info IE
Extension Information is part of the GPRS Cell Options IE, as
specified in Chapter 12.24 of TS 04.60.  It is needed for
indicating EDGE capabilities of the BTS to the MS.

This simply adds the code to encode this IE as part of SI13,
but does not actually use the code yet.
2010-04-18 21:25:56 +02:00
Harald Welte
2c57232489 add an example config file for nanoBTS multi-trx case 2010-04-18 21:25:18 +02:00
Harald Welte
ad9f7830fb update the openbts.cfg.nanobts example 2010-04-18 21:08:26 +02:00
Harald Welte
57ba7e3093 GPRS: BVCI 0 and 1 are not permitted.
According to TS 08.18, BVCI=0 is for the SIGNALLING entity,
and BVCI=1 is for the PTM entity.  Both should not be used
by the PTP entity that we're configuring here.
2010-04-18 14:00:26 +02:00
Harald Welte
6ba3bcbbc6 BVCI 0 is not within the permitted range 2010-04-18 13:59:53 +02:00
Holger Hans Peter Freyther
bb110f91e8 [statistics] Keep track of OML/RSL failures of the BTS. 2010-04-17 06:48:43 +02:00
Holger Hans Peter Freyther
3ba36d5b57 [statistics] Keep track of rf failures and rll release failures
Add two new counters to count the RF Failures and the RLL Release
failure and make them available via the vty interface.
2010-04-17 06:48:29 +02:00
Holger Hans Peter Freyther
bda581963d Merge branch 'on-waves/mgcp' 2010-04-17 06:46:06 +02:00
Holger Hans Peter Freyther
8d9833ef83 [mgcp] Fix vty file generation for the BSC nat and other cases
The current setting was not properly written out, this commit is
fixing it. This includes indention, empty bts ip, wrong command
for endpoints and the wrong number (+1 as zero is allocated but
unused).
2010-04-17 06:45:08 +02:00
Holger Hans Peter Freyther
2ba40afc36 Add rf_locked to the configuration writing. 2010-04-17 06:42:48 +02:00
Holger Hans Peter Freyther
e0ec326867 [vty] Separate BSC and MSC statistics. Make it easy to print them.
Move the statistics command into the MSC part and move the
BSC statistics printing into a subroutine.
2010-04-15 11:28:14 +02:00
Holger Hans Peter Freyther
2d425059af [mgcp] Only write audio_name/payload when it is actually set. 2010-04-15 11:26:35 +02:00
Holger Hans Peter Freyther
135f797a37 [bsc_init] When the RSL/OML connection drops, free all lchans
Free all allocated channels on the TRX that failed, go through
lchan_free to signal higher layers and then force a reset of
the channel. Make the TRX and TS unusable by setting the operational
set to 0 (not really defined) which should be reset once the
RSL is coming up again.
2010-04-15 11:24:53 +02:00
Holger Hans Peter Freyther
f8eff2e4b5 [ipa] Fix the reporting of link down...
Now bsc_init.c is able to handle the link down messages.
2010-04-15 11:19:08 +02:00
Holger Hans Peter Freyther
70402a4e4d [ipa] Handle losing the RSL/OML connection..
This is addressing multiple issues regarding the loss of the
OML/RSL link to the BTS.

1.) When we lose the OML link, close down all RSL connections
on all TRXs (only tested with one TRX) and free the e1inp_line
allocated for the OML connection.
2.) When we lose the RSL link on any TRX and we know to which
lines this connection belongs, we will close down the OML connection
as we have a problem to just reactivate one RSL link.
3.) When we lose the RSL link on any TRX and we do not know
where it belongs to we will free the bfd we have allocated in the
rsl listen/accept method and we properly close the socket (i could
not test this one properly). This is made under the assumption
the BTS has not responded to the ID request.
4.) When we already have a bts->oml_link we will throw it away
and use the new link (it should not happen) and the same applies
to the rsl link.
2010-04-15 11:17:24 +02:00
Sylvain Munaut
b54dda4cef ipaccess: Send RTP Payload IE for CRCX & MDCX
For GSM V1 FR, the payload type is fixed to 3 in the RFC.
But for the other codecs, the payload type is dynamically assigned
between 96 and 127. Here, we use a static mapping internal to OpenBSC.

This patch is needed to make a rather old 139 unit (with sw version
120a002_v149b42d0) work with something else than FR codec. I also tested
this patch on a newer 139 (with sw version 120a352_v267b22d0) to make
sure it didn't add a regression. More testing with newer EDGE units
should be done by whoever has some of theses.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-04-12 19:58:57 +02:00
Sylvain Munaut
b998d7b219 abis_nm: Fix ACTIVATE SW parameters
The previous code only sent the FILE_ID tag data part,
but according to the GSM 12.21 spec, section 8.3.6, the
full SW Description 'object' must be sent so that includes
the NM_ATT_SW_DESCR tag, the whole FILE_ID and the whole
FILE_VERSION (including tags & length fields).

Note that functionnaly on a nanoBTS 139 I couldn't see any
difference ... whatever I send in there it works ...

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2010-04-12 19:58:57 +02:00
Holger Hans Peter Freyther
63cb447fd5 Revert "ipa: Reduce the throttling of the IPA msges"
Reducing the throttling to this value created a regression with
bringing up RSL on the nanoBTS 900. We do seem to have a bug/issue
in the bsc_init code and might send a command too early without this
longer wait period and then the state transition does not happen.

For now it is agreed that reverting is the best thing to do.

Debugged-by: Sylvain Munaut <246tnt@gmail.com>

This reverts commit f5284ae1cf.
2010-04-11 10:14:16 +02:00
Holger Hans Peter Freyther
5eec9d91d8 [rsl] Set the right state when asking for the activation.
Set the state to activation to avoid a warning about the
getting a CHAN ACK without waiting for it. We set it in
the code to make sure it is set after all error checking
to avoid inconsistent state as the state is only set back
to NONE/ACT due replies from the BTS.
2010-04-10 00:16:04 +02:00
Holger Hans Peter Freyther
63d18b51a7 [rsl] Set the release state from within the lchan class
Currently our GSM04.11 code is closing the link for SAPI=3
and this would mean that the whole channel would be scheduled
for close... where we only want to close everything when freeing
the lchan or handling an error.
2010-04-10 00:14:55 +02:00
Holger Hans Peter Freyther
74419497fc [rsl] Introduce a method to set the state of the lchan
Setting the state through a dedicated method allows us to
track the state transitions and check if they are done in
a proper way.
2010-04-10 00:13:53 +02:00
Holger Hans Peter Freyther
ccfd572647 [rsl] Remove method that is not called by anything. 2010-04-10 00:11:17 +02:00
Holger Hans Peter Freyther
07ba16fe03 [vty] Remove unused variables due them only being used in the layer3
I moved the extra code to the layer3 VTY implementation but didn't
remove the variables while doign so, silent compiler warnings.
2010-04-10 00:08:59 +02:00
Holger Hans Peter Freyther
e1ffc08f72 [vty] Forward declare the extra init function the base is calling 2010-04-10 00:08:28 +02:00
Holger Hans Peter Freyther
ef8117883b [paging] Include chan_alloc.h to silence a compiler warning
paging.c:259: warning: implicit declaration of function ‘trx_is_usable’
2010-04-10 00:06:17 +02:00
Holger Hans Peter Freyther
ae80f9291a Return anything from append_lsa_params. 2010-04-10 00:05:16 +02:00
Holger Hans Peter Freyther
1469600b0d [paging] Start with a smaller paging limit...
The value 20 is just a random number and it really depends
on the number of TRX on a bts to be a sane or insane limit.
2010-04-10 00:01:03 +02:00
Holger Hans Peter Freyther
c50b836540 [paging] Move code to use LOGP and print some more information 2010-04-10 00:00:51 +02:00
Holger Hans Peter Freyther
754e801826 [paging] Simplify the last request and treat llist as a queue
The current code was overly complex. It tried to iterate over
the list in a round robin and we had to keep track of the last
element, see if we remove that one, check if the list becomes
empty... This can all replaced by treating the double linked
list as a queue. We take the item at the front, do something
on it and then and then put it back to the list at the end.
2010-04-10 00:00:15 +02:00
Holger Hans Peter Freyther
19722d4411 paging: Avoid integer underflow on ipaccess
On the nanoBTS we do not receive any load indication for the
paging channel and we just decrement our available slots and
the unsigned int wraps to the maximum value. Together with a
not yet understood bug this makes us go amock.

For the nanoBTS and even the Siemens BS11 resetting the load
to 20 after two seconds should be just fine. For the nanoBTS
we would need to reset the 20 a lot more earlier but we need
to take a look at how often we run low.
2010-04-09 23:59:52 +02:00
Holger Hans Peter Freyther
5615b982c2 [mgcp] Improve the endpoint display on the vty..
Make sure one understands the two values for number of
incoming packets..
2010-04-09 23:53:08 +02:00
Holger Hans Peter Freyther
aff596b8e1 [mgcp] Print the IP addr of the BTS we have detected. 2010-04-09 23:53:00 +02:00
Holger Hans Peter Freyther
07d838a3bf [paging] Do not use request after it was was destroyed..
Increment the counter before we call the remove request
which is freeing the request...
2010-04-08 17:10:37 +02:00
Holger Hans Peter Freyther
d4e7888ae3 [paging] Increase the time used to send paging messages to the BTS
Send a Paging Request to the BTS every two seconds. This way it is
unlikely that a phone will try to respond to two paging requests as
it is currently happening.
2010-04-07 23:14:36 +02:00
Holger Hans Peter Freyther
6c8c0ddbe2 [ipa] When including MGCP our messages might be bigger than 300 byte
The length field of the IPA header allows to have 16bit numbers
and I just ran into the 300 byte limit with MGCP messages. Make it
three times the size and see how long this is going to be enough.
2010-04-07 23:10:38 +02:00
Holger Hans Peter Freyther
19bab73d79 [rsl] Speculative crash fix in the RSL rcv message
The theory is that the BTS is almost dead and sends out
a incomplete message and we crash with that. I have not
been able to completely verify that.
2010-04-07 23:09:21 +02:00
Holger Hans Peter Freyther
c19a65baae Merge branch 'master' into on-waves/mgcp 2010-04-07 23:03:27 +02:00
Holger Hans Peter Freyther
1ea8dbec90 [mgcp] Fix navigation in the vty hierachy (make exit work)
Make exit from the MGCP node work properly.
2010-04-07 23:01:08 +02:00
Holger Hans Peter Freyther
500ff97c21 Fix compiler warning about void return in non void method. 2010-04-07 23:00:23 +02:00
Holger Hans Peter Freyther
441273766a [mgcp] Add the logging commands for the MGCP command. 2010-04-07 22:55:17 +02:00
Holger Hans Peter Freyther
014136da47 Merge branch 'on-waves/sccp' 2010-04-07 22:54:12 +02:00
Holger Hans Peter Freyther
91b5a31a2c Merge branch 'on-waves/mgcp' 2010-04-07 22:54:07 +02:00
Holger Hans Peter Freyther
575b89585f [mgcp] Print the errno/strerror when we can not receive from our socket 2010-04-07 22:52:40 +02:00
Holger Hans Peter Freyther
408cc4ace9 [mgcp] Add an option to allow using reallocing an endpoint
For some mode of operation it can be acceptable to reallocate
an already allocated endpoint. This can be the case when we
only deal with one call agent that is keeping track of the
endpoint but slightly confused.
2010-04-07 22:52:25 +02:00
Holger Hans Peter Freyther
b4b135efbf [mgcp] Count incoming RTP packets from the BTS and remote 2010-04-07 22:51:59 +02:00
Holger Hans Peter Freyther
54fa799129 vty: Fix the byteorder... of the bound_ip
We are storing the bound_ip in host byteorder but when
using ntohl we need to convert it back to to network
byte order.
2010-04-07 22:51:37 +02:00
Holger Hans Peter Freyther
b4c7b274a1 [mgcp] Reset the the address when freeing the endp as well 2010-04-06 12:13:19 +02:00
Holger Hans Peter Freyther
7279d24232 [mgcp] Do not patch RTP payload when type is set to -1.
For the nat we might or might not want to patch it, do not
patch if we have no valid rtp payload type.
2010-04-06 12:12:52 +02:00
Holger Hans Peter Freyther
ef8253c495 [mgcp] Use a different port to more easily differentiate 2010-04-05 22:04:23 +02:00
Holger Hans Peter Freyther
6c0729fe70 [mgcp] Print the BTS IP addr of the endpoint. 2010-04-05 22:04:15 +02:00
Holger Hans Peter Freyther
e125d40f66 [mgcp] Start to look into the MGCP messages and extract the CI
we will need the call identifier for the MDCX and DLCX message
for now we were just assuming it would increment, use som python
to extract the CI from a possible response, also switch back to
a blocking read to test the BSC nat.
2010-04-05 22:04:07 +02:00
Holger Hans Peter Freyther
58df0ea9a0 [mgcp] Fix the transaction id of the AUEP request 2010-04-05 22:03:41 +02:00
Holger Hans Peter Freyther
8b120f0ef9 [mgcp] Look at the bts addr set at the endpoint
This will allow to discover the ports of a bts when we only know
the addr and have multiple bts's to handle.
2010-04-05 22:03:04 +02:00
Holger Hans Peter Freyther
f2f1591ce7 [mgcp] Export header parsing via mgcp internal
This will be used by the NAT code to implement custom protocol
handling on top of that.
2010-04-05 22:02:54 +02:00
Holger Hans Peter Freyther
f36a11a35d [mgcp] Do not operate on the ->data pointer, use ->l2h instead
This would have been broken once we attempt to parse encapsulated
MGCP messages.
2010-04-05 22:02:47 +02:00
Holger Hans Peter Freyther
c77efdf057 [mgcp] Degrade verbosity to debug 2010-04-05 22:02:38 +02:00
Holger Hans Peter Freyther
b79994c952 [mgcp] Add a new config option to set the call agent ip addr
In the case of the nat we only want to communicate with one
upstream call agent and this can now be configured.
2010-04-05 22:02:29 +02:00
Holger Hans Peter Freyther
616d222518 [mgcp] Add a helper function to convert from GSM0808 ts/mux to MGCP endpoint
Move the conversion of GSM0808 timeslot and multiplex from
the bssap.c into the mgcp.h so it can be reused by multiple
users. The weird math comes from the mapping of the MSC...
2010-04-05 22:02:16 +02:00
Holger Hans Peter Freyther
64e4e77558 [mgcp] Handle the RSIP with resetting all endpoints
We could change that the message came from a special ip
address/port to secure this service in general but we don't
do that right now.
2010-04-05 22:01:52 +02:00
Holger Hans Peter Freyther
9bdcc9ca75 [mgcp] Add some parsing for RSIP messages coming in
This will just call a callback and leave all the handling
to the application.
2010-04-05 22:01:44 +02:00
Holger Hans Peter Freyther
e7d2ae69c9 [mgcp] Remove unused method from the mgcp
This was removed when sending the RSIP was
removed from the code.
2010-04-05 22:01:36 +02:00
Holger Hans Peter Freyther
52a66aa27e [mgcp] Switch from DEBUG to LOGP in the mgcp_main.c 2010-04-05 22:01:28 +02:00
Holger Hans Peter Freyther
13d67b7ea3 [mgcp] Remove the sending of RSIP
This message is ignored by the call agent and we were
sending this on the first request which we maybe should
not ignore...
2010-04-05 22:01:20 +02:00
Holger Hans Peter Freyther
b71517f07e [sccp] Add a force_free method for connections
E.g. when the underlying connection transport medium is gone
one needs to force to close SCCP connections, add this helper.

It will remove the connection from the list of connections and
it will free the data.
2010-04-05 22:00:24 +02:00
Holger Hans Peter Freyther
95e4d34f06 [mgcp] The networking code needs a source addrs..
Make the source address mandantory and complain about
complain when it is missing. The address is mandantory
as it needs to be put into the MGCP messages...
2010-03-30 15:35:57 +02:00
Holger Hans Peter Freyther
f5b6aa60ce [mgcp] Move mgcp init into the main method... 2010-03-30 15:35:48 +02:00
Holger Hans Peter Freyther
c38b5884ff [mgcp] Fix format string usage 2010-03-30 15:35:39 +02:00
Holger Hans Peter Freyther
4079105a6c Merge remote branch 'origin/master' into on-waves/mgcp 2010-03-30 15:35:26 +02:00
Holger Hans Peter Freyther
774f0723bf [mgcp] Do not print potentially many messages... 2010-03-01 18:53:05 +01:00
Holger Hans Peter Freyther
88c6eeaa7d [mgcp] Set the right variable back to NULL 2010-03-01 18:52:04 +01:00
44 changed files with 1183 additions and 306 deletions

View File

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

View File

@@ -72,6 +72,8 @@ int rsl_release_request(struct gsm_lchan *lchan, u_int8_t link_id, u_int8_t rele
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
/* to be provided by external code */
int abis_rsl_sendmsg(struct msgb *msg);
int rsl_deact_sacch(struct gsm_lchan *lchan);

View File

@@ -93,6 +93,10 @@ struct bsc_connection {
/* 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;
};
@@ -110,8 +114,10 @@ struct sccp_connections {
struct sccp_source_reference real_ref;
struct sccp_source_reference patched_ref;
struct sccp_source_reference remote_ref;
int has_remote_ref;
/* GSM audio handling. That is 32 * multiplex + ts */
int crcx;
int msc_timeslot;
int bsc_timeslot;
};
@@ -146,6 +152,8 @@ struct bsc_config {
char *imsi_deny;
regex_t imsi_deny_re;
int forbid_paging;
/* backpointer */
struct bsc_nat *nat;
@@ -160,8 +168,6 @@ struct bsc_endpoint {
char *transaction_id;
/* the bsc we are talking to */
struct bsc_connection *bsc;
/* pending delete */
int pending_delete;
};
/**
@@ -228,6 +234,7 @@ 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 *);
/**
* parse the given message into the above structure
@@ -248,17 +255,17 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
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_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 u_int8_t *data, unsigned int length);
int bsc_mgcp_assign(struct sccp_connections *, struct msgb *msg);
void bsc_mgcp_clear(struct sccp_connections *);
void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int);
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_init(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);

View File

@@ -66,6 +66,8 @@ struct e1inp_ts {
struct {
/* list of all signalling links on this TS */
struct llist_head sign_links;
/* delay for the queue */
int delay;
/* timer when to dequeue next frame */
struct timer_list tx_timer;
} sign;
@@ -93,6 +95,7 @@ struct e1inp_driver {
struct llist_head list;
const char *name;
int (*want_write)(struct e1inp_ts *ts);
int default_delay;
};
struct e1inp_line {

View File

@@ -73,17 +73,18 @@ enum gsm_paging_event {
GSM_PAGING_OOM,
};
enum bts_gprs_mode {
BTS_GPRS_NONE = 0,
BTS_GPRS_GPRS = 1,
BTS_GPRS_EGPRS = 2,
};
struct msgb;
typedef int gsm_cbfn(unsigned int hooknum,
unsigned int event,
struct msgb *msg,
void *data, void *param);
/* communications link with a BTS */
struct gsm_bts_link {
struct gsm_bts *bts;
};
struct sccp_connection;
/* Real authentication information containing Ki */
@@ -126,6 +127,7 @@ struct bss_sccp_connection_data {
struct timer_list T10;
/* for SCCP ... */
struct timer_list sccp_cc_timeout;
struct timer_list sccp_it;
/* audio handling */
@@ -399,6 +401,10 @@ struct gsm_bts_paging_state {
struct gsm_bts *bts;
struct timer_list work_timer;
struct timer_list credit_timer;
/* free chans needed */
int free_chans_need;
/* load */
u_int16_t available_slots;
@@ -503,7 +509,7 @@ struct gsm_bts {
/* Not entirely sure how ip.access specific this is */
struct {
int enabled;
enum bts_gprs_mode mode;
struct {
struct gsm_nm_state nm_state;
u_int16_t nsei;
@@ -515,6 +521,10 @@ struct gsm_bts {
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;
@@ -759,6 +769,9 @@ 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);
/* A parsed GPRS routing area */

View File

@@ -73,5 +73,6 @@ struct mgcp_msg_ptr {
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);
#endif

View File

@@ -71,6 +71,7 @@ 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 */
@@ -79,6 +80,16 @@ 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 */

View File

@@ -411,4 +411,10 @@ struct sccp_data_it {
u_int8_t credit;
} __attribute__((packed));
struct sccp_proto_err {
u_int8_t type;
struct sccp_source_reference destination_local_reference;
u_int8_t error_cause;
};
#endif

View File

@@ -28,7 +28,7 @@
/* 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);
struct buffer *buffer_new(void *ctx, size_t);
/* Free all data in the buffer. */
void buffer_reset(struct buffer *);

View File

@@ -822,15 +822,56 @@ static int ipacc_sw_activate(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i
return abis_nm_sendmsg(bts, msg);
}
static int abis_nm_parse_sw_descr(const u_int8_t *sw_descr, int sw_descr_len)
{
static const struct tlv_definition sw_descr_def = {
.def = {
[NM_ATT_FILE_ID] = { TLV_TYPE_TL16V, },
[NM_ATT_FILE_VERSION] = { TLV_TYPE_TL16V, },
},
};
u_int8_t tag;
u_int16_t tag_len;
const u_int8_t *val;
int ofs = 0, len;
/* Classic TLV parsing doesn't work well with SW_DESCR because of it's
* nested nature and the fact you have to assume it contains only two sub
* tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
if (sw_descr[0] != NM_ATT_SW_DESCR) {
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
return -1;
}
ofs += 1;
len = tlv_parse_one(&tag, &tag_len, &val,
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
if (len < 0 || (tag != NM_ATT_FILE_ID)) {
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
return -2;
}
ofs += len;
len = tlv_parse_one(&tag, &tag_len, &val,
&sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
DEBUGP(DNM, "FILE_VERSION attribute identifier not found!\n");
return -3;
}
ofs += len;
return ofs;
}
static int abis_nm_rx_sw_act_req(struct msgb *mb)
{
struct abis_om_hdr *oh = msgb_l2(mb);
struct abis_om_fom_hdr *foh = msgb_l3(mb);
struct tlv_parsed tp;
const u_int8_t *sw_config;
int sw_config_len;
int file_id_len;
int ret;
int ret, sw_config_len, sw_descr_len;
debugp_foh(foh);
@@ -854,20 +895,16 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
DEBUGP(DNM, "Found SW config: %s\n", hexdump(sw_config, sw_config_len));
}
if (sw_config[0] != NM_ATT_SW_DESCR)
DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
if (sw_config[1] != NM_ATT_FILE_ID)
DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
file_id_len = sw_config[2] * 256 + sw_config[3];
/* Use the first SW_DESCR present in SW config */
sw_descr_len = abis_nm_parse_sw_descr(sw_config, sw_config_len);
if (sw_descr_len < 0)
return -EINVAL;
/* Assumes first SW file in list is the one to be activated */
/* sw_config + 4 to skip over 2 attribute ID bytes and 16-bit length field */
return ipacc_sw_activate(mb->trx->bts, foh->obj_class,
foh->obj_inst.bts_nr,
foh->obj_inst.trx_nr,
foh->obj_inst.ts_nr,
sw_config + 4,
file_id_len);
sw_config, sw_descr_len);
}
/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */

View File

@@ -1240,6 +1240,10 @@ static int rsl_rx_ccch_load(struct msgb *msg)
switch (rslh->data[0]) {
case RSL_IE_PAGING_LOAD:
pg_buf_space = rslh->data[1] << 8 | rslh->data[2];
if (is_ipaccess_bts(msg->trx->bts) && pg_buf_space == 0xffff) {
/* paging load below configured threshold, use 50 as default */
pg_buf_space = 50;
}
paging_update_buffer_space(msg->trx->bts, pg_buf_space);
break;
case RSL_IE_RACH_LOAD:

View File

@@ -378,11 +378,11 @@ static unsigned char nanobts_attr_cell[] = {
4, /* N3103 */
8, /* N3105 */
15, /* RLC CV countdown */
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00,
NM_ATT_IPACC_CODING_SCHEMES, 0, 2, 0x0f, 0x00, /* CS1..CS4 */
NM_ATT_IPACC_RLC_CFG_2, 0, 5,
0x00, 250,
0x00, 250,
2, /* MCS2 */
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 */
@@ -418,16 +418,15 @@ 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 == 2 &&
if ((new_state->operational == NM_OPSTATE_ENABLED &&
new_state->availability == NM_AVSTATE_OK) ||
(new_state->operational == 1 &&
(new_state->operational == NM_OPSTATE_DISABLED &&
new_state->availability == NM_AVSTATE_OFF_LINE))
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,9 +440,8 @@ 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 == 1 &&
if (new_state->operational == NM_OPSTATE_DISABLED &&
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);
@@ -457,16 +455,16 @@ 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 == 1 &&
if (new_state->operational == NM_OPSTATE_DISABLED &&
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.enabled)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == 5) {
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));
@@ -478,9 +476,9 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
break;
case NM_OC_GPRS_CELL:
bts = container_of(obj, struct gsm_bts, gprs.cell);
if (!bts->gprs.enabled)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
if (new_state->availability == 5) {
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));
@@ -493,7 +491,7 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
case NM_OC_GPRS_NSVC:
nsvc = obj;
bts = nsvc->bts;
if (!bts->gprs.enabled)
if (bts->gprs.mode == BTS_GPRS_NONE)
break;
/* We skip NSVC1 since we only use NSVC0 */
if (nsvc->id == 1)
@@ -801,7 +799,7 @@ static int set_system_infos(struct gsm_bts_trx *trx)
DEBUGP(DRR, "SI%2u: %s\n", i, hexdump(si_tmp, rc));
rsl_bcch_info(trx, i, si_tmp, sizeof(si_tmp));
}
if (bts->gprs.enabled) {
if (bts->gprs.mode != BTS_GPRS_NONE) {
i = 13;
rc = gsm_generate_si(si_tmp, trx->bts, RSL_SYSTEM_INFO_13);
if (rc < 0)
@@ -855,6 +853,22 @@ 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;
@@ -888,6 +902,11 @@ static void patch_nm_tables(struct gsm_bts *bts)
/* 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;
}
}
static void bootstrap_rsl(struct gsm_bts_trx *trx)

View File

@@ -60,13 +60,17 @@ static struct log_target *stderr_target;
struct gsm_network *bsc_gsmnet = 0;
static const char *config_file = "openbsc.cfg";
static char *msc_address = NULL;
static struct bsc_msc_connection *msc_con;
static struct in_addr local_addr;
static LLIST_HEAD(active_connections);
static struct write_queue mgcp_agent;
static const char *rf_ctl = NULL;
extern int ipacc_rtp_direct;
/* msc handling */
static struct bsc_msc_connection *msc_con;
static struct timer_list msc_ping_timeout;
static struct timer_list msc_pong_timeout;
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);
@@ -95,6 +99,7 @@ struct bss_sccp_connection_data *bss_sccp_create_data()
void bss_sccp_free_data(struct bss_sccp_connection_data *data)
{
bsc_del_timer(&data->T10);
bsc_del_timer(&data->sccp_cc_timeout);
bsc_del_timer(&data->sccp_it);
if (data->sccp)
bsc_free_queued(data->sccp);
@@ -112,6 +117,41 @@ static void sccp_it_fired(void *_data)
bsc_schedule_timer(&data->sccp_it, SCCP_IT_TIMER, 0);
}
static void bss_force_close(struct bss_sccp_connection_data *bss)
{
if (bss->lchan) {
bss->lchan->msc_data = NULL;
put_subscr_con(&bss->lchan->conn, 0);
bss->lchan = NULL;
}
if (bss->secondary_lchan) {
bss->secondary_lchan->msc_data = NULL;
put_subscr_con(&bss->secondary_lchan->conn, 0);
bss->secondary_lchan = NULL;
}
/* force the close by poking stuff */
if (bss->sccp) {
sccp_connection_force_free(bss->sccp);
bss->sccp = NULL;
}
bss_sccp_free_data(bss);
}
/* check if this connection was ever confirmed and then recycle */
static void sccp_check_cc(void *_data)
{
struct bss_sccp_connection_data *data = _data;
if (data->sccp->connection_state >= SCCP_CONNECTION_STATE_ESTABLISHED)
return;
LOGP(DMSC, LOGL_ERROR, "The connection was never established\n");
bss_force_close(data);
}
/* GSM subscriber drop-ins */
extern struct llist_head *subscr_bsc_active_subscriber(void);
@@ -200,8 +240,12 @@ void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
LOGP(DMSC, LOGL_DEBUG, "Connection established: %p\n", conn);
/* start the inactivity test timer */
con_data = (struct bss_sccp_connection_data *) conn->data_ctx;
/* stop the CC timeout */
bsc_del_timer(&con_data->sccp_cc_timeout);
/* start the inactivity test timer */
con_data->sccp_it.cb = sccp_it_fired;
con_data->sccp_it.data = con_data;
bsc_schedule_timer(&con_data->sccp_it, SCCP_IT_TIMER, 0);
@@ -263,6 +307,11 @@ static int open_sccp_connection(struct msgb *layer3)
sccp_connection->data_ctx = con_data;
layer3->lchan->msc_data = con_data;
/* Make sure we open the connection */
con_data->sccp_cc_timeout.data = con_data;
con_data->sccp_cc_timeout.cb = sccp_check_cc;
bsc_schedule_timer(&con_data->sccp_cc_timeout, 10, 0);
/* FIXME: Use transaction for this */
use_subscr_con(&layer3->lchan->conn);
sccp_connection_connect(sccp_connection, &sccp_ssn_bssap, data);
@@ -372,7 +421,8 @@ static int handle_ass_compl(struct msgb *msg)
old_chan->msc_data = NULL;
/* give up the old channel to not do a SACCH deactivate */
subscr_put(old_chan->conn.subscr);
if (old_chan->conn.subscr)
subscr_put(old_chan->conn.subscr);
old_chan->conn.subscr = NULL;
put_subscr_con(&old_chan->conn, 1);
@@ -819,31 +869,54 @@ static void msc_connection_was_lost(struct bsc_msc_connection *msc)
LOGP(DMSC, LOGL_ERROR, "Lost MSC connection. Freing stuff.\n");
llist_for_each_entry_safe(bss, tmp, &active_connections, active_connections) {
if (bss->lchan) {
bss->lchan->msc_data = NULL;
put_subscr_con(&bss->lchan->conn, 0);
bss->lchan = NULL;
}
if (bss->secondary_lchan) {
bss->secondary_lchan->msc_data = NULL;
put_subscr_con(&bss->secondary_lchan->conn, 0);
bss->secondary_lchan = NULL;
}
/* force the close by poking stuff */
if (bss->sccp) {
sccp_connection_force_free(bss->sccp);
bss->sccp = NULL;
}
bss_sccp_free_data(bss);
bss_force_close(bss);
}
bsc_del_timer(&msc_ping_timeout);
bsc_del_timer(&msc_pong_timeout);
msc->is_authenticated = 0;
bsc_msc_schedule_connect(msc);
}
static void msc_pong_timeout_cb(void *data)
{
LOGP(DMSC, LOGL_ERROR, "MSC didn't answer PING. Closing connection.\n");
bsc_msc_lost(msc_con);
}
static void send_ping(void)
{
struct msgb *msg;
msg = msgb_alloc_headroom(4096, 128, "ping");
if (!msg) {
LOGP(DMSC, LOGL_ERROR, "Failed to create PING.\n");
return;
}
msg->l2h = msgb_put(msg, 1);
msg->l2h[0] = IPAC_MSGT_PING;
msc_queue_write(msg, IPAC_PROTO_IPACCESS);
}
static void msc_ping_timeout_cb(void *data)
{
send_ping();
/* send another ping in 20 seconds */
bsc_schedule_timer(&msc_ping_timeout, 20, 0);
/* also start a pong timer */
bsc_schedule_timer(&msc_pong_timeout, 5, 0);
}
static void msc_connection_connected(struct bsc_msc_connection *con)
{
msc_ping_timeout_cb(con);
}
/*
* callback with IP access data
*/
@@ -876,6 +949,8 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
initialize_if_needed();
else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
send_id_get_response(bfd->fd);
} else if (msg->l2h[0] == IPAC_MSGT_PONG) {
bsc_del_timer(&msc_pong_timeout);
}
} else if (hh->proto == IPAC_PROTO_SCCP) {
sccp_system_incoming(msg);
@@ -1104,7 +1179,11 @@ int main(int argc, char **argv)
exit(1);
}
msc_ping_timeout.cb = msc_ping_timeout_cb;
msc_pong_timeout.cb = msc_pong_timeout_cb;
msc_con->connection_loss = msc_connection_was_lost;
msc_con->connected = msc_connection_connected;
msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
msc_con->write_queue.write_cb = msc_sccp_do_write;
bsc_msc_connect(msc_con);

View File

@@ -40,6 +40,8 @@
#define BSSMAP_MSG_SIZE 512
#define BSSMAP_MSG_HEADROOM 128
#define LINK_ID_CB 0
static void bts_queue_send(struct msgb *msg, int link_id);
static void bssmap_free_secondary(struct bss_sccp_connection_data *data);
@@ -289,7 +291,8 @@ static void bssmap_free_secondary(struct bss_sccp_connection_data *data)
lchan->msc_data = NULL;
/* give up the new channel to not do a SACCH deactivate */
subscr_put(lchan->conn.subscr);
if (lchan->conn.subscr)
subscr_put(lchan->conn.subscr);
lchan->conn.subscr = NULL;
put_subscr_con(&lchan->conn, 1);
}
@@ -414,7 +417,8 @@ static int handle_new_assignment(struct msgb *msg, int full_rate, int chan_mode)
memcpy(&new_lchan->encr, &msg->lchan->encr, sizeof(new_lchan->encr));
new_lchan->ms_power = msg->lchan->ms_power;
new_lchan->bs_power = msg->lchan->bs_power;
new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr);
if (msg->lchan->conn.subscr)
new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr);
/* copy new data to it */
use_subscr_con(&new_lchan->conn);
@@ -1234,7 +1238,7 @@ static void bts_queue_send(struct msgb *msg, int link_id)
if (msg->lchan->sapis[link_id & 0x7] != LCHAN_SAPI_UNUSED) {
rsl_data_request(msg, link_id);
} else {
msg->smsh = (unsigned char*) link_id;
msg->cb[LINK_ID_CB] = link_id;
msgb_enqueue(&data->gsm_queue, msg);
++data->gsm_queue_size;
@@ -1250,7 +1254,7 @@ static void bts_queue_send(struct msgb *msg, int link_id)
LOGP(DMSC, LOGL_DEBUG, "Queueing GSM0408 message on %p. Queue size: %d\n",
data->sccp, data->gsm_queue_size + 1);
msg->smsh = (unsigned char*) link_id;
msg->cb[LINK_ID_CB] = link_id;
msgb_enqueue(&data->gsm_queue, msg);
++data->gsm_queue_size;
}
@@ -1276,7 +1280,7 @@ void bts_send_queued(struct bss_sccp_connection_data *data)
while (!llist_empty(&data->gsm_queue)) {
/* this is not allowed to fail */
msg = msgb_dequeue(&data->gsm_queue);
rsl_data_request(msg, (int) msg->smsh);
rsl_data_request(msg, msg->cb[LINK_ID_CB]);
}
data->gsm_queue_size = 0;
@@ -1298,7 +1302,7 @@ void bts_unblock_queue(struct bss_sccp_connection_data *data)
/* now queue them again to send RSL establish and such */
while (!llist_empty(&head)) {
msg = msgb_dequeue(&head);
bts_queue_send(msg, (int) msg->smsh);
bts_queue_send(msg, msg->cb[LINK_ID_CB]);
}
}

View File

@@ -389,6 +389,7 @@ static void _lchan_handle_release(struct gsm_lchan *lchan)
lchan->conn.use_count);
rsl_release_request(lchan, 0, lchan->release_reason);
rsl_lchan_set_state(lchan, LCHAN_S_REL_REQ);
}
/* called from abis rsl */

View File

@@ -303,6 +303,10 @@ int e1inp_ts_config(struct e1inp_ts *ts, struct e1inp_line *line,
switch (type) {
case E1INP_TS_TYPE_SIGN:
if (line->driver)
ts->sign.delay = line->driver->default_delay;
else
ts->sign.delay = 100000;
INIT_LLIST_HEAD(&ts->sign.sign_links);
break;
case E1INP_TS_TYPE_TRAU:

View File

@@ -675,7 +675,7 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
GSM411_RP_CAUSE_INV_MAND_INF);
return -EIO;
}
msg->smsh = tpdu;
msg->l4h = tpdu;
DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));

View File

@@ -257,7 +257,6 @@ int gsm0480_send_ussd_response(const struct msgb *in_msg, const char *response_t
if (((strlen(response_text) * 7) % 8) != 0)
response_len += 1;
msg->bts_link = in_msg->bts_link;
msg->lchan = in_msg->lchan;
/* First put the payload text into the message */
@@ -304,7 +303,6 @@ int gsm0480_send_ussd_reject(const struct msgb *in_msg,
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
msg->bts_link = in_msg->bts_link;
msg->lchan = in_msg->lchan;
/* First insert the problem code */

View File

@@ -222,6 +222,10 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
}
bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
bts->paging.free_chans_need = -1;
bts->rach_b_thresh = -1;
bts->rach_ldavg_slots = -1;
llist_add_tail(&bts->list, &net->bts_list);
return bts;
@@ -512,6 +516,23 @@ const char *rrlp_mode_name(enum rrlp_mode mode)
return get_value_string(rrlp_mode_names, mode);
}
static const struct value_string bts_gprs_mode_names[] = {
{ BTS_GPRS_NONE, "none" },
{ BTS_GPRS_GPRS, "gprs" },
{ BTS_GPRS_EGPRS, "egprs" },
{ 0, NULL }
};
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg)
{
return get_string_value(bts_gprs_mode_names, arg);
}
const char *bts_gprs_mode_name(enum bts_gprs_mode mode)
{
return get_value_string(bts_gprs_mode_names, mode);
}
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
{
struct gsm_meas_rep *meas_rep;

View File

@@ -230,7 +230,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
/* update lchan pointer of transaction */
trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn);
ho->old_lchan->state = LCHAN_S_INACTIVE;
rsl_lchan_set_state(ho->old_lchan, LCHAN_S_INACTIVE);
/* do something to re-route the actual speech frames ! */

View File

@@ -265,6 +265,7 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
trx->rsl_link = e1inp_sign_link_create(e1i_ts,
E1INP_SIGN_RSL, trx,
trx->rsl_tei, 0);
trx->rsl_link->ts->sign.delay = 10;
/* get rid of our old temporary bfd */
memcpy(newbfd, bfd, sizeof(*newbfd));
@@ -572,7 +573,7 @@ static int handle_ts1_write(struct bsc_fd *bfd)
e1i_ts->sign.tx_timer.data = e1i_ts;
/* Reducing this might break the nanoBTS 900 init. */
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 100000);
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
return ret;
}
@@ -606,6 +607,7 @@ static int ipaccess_fd_cb(struct bsc_fd *bfd, unsigned int what)
struct e1inp_driver ipaccess_driver = {
.name = "ip.access",
.want_write = ts_want_write,
.default_delay = 100000,
};
/* callback of the OML listening filedescriptor */

View File

@@ -235,7 +235,7 @@ static int handle_ts1_write(struct bsc_fd *bfd)
/* set tx delay timer for next event */
e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
e1i_ts->sign.tx_timer.data = e1i_ts;
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, 50000);
bsc_schedule_timer(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
return ret;
}
@@ -375,6 +375,7 @@ static int activate_bchan(struct e1inp_line *line, int ts, int act)
struct e1inp_driver misdn_driver = {
.name = "mISDNuser",
.want_write = ts_want_write,
.default_delay = 50000,
};
static int mi_e1_setup(struct e1inp_line *line, int release_l2)

View File

@@ -59,6 +59,7 @@ static int sw_load_state = 0;
static int oml_state = 0;
static int dump_files = 0;
static char *firmware_analysis = NULL;
static int trx_nr = 0;
struct sw_load {
u_int8_t file_id[255];
@@ -316,7 +317,8 @@ static void bootstrap_om(struct gsm_bts *bts)
memcpy(buf+3, unit_id, len);
buf[3+len] = 0;
printf("setting Unit ID to '%s'\n", unit_id);
abis_nm_ipaccess_set_nvattr(bts->c0, buf, 3+len+1);
abis_nm_ipaccess_set_nvattr(gsm_bts_trx_by_nr(bts, trx_nr),
buf, 3+len+1);
}
if (prim_oml_ip) {
struct in_addr ia;
@@ -354,7 +356,8 @@ static void bootstrap_om(struct gsm_bts *bts)
*cur++ = nv_mask >> 8;
printf("setting NV Flags/Mask to 0x%04x/0x%04x\n",
nv_flags, nv_mask);
abis_nm_ipaccess_set_nvattr(bts->c0, buf, 3+len);
abis_nm_ipaccess_set_nvattr(gsm_bts_trx_by_nr(bts, trx_nr),
buf, 3+len);
}
if (restart && !prim_oml_ip && !software) {
@@ -605,6 +608,7 @@ static void print_help(void)
printf(" -d --software firmware\n");
printf(" -f --firmware firmware Provide firmware information\n");
printf(" -w --write-firmware. This will dump the firmware parts to the filesystem. Use with -f.\n");
printf(" -t --trx NR. The TRX to use for the Unit ID and NVRAM attributes.\n");
}
int main(int argc, char **argv)
@@ -639,9 +643,11 @@ int main(int argc, char **argv)
{ "software", 1, 0, 'd' },
{ "firmware", 1, 0, 'f' },
{ "write-firmware", 0, 0, 'w' },
{ "trx", 1, 0, 't' },
{ 0, 0, 0, 0 },
};
c = getopt_long(argc, argv, "u:o:rn:l:hs:d:f:w", long_options,
c = getopt_long(argc, argv, "u:o:rn:l:hs:d:f:wt:", long_options,
&option_index);
if (c == -1)
@@ -683,6 +689,9 @@ int main(int argc, char **argv)
case 'w':
dump_files = 1;
break;
case 't':
trx_nr = atoi(optarg);
break;
case 'h':
print_usage();
print_help();
@@ -724,6 +733,8 @@ int main(int argc, char **argv)
exit(1);
}
bts->oml_link->ts->sign.delay = 10;
bts->c0->rsl_link->ts->sign.delay = 10;
while (1) {
rc = bsc_select_main(0);
if (rc < 0)

View File

@@ -128,6 +128,15 @@ static int mgcp_rsip_cb(struct mgcp_config *cfg)
return 0;
}
static int mgcp_change_cb(struct mgcp_config *cfg, int endpoint, int state, int local_rtp)
{
if (state != MGCP_ENDP_MDCX)
return 0;
mgcp_send_dummy(&cfg->endpoints[endpoint]);
return 0;
}
static int read_call_agent(struct bsc_fd *fd, unsigned int what)
{
struct sockaddr_in addr;
@@ -200,6 +209,7 @@ int main(int argc, char** argv)
/* set some callbacks */
cfg->reset_cb = mgcp_rsip_cb;
cfg->change_cb = mgcp_change_cb;
/* we need to bind a socket */
if (rc == 0) {

View File

@@ -31,7 +31,6 @@
#include <arpa/inet.h>
#include <osmocore/msgb.h>
#include <osmocore/talloc.h>
#include <osmocore/select.h>
#include <openbsc/debug.h>
@@ -73,6 +72,8 @@ enum {
PROTO_RTCP,
};
#define DUMMY_LOAD 0x23
static int udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
{
@@ -84,6 +85,14 @@ static int udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
}
int mgcp_send_dummy(struct mgcp_endpoint *endp)
{
static char buf[] = { DUMMY_LOAD };
return udp_send(endp->local_rtp.fd, &endp->remote,
endp->net_rtp, buf, 1);
}
static void patch_payload(int payload, char *data, int len)
{
struct rtp_hdr *rtp_hdr;
@@ -163,9 +172,17 @@ static int rtp_data_cb(struct bsc_fd *fd, unsigned int what)
LOGP(DMGCP, LOGL_NOTICE, "Found BTS for endpoint: 0x%x on port: %d/%d of %s\n",
ENDPOINT_NUMBER(endp), ntohs(endp->bts_rtp), ntohs(endp->bts_rtcp),
inet_ntoa(addr.sin_addr));
}
}
/* throw away dummy message */
if (rc == 1 && buf[0] == DUMMY_LOAD) {
LOGP(DMGCP, LOGL_NOTICE, "Filtered dummy on 0x%x\n",
ENDPOINT_NUMBER(endp));
return 0;
}
/* do this before the loop handling */
if (dest == DEST_NETWORK)
++endp->in_bts;

View File

@@ -389,6 +389,7 @@ static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
if (cfg->force_realloc) {
LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
ENDPOINT_NUMBER(endp));
mgcp_free_endp(endp);
} else {
LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
ENDPOINT_NUMBER(endp));
@@ -485,6 +486,7 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
const char *trans_id;
struct mgcp_endpoint *endp;
int error_code = 500;
int silent = 0;
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
if (found != 0)
@@ -517,6 +519,9 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
goto error3;
}
break;
case 'Z':
silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0;
break;
case '\0':
/* SDP file begins */
break;
@@ -562,6 +567,8 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
case MGCP_POLICY_REJECT:
LOGP(DMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n",
ENDPOINT_NUMBER(endp));
if (silent)
goto out_silent;
return create_response(500, "MDCX", trans_id);
break;
case MGCP_POLICY_DEFER:
@@ -579,6 +586,9 @@ static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
ENDPOINT_NUMBER(endp), inet_ntoa(endp->remote), ntohs(endp->net_rtp));
if (cfg->change_cb)
cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX, endp->rtp_port);
if (silent)
goto out_silent;
return create_response_with_sdp(endp, "MDCX", trans_id);
error:
@@ -589,6 +599,10 @@ error:
error3:
return create_response(error_code, "MDCX", trans_id);
out_silent:
return NULL;
}
static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
@@ -598,6 +612,7 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
const char *trans_id;
struct mgcp_endpoint *endp;
int error_code = 500;
int silent = 0;
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
if (found != 0)
@@ -619,6 +634,9 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
if (verify_ci(endp, (const char *)&msg->l3h[line_start + 3]) != 0)
goto error3;
break;
case 'Z':
silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0;
break;
}
default:
LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
@@ -634,6 +652,8 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
case MGCP_POLICY_REJECT:
LOGP(DMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n",
ENDPOINT_NUMBER(endp));
if (silent)
goto out_silent;
return create_response(500, "DLCX", trans_id);
break;
case MGCP_POLICY_DEFER:
@@ -647,10 +667,14 @@ static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
}
/* free the connection */
LOGP(DMGCP, LOGL_NOTICE, "Deleted endpoint on: 0x%x Server: %s:%u\n",
ENDPOINT_NUMBER(endp), inet_ntoa(endp->remote), ntohs(endp->net_rtp));
mgcp_free_endp(endp);
if (cfg->change_cb)
cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX, endp->rtp_port);
if (silent)
goto out_silent;
return create_response(250, "DLCX", trans_id);
error:
@@ -661,6 +685,9 @@ error:
error3:
return create_response(error_code, "DLCX", trans_id);
out_silent:
return NULL;
}
static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg)

View File

@@ -26,6 +26,8 @@
#include <openbsc/mgcp.h>
#include <openbsc/mgcp_internal.h>
#include <sccp/sccp.h>
#include <osmocore/talloc.h>
#include <osmocore/gsm0808.h>
@@ -37,10 +39,12 @@
int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
{
struct sccp_connections *mcon;
struct tlv_parsed tp;
u_int16_t cic;
u_int8_t timeslot;
u_int8_t multiplex;
int combined;
if (!msg->l3h) {
LOGP(DNAT, LOGL_ERROR, "Assignment message should have l3h pointer.\n");
@@ -62,18 +66,27 @@ int bsc_mgcp_assign(struct sccp_connections *con, struct msgb *msg)
timeslot = cic & 0x1f;
multiplex = (cic & ~0x1f) >> 5;
con->msc_timeslot = (32 * multiplex) + timeslot;
combined = (32 * multiplex) + timeslot;
/* find stale connections using that endpoint */
llist_for_each_entry(mcon, &con->bsc->nat->sccp_connections, list_entry) {
if (mcon->msc_timeslot == combined) {
LOGP(DNAT, LOGL_ERROR,
"Timeslot %d was assigned to 0x%x and now 0x%x\n",
combined,
sccp_src_ref_to_int(&mcon->patched_ref),
sccp_src_ref_to_int(&con->patched_ref));
bsc_mgcp_dlcx(mcon);
}
}
con->msc_timeslot = combined;
con->bsc_timeslot = con->msc_timeslot;
return 0;
}
void bsc_mgcp_clear(struct sccp_connections *con)
{
con->msc_timeslot = -1;
con->bsc_timeslot = -1;
}
void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
static void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
{
if (nat->bsc_endpoints[i].transaction_id) {
talloc_free(nat->bsc_endpoints[i].transaction_id);
@@ -81,17 +94,75 @@ void bsc_mgcp_free_endpoint(struct bsc_nat *nat, int i)
}
nat->bsc_endpoints[i].bsc = NULL;
mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
}
void bsc_mgcp_free_endpoints(struct bsc_nat *nat)
{
int i;
for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i)
for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i){
bsc_mgcp_free_endpoint(nat, i);
mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
}
}
/* send a MDCX where we do not want a response */
static void bsc_mgcp_send_mdcx(struct bsc_connection *bsc, struct mgcp_endpoint *endp)
{
char buf[2096];
int len;
len = snprintf(buf, sizeof(buf),
"MDCX 23 %x@mgw MGCP 1.0\r\n"
"Z: noanswer\r\n"
"\r\n"
"c=IN IP4 %s\r\n"
"m=audio %d RTP/AVP 255\r\n",
ENDPOINT_NUMBER(endp),
bsc->nat->mgcp_cfg->source_addr,
endp->rtp_port);
if (len < 0) {
LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
return;
}
}
static void bsc_mgcp_send_dlcx(struct bsc_connection *bsc, int endpoint)
{
char buf[2096];
int len;
len = snprintf(buf, sizeof(buf),
"DLCX 23 %x@mgw MGCP 1.0\r\n"
"Z: noanswer\r\n", endpoint);
if (len < 0) {
LOGP(DMGCP, LOGL_ERROR, "snprintf for DLCX failed.\n");
return;
}
bsc_write_mgcp(bsc, (u_int8_t *) buf, len);
}
void bsc_mgcp_init(struct sccp_connections *con)
{
con->msc_timeslot = -1;
con->bsc_timeslot = -1;
con->crcx = 0;
}
void bsc_mgcp_dlcx(struct sccp_connections *con)
{
/* send a DLCX down the stream */
if (con->bsc_timeslot != -1 && con->crcx) {
int endp = mgcp_timeslot_to_endpoint(0, con->msc_timeslot);
bsc_mgcp_send_dlcx(con->bsc, endp);
bsc_mgcp_free_endpoint(con->bsc->nat, endp);
}
bsc_mgcp_init(con);
}
struct sccp_connections *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint)
{
struct sccp_connections *con = NULL;
@@ -125,10 +196,18 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
bsc_endp = &nat->bsc_endpoints[endpoint];
mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
if (bsc_endp->transaction_id) {
LOGP(DMGCP, LOGL_ERROR, "Endpoint 0x%x had pending transaction: '%s'\n",
endpoint, bsc_endp->transaction_id);
talloc_free(bsc_endp->transaction_id);
bsc_endp->transaction_id = NULL;
}
bsc_endp->bsc = NULL;
sccp = bsc_mgcp_find_con(nat, endpoint);
if (!sccp) {
LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for a new connection on 0x%x for %d\n", endpoint, state);
LOGP(DMGCP, LOGL_ERROR, "Did not find BSC for change on endpoint: 0x%x state: %d\n", endpoint, state);
switch (state) {
case MGCP_ENDP_CRCX:
@@ -147,12 +226,6 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
}
}
if (bsc_endp->transaction_id) {
LOGP(DMGCP, LOGL_ERROR, "One transaction with id '%s' on 0x%x\n",
bsc_endp->transaction_id, endpoint);
talloc_free(bsc_endp->transaction_id);
}
/* we need to generate a new and patched message */
bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length,
nat->mgcp_cfg->source_addr, mgcp_endp->rtp_port);
@@ -164,7 +237,6 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
bsc_endp->transaction_id = talloc_strdup(nat, transaction_id);
bsc_endp->bsc = sccp->bsc;
bsc_endp->pending_delete = 0;
/* we need to update some bits */
if (state == MGCP_ENDP_CRCX) {
@@ -176,15 +248,21 @@ int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const c
} else {
mgcp_endp->bts = sock.sin_addr;
}
} else if (state == MGCP_ENDP_DLCX) {
/* we will free the endpoint now in case the BSS does not respond */
bsc_mgcp_clear(sccp);
bsc_endp->pending_delete = 1;
mgcp_free_endp(mgcp_endp);
}
bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
return MGCP_POLICY_DEFER;
/* send the message and a fake MDCX for force sending of a dummy packet */
sccp->crcx = 1;
bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
bsc_mgcp_send_mdcx(sccp->bsc, mgcp_endp);
return MGCP_POLICY_DEFER;
} else if (state == MGCP_ENDP_DLCX) {
/* we will free the endpoint now and send a DLCX to the BSC */
msgb_free(bsc_msg);
bsc_mgcp_dlcx(sccp);
return MGCP_POLICY_CONT;
} else {
bsc_write(sccp->bsc, bsc_msg, NAT_IPAC_PROTO_MGCP);
return MGCP_POLICY_DEFER;
}
}
/*
@@ -234,13 +312,7 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg)
return;
}
/* make it point to our endpoint if it was not deleted */
if (bsc_endp->pending_delete) {
bsc_endp->bsc = NULL;
bsc_endp->pending_delete = 0;
} else {
endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
}
endp->ci = bsc_mgcp_extract_ci((const char *) msg->l2h);
/* free some stuff */
talloc_free(bsc_endp->transaction_id);
@@ -401,7 +473,7 @@ static int mgcp_do_write(struct bsc_fd *bfd, struct msgb *msg)
return rc;
}
int bsc_mgcp_init(struct bsc_nat *nat)
int bsc_mgcp_nat_init(struct bsc_nat *nat)
{
int on;
struct sockaddr_in addr;
@@ -481,11 +553,7 @@ void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc)
if (bsc_endp->bsc != bsc)
continue;
bsc_endp->bsc = NULL;
bsc_endp->pending_delete = 0;
if (bsc_endp->transaction_id)
talloc_free(bsc_endp->transaction_id);
bsc_endp->transaction_id = NULL;
bsc_mgcp_free_endpoint(bsc->nat, i);
mgcp_free_endp(&bsc->nat->mgcp_cfg->endpoints[i]);
}
}

View File

@@ -59,7 +59,6 @@ static const char *msc_ip = NULL;
static struct bsc_nat *nat;
static void bsc_send_data(struct bsc_connection *bsc, const u_int8_t *data, unsigned int length, int);
static void remove_bsc_connection(struct bsc_connection *connection);
static void msc_send_reset(struct bsc_msc_connection *con);
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num)
@@ -90,6 +89,14 @@ int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
return -1;
}
static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg)
{
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
msgb_free(msg);
}
}
static void send_reset_ack(struct bsc_connection *bsc)
{
static const u_int8_t gsm_reset_ack[] = {
@@ -101,6 +108,55 @@ static void send_reset_ack(struct bsc_connection *bsc)
bsc_send_data(bsc, gsm_reset_ack, sizeof(gsm_reset_ack), IPAC_PROTO_SCCP);
}
static void send_ping(struct bsc_connection *bsc)
{
static const u_int8_t id_ping[] = {
IPAC_MSGT_PING,
};
bsc_send_data(bsc, id_ping, sizeof(id_ping), IPAC_PROTO_IPACCESS);
}
static void send_pong(struct bsc_connection *bsc)
{
static const u_int8_t id_pong[] = {
IPAC_MSGT_PONG,
};
bsc_send_data(bsc, id_pong, sizeof(id_pong), IPAC_PROTO_IPACCESS);
}
static void bsc_pong_timeout(void *_bsc)
{
struct bsc_connection *bsc = _bsc;
LOGP(DNAT, LOGL_ERROR, "BSC Nr: %d PONG timeout.\n", bsc->cfg->nr);
bsc_close_connection(bsc);
}
static void bsc_ping_timeout(void *_bsc)
{
struct bsc_connection *bsc = _bsc;
send_ping(bsc);
/* send another ping in 20 seconds */
bsc_schedule_timer(&bsc->ping_timeout, 20, 0);
/* also start a pong timer */
bsc_schedule_timer(&bsc->pong_timeout, 5, 0);
}
static void start_ping_pong(struct bsc_connection *bsc)
{
bsc->pong_timeout.data = bsc;
bsc->pong_timeout.cb = bsc_pong_timeout;
bsc->ping_timeout.data = bsc;
bsc->ping_timeout.cb = bsc_ping_timeout;
bsc_ping_timeout(bsc);
}
static void send_id_ack(struct bsc_connection *bsc)
{
static const u_int8_t id_ack[] = {
@@ -147,10 +203,7 @@ static void nat_send_rlsd(struct sccp_connections *conn)
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
msgb_free(msg);
}
queue_for_msc(msc_con, msg);
}
static void nat_send_rlc(struct sccp_source_reference *src,
@@ -173,10 +226,7 @@ static void nat_send_rlc(struct sccp_source_reference *src,
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
msgb_free(msg);
}
queue_for_msc(msc_con, msg);
}
static void send_mgcp_reset(struct bsc_connection *bsc)
@@ -311,7 +361,9 @@ send_to_all:
if (parsed->ipa_proto == IPAC_PROTO_SCCP && parsed->gsm_type == BSS_MAP_MSG_PAGING) {
int lac;
bsc = bsc_nat_find_bsc(nat, msg, &lac);
if (bsc)
if (bsc && bsc->cfg->forbid_paging)
LOGP(DNAT, LOGL_DEBUG, "Paging forbidden for BTS: %d\n", bsc->cfg->nr);
else if (bsc)
bsc_send_data(bsc, msg->l2h, msgb_l2len(msg), parsed->ipa_proto);
else
LOGP(DNAT, LOGL_ERROR, "Could not determine BSC for paging on lac: %d/0x%x\n",
@@ -340,7 +392,7 @@ static void msc_connection_was_lost(struct bsc_msc_connection *con)
LOGP(DMSC, LOGL_ERROR, "Closing all connections downstream.\n");
llist_for_each_entry_safe(bsc, tmp, &nat->bsc_connections, list_entry)
remove_bsc_connection(bsc);
bsc_close_connection(bsc);
nat->first_contact = 0;
bsc_mgcp_free_endpoints(nat);
@@ -367,10 +419,7 @@ static void msc_send_reset(struct bsc_msc_connection *msc_con)
msg->l2h = msgb_put(msg, sizeof(reset));
memcpy(msg->l2h, reset, msgb_l2len(msg));
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DMSC, LOGL_ERROR, "Failed to enqueue reset msg.\n");
msgb_free(msg);
}
queue_for_msc(msc_con, msg);
LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
}
@@ -382,13 +431,12 @@ static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
struct ipaccess_head *hh;
if (!msg) {
if (error == 0) {
if (error == 0)
LOGP(DNAT, LOGL_FATAL, "The connection the MSC was lost, exiting\n");
bsc_msc_lost(msc_con);
return -1;
}
else
LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
bsc_msc_lost(msc_con);
return -1;
}
@@ -432,29 +480,33 @@ static int ipaccess_msc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
* remove it from the patching of SCCP header lists
* as well. Maybe in the future even close connection..
*/
static void remove_bsc_connection(struct bsc_connection *connection)
void bsc_close_connection(struct bsc_connection *connection)
{
struct sccp_connections *sccp_patch, *tmp;
bsc_unregister_fd(&connection->write_queue.bfd);
close(connection->write_queue.bfd.fd);
write_queue_clear(&connection->write_queue);
llist_del(&connection->list_entry);
/* stop the timeout timer */
bsc_del_timer(&connection->id_timeout);
bsc_del_timer(&connection->ping_timeout);
bsc_del_timer(&connection->pong_timeout);
/* remove all SCCP connections */
llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) {
if (sccp_patch->bsc != connection)
continue;
nat_send_rlsd(sccp_patch);
if (sccp_patch->has_remote_ref)
nat_send_rlsd(sccp_patch);
sccp_connection_destroy(sccp_patch);
}
/* close endpoints allocated by this BSC */
bsc_mgcp_clear_endpoints_for(connection);
bsc_unregister_fd(&connection->write_queue.bfd);
close(connection->write_queue.bfd.fd);
write_queue_clear(&connection->write_queue);
llist_del(&connection->list_entry);
talloc_free(connection);
}
@@ -468,7 +520,7 @@ static void ipaccess_close_bsc(void *data)
getpeername(conn->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
LOGP(DNAT, LOGL_ERROR, "BSC on %s didn't respond to identity request. Closing.\n",
inet_ntoa(sock.sin_addr));
remove_bsc_connection(conn);
bsc_close_connection(conn);
}
static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
@@ -476,6 +528,12 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
struct bsc_config *conf;
const char* token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
if (bsc->cfg) {
LOGP(DNAT, LOGL_ERROR, "Reauth on fd %d bsc nr %d\n",
bsc->write_queue.bfd.fd, bsc->cfg->nr);
return;
}
llist_for_each_entry(conf, &bsc->nat->bsc_configs, entry) {
if (strcmp(conf->token, token) == 0) {
counter_inc(conf->stats.net.reconn);
@@ -483,6 +541,7 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
bsc->cfg = conf;
bsc_del_timer(&bsc->id_timeout);
LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d\n", conf->nr, conf->lac);
start_ping_pong(bsc);
return;
}
}
@@ -524,17 +583,17 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
case SCCP_MSG_TYPE_CR:
if (create_sccp_src_ref(bsc, msg, parsed) != 0)
goto exit2;
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
break;
case SCCP_MSG_TYPE_RLSD:
case SCCP_MSG_TYPE_CREF:
case SCCP_MSG_TYPE_DT1:
case SCCP_MSG_TYPE_CC:
case SCCP_MSG_TYPE_IT:
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
break;
case SCCP_MSG_TYPE_RLC:
con = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
remove_sccp_src_ref(bsc, msg, parsed);
break;
case SCCP_MSG_TYPE_UDT:
@@ -556,15 +615,13 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
}
if (con && con->bsc != bsc) {
LOGP(DNAT, LOGL_ERROR, "Found the wrong entry.\n");
LOGP(DNAT, LOGL_ERROR, "The connection belongs to a different BTS: input: %d con: %d\n",
bsc->cfg->nr, con->bsc->cfg->nr);
goto exit2;
}
/* send the non-filtered but maybe modified msg */
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
LOGP(DNAT, LOGL_ERROR, "Can not queue message for the MSC.\n");
msgb_free(msg);
}
queue_for_msc(msc_con, msg);
talloc_free(parsed);
return 0;
@@ -598,14 +655,19 @@ static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
int error;
struct bsc_connection *bsc = bfd->data;
struct msgb *msg = ipaccess_read_msg(bfd, &error);
struct ipaccess_head *hh;
if (!msg) {
if (error == 0) {
LOGP(DNAT, LOGL_ERROR, "The connection to the BSC was lost. Cleaning it\n");
remove_bsc_connection(bsc);
} else {
LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
}
if (error == 0)
LOGP(DNAT, LOGL_ERROR,
"The connection to the BSC Nr: %d was lost. Cleaning it\n",
bsc->cfg ? bsc->cfg->nr : -1);
else
LOGP(DNAT, LOGL_ERROR,
"Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n",
bsc->cfg ? bsc->cfg->nr : -1, error);
bsc_close_connection(bsc);
return -1;
}
@@ -613,6 +675,21 @@ static int ipaccess_bsc_read_cb(struct bsc_fd *bfd)
LOGP(DNAT, LOGL_DEBUG, "MSG from BSC: %s proto: %d\n", hexdump(msg->data, msg->len), msg->l2h[0]);
/* Handle messages from the BSC */
hh = (struct ipaccess_head *) msg->data;
/* stop the pong timeout */
if (hh->proto == IPAC_PROTO_IPACCESS) {
if (msg->l2h[0] == IPAC_MSGT_PONG) {
bsc_del_timer(&bsc->pong_timeout);
msgb_free(msg);
return 0;
} else if (msg->l2h[0] == IPAC_MSGT_PING) {
send_pong(bsc);
msgb_free(msg);
return 0;
}
}
/* FIXME: Currently no PONG is sent to the BSC */
/* FIXME: Currently no ID ACK is sent to the BSC */
forward_sccp_to_msc(bsc, msg);
@@ -672,7 +749,6 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
return -1;
}
write_queue_init(&bsc->write_queue, 100);
bsc->write_queue.bfd.data = bsc;
bsc->write_queue.bfd.fd = ret;
bsc->write_queue.read_cb = ipaccess_bsc_read_cb;
@@ -817,9 +893,20 @@ static void signal_handler(int signal)
}
}
extern void *tall_msgb_ctx;
extern void *tall_ctr_ctx;
static void talloc_init_ctx()
{
tall_bsc_ctx = talloc_named_const(NULL, 0, "nat");
tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
}
int main(int argc, char** argv)
{
talloc_init_ctx();
log_init(&log_info);
stderr_target = log_target_create_stderr();
log_add_target(stderr_target);
log_set_all_filter(stderr_target, 1);
@@ -858,7 +945,7 @@ int main(int argc, char** argv)
/*
* Setup the MGCP code..
*/
if (bsc_mgcp_init(nat) != 0)
if (bsc_mgcp_nat_init(nat) != 0)
return -4;
/* connect to the MSC */

View File

@@ -70,6 +70,7 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
return NULL;
con->nat = nat;
write_queue_init(&con->write_queue, 100);
return con;
}
@@ -99,7 +100,7 @@ void sccp_connection_destroy(struct sccp_connections *conn)
LOGP(DNAT, LOGL_DEBUG, "Destroy 0x%x <-> 0x%x mapping for con %p\n",
sccp_src_ref_to_int(&conn->real_ref),
sccp_src_ref_to_int(&conn->patched_ref), conn->bsc);
bsc_mgcp_clear(conn);
bsc_mgcp_dlcx(conn);
llist_del(&conn->list_entry);
talloc_free(conn);
}
@@ -127,7 +128,11 @@ struct bsc_connection *bsc_nat_find_bsc(struct bsc_nat *nat, struct msgb *msg, i
data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST);
if (data[0] != CELL_IDENT_LAC) {
/* No need to try a different BSS */
if (data[0] == CELL_IDENT_BSS) {
return NULL;
} else if (data[0] != CELL_IDENT_LAC) {
LOGP(DNAT, LOGL_ERROR, "Unhandled cell ident discrminator: %d\n", data[0]);
return NULL;
}

View File

@@ -69,6 +69,7 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
vty_out(vty, " imsi allow %s%s", bsc->imsi_allow, VTY_NEWLINE);
if (bsc->imsi_deny)
vty_out(vty, " imsi deny %s%s", bsc->imsi_deny, VTY_NEWLINE);
vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
}
static int config_write_bsc(struct vty *vty)
@@ -85,12 +86,16 @@ DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
SHOW_STR "Display information about current SCCP connections")
{
struct sccp_connections *con;
vty_out(vty, "Listing all opening SCCP connections%s", VTY_NEWLINE);
llist_for_each_entry(con, &_nat->sccp_connections, list_entry) {
vty_out(vty, "SCCP for BSC: Nr: %d lac: %d BSC ref: 0x%x Local ref: 0x%x MSC/BSC mux: 0x%x/0x%x%s",
vty_out(vty, "For BSC Nr: %d lac: %d; BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x%s",
con->bsc->cfg ? con->bsc->cfg->nr : -1,
con->bsc->cfg ? con->bsc->cfg->lac : -1,
sccp_src_ref_to_int(&con->real_ref),
sccp_src_ref_to_int(&con->patched_ref),
con->has_remote_ref,
sccp_src_ref_to_int(&con->remote_ref),
con->msc_timeslot, con->bsc_timeslot,
VTY_NEWLINE);
}
@@ -107,7 +112,7 @@ DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
vty_out(vty, "BSC lac: %d, %d auth: %d fd: %d peername: %s%s",
vty_out(vty, "BSC nr: %d lac: %d auth: %d fd: %d peername: %s%s",
con->cfg ? con->cfg->nr : -1,
con->cfg ? con->cfg->lac : -1,
con->authenticated, con->write_queue.bfd.fd,
@@ -117,8 +122,8 @@ DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
return CMD_SUCCESS;
}
DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "bsc config show",
"Display information about known BSC configs")
DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
SHOW_STR "Display information about known BSC configs")
{
struct bsc_config *conf;
llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
@@ -128,6 +133,8 @@ DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "bsc config show",
conf->imsi_allow ? conf->imsi_allow: "any",
conf->imsi_deny ? conf->imsi_deny : "none",
VTY_NEWLINE);
vty_out(vty, " paging forbidden: %d%s",
conf->forbid_paging, VTY_NEWLINE);
}
return CMD_SUCCESS;
@@ -135,11 +142,16 @@ DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "bsc config show",
DEFUN(show_stats,
show_stats_cmd,
"show statistics",
SHOW_STR "Display network statistics\n")
"show statistics [NR]",
SHOW_STR "Display network statistics")
{
struct bsc_config *conf;
int nr = -1;
if (argc == 1)
nr = atoi(argv[0]);
vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
counter_get(_nat->stats.sccp.conn),
@@ -151,6 +163,9 @@ DEFUN(show_stats,
counter_get(_nat->stats.bsc.auth_fail), VTY_NEWLINE);
llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
if (argc == 1 && nr != conf->nr)
continue;
vty_out(vty, " BSC lac: %d nr: %d%s",
conf->lac, conf->nr, VTY_NEWLINE);
vty_out(vty, " SCCP Connnections %lu total, %lu calls%s",
@@ -163,6 +178,24 @@ DEFUN(show_stats,
return CMD_SUCCESS;
}
DEFUN(close_bsc,
close_bsc_cmd,
"close bsc connection BSC_NR",
"Close the connection with the BSC identified by the config number.")
{
struct bsc_connection *bsc;
int bsc_nr = atoi(argv[0]);
llist_for_each_entry(bsc, &_nat->bsc_connections, list_entry) {
if (!bsc->cfg || bsc->cfg->nr != bsc_nr)
continue;
bsc_close_connection(bsc);
break;
}
return CMD_SUCCESS;
}
DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
{
vty->index = _nat;
@@ -224,7 +257,7 @@ DEFUN(cfg_nat_msc_port,
}
/* per BSC configuration */
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure\n")
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
{
int bsc_nr = atoi(argv[0]);
struct bsc_config *bsc;
@@ -259,7 +292,7 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", "Set the token")
}
DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
"Set the Location Area Code (LAC) of this BSC\n")
"Set the Location Area Code (LAC) of this BSC")
{
struct bsc_config *tmp;
struct bsc_config *conf = vty->index;
@@ -315,6 +348,21 @@ DEFUN(cfg_bsc_imsi_deny,
return CMD_SUCCESS;
}
DEFUN(cfg_bsc_paging,
cfg_bsc_paging_cmd,
"paging forbidden (0|1)",
"Forbid sending PAGING REQUESTS to the BSC.")
{
struct bsc_config *conf = vty->index;
if (strcmp("1", argv[0]) == 0)
conf->forbid_paging = 1;
else
conf->forbid_paging = 0;
return CMD_SUCCESS;
}
int bsc_nat_vty_init(struct bsc_nat *nat)
{
_nat = nat;
@@ -327,6 +375,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(VIEW_NODE, &show_bsc_cmd);
install_element(VIEW_NODE, &show_bsc_cfg_cmd);
install_element(VIEW_NODE, &show_stats_cmd);
install_element(VIEW_NODE, &close_bsc_cmd);
openbsc_vty_add_cmds();
@@ -347,6 +396,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(BSC_NODE, &cfg_bsc_lac_cmd);
install_element(BSC_NODE, &cfg_bsc_imsi_allow_cmd);
install_element(BSC_NODE, &cfg_bsc_imsi_deny_cmd);
install_element(BSC_NODE, &cfg_bsc_paging_cmd);
mgcp_vty_init();

View File

@@ -85,6 +85,28 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
{
struct sccp_connections *conn;
/* Some commercial BSCs like to reassign there SRC ref */
llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
if (conn->bsc != bsc)
continue;
if (memcmp(&conn->real_ref, parsed->src_local_ref, sizeof(conn->real_ref)) != 0)
continue;
/* the BSC has reassigned the SRC ref and we failed to keep track */
memset(&conn->remote_ref, 0, sizeof(conn->remote_ref));
if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
LOGP(DNAT, LOGL_ERROR, "BSC %d reused src ref: %d and we failed to generate a new id.\n",
bsc->cfg->nr, sccp_src_ref_to_int(parsed->src_local_ref));
llist_del(&conn->list_entry);
talloc_free(conn);
return -1;
} else {
bsc_mgcp_dlcx(conn);
return 0;
}
}
conn = talloc_zero(bsc->nat, struct sccp_connections);
if (!conn) {
LOGP(DNAT, LOGL_ERROR, "Memory allocation failure.\n");
@@ -99,7 +121,7 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
return -1;
}
bsc_mgcp_clear(conn);
bsc_mgcp_init(conn);
llist_add_tail(&conn->list_entry, &bsc->nat->sccp_connections);
counter_inc(bsc->cfg->stats.sccp.conn);
counter_inc(bsc->cfg->nat->stats.sccp.conn);
@@ -119,6 +141,7 @@ int update_sccp_src_ref(struct sccp_connections *sccp, struct bsc_nat_parsed *pa
}
sccp->remote_ref = *parsed->src_local_ref;
sccp->has_remote_ref = 1;
LOGP(DNAT, LOGL_DEBUG, "Updating 0x%x to remote 0x%x on %p\n",
sccp_src_ref_to_int(&sccp->patched_ref),
sccp_src_ref_to_int(&sccp->remote_ref), sccp->bsc);
@@ -182,11 +205,14 @@ struct sccp_connections *patch_sccp_src_ref_to_bsc(struct msgb *msg,
*/
struct sccp_connections *patch_sccp_src_ref_to_msc(struct msgb *msg,
struct bsc_nat_parsed *parsed,
struct bsc_nat *nat)
struct bsc_connection *bsc)
{
struct sccp_connections *conn;
llist_for_each_entry(conn, &nat->sccp_connections, list_entry) {
llist_for_each_entry(conn, &bsc->nat->sccp_connections, list_entry) {
if (conn->bsc != bsc)
continue;
if (parsed->src_local_ref) {
if (equal(parsed->src_local_ref, &conn->real_ref)) {
*parsed->src_local_ref = conn->patched_ref;

View File

@@ -1,6 +1,6 @@
!
! OpenBSC configuration saved from vty
!
! !
password foo
!
line vty
@@ -11,17 +11,52 @@ network
mobile network code 1
short name OpenBSC
long name OpenBSC
auth policy closed
location updating reject cause 13
encryption a5 0
neci 0
rrlp mode none
mm info 1
handover 0
handover window rxlev averaging 10
handover window rxqual averaging 1
handover window rxlev neighbor averaging 10
handover power budget interval 6
handover power budget hysteresis 3
handover maximum distance 9999
timer t3101 10
timer t3103 0
timer t3105 0
timer t3107 0
timer t3109 0
timer t3111 0
timer t3113 60
timer t3115 0
timer t3117 0
timer t3119 0
timer t3141 0
bts 0
type nanobts
ip.access unit_id 1801 0
band GSM1800
band DCS1800
cell_identity 0
location_area_code 1
training_sequence_code 7
base_station_id_code 63
ms max power 15
cell reselection hysteresis 4
rxlev access min 0
channel allocator ascending
rach tx integer 9
rach max transmission 7
ip.access unit_id 1801 0
oml ip.access stream_id 255
gprs mode none
trx 0
rf_locked 0
arfcn 514
nominal power 23
max_power_red 20
rsl e1 tei 0
timeslot 0
phys_chan_config CCCH+SDCCH4
timeslot 1

View File

@@ -0,0 +1,97 @@
!
! OpenBSC configuration saved from vty
! !
password foo
!
line vty
no login
!
network
network country code 1
mobile network code 1
short name OpenBSC
long name OpenBSC
auth policy closed
location updating reject cause 13
encryption a5 0
neci 0
rrlp mode none
mm info 0
handover 0
handover window rxlev averaging 10
handover window rxqual averaging 1
handover window rxlev neighbor averaging 10
handover power budget interval 6
handover power budget hysteresis 3
handover maximum distance 9999
timer t3101 10
timer t3103 0
timer t3105 0
timer t3107 0
timer t3109 0
timer t3111 0
timer t3113 60
timer t3115 0
timer t3117 0
timer t3119 0
timer t3141 0
bts 0
type nanobts
band DCS1800
cell_identity 0
location_area_code 1
training_sequence_code 7
base_station_id_code 63
ms max power 15
cell reselection hysteresis 4
rxlev access min 0
channel allocator ascending
rach tx integer 9
rach max transmission 7
ip.access unit_id 1800 0
oml ip.access stream_id 255
gprs mode none
trx 0
rf_locked 0
arfcn 871
nominal power 23
max_power_red 0
rsl e1 tei 0
timeslot 0
phys_chan_config CCCH+SDCCH4
timeslot 1
phys_chan_config SDCCH8
timeslot 2
phys_chan_config TCH/F
timeslot 3
phys_chan_config TCH/F
timeslot 4
phys_chan_config TCH/F
timeslot 5
phys_chan_config TCH/F
timeslot 6
phys_chan_config TCH/F
timeslot 7
phys_chan_config TCH/F
trx 1
rf_locked 0
arfcn 873
nominal power 23
max_power_red 0
rsl e1 tei 0
timeslot 0
phys_chan_config CCCH+SDCCH4
timeslot 1
phys_chan_config SDCCH8
timeslot 2
phys_chan_config TCH/F
timeslot 3
phys_chan_config TCH/F
timeslot 4
phys_chan_config TCH/F
timeslot 5
phys_chan_config TCH/F
timeslot 6
phys_chan_config TCH/F
timeslot 7
phys_chan_config TCH/F

View File

@@ -45,9 +45,12 @@
#include <openbsc/signal.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/gsm_data.h>
#include <openbsc/chan_alloc.h>
void *tall_paging_ctx;
#define PAGING_TIMER 0, 500000
static unsigned int calculate_group(struct gsm_bts *bts, struct gsm_subscriber *subscr)
{
int ccch_conf;
@@ -95,6 +98,72 @@ static void page_ms(struct gsm_paging_request *request)
request->chan_type);
}
static void paging_schedule_if_needed(struct gsm_bts_paging_state *paging_bts)
{
if (llist_empty(&paging_bts->pending_requests))
return;
if (!bsc_timer_pending(&paging_bts->work_timer))
bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
}
static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts);
static void paging_give_credit(void *data)
{
struct gsm_bts_paging_state *paging_bts = data;
LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n", paging_bts->bts->nr);
paging_bts->available_slots = 20;
paging_handle_pending_requests(paging_bts);
}
static int can_send_pag_req(struct gsm_bts *bts, int rsl_type)
{
struct pchan_load pl;
int count;
memset(&pl, 0, sizeof(pl));
bts_chan_load(&pl, bts);
switch (rsl_type) {
case RSL_CHANNEED_TCH_F:
case RSL_CHANNEED_TCH_ForH:
goto count_tch;
break;
case RSL_CHANNEED_SDCCH:
goto count_sdcch;
break;
case RSL_CHANNEED_ANY:
default:
if (bts->network->pag_any_tch)
goto count_tch;
else
goto count_sdcch;
break;
}
return 0;
/* could available SDCCH */
count_sdcch:
count = 0;
count += pl.pchan[GSM_PCHAN_SDCCH8_SACCH8C].total
- pl.pchan[GSM_PCHAN_SDCCH8_SACCH8C].used;
count += pl.pchan[GSM_PCHAN_CCCH_SDCCH4].total
- pl.pchan[GSM_PCHAN_CCCH_SDCCH4].used;
return bts->paging.free_chans_need > count;
count_tch:
count = 0;
count += pl.pchan[GSM_PCHAN_TCH_F].total
- pl.pchan[GSM_PCHAN_TCH_F].used;
if (bts->network->neci)
count += pl.pchan[GSM_PCHAN_TCH_H].total
- pl.pchan[GSM_PCHAN_TCH_H].used;
return bts->paging.free_chans_need > count;
}
/*
* This is kicked by the periodic PAGING LOAD Indicator
* coming from abis_rsl.c
@@ -104,8 +173,7 @@ static void page_ms(struct gsm_paging_request *request)
*/
static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_bts)
{
struct gsm_paging_request *initial_request = NULL;
struct gsm_paging_request *current_request = NULL;
struct gsm_paging_request *request = NULL;
/*
* Determine if the pending_requests list is empty and
@@ -117,39 +185,37 @@ static void paging_handle_pending_requests(struct gsm_bts_paging_state *paging_b
}
/*
* In case the BTS does not provide us with load indication just fill
* up our slots for this round. We should be able to page 20 subscribers
* every two seconds. So we will just give the BTS some extra credit.
* We will have to see how often we run out of this credit, so we might
* need a low watermark and then add credit or give 20 every run when
* the bts sets an option for that.
* In case the BTS does not provide us with load indication and we
* ran out of slots, call an autofill routine. It might be that the
* BTS did not like our paging messages and then we have counted down
* to zero and we do not get any messages.
*/
if (paging_bts->available_slots == 0) {
LOGP(DPAG, LOGL_NOTICE, "No slots available on bts nr %d\n",
paging_bts->bts->nr);
paging_bts->available_slots = 20;
paging_bts->credit_timer.cb = paging_give_credit;
paging_bts->credit_timer.data = paging_bts;
bsc_schedule_timer(&paging_bts->credit_timer, 5, 0);
return;
}
initial_request = llist_entry(paging_bts->pending_requests.next,
struct gsm_paging_request, entry);
current_request = initial_request;
request = llist_entry(paging_bts->pending_requests.next,
struct gsm_paging_request, entry);
do {
/* handle the paging request now */
page_ms(current_request);
paging_bts->available_slots--;
/* we need to determine the number of free channels */
if (paging_bts->free_chans_need != -1) {
if (can_send_pag_req(request->bts, request->chan_type) != 0)
goto skip_paging;
}
/* take the current and add it to the back */
llist_del(&current_request->entry);
llist_add_tail(&current_request->entry, &paging_bts->pending_requests);
/* handle the paging request now */
page_ms(request);
paging_bts->available_slots--;
/* take the next request */
current_request = llist_entry(paging_bts->pending_requests.next,
struct gsm_paging_request, entry);
} while (paging_bts->available_slots > 0
&& initial_request != current_request);
/* take the current and add it to the back */
llist_del(&request->entry);
llist_add_tail(&request->entry, &paging_bts->pending_requests);
bsc_schedule_timer(&paging_bts->work_timer, 2, 0);
skip_paging:
bsc_schedule_timer(&paging_bts->work_timer, PAGING_TIMER);
}
static void paging_worker(void *data)
@@ -232,9 +298,7 @@ static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr,
req->T3113.data = req;
bsc_schedule_timer(&req->T3113, bts->network->T3113, 0);
llist_add_tail(&req->entry, &bts_entry->pending_requests);
if (!bsc_timer_pending(&bts_entry->work_timer))
bsc_schedule_timer(&bts_entry->work_timer, 2, 0);
paging_schedule_if_needed(bts_entry);
return 0;
}
@@ -324,7 +388,9 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr,
void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t free_slots)
{
bsc_del_timer(&bts->paging.credit_timer);
bts->paging.available_slots = free_slots;
paging_schedule_if_needed(&bts->paging);
}
unsigned int paging_pending_requests_nr(struct gsm_bts *bts)

View File

@@ -133,6 +133,7 @@ static int append_lsa_params(struct bitvec *bv,
const struct gsm48_lsa_params *lsa_params)
{
/* FIXME */
return -1;
}
/* Generate SI4 Rest Octets (Chapter 10.5.2.35) */
@@ -318,8 +319,31 @@ static int append_gprs_cell_opt(struct bitvec *bv,
/* hard-code no PAN_{DEC,INC,MAX} */
bitvec_set_bit(bv, 0);
/* no extension information (EDGE) */
bitvec_set_bit(bv, 0);
if (!gco->ext_info_present) {
/* no extension information */
bitvec_set_bit(bv, 0);
} else {
/* extension information */
bitvec_set_bit(bv, 1);
if (!gco->ext_info.egprs_supported) {
/* 6bit length of extension */
bitvec_set_uint(bv, (1 + 3)-1, 6);
/* EGPRS supported in the cell */
bitvec_set_bit(bv, 0);
} else {
/* 6bit length of extension */
bitvec_set_uint(bv, (1 + 5 + 3)-1, 6);
/* EGPRS supported in the cell */
bitvec_set_bit(bv, 1);
/* 1bit EGPRS PACKET CHANNEL REQUEST */
bitvec_set_bit(bv, gco->ext_info.use_egprs_p_ch_req);
/* 4bit BEP PERIOD */
bitvec_set_uint(bv, gco->ext_info.bep_period, 4);
}
bitvec_set_bit(bv, gco->ext_info.pfc_supported);
bitvec_set_bit(bv, gco->ext_info.dtm_supported);
bitvec_set_bit(bv, gco->ext_info.bss_paging_coordination);
}
return 0;
}
@@ -334,7 +358,7 @@ static void append_gprs_pwr_ctrl_pars(struct bitvec *bv,
bitvec_set_uint(bv, pcp->n_avg_i, 4);
}
/* Generate SI13 Rest Octests (Chapter 10.5.2.37b) */
/* Generate SI13 Rest Octests (04.08 Chapter 10.5.2.37b) */
int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
{
struct bitvec bv;
@@ -390,6 +414,11 @@ int rest_octets_si13(u_int8_t *data, const struct gsm48_si13_info *si13)
break;
}
}
/* 3GPP TS 44.018 Release 6 / 10.5.2.37b */
bitvec_set_bit(&bv, H); /* added Release 99 */
/* claim our SGSN is compatible with Release 99, as EDGE and EGPRS
* was only added in this Release */
bitvec_set_bit(&bv, 1);
}
bitvec_spare_padding(&bv, (bv.data_len*8)-1);
return bv.data_len;

View File

@@ -81,7 +81,7 @@ static struct sccp_data_callback *_find_ssn(u_int8_t ssn)
/* need to add one */
cb = talloc_zero(tall_sccp_ctx, struct sccp_data_callback);
if (!cb) {
DEBUGP(DSCCP, "Failed to allocate sccp callback.\n");
LOGP(DSCCP, LOGL_ERROR, "Failed to allocate sccp callback.\n");
return NULL;
}
@@ -108,13 +108,13 @@ static int copy_address(struct sccp_address *addr, u_int8_t offset, struct msgb
u_int8_t length;
if (room <= 0) {
DEBUGP(DSCCP, "Not enough room for an address: %u\n", room);
LOGP(DSCCP, LOGL_ERROR, "Not enough room for an address: %u\n", room);
return -1;
}
length = msgb->l2h[offset];
if (room <= length) {
DEBUGP(DSCCP, "Not enough room for optional data %u %u\n", room, length);
LOGP(DSCCP, LOGL_ERROR, "Not enough room for optional data %u %u\n", room, length);
return -1;
}
@@ -122,7 +122,7 @@ static int copy_address(struct sccp_address *addr, u_int8_t offset, struct msgb
party = (struct sccp_called_party_address *)(msgb->l2h + offset + 1);
if (party->point_code_indicator) {
if (length <= read + 2) {
DEBUGP(DSCCP, "POI does not fit %u\n", length);
LOGP(DSCCP, LOGL_ERROR, "POI does not fit %u\n", length);
return -1;
}
@@ -133,7 +133,7 @@ static int copy_address(struct sccp_address *addr, u_int8_t offset, struct msgb
if (party->ssn_indicator) {
if (length <= read + 1) {
DEBUGP(DSCCP, "SSN does not fit %u\n", length);
LOGP(DSCCP, LOGL_ERROR, "SSN does not fit %u\n", length);
return -1;
}
@@ -142,7 +142,7 @@ static int copy_address(struct sccp_address *addr, u_int8_t offset, struct msgb
}
if (party->global_title_indicator) {
DEBUGP(DSCCP, "GTI not supported %u\n", *(u_int8_t *)party);
LOGP(DSCCP, LOGL_ERROR, "GTI not supported %u\n", *(u_int8_t *)party);
return -1;
}
@@ -156,7 +156,8 @@ static int check_address(struct sccp_address *addr)
if (addr->address.ssn_indicator != 1
|| addr->address.global_title_indicator == 1
|| addr->address.routing_indicator != 1) {
DEBUGP(DSCCP, "Invalid called address according to 08.06: 0x%x 0x%x\n",
LOGP(DSCCP, LOGL_ERROR,
"Invalid called address according to 08.06: 0x%x 0x%x\n",
*(u_int8_t *)&addr->address, addr->ssn);
return -1;
}
@@ -176,7 +177,7 @@ static int _sccp_parse_optional_data(const int offset,
return 0;
if (read + 1 >= room) {
DEBUGP(DSCCP, "no place for length\n");
LOGP(DSCCP, LOGL_ERROR, "no place for length\n");
return 0;
}
@@ -185,7 +186,8 @@ static int _sccp_parse_optional_data(const int offset,
if (room <= read) {
DEBUGP(DSCCP, "no space for the data: type: %d read: %d room: %d l2: %d\n",
LOGP(DSCCP, LOGL_ERROR,
"no space for the data: type: %d read: %d room: %d l2: %d\n",
type, read, room, msgb_l2len(msgb));
return 0;
}
@@ -214,7 +216,7 @@ int _sccp_parse_connection_request(struct msgb *msgb, struct sccp_parse_result *
/* header check */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
@@ -224,7 +226,7 @@ int _sccp_parse_connection_request(struct msgb *msgb, struct sccp_parse_result *
return -1;
if (check_address(&result->called) != 0) {
DEBUGP(DSCCP, "Invalid called address according to 08.06: 0x%x 0x%x\n",
LOGP(DSCCP, LOGL_ERROR, "Invalid called address according to 08.06: 0x%x 0x%x\n",
*(u_int8_t *)&result->called.address, result->called.ssn);
return -1;
}
@@ -236,7 +238,7 @@ int _sccp_parse_connection_request(struct msgb *msgb, struct sccp_parse_result *
*/
memset(&optional_data, 0, sizeof(optional_data));
if (_sccp_parse_optional_data(optional_offset + req->optional_start, msgb, &optional_data) != 0) {
DEBUGP(DSCCP, "parsing of optional data failed.\n");
LOGP(DSCCP, LOGL_ERROR, "parsing of optional data failed.\n");
return -1;
}
@@ -260,14 +262,14 @@ int _sccp_parse_connection_released(struct msgb *msgb, struct sccp_parse_result
/* we don't have enough size for the struct */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb > header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb > header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
memset(&optional_data, 0, sizeof(optional_data));
if (_sccp_parse_optional_data(optional_offset + rls->optional_start, msgb, &optional_data) != 0) {
DEBUGP(DSCCP, "parsing of optional data failed.\n");
LOGP(DSCCP, LOGL_ERROR, "parsing of optional data failed.\n");
return -1;
}
@@ -295,7 +297,7 @@ int _sccp_parse_connection_refused(struct msgb *msgb, struct sccp_parse_result *
/* header check */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
@@ -306,7 +308,7 @@ int _sccp_parse_connection_refused(struct msgb *msgb, struct sccp_parse_result *
memset(&optional_data, 0, sizeof(optional_data));
if (_sccp_parse_optional_data(optional_offset + ref->optional_start, msgb, &optional_data) != 0) {
DEBUGP(DSCCP, "parsing of optional data failed.\n");
LOGP(DSCCP, LOGL_ERROR, "parsing of optional data failed.\n");
return -1;
}
@@ -333,7 +335,7 @@ int _sccp_parse_connection_confirm(struct msgb *msgb, struct sccp_parse_result *
/* header check */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
@@ -344,7 +346,7 @@ int _sccp_parse_connection_confirm(struct msgb *msgb, struct sccp_parse_result *
memset(&optional_data, 0, sizeof(optional_data));
if (_sccp_parse_optional_data(optional_offset + con->optional_start, msgb, &optional_data) != 0) {
DEBUGP(DSCCP, "parsing of optional data failed.\n");
LOGP(DSCCP, LOGL_ERROR, "parsing of optional data failed.\n");
return -1;
}
@@ -366,7 +368,7 @@ int _sccp_parse_connection_release_complete(struct msgb *msgb, struct sccp_parse
/* header check */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
@@ -387,13 +389,13 @@ int _sccp_parse_connection_dt1(struct msgb *msgb, struct sccp_parse_result *resu
/* we don't have enough size for the struct */
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb > header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb > header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
if (dt1->segmenting != 0) {
DEBUGP(DSCCP, "This packet has segmenting, not supported: %d\n", dt1->segmenting);
LOGP(DSCCP, LOGL_ERROR, "This packet has segmenting, not supported: %d\n", dt1->segmenting);
return -1;
}
@@ -401,7 +403,7 @@ int _sccp_parse_connection_dt1(struct msgb *msgb, struct sccp_parse_result *resu
/* some more size checks in here */
if (msgb_l2len(msgb) < variable_offset + dt1->variable_start + 1) {
DEBUGP(DSCCP, "Not enough space for variable start: %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "Not enough space for variable start: %u %u\n",
msgb_l2len(msgb), dt1->variable_start);
return -1;
}
@@ -410,7 +412,7 @@ int _sccp_parse_connection_dt1(struct msgb *msgb, struct sccp_parse_result *resu
msgb->l3h = &msgb->l2h[dt1->variable_start + variable_offset + 1];
if (msgb_l3len(msgb) < result->data_len) {
DEBUGP(DSCCP, "Not enough room for the payload: %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "Not enough room for the payload: %u %u\n",
msgb_l3len(msgb), result->data_len);
return -1;
}
@@ -428,7 +430,7 @@ int _sccp_parse_udt(struct msgb *msgb, struct sccp_parse_result *result)
struct sccp_data_unitdata *udt = (struct sccp_data_unitdata *)msgb->l2h;
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
@@ -438,7 +440,7 @@ int _sccp_parse_udt(struct msgb *msgb, struct sccp_parse_result *result)
return -1;
if (check_address(&result->called) != 0) {
DEBUGP(DSCCP, "Invalid called address according to 08.06: 0x%x 0x%x\n",
LOGP(DSCCP, LOGL_ERROR, "Invalid called address according to 08.06: 0x%x 0x%x\n",
*(u_int8_t *)&result->called.address, result->called.ssn);
return -1;
}
@@ -447,13 +449,13 @@ int _sccp_parse_udt(struct msgb *msgb, struct sccp_parse_result *result)
return -1;
if (check_address(&result->calling) != 0) {
DEBUGP(DSCCP, "Invalid called address according to 08.06: 0x%x 0x%x\n",
LOGP(DSCCP, LOGL_ERROR, "Invalid called address according to 08.06: 0x%x 0x%x\n",
*(u_int8_t *)&result->called.address, result->called.ssn);
}
/* we don't have enough size for the data */
if (msgb_l2len(msgb) < data_offset + udt->variable_data + 1) {
DEBUGP(DSCCP, "msgb < header + offset %u %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header + offset %u %u %u\n",
msgb_l2len(msgb), header_size, udt->variable_data);
return -1;
}
@@ -463,7 +465,7 @@ int _sccp_parse_udt(struct msgb *msgb, struct sccp_parse_result *result)
result->data_len = msgb_l3len(msgb);
if (msgb_l3len(msgb) != msgb->l3h[-1]) {
DEBUGP(DSCCP, "msgb is truncated is: %u should: %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb is truncated is: %u should: %u\n",
msgb_l3len(msgb), msgb->l3h[-1]);
return -1;
}
@@ -478,7 +480,7 @@ static int _sccp_parse_it(struct msgb *msgb, struct sccp_parse_result *result)
struct sccp_data_it *it;
if (msgb_l2len(msgb) < header_size) {
DEBUGP(DSCCP, "msgb < header_size %u %u\n",
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
@@ -490,6 +492,23 @@ static int _sccp_parse_it(struct msgb *msgb, struct sccp_parse_result *result)
return 0;
}
static int _sccp_parse_err(struct msgb *msgb, struct sccp_parse_result *result)
{
static const u_int32_t header_size = sizeof(struct sccp_proto_err);
struct sccp_proto_err *err;
if (msgb_l2len(msgb) < header_size) {
LOGP(DSCCP, LOGL_ERROR, "msgb < header_size %u %u\n",
msgb_l2len(msgb), header_size);
return -1;
}
err = (struct sccp_proto_err *) msgb->l2h;
result->data_len = 0;
result->destination_local_reference = &err->destination_local_reference;
return 0;
}
/*
* Send UDT. Currently we have a fixed address...
@@ -501,7 +520,7 @@ static int _sccp_send_data(int class, const struct sockaddr_sccp *in,
u_int8_t *data;
if (msgb_l3len(payload) > 256) {
DEBUGP(DSCCP, "The payload is too big for one udt\n");
LOGP(DSCCP, LOGL_ERROR, "The payload is too big for one udt\n");
return -1;
}
@@ -546,7 +565,7 @@ static int _sccp_handle_read(struct msgb *msgb)
cb = _find_ssn(result.called.ssn);
if (!cb || !cb->read_cb) {
DEBUGP(DSCCP, "No routing for UDT for called SSN: %u\n", result.called.ssn);
LOGP(DSCCP, LOGL_ERROR, "No routing for UDT for called SSN: %u\n", result.called.ssn);
return -1;
}
@@ -595,7 +614,7 @@ static int assign_source_local_reference(struct sccp_connection *connection)
++last_ref;
/* do not use the reversed word and wrap around */
if ((last_ref & 0x00FFFFFF) == 0x00FFFFFF) {
DEBUGP(DSCCP, "Wrapped searching for a free code\n");
LOGP(DSCCP, LOGL_DEBUG, "Wrapped searching for a free code\n");
last_ref = 0;
++wrapped;
}
@@ -606,7 +625,7 @@ static int assign_source_local_reference(struct sccp_connection *connection)
}
} while (wrapped != 2);
DEBUGP(DSCCP, "Finding a free reference failed\n");
LOGP(DSCCP, LOGL_ERROR, "Finding a free reference failed\n");
return -1;
}
@@ -686,13 +705,13 @@ static int _sccp_send_connection_request(struct sccp_connection *connection,
if (msg && (msgb_l3len(msg) < 3 || msgb_l3len(msg) > 130)) {
DEBUGP(DSCCP, "Invalid amount of data... %d\n", msgb_l3len(msg));
LOGP(DSCCP, LOGL_ERROR, "Invalid amount of data... %d\n", msgb_l3len(msg));
return -1;
}
/* try to find a id */
if (assign_source_local_reference(connection) != 0) {
DEBUGP(DSCCP, "Assigning a local reference failed.\n");
LOGP(DSCCP, LOGL_ERROR, "Assigning a local reference failed.\n");
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_SETUP_ERROR);
return -1;
}
@@ -744,7 +763,7 @@ static int _sccp_send_connection_data(struct sccp_connection *conn, struct msgb
int extra_size;
if (msgb_l3len(_data) < 2 || msgb_l3len(_data) > 256) {
DEBUGP(DSCCP, "data size too big, segmenting unimplemented.\n");
LOGP(DSCCP, LOGL_ERROR, "data size too big, segmenting unimplemented.\n");
return -1;
}
@@ -840,14 +859,14 @@ static int _sccp_handle_connection_request(struct msgb *msgb)
cb = _find_ssn(result.called.ssn);
if (!cb || !cb->accept_cb) {
DEBUGP(DSCCP, "No routing for CR for called SSN: %u\n", result.called.ssn);
LOGP(DSCCP, LOGL_ERROR, "No routing for CR for called SSN: %u\n", result.called.ssn);
return -1;
}
/* check if the system wants this connection */
connection = talloc_zero(tall_sccp_ctx, struct sccp_connection);
if (!connection) {
DEBUGP(DSCCP, "Allocation failed\n");
LOGP(DSCCP, LOGL_ERROR, "Allocation failed\n");
return -1;
}
@@ -859,7 +878,7 @@ static int _sccp_handle_connection_request(struct msgb *msgb)
* one....
*/
if (destination_local_reference_is_free(result.source_local_reference) != 0) {
DEBUGP(DSCCP, "Need to reject connection with existing reference\n");
LOGP(DSCCP, LOGL_ERROR, "Need to reject connection with existing reference\n");
_sccp_send_refuse(result.source_local_reference, SCCP_REFUSAL_SCCP_FAILURE);
talloc_free(connection);
return -1;
@@ -879,7 +898,7 @@ static int _sccp_handle_connection_request(struct msgb *msgb)
llist_add_tail(&connection->list, &sccp_connections);
if (_sccp_send_connection_confirm(connection) != 0) {
DEBUGP(DSCCP, "Sending confirm failed... no available source reference?\n");
LOGP(DSCCP, LOGL_ERROR, "Sending confirm failed... no available source reference?\n");
_sccp_send_refuse(result.source_local_reference, SCCP_REFUSAL_SCCP_FAILURE);
_sccp_set_connection_state(connection, SCCP_CONNECTION_STATE_REFUSED);
@@ -922,7 +941,7 @@ static int _sccp_handle_connection_release_complete(struct msgb *msgb)
}
DEBUGP(DSCCP, "Release complete of unknown connection\n");
LOGP(DSCCP, LOGL_ERROR, "Release complete of unknown connection\n");
return -1;
found:
@@ -950,7 +969,7 @@ static int _sccp_handle_connection_dt1(struct msgb *msgb)
}
}
DEBUGP(DSCCP, "No connection found for dt1 data\n");
LOGP(DSCCP, LOGL_ERROR, "No connection found for dt1 data\n");
return -1;
found:
@@ -1009,7 +1028,7 @@ static int _sccp_handle_connection_released(struct msgb *msgb)
}
DEBUGP(DSCCP, "Unknown connection was released.\n");
LOGP(DSCCP, LOGL_ERROR, "Unknown connection was released.\n");
return -1;
/* we have found a connection */
@@ -1021,7 +1040,7 @@ found:
/* generate a response */
if (_sccp_send_connection_release_complete(conn) != 0) {
DEBUGP(DSCCP, "Sending release confirmed failed\n");
LOGP(DSCCP, LOGL_ERROR, "Sending release confirmed failed\n");
return -1;
}
@@ -1046,7 +1065,7 @@ static int _sccp_handle_connection_refused(struct msgb *msgb)
}
}
DEBUGP(DSCCP, "Refused but no connection found\n");
LOGP(DSCCP, LOGL_ERROR, "Refused but no connection found\n");
return -1;
found:
@@ -1079,7 +1098,7 @@ static int _sccp_handle_connection_confirm(struct msgb *msgb)
}
}
DEBUGP(DSCCP, "Confirmed but no connection found\n");
LOGP(DSCCP, LOGL_ERROR, "Confirmed but no connection found\n");
return -1;
found:
@@ -1108,7 +1127,7 @@ int sccp_system_init(void (*outgoing)(struct msgb *data, void *ctx), void *ctx)
int sccp_system_incoming(struct msgb *msgb)
{
if (msgb_l2len(msgb) < 1 ) {
DEBUGP(DSCCP, "Too short packet\n");
LOGP(DSCCP, LOGL_ERROR, "Too short packet\n");
return -1;
}
@@ -1137,7 +1156,7 @@ int sccp_system_incoming(struct msgb *msgb)
return _sccp_handle_read(msgb);
break;
default:
DEBUGP(DSCCP, "unimplemented msg type: %d\n", type);
LOGP(DSCCP, LOGL_ERROR, "unimplemented msg type: %d\n", type);
};
return -1;
@@ -1148,7 +1167,7 @@ int sccp_connection_write(struct sccp_connection *connection, struct msgb *data)
{
if (connection->connection_state < SCCP_CONNECTION_STATE_CONFIRM
|| connection->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
DEBUGP(DSCCP, "sccp_connection_write: Wrong connection state: %p %d\n",
LOGP(DSCCP, LOGL_ERROR, "sccp_connection_write: Wrong connection state: %p %d\n",
connection, connection->connection_state);
return -1;
}
@@ -1165,7 +1184,7 @@ int sccp_connection_send_it(struct sccp_connection *connection)
{
if (connection->connection_state < SCCP_CONNECTION_STATE_CONFIRM
|| connection->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
DEBUGP(DSCCP, "sccp_connection_write: Wrong connection state: %p %d\n",
LOGP(DSCCP, LOGL_ERROR, "sccp_connection_write: Wrong connection state: %p %d\n",
connection, connection->connection_state);
return -1;
}
@@ -1178,7 +1197,7 @@ int sccp_connection_close(struct sccp_connection *connection, int cause)
{
if (connection->connection_state < SCCP_CONNECTION_STATE_CONFIRM
|| connection->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
DEBUGPC(DSCCP, "Can not close the connection. It was never opened: %p %d\n",
LOGP(DSCCP, LOGL_ERROR, "Can not close the connection. It was never opened: %p %d\n",
connection, connection->connection_state);
return -1;
}
@@ -1190,7 +1209,7 @@ int sccp_connection_free(struct sccp_connection *connection)
{
if (connection->connection_state > SCCP_CONNECTION_STATE_NONE
&& connection->connection_state < SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
DEBUGP(DSCCP, "The connection needs to be released before it is freed");
LOGP(DSCCP, LOGL_ERROR, "The connection needs to be released before it is freed");
return -1;
}
@@ -1318,6 +1337,9 @@ int sccp_parse_header(struct msgb *msg, struct sccp_parse_result *result)
case SCCP_MSG_TYPE_IT:
return _sccp_parse_it(msg, result);
break;
case SCCP_MSG_TYPE_ERR:
return _sccp_parse_err(msg, result);
break;
};
LOGP(DSCCP, LOGL_ERROR, "Unimplemented MSG Type: 0x%x\n", type);

View File

@@ -402,6 +402,16 @@ static struct gsm48_si13_info si13_default = {
.t3192 = 500,
.drx_timer_max = 3,
.bs_cv_max = 15,
.ext_info_present = 0,
.ext_info = {
/* The values below are just guesses ! */
.egprs_supported = 0,
.use_egprs_p_ch_req = 1,
.bep_period = 4,
.pfc_supported = 0,
.dtm_supported = 0,
.bss_paging_coordination = 0,
},
},
.pwr_ctrl_pars = {
.alpha = 10, /* a = 1.0 */
@@ -448,7 +458,18 @@ static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)
{
si_info.gprs_ind.present = bts->gprs.enabled;
switch (bts->gprs.mode) {
case BTS_GPRS_EGPRS:
si13_default.cell_opts.ext_info_present = 1;
si13_default.cell_opts.ext_info.egprs_supported = 1;
/* fallthrough */
case BTS_GPRS_GPRS:
si_info.gprs_ind.present = 1;
break;
case BTS_GPRS_NONE:
si_info.gprs_ind.present = 0;
break;
}
switch (type) {
case RSL_SYSTEM_INFO_1:

View File

@@ -65,11 +65,11 @@ struct buffer_data {
#define BUFFER_DATA_FREE(D) talloc_free((D))
/* Make new buffer. */
struct buffer *buffer_new(size_t size)
struct buffer *buffer_new(void *ctx, size_t size)
{
struct buffer *b;
b = talloc_zero(tall_vty_ctx, struct buffer);
b = talloc_zero(ctx, struct buffer);
if (size)
b->size = size;
@@ -138,7 +138,7 @@ static struct buffer_data *buffer_add(struct buffer *b)
{
struct buffer_data *d;
d = _talloc_zero(tall_vty_ctx,
d = _talloc_zero(b,
offsetof(struct buffer_data, data[b->size]),
"buffer_add");
if (!d)

View File

@@ -51,10 +51,10 @@ struct vty *vty_new()
if (!new)
goto out;
new->obuf = buffer_new(0); /* Use default buffer size. */
new->obuf = buffer_new(new, 0); /* Use default buffer size. */
if (!new->obuf)
goto out_new;
new->buf = _talloc_zero(tall_vty_ctx, VTY_BUFSIZ, "vty_new->buf");
new->buf = _talloc_zero(new, VTY_BUFSIZ, "vty_new->buf");
if (!new->buf)
goto out_obuf;
@@ -170,8 +170,7 @@ void vty_close(struct vty *vty)
/* Check configure. */
vty_config_unlock(vty);
/* FIXME: memory leak. We need to call telnet_close_client() but don't
* have bfd */
/* VTY_CLOSED is handled by the telnet_interface */
vty_event(VTY_CLOSED, vty->fd, vty);
/* OK free vty. */
@@ -211,7 +210,7 @@ int vty_out(struct vty *vty, const char *format, ...)
else
size = size * 2;
p = talloc_realloc_size(tall_vty_ctx, p, size);
p = talloc_realloc_size(vty, p, size);
if (!p)
return -1;
@@ -358,7 +357,7 @@ static void vty_ensure(struct vty *vty, int length)
{
if (vty->max <= length) {
vty->max *= 2;
vty->buf = talloc_realloc_size(tall_vty_ctx, vty->buf, vty->max);
vty->buf = talloc_realloc_size(vty, vty->buf, vty->max);
// FIXME: check return
}
}
@@ -459,7 +458,7 @@ static void vty_hist_add(struct vty *vty)
/* Insert history entry. */
if (vty->hist[vty->hindex])
talloc_free(vty->hist[vty->hindex]);
vty->hist[vty->hindex] = talloc_strdup(tall_vty_ctx, vty->buf);
vty->hist[vty->hindex] = talloc_strdup(vty, vty->buf);
/* History index rotation. */
vty->hindex++;
@@ -916,7 +915,7 @@ static void vty_complete_command(struct vty *vty)
vty_backward_pure_word(vty);
vty_insert_word_overwrite(vty, matched[0]);
vty_self_insert(vty, ' ');
//talloc_free(matched[0]);
talloc_free(matched[0]);
break;
case CMD_COMPLETE_MATCH:
vty_prompt(vty);
@@ -924,8 +923,6 @@ static void vty_complete_command(struct vty *vty)
vty_backward_pure_word(vty);
vty_insert_word_overwrite(vty, matched[0]);
talloc_free(matched[0]);
vector_only_index_free(matched);
return;
break;
case CMD_COMPLETE_LIST_MATCH:
for (i = 0; matched[i] != NULL; i++) {
@@ -966,7 +963,7 @@ vty_describe_fold(struct vty *vty, int cmd_width,
return;
}
buf = _talloc_zero(tall_vty_ctx, strlen(desc->str) + 1, "describe_fold");
buf = _talloc_zero(vty, strlen(desc->str) + 1, "describe_fold");
if (!buf)
return;

View File

@@ -350,6 +350,13 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
vty_out(vty, " rach max transmission %u%s",
rach_max_trans_raw2val(bts->si_common.rach_control.max_trans),
VTY_NEWLINE);
if (bts->rach_b_thresh != -1)
vty_out(vty, " rach nm busy threshold %u%s",
bts->rach_b_thresh, VTY_NEWLINE);
if (bts->rach_ldavg_slots != -1)
vty_out(vty, " rach nm load average %u%s",
bts->rach_ldavg_slots, VTY_NEWLINE);
if (bts->si_common.rach_control.cell_bar)
vty_out(vty, " cell barred 1%s", VTY_NEWLINE);
if (is_ipaccess_bts(bts)) {
@@ -360,8 +367,14 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
config_write_e1_link(vty, &bts->oml_e1_link, " oml ");
vty_out(vty, " oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE);
}
vty_out(vty, " gprs enabled %u%s", bts->gprs.enabled, VTY_NEWLINE);
if (bts->gprs.enabled) {
/* if we have a limit, write it */
if (bts->paging.free_chans_need >= 0)
vty_out(vty, " paging free %d%s", bts->paging.free_chans_need, VTY_NEWLINE);
vty_out(vty, " gprs mode %s%s", bts_gprs_mode_name(bts->gprs.mode),
VTY_NEWLINE);
if (bts->gprs.mode != BTS_GPRS_NONE) {
vty_out(vty, " gprs routing area %u%s", bts->gprs.rac,
VTY_NEWLINE);
vty_out(vty, " gprs cell bvci %u%s", bts->gprs.cell.bvci,
@@ -614,10 +627,6 @@ DEFUN(show_ts,
static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr)
{
int rc;
struct gsm_auth_info ainfo;
struct gsm_auth_tuple atuple;
vty_out(vty, " ID: %llu, Authorized: %d%s", subscr->id,
subscr->authorized, VTY_NEWLINE);
if (subscr->name)
@@ -990,7 +999,7 @@ DEFUN(drop_bts,
ipaccess_drop_rsl(trx);
}
} else {
vty_out(vty, "Argument must be 'oml# or 'rsl'.%s", VTY_NEWLINE);
vty_out(vty, "Argument must be 'oml' or 'rsl'.%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1602,6 +1611,26 @@ DEFUN(cfg_bts_rach_max_trans,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_rach_nm_b_thresh,
cfg_bts_rach_nm_b_thresh_cmd,
"rach nm busy threshold <0-255>",
"Set the NM Busy Threshold in DB")
{
struct gsm_bts *bts = vty->index;
bts->rach_b_thresh = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_rach_nm_ldavg,
cfg_bts_rach_nm_ldavg_cmd,
"rach nm load average <0-65535>",
"Set the NM Loadaver Slots value")
{
struct gsm_bts *bts = vty->index;
bts->rach_ldavg_slots = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_cell_barred, cfg_bts_cell_barred_cmd,
"cell barred (0|1)",
"Should this cell be barred from access?")
@@ -1658,12 +1687,12 @@ DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
}
DEFUN(cfg_bts_prs_bvci, cfg_bts_gprs_bvci_cmd,
"gprs cell bvci <0-65535>",
"gprs cell bvci <2-65535>",
"GPRS BSSGP VC Identifier")
{
struct gsm_bts *bts = vty->index;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1679,7 +1708,7 @@ DEFUN(cfg_bts_gprs_nsei, cfg_bts_gprs_nsei_cmd,
{
struct gsm_bts *bts = vty->index;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1697,7 +1726,7 @@ DEFUN(cfg_bts_gprs_nsvci, cfg_bts_gprs_nsvci_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1714,7 +1743,7 @@ DEFUN(cfg_bts_gprs_nsvc_lport, cfg_bts_gprs_nsvc_lport_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1731,7 +1760,7 @@ DEFUN(cfg_bts_gprs_nsvc_rport, cfg_bts_gprs_nsvc_rport_cmd,
struct gsm_bts *bts = vty->index;
int idx = atoi(argv[0]);
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1749,7 +1778,7 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
int idx = atoi(argv[0]);
struct in_addr ia;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1760,13 +1789,23 @@ DEFUN(cfg_bts_gprs_nsvc_rip, cfg_bts_gprs_nsvc_rip_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_pag_free, cfg_bts_pag_free_cmd,
"paging free FREE_NR",
"Only page when having a certain amount of free slots. -1 to disable")
{
struct gsm_bts *bts = vty->index;
bts->paging.free_chans_need = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
"gprs routing area <0-255>",
"GPRS Routing Area Code")
{
struct gsm_bts *bts = vty->index;
if (!bts->gprs.enabled) {
if (bts->gprs.mode == BTS_GPRS_NONE) {
vty_out(vty, "%% GPRS not enabled on this BTS%s", VTY_NEWLINE);
return CMD_WARNING;
}
@@ -1776,13 +1815,13 @@ DEFUN(cfg_bts_gprs_rac, cfg_bts_gprs_rac_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_gprs_enabled, cfg_bts_gprs_enabled_cmd,
"gprs enabled <0-1>",
"GPRS Enabled on this BTS")
DEFUN(cfg_bts_gprs_mode, cfg_bts_gprs_mode_cmd,
"gprs mode (none|gprs|egprs)",
"GPRS Mode for this BTS")
{
struct gsm_bts *bts = vty->index;
bts->gprs.enabled = atoi(argv[0]);
bts->gprs.mode = bts_gprs_mode_parse(argv[0]);
return CMD_SUCCESS;
}
@@ -1965,6 +2004,8 @@ DEFUN(cfg_ts_e1_subslot,
return CMD_SUCCESS;
}
extern int bsc_vty_init_extra(struct gsm_network *net);
int bsc_vty_init(struct gsm_network *net)
{
gsmnet = net;
@@ -2046,12 +2087,14 @@ int bsc_vty_init(struct gsm_network *net)
install_element(BTS_NODE, &cfg_bts_challoc_cmd);
install_element(BTS_NODE, &cfg_bts_rach_tx_integer_cmd);
install_element(BTS_NODE, &cfg_bts_rach_max_trans_cmd);
install_element(BTS_NODE, &cfg_bts_rach_nm_b_thresh_cmd);
install_element(BTS_NODE, &cfg_bts_rach_nm_ldavg_cmd);
install_element(BTS_NODE, &cfg_bts_cell_barred_cmd);
install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_enabled_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_mode_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_rac_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_bvci_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_nsei_cmd);
@@ -2059,6 +2102,7 @@ int bsc_vty_init(struct gsm_network *net)
install_element(BTS_NODE, &cfg_bts_gprs_nsvc_lport_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rport_cmd);
install_element(BTS_NODE, &cfg_bts_gprs_nsvc_rip_cmd);
install_element(BTS_NODE, &cfg_bts_pag_free_cmd);
install_element(BTS_NODE, &cfg_trx_cmd);
install_node(&trx_node, dummy_config_write);

View File

@@ -58,7 +58,7 @@ static int dummy_config_write(struct vty *v)
static struct buffer *argv_to_buffer(int argc, const char *argv[], int base)
{
struct buffer *b = buffer_new(1024);
struct buffer *b = buffer_new(NULL, 1024);
int i;
if (!b)

View File

@@ -96,6 +96,12 @@ static const u_int8_t connnection_it[] = {
0x00, 0x00, 0x00, 0x00,
};
/* error in both directions */
static const u_int8_t proto_error[] = {
0x00, 0x05, 0xfd,
0x0f, 0x22, 0x33, 0x44, 0x00,
};
/* MGCP wrap... */
static const u_int8_t mgcp_msg[] = {
0x00, 0x03, 0xfc,
@@ -176,6 +182,19 @@ static const struct filter_result results[] = {
.dir = DIR_MSC,
.result = 0,
},
{
.data = proto_error,
.length = ARRAY_SIZE(proto_error),
.dir = DIR_BSC,
.result = 0,
},
{
.data = proto_error,
.length = ARRAY_SIZE(proto_error),
.dir = DIR_MSC,
.result = 0,
},
};
static void test_filter(void)
@@ -248,7 +267,7 @@ static void test_contrack()
/* 1.) create a connection */
copy_to_msg(msg, bsc_cr, sizeof(bsc_cr));
parsed = bsc_nat_parse(msg);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
if (con_found != NULL) {
fprintf(stderr, "Con should not exist %p\n", con_found);
abort();
@@ -258,7 +277,7 @@ static void test_contrack()
fprintf(stderr, "Failed to create a ref\n");
abort();
}
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
if (!con_found || con_found->bsc != con) {
fprintf(stderr, "Failed to find the con: %p\n", con_found);
abort();
@@ -282,7 +301,7 @@ static void test_contrack()
/* 3.) send some data */
copy_to_msg(msg, bsc_dtap, sizeof(bsc_dtap));
parsed = bsc_nat_parse(msg);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
VERIFY(con_found, con, msg, bsc_dtap_patched, "BSC DTAP");
/* 4.) receive some data */
@@ -300,7 +319,7 @@ static void test_contrack()
/* 6.) confirm the connection close */
copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
parsed = bsc_nat_parse(msg);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
if (!con_found || con_found->bsc != con) {
fprintf(stderr, "Failed to find the con: %p\n", con_found);
abort();
@@ -314,7 +333,7 @@ static void test_contrack()
copy_to_msg(msg, bsc_rlc, sizeof(bsc_rlc));
parsed = bsc_nat_parse(msg);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, nat);
con_found = patch_sccp_src_ref_to_msc(msg, parsed, con);
/* verify that it is gone */
if (con_found != NULL) {
@@ -376,6 +395,8 @@ static void test_paging(void)
static void test_mgcp_ass_tracking(void)
{
struct bsc_connection *bsc;
struct bsc_nat *nat;
struct sccp_connections con;
struct bsc_nat_parsed *parsed;
struct msgb *msg;
@@ -383,6 +404,14 @@ static void test_mgcp_ass_tracking(void)
fprintf(stderr, "Testing MGCP.\n");
memset(&con, 0, sizeof(con));
nat = bsc_nat_alloc();
nat->bsc_endpoints = talloc_zero_array(nat,
struct bsc_endpoint,
33);
bsc = bsc_connection_alloc(nat);
bsc->cfg = bsc_config_alloc(nat, "foo", 2323);
con.bsc = bsc;
msg = msgb_alloc(4096, "foo");
copy_to_msg(msg, ass_cmd, sizeof(ass_cmd));
parsed = bsc_nat_parse(msg);
@@ -402,11 +431,13 @@ static void test_mgcp_ass_tracking(void)
}
talloc_free(parsed);
bsc_mgcp_clear(&con);
bsc_mgcp_dlcx(&con);
if (con.bsc_timeslot != -1 || con.msc_timeslot != -1) {
fprintf(stderr, "Clearing should remove the mapping.\n");
abort();
}
talloc_free(nat);
}
/* test the code to find a given connection */

View File

@@ -38,4 +38,6 @@ int main(int argc, char** argv)
DEBUGP(DRLL, "You should see this\n");
DEBUGP(DCC, "You should see this\n");
DEBUGP(DMM, "You should not see this\n");
return 0;
}

View File

@@ -264,6 +264,10 @@ static const u_int8_t it_test[] = {
0x10, 0x01, 0x07,
0x94, 0x01, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00 };
static const u_int8_t proto_err[] = {
0x0f, 0x0c, 0x04, 0x00, 0x00,
};
static const struct sccp_parse_header_result parse_result[] = {
{
.msg_type = SCCP_MSG_TYPE_IT,
@@ -287,6 +291,21 @@ static const struct sccp_parse_header_result parse_result[] = {
.input = it_test,
.input_len = sizeof(it_test),
},
{
.msg_type = SCCP_MSG_TYPE_ERR,
.wanted_len = 0,
.src_ssn = -1,
.dst_ssn = -1,
.has_src_ref = 0,
.has_dst_ref = 1,
.dst_ref = {
.octet1 = 0x0c,
.octet2 = 0x04,
.octet3 = 0x00,
},
.input = proto_err,
.input_len = sizeof(proto_err),
},
};
@@ -777,7 +796,7 @@ static void test_sccp_parsing(void)
memset(&result, 0, sizeof(result));
if (sccp_parse_header(msg, &result) != 0) {
fprintf(stderr, "Failed to parse test: %d\n", current_test);
fprintf(stderr, "Failed to sccp parse test: %d\n", current_test);
} else {
if (parse_result[current_test].wanted_len != result.data_len) {
fprintf(stderr, "Unexpected data length.\n");