Compare commits

...

67 Commits

Author SHA1 Message Date
Pau Espin Pedrol
6ccdaa243f Bump version: 1.7.0.138-ace0b-dirty → 1.8.0
Change-Id: I64ff22193ab2a95a9a7d66e9957a875d096e23de
2021-02-23 18:28:45 +01:00
Pau Espin Pedrol
ace0b946ff tests: Replace deprecated API log_set_print_filename
Change-Id: I761d2bf99aa5a009ff489584d804634e58588125
2021-02-19 13:33:52 +01:00
Pau Espin Pedrol
a34036c296 .gitignore: Ignore new autofoo tmp files
Change-Id: I792f5cd80bee6572ee60269ac44a12d10b5e3a5f
2021-02-04 12:50:27 +01:00
Oliver Smith
9fec391d6e configure.ac: set -std=gnu11
Change-Id: Ic2a1f20be65810a86cdc36aaa459819146a0bfcc
2021-01-28 09:28:08 +00:00
Oliver Smith
a835fa85d7 contrib/jenkins: don't build osmo-gsm-manuals
Related: OS#4912
Change-Id: Idb179c5618797bb245fad857fa79242c43d539a2
2021-01-13 13:14:39 +01:00
Vadim Yanitskiy
2c66c15227 fixup mgcp_trunk: increase default number of virtual endpoints
In change I55605ea083565b6950d0820e3f72c50c9dc19ffa, the default
number of endpoints was increased to 512, however the
configuration examples were not updated.

Change-Id: I449a612065a5208c9f70ae74f594e8d45eb344cf
Related: OS#4711, SYS#5262
2021-01-02 11:29:29 +01:00
Philipp Maier
92a73cd637 mgcp_client: get rid of magic numbers for E1 slots
use NUM_E1_TS-1 instead of 31 in relation of E1 timeslot count

Change-Id: Iee134d70f05883fcd2e58e0b9c78ed70aea16695
2020-12-10 15:23:17 +00:00
Philipp Maier
6e2795bfbf usermanual: add chapter about mgcp endpoints
The manual does not say much about the endpoint naming, even though
osmo-mgw is oriented at RFC 3435 the endpoint names are specific to
osmo-mgw. In particular the E1/T1 endpoints and their overlapping need
some explaination

Change-Id: I16265eb667221959a69f33701d024bd8d9b22040
2020-12-01 12:04:38 +00:00
Philipp Maier
276b595361 configuration: add section about E1 trunks
The cunfiguration chapter does not say anything about E1 trunk
configurations, lets add a subsection that explains how an E1
trunk is added.

Change-Id: I4059771df0f115242398d1af499c837005a7dabc
2020-12-01 12:04:38 +00:00
Philipp Maier
3c293b418b mgcp_trunk: get rid of magic numbers for E1 slots
use NUM_E1_TS-1 instead of 31 in relation of E1 timeslot count

Change-Id: I1cf5fa17f7455448a08ec3c32febca450eadb21e
2020-11-27 15:12:33 +01:00
Philipp Maier
41425e9b85 mgcp_vty: add missing VTY commands for E1 trunks
The E1 trunk lacks the VTY commands force-realloc and rtp-accept-all.
However, the function that write the E1 trunk config includes those
commands. Also they would be applicable, so lets add those two commands
also for E1 trunks.

Change-Id: Ief2bc7502bb8d1e0f9c784d42edbe1aed5ffb728
2020-11-26 21:52:00 +01:00
Philipp Maier
31682a3274 mgcp_vty: fix config write for trunk 0
When a trunk 0 is created (which is legal) than it is impossible to
write this trunk back to the config. The reason for this that there is
still a filtering in place from the time where trunk 0 was not allowed.
This filter needs to be extended to filter only virtual trunk 0 but not
E1 trunk 0 out.

Change-Id: Iad6b577b5a711c35f98c477351fde567d8c87298
2020-11-26 00:41:36 +01:00
Philipp Maier
870f94b493 configuration: add note that changes to trunks need a restart
Change-Id: I06e3f8fed9a6784be773fbdd6a1e3d6b41f7b0bb
2020-11-25 18:13:25 +01:00
Philipp Maier
242e9ada91 configuration: drop note about lackin E1 support
We have now support for E1 trunks

Change-Id: If62f2b646c3b649fa3cbb5ea7007e17b80086bce
2020-11-25 16:22:40 +01:00
Philipp Maier
9b444fd417 configuration: remove hint towards trunk 0 limit
The trunk 0 was reserved for rtpbridge in earlier versions of osmo-mgw,
this was due to internal technical limitations which no longer exist.

Change-Id: Ic322f7dcf28db827187a4537e2634a887bd7b13b
2020-11-25 16:09:16 +01:00
Philipp Maier
e9473f610e overview: add graph to show E1 integration
Add a graph similar to "OsmoMGW used with OsmoMSC" that shows the
integration of a legacy E1 BTS into a AoIP network

Change-Id: I71dc2f4a188fbc25e81050be3dd4c83e1797e63d
2020-11-25 15:56:55 +01:00
Philipp Maier
53002b3a00 overview: fix graph "OsmoMGW used with OsmoMSC"
The graph "OsmoMGW used with OsmoMSC" shows a BSC entity that accepts
AoIP and RTP, however osmo-bsc has no RTP proxy functionality. It makes
probably more sense to remove the BTS from the graph and call "BSC" "2G
BSS"

Change-Id: I6c7d26b6e45d0f953b82bca3ae7b2f26600982b2
2020-11-25 15:47:35 +01:00
Philipp Maier
a098b65252 overview: fix graph "OsmoMGW used with OsmoBSC"
The graph "OsmoMGW used with OsmoBSC" shows an RTP and 3GPP AoIP going
to OsmoMSC, this is technically wrong since osmoMSC has no RTP proxy
functionality whatsoever. Since the graph is not so much about OsmoMSC
it makes more sense to label OsmoMSC with "core-network", then it makes
sense and correctly highlights the role of osmo-mgw on the BSS side.

Change-Id: If3550a101e1e3cc2a25e21dcfe5474134015a6a7
2020-11-25 15:38:49 +01:00
Philipp Maier
78b0055e5e overview: update section limitations.
The limitations section is outdated. We now have support for osmux and
E1 timeslots with trau frames. However, we did not mention that we still
have no transcoding as well.

Change-Id: Ia0fe8be96bbf880cfcd9d18256f4ac23a6efae79
2020-11-25 15:11:30 +01:00
Vadim Yanitskiy
648bec3982 main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
Change-Id: Icb19a635fb7526058d3c47e24ed7d72584dffb0f
Depends: Ie2022a7f9e167e5ceacf15350c037dd43768ff40
Related: SYS#4910
2020-10-24 05:21:06 +07:00
Harald Welte
c2a8f59560 use osmo_fd_setup() whenever applicable
Change-Id: I1586e855d37670af2602fc26b5d1fc72a32d1929
2020-10-21 11:56:17 +00:00
Pau Espin Pedrol
38404969df contrib/jenkins: Enable parallel make in make distcheck
Change-Id: I8b73a9cdd0e481075a234abd9e94bd5c4396f168
Related: OS#4421
2020-10-12 19:34:58 +02:00
Philipp Maier
19c430feba mgcp_vty: add user attributes to configuration commands
To make clear which configuration changes (configure terminal)
apply when, add appropriate user attributes to VTY commands.

Change-Id: I2d9487801b3b78f94577264b56d217c926ef76a9
Related: SYS#4937, OS#1601
2020-10-08 19:26:51 +02:00
Vadim Yanitskiy
3ba409558e vty: use install_lib_element() and install_lib_element_ve()
See https://lists.osmocom.org/pipermail/openbsc/2020-October/013278.html.

Change-Id: I0eff9e0daa1c4327fec8034755986d768f9ba511
Depends: I8baf31ace93c536421893c2aa4e3d9d298dcbcc6
Related: SYS#4937
2020-10-04 16:48:55 +07:00
Philipp Maier
60be627557 mgcp_e1: do not expose function mgcp_e1_init()
The initialization of the E1 line in mgcp_e1.c is controlled internally,
there is no need to expose the function mgcp_e1_init(), lets make it
static and remove the prefix mgcp_

Change-Id: I6aba1c55c9b1d729709ee1fba2994c77bd848a9b
2020-09-23 10:25:52 +02:00
Philipp Maier
8cfe7df3f1 mgcp_vty: deprecate bind early command
The VTY command "bind early" is deprecated but it prints an error
message and the DEFUN is not set to DEFUN_DEPRECATED.

Change-Id: I594a87d2f63826a9d7b4f6a380586b08b3b79518
2020-09-23 10:25:52 +02:00
Philipp Maier
ba94b6d7be mgcp_vty: remove remains of loopback functionality
There exist trunk_loop commands, which sets an trunk->audio_loop
variable, however all it does is to turn on a log message. There is no
actual implementation present. Lets set the VTY commands to
DEFUN_DEPRECATED and remove the variable.

Change-Id: I72b0f8b908e32643e6e3db6ac024371b13c074a1
2020-09-22 16:17:38 +02:00
Pau Espin Pedrol
30e01355f6 cosmetic: Fix typo in comment
Change-Id: Ie982e6721f9840ac9c0bca62646f5c97cc0b1139
2020-09-21 15:45:38 +02:00
Pau Espin Pedrol
06624e13d4 mgw: Fix return value documentation for API mgcp_verify_call_id
Change-Id: Ib5d32baf3a10dad73de29b4388eab14b93ab6f09
2020-09-21 15:45:38 +02:00
Pau Espin Pedrol
19539866e5 mgw: Avoid logging notice message each time we receive nt param in LCO
We don't really use it so far and it doesn't deserve a NOTICE message.

Change-Id: I058dc37fe6229e879284a8f5e7677d6016129c47
2020-09-21 15:45:21 +02:00
Pau Espin Pedrol
1dc2dcebbf cosmetic: Fix typo in comment
Change-Id: I87894dc710823226c1891c919a11ea32c326d3b9
2020-09-21 11:25:18 +02:00
Pau Espin Pedrol
6049a63d1d mgw: Don't be case-sensitive when parsing X-Osmo-IGN param
Some implementations like our TTCN3 encoder set all param characters in
caps.

Related: SYS#5063
Change-Id: Ie4bc5e86551c55021ca6ca2fbc6fc56a26f5fb16
2020-09-21 11:03:25 +02:00
Philipp Maier
3ef8e76534 cosmetic: mgcp_client_fsm: change error message.
The error message: "abrupt FSM termination with connections still
present, sending unconditional DLCX..." implies a more serious problem
than in actually is. Even when connections are present on the
mgcp_client_fsm while it terminates, normal operation is still possible.
Lets change the loglevel to NOTICE and remove the "aprupt" from the
phrase.

Change-Id: I9749c024e208835bd4188bace13f723008de54c8
Related: SYS#5082
2020-09-18 08:46:21 +00:00
Neels Hofmeyr
fbf07f3f69 change timer T2427001 to X2427
libosmo-mgcp-client looks up this timer in a caller provided osmo_tdef
definition. So far, all of our libosmo-mgcp-client callers do not configure
such a timer, so that we always use the default timer value.

We have introduced X timers (negative numbers) to indicate Osmocom specific
timers, and reserve T timers for 3GPP specified ones. So now is still a good
chance to move this timer to the Osmocom X realm.

Remove a comment about this timer at an unrelated place. It is still described
at osmo_mgcpc_ep_alloc().

Change-Id: If097f52701fd81f29bcca1d252f4fb4fca8a04f7
2020-09-16 00:02:31 +02:00
Pau Espin Pedrol
de133113a0 mgw: osmux: Fix conn watchdog timeout not updated
It is currently done upon receival of RTP packets in rx_rtp for pure RTP
conns, but nothing similar is done for Osmux conns, which eventually
trigger a connection time out.

Change-Id: Id592d7db7b9399a497176e0d28cc826b3bce48c0
2020-09-08 17:51:45 +02:00
Pau Espin Pedrol
6d0a59a1bf mgw: Release endpoint after last conn times out
Otherwise some state is kept, like the previous CallId, which may then
provoke issues next time the endpoint is to be used.

Change-Id: I3ac4f4542c1c8c877127c64acce6c82b458f697f
2020-09-08 16:50:24 +02:00
Pau Espin Pedrol
2491401932 mgw: osmux: Avoid sending packets on recvonly connection
Change-Id: I87b1fb7d73cbbb2a5d4d8a40a9527a3e05d9947b
2020-09-08 12:57:35 +02:00
Pau Espin Pedrol
fbbe8f2f98 mgw: Announce and rebind new local address if change required during MDCX
MDCX may provide a new remote address, which means we may need to update
our announced IP addr and re-bind our local end. This can happen for
instance if MGW initially provided an IPv4 during CRCX ACK, and now MDCX
tells us the remote has an IPv6 address.

Change-Id: Iaed424e2c209e1753e1f579752fc684aaad7a512
2020-09-07 18:12:59 +02:00
Pau Espin Pedrol
71d42e778a mgw: Find and store RTP conn local_addr once during CRCX handling
It doesn't make sense to call the function several times since anyway we
are only binding during
allocate_port()->mgcp_bind_net_rtp_port()->bind_rtp()->mgcp_create_bind()->osmo_sock_init2().

Let's better calculate the local IP addr once and use that stored value.
THis is a previous step towards next commit updating the local IP addr
and re-bindng if encessary.

Change-Id: I803b99c5e5fe0f92a5bf6796d8c25df88d1608e6
2020-09-07 18:12:59 +02:00
Pau Espin Pedrol
8a2a1b22fe mgw: Introduce VTY cmd 'rtp bind-ip-v6' command
This commit allows for fully IPv6 systems to work fine. However, if a
remote endpoint still wants to use IPv4, it will fail since at this
point osmo-mgw still doesn't re-bind the local end of the connection to
an IPv4 after having initially bound it to an IPv6 one. This kind of
scenarios get fixed in next commits.

TODO: really bind the socket if a different IP address is requested.

Change-Id: I8ed94bd3f674f498e6ba315f44a351fff9c1be15
2020-09-07 18:12:59 +02:00
Pau Espin Pedrol
a790f0c082 mgw: Initial IPv6 support
This commit contains the bulky work of moving all address parsing to
support IPv6 together with IPv4.
Some specific patches required for full IPv6+IPv4 support requiring
behavioral changes come after this one.

Full Osmux IPv6 support is left out of the scope of this patch.

Depends: libosmocore.git Ie07a38b05b7888885dba4ae795e9f3d9a561543d (> 1.4.0)
Depends: libosmocore.git I59bf4b4b3ed14766a5a5285923d1ffa9fc8b2294 (> 1.4.0)
Change-Id: I504ca776d88fd852bbaef07060c125980db3fdd7
2020-09-07 18:12:59 +02:00
Pau Espin Pedrol
0ab152b2c6 mgw: Fix mgcp_rtp_end field description comment
Change-Id: Ieb044daaaa47572cd9a2524ea69e903200527d17
2020-09-07 15:55:30 +02:00
Pau Espin Pedrol
2741d6bb0e mgcp_client: copy back Connection Information from MDCX ACK
This is needed in case MGW changes the local IP address (for instance
because it initlaly offered an IPv4 address, and a client submitted a
remote IPv6 address, so MGW needs then to offer a local IPv6 address for
the RTP connection to be possible).

Change-Id: Ie964412b81fe6e10914790baaea724ca5f772adc
2020-09-07 15:55:30 +02:00
Pau Espin Pedrol
74d0e5c318 mgcp_client: Deprecate unused IPv4-only API
The API and related implementation fields are not used internally nor
externally, and only support IPv4. Let's simply deprecate the API and
drop all the uneeded implementation.

Change-Id: I905d4c4efabb6b4a4bc5c02e956808777243cadc
2020-09-07 15:55:30 +02:00
Pau Espin Pedrol
c4ef4a21c6 mgcp_client: Support validating IPv6 addresses in CRCX and MDCX commands
Change-Id: Ie97675f173dc3a223f6c2ced913906d760ffb732
2020-09-07 15:55:30 +02:00
Pau Espin Pedrol
ee2f33bf9a mgcp_client: Make MGCP_CLIENT_LOCAL_ADDR_DEFAULT IPv6 compatible
If "0.0.0.0", the default, is passed together with an IPv6 configured
address (ex: "mgw remote-ip ::1") in VTY, socket creation will fail due
to address version mismatch (because getaddrinfo() returns only an IPv4
address in the local result set).
If instead NULL is passed, then 2 entries are returned, one in IPv4 and
one in IPv6, and osmo_sock_init2 is smart enough to take one or another
when passed AF_UNSPEC.

Change-Id: I1be6f3b71486ce1782ba6b8c62f25145b42ec894
2020-09-07 15:55:30 +02:00
Pau Espin Pedrol
531470a0ca mgcp_client: Allow setting IPv6 addresses
Change-Id: I257218b2ad7cbdd0ac4ae7fa75802bed74ce983f
2020-09-07 15:55:30 +02:00
Pau Espin Pedrol
9dc73593a3 mgcp_client: Allow submitting and parsing IPv6 addr in SDP
Existing mgcp_client_test code required the '.' to trigger the same code
path, since with this commit we do extra checks and without a dot the
address is not accepted as IPv4 by osmo_ip_str_type().

Change-Id: I936bf57d37f5f0607dfe7fc66c37e424c3793f9b
2020-09-07 15:55:30 +02:00
Philipp Maier
ae6858bddf mgcp_trunk: increase default number of virtual endpoints
The VTY default for the number of endpoints is 32. This is sufficient
for small setups and lab testing, but for medium sized setupts the limit
might be reached soon. Lets increase the default to 512 virtual endpoints.

Change-Id: I55605ea083565b6950d0820e3f72c50c9dc19ffa
Related: OS#4711
2020-09-07 12:11:25 +02:00
Philipp Maier
99d4d368e8 mgcp_endp: use NUM_E1_TS from e1_input.h
do not introduce another define constant, use NUM_E1_TS as number of E1
timeslots.

Change-Id: I3bbfb6822d5595f9d243849141883490fa8037cb
2020-09-07 12:00:51 +02:00
Pau Espin Pedrol
8667d5169d mgcp_client: Use INET6_ADDRSTRLEN to store addresses in str format
Warning: This breaks libosmo-mgcp-cli ABI!

Related: SYS#4915
Change-Id: Ib778e9a72764103b52a462ea3c7fb56b23c1bcd6
2020-08-31 17:10:08 +02:00
Pau Espin Pedrol
1add5a53cb mgcp-client: Fix trailing whitespace in mgcp_client_fsm.h
Change-Id: Iad9ee764c1b6d7960a810a3eef95b207596e4796
2020-08-31 17:10:08 +02:00
Pau Espin Pedrol
729bf3e45a mgcp-client: Support IPv6 in osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr() implementation
Change-Id: Ibbfc1c2485636502dc0f3aef3922432cc7fd6170
2020-08-31 17:10:08 +02:00
Philipp Maier
2f34b53b5b mgcp_e1: remove unused struct member trunk->e1.line
The struct member trunk->e1.line is never set. Also it is always
possible to use e1inp_line_find() to get a pointer to the e1.line.
Lets remove it.

Change-Id: Id4ff52285917ce3885b8dad3a16270999c9da0aa
2020-08-31 16:21:03 +02:00
Philipp Maier
ad79f9eb99 mgcp_e1: make E1 ts initalization more debugable
The E1 timeslot initalization may fail silently in the last steps. There
is an error code returned, but no log lines are printed. This can make
debugging difficult.

Change-Id: I9aab17fc1ba6666c81b14035a8f1f17e5a55adaf
2020-08-31 16:21:03 +02:00
Harald Welte
9e494e67c7 Add example osmo-mgw configuration file for Abis/E1
In this example, we are using the first span (0) of the first DAHDI card
and use it as 'trunk 1' in the MGW.

Change-Id: I0a97da5163a94379b327403b1258696855836bad
2020-08-28 15:00:32 +02:00
Alexander Couzens
5322473d04 configure.ac: require libosmoabis + libosmotrau >= 1.0.0
Since osmo-mgw supports trau frames it requries a newer version.
The spec file already requires those newer version.

Change-Id: If6c7ecdde09c6e09ded7e0959b7765a01a31d702
2020-08-21 18:37:42 +02:00
Pau Espin Pedrol
c57ad7ff9a cosmetic: Rename main talloc ctx
It contained name from a different program, probably due to main.c being
copied over during project start.

Change-Id: I4bfa40eec0277705f5d3335d779bff35518470a8
2020-08-20 08:43:52 +00:00
Pau Espin Pedrol
c59b5c533d Support setting rt-prio and cpu-affinity mask through VTY
Change-Id: Icfafea073a0cdac289a651d61632b4c6af39c6a9
Depends: libosmocore.git Change-Id If76a4bd2cc7b3c7adf5d84790a944d78be70e10a
Depends: osmo-gsm-masnuals.git Change-Id Icd75769ef630c3fa985fc5e2154d5521689cdd3c
Related: SYS#4986
2020-08-20 08:43:52 +00:00
Philipp Maier
0653cc8a7c mgcp_trunk: drop "trunk 0" limitation
Due to the internal handling of the trunks it was not possible to allow
an E1 trunk that has the ID 0. However this limitation is no longer
present, so we now can allow an E1 trunk with ID 0.

Change-Id: I302c2007628f607033686e277c407232351e66ad
Related: OS#2659
2020-08-20 06:21:41 +00:00
Philipp Maier
246233d0d4 cosmetic: add missing new-line
Change-Id: I4a4a7515e8d92ab39576c33765dd3dc581453ceb
2020-08-18 20:11:38 +02:00
Philipp Maier
a910a81b7c mgcp_protocol: log when endpoint is unavailable
When endpoints become unavailable when MDCX/CRCX/DLCX are executed on
them a major problem may be the cause, lets make sure that those events
are logged.

Change-Id: I059b7e29f960e75a53bfb5dfb2b83ab3d79e84f3
2020-08-18 20:11:11 +02:00
Philipp Maier
c8acee2234 mgcp_e1: use return value of e1inp_line_update()
The function e1inp_line_update() is called without assigning its return
code to the rc variable.

Change-Id: Ia72ea2dca210b038766151d547f66b7b7139a2c4
Fixes: CID#212160
2020-08-15 07:43:38 +00:00
Harald Welte
55863e42c1 osmo-mgw.spec.in: Add missing dependency to libosmotrau
Change-Id: I2d5f8b1d852079b8f82adb681d7e6b72a8358cf1
2020-08-14 09:48:35 +02:00
Vadim Yanitskiy
6177cae2a2 debian/control: change maintainer to the Osmocom team / mailing list
Change-Id: I1bb002b257d4bef83d181d615411e443c1831f00
2020-08-13 16:09:02 +07:00
Harald Welte
6af3ccf65d osmo-mgw.spec.in: Fix dependency to libosmoabis
Confusingly, in Debian the package is called libosmo-abis, but in
the CentOS/RPM it's called libosmoabis.  Fixes a bug introduced
in I45717bda3ef7eba1ef59b993cc8a69bf2f92a29f

Change-Id: I97dfec72a99295148e84e60c1e5037381f736c03
2020-08-13 09:35:12 +02:00
Harald Welte
03cb5f3397 debian/control + SPEC: Add missing build dependency to libosmo-abis
In I6b93809b5ac7d01af55888347dd787b0bc997ae1 we introduced E1 support
to osmo-mgw, but failed to add it to the build dependencies of the
Debian packages, making network:osmocmo:nightly builds fail.

Change-Id: I45717bda3ef7eba1ef59b993cc8a69bf2f92a29f
2020-08-13 07:28:55 +02:00
44 changed files with 1481 additions and 552 deletions

1
.gitignore vendored
View File

@@ -16,6 +16,7 @@ src/osmo-mgw/osmo-mgw
*.gcda
*.gcno
*.pc
*~
#configure
aclocal.m4

View File

@@ -9,6 +9,8 @@ AC_CONFIG_AUX_DIR([.])
AM_INIT_AUTOMAKE([dist-bzip2])
AC_CONFIG_TESTDIR(tests)
CFLAGS="$CFLAGS -std=gnu11"
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -47,13 +49,13 @@ AC_SEARCH_LIBS([dlsym], [dl dld], [LIBRARY_DLSYM="$LIBS";LIBS=""])
AC_SUBST(LIBRARY_DLSYM)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 0.6.0)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.5.0)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.1.0)
PKG_CHECK_MODULES(LIBOSMOTRAU, libosmotrau >= 1.1.0)
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(

View File

@@ -36,7 +36,6 @@ osmo-build-dep.sh libosmo-netif
# Additional configure options and depends
CONFIG=""
if [ "$WITH_MANUALS" = "1" ]; then
osmo-build-dep.sh osmo-gsm-manuals
CONFIG="--enable-manuals"
fi
@@ -56,12 +55,12 @@ LD_LIBRARY_PATH="$inst/lib" $MAKE check \
|| cat-testlogs.sh
LD_LIBRARY_PATH="$inst/lib" \
DISTCHECK_CONFIGURE_FLAGS="--enable-vty-tests --enable-external-tests $CONFIG" \
$MAKE distcheck \
$MAKE $PARALLEL_MAKE distcheck \
|| cat-testlogs.sh
if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
make -C "$base/doc/manuals" publish
fi
$MAKE maintainer-clean
$MAKE $PARALLEL_MAKE maintainer-clean
osmo-clean-workspace.sh

View File

@@ -29,28 +29,30 @@ BuildRequires: pkgconfig >= 0.20
%if 0%{?suse_version}
BuildRequires: systemd-rpm-macros
%endif
BuildRequires: pkgconfig(libosmo-netif) >= 0.6.0
BuildRequires: pkgconfig(libosmocore) >= 1.0.0
BuildRequires: pkgconfig(libosmoctrl) >= 1.1.0
BuildRequires: pkgconfig(libosmogsm) >= 1.0.0
BuildRequires: pkgconfig(libosmovty) >= 1.0.0
BuildRequires: pkgconfig(libosmocoding) >= 1.0.0
BuildRequires: pkgconfig(libosmo-netif) >= 1.1.0
BuildRequires: pkgconfig(libosmocore) >= 1.5.0
BuildRequires: pkgconfig(libosmoctrl) >= 1.5.0
BuildRequires: pkgconfig(libosmogsm) >= 1.5.0
BuildRequires: pkgconfig(libosmovty) >= 1.5.0
BuildRequires: pkgconfig(libosmocoding) >= 1.5.0
BuildRequires: pkgconfig(libosmoabis) >= 1.1.0
BuildRequires: pkgconfig(libosmotrau) >= 1.1.0
%{?systemd_requires}
%description
OsmoMGW is Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks.
%package -n libosmo-mgcp-client6
%package -n libosmo-mgcp-client8
Summary: Osmocom's Media Gateway Control Protocol client library
Group: System/Libraries
%description -n libosmo-mgcp-client6
%description -n libosmo-mgcp-client8
Osmocom's Media Gateway Control Protocol client library.
%package -n libosmo-mgcp-client-devel
Summary: Development files for Osmocom's Media Gateway Control Protocol client library
Group: Development/Libraries/C and C++
Requires: libosmo-mgcp-client6 = %{version}
Requires: libosmo-mgcp-client8 = %{version}
%description -n libosmo-mgcp-client-devel
Osmocom's Media Gateway Control Protocol client librarary.
@@ -88,8 +90,8 @@ find %{buildroot} -type f -name "*.la" -delete -print
%check
make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%post -n libosmo-mgcp-client6 -p /sbin/ldconfig
%postun -n libosmo-mgcp-client6 -p /sbin/ldconfig
%post -n libosmo-mgcp-client8 -p /sbin/ldconfig
%postun -n libosmo-mgcp-client8 -p /sbin/ldconfig
%if 0%{?suse_version}
%preun
@@ -111,12 +113,13 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%dir %{_docdir}/%{name}/examples
%dir %{_docdir}/%{name}/examples/osmo-mgw
%{_docdir}/%{name}/examples/osmo-mgw/osmo-mgw.cfg
%{_docdir}/%{name}/examples/osmo-mgw/osmo-mgw-abis_e1.cfg
%{_bindir}/osmo-mgw
%{_unitdir}/osmo-mgw.service
%dir %{_sysconfdir}/osmocom
%config(noreplace) %{_sysconfdir}/osmocom/osmo-mgw.cfg
%files -n libosmo-mgcp-client6
%files -n libosmo-mgcp-client8
%{_libdir}/libosmo-mgcp-client.so.6*
%files -n libosmo-mgcp-client-devel

160
debian/changelog vendored
View File

@@ -1,3 +1,163 @@
osmo-mgw (1.8.0) unstable; urgency=medium
[ Harald Welte ]
* Fix number of endpoints of default trunk
* Add CTRL interface to osmo-mgw
* Update per-trunk global packet/byte counters in real-time
* remove accidential TODO-RELEASE entry
* mgcp_protocol: Avoid code duplication between virtual + other trunks
* osmo-mgw.spec.in: Use %config(noreplace) to retain current config file
* mgcp_client_init(): consider "talloc returns NULL" case
* mgcp_client_pending_add(): Consider "talloc returns NULL" case
* libosmo-mgcp-client: fix memleak in case if no response is received
* debian/control + SPEC: Add missing build dependency to libosmo-abis
* osmo-mgw.spec.in: Fix dependency to libosmoabis
* osmo-mgw.spec.in: Add missing dependency to libosmotrau
* Add example osmo-mgw configuration file for Abis/E1
* use osmo_fd_setup() whenever applicable
[ Neels Hofmeyr ]
* fix vty dump_trunk: start from zero, do not omit first CONN
* allow larger MGCP client wqueue: 10 -> 1024
* add osmo-mgw --vty-ref-xml: dump VTY ref XML to stdout
* manuals: generate vty reference xml at build time
* refactor: use msgb to receive, pass and send RTP packets
* change timer T2427001 to X2427
[ Philipp Maier ]
* doc: do not bind osmo-mgw to random ip-address
* cosmetic: remove excess newlines
* mgcp: remove unused callback pointer
* mgcp: find better locations for LOGPCONN and LOGPENDP
* vty: fix unreachable code (error msg on trunk alloc fail)
* mgcp_vty: fix indentation
* osmo-mgw: rename struct mgcp_trunk_config and symbol tcfg
* mgcp_vty: fix indentation in VTY config write
* osmo-mgw: refactor endpoint and trunk handling
* mgcp_trunk: remove audio_name and audio_payload
* ratectr: move rate counter definitions into mgcp_ratectr.h
* cosmetic: fix doxygen
* cosmetic: fix doxygen
* cosmetic: fix doxygen for mgcp_cleanup_rtp_bridge_cb()
* trunk: get rid of virt_trunk pointer
* cosmetic: remove excess space
* endp: move endpoint name generation into mgcp_endp.c
* endp: add name generator function for E1 endpoints
* mgcp_client: add docstring for mgcp_client_rtpbridge_wildcard()
* mgcp_trunk: fix docstring for mgcp_trunk_alloc()
* mgcp_osmux: remove unused define constants
* mgcp_trunk: move enum mgcp_trunk_type to mgcp_trunk.h
* mgcp_trunk: use enum type for trunk type variable
* trunk: parse E1 trunk number
* endp: add typeset for e1-endpoints
* mgcp_conn: move struct mgcp_conn mgcp_conn.h
* mgcp_internal: remove forward declaration struct mgcp_endpoint_type
* endp: add E1 endpoint interlocking
* endp: require domain name also for E1 endpoints
* mgcp_trunk: pick trunk by number and type
* mgcp_client: add function to generate e1-endpoint names
* mgcp_endp: use define constant to define max number of E1 subslots
* mgcp_endp.c: cosmetic: fix sourcecode formatting
* mgcp_trunk: remove double check
* mgcp_test: do not access endpoint array elements directly
* mgcp_vty: fix endpoint number configuration
* mgcp_test: remove trunk2 from unit-test
* mgcp_trunk: use talloc_zero_array instead of _talloc_zero_array
* mgcp_protocol: remove unused variable
* mgcp_e1: finish E1 support, add E1 support from libosmoabis
* get rid of mgcp_internal.h
* mgcp_ratectr: fix comments in header file
* mgcp_e1: use return value of e1inp_line_update()
* mgcp_protocol: log when endpoint is unavailable
* cosmetic: add missing new-line
* mgcp_trunk: drop "trunk 0" limitation
* mgcp_e1: make E1 ts initalization more debugable
* mgcp_e1: remove unused struct member trunk->e1.line
* mgcp_endp: use NUM_E1_TS from e1_input.h
* mgcp_trunk: increase default number of virtual endpoints
* cosmetic: mgcp_client_fsm: change error message.
* mgcp_vty: remove remains of loopback functionality
* mgcp_vty: deprecate bind early command
* mgcp_e1: do not expose function mgcp_e1_init()
* mgcp_vty: add user attributes to configuration commands
* overview: update section limitations.
* overview: fix graph "OsmoMGW used with OsmoBSC"
* overview: fix graph "OsmoMGW used with OsmoMSC"
* overview: add graph to show E1 integration
* configuration: remove hint towards trunk 0 limit
* configuration: drop note about lackin E1 support
* configuration: add note that changes to trunks need a restart
* mgcp_vty: fix config write for trunk 0
* mgcp_vty: add missing VTY commands for E1 trunks
* mgcp_trunk: get rid of magic numbers for E1 slots
* configuration: add section about E1 trunks
* usermanual: add chapter about mgcp endpoints
* mgcp_client: get rid of magic numbers for E1 slots
[ Eric ]
* tests: dlopen does not imply availability of dlsym..
* configure.ac: fix libtool issue with clang and sanitizer
[ Alexander Chemeris ]
* vty: Prepend VTY output of counters for better visual separation.
* counters: Implement more useful counters.
* mgcp_network: Fix a typo in the comment bahviour -> behaviour
* rtp_bridge: Demote a chatty ERROR log message to DEBUG level.
[ Pau Espin Pedrol ]
* Use OSMO_FD_* instead of deprecated BSC_FD_*
* Support setting rt-prio and cpu-affinity mask through VTY
* cosmetic: Rename main talloc ctx
* mgcp-client: Support IPv6 in osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr() implementation
* mgcp-client: Fix trailing whitespace in mgcp_client_fsm.h
* mgcp_client: Use INET6_ADDRSTRLEN to store addresses in str format
* mgcp_client: Allow submitting and parsing IPv6 addr in SDP
* mgcp_client: Allow setting IPv6 addresses
* mgcp_client: Make MGCP_CLIENT_LOCAL_ADDR_DEFAULT IPv6 compatible
* mgcp_client: Support validating IPv6 addresses in CRCX and MDCX commands
* mgcp_client: Deprecate unused IPv4-only API
* mgcp_client: copy back Connection Information from MDCX ACK
* mgw: Fix mgcp_rtp_end field description comment
* mgw: Initial IPv6 support
* mgw: Introduce VTY cmd 'rtp bind-ip-v6' command
* mgw: Find and store RTP conn local_addr once during CRCX handling
* mgw: Announce and rebind new local address if change required during MDCX
* mgw: osmux: Avoid sending packets on recvonly connection
* mgw: Release endpoint after last conn times out
* mgw: osmux: Fix conn watchdog timeout not updated
* mgw: Don't be case-sensitive when parsing X-Osmo-IGN param
* cosmetic: Fix typo in comment
* mgw: Avoid logging notice message each time we receive nt param in LCO
* mgw: Fix return value documentation for API mgcp_verify_call_id
* cosmetic: Fix typo in comment
* contrib/jenkins: Enable parallel make in make distcheck
* .gitignore: Ignore new autofoo tmp files
* tests: Replace deprecated API log_set_print_filename
[ Oliver Smith ]
* contrib: import RPM spec
* contrib: integrate RPM spec
* Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
* contrib/jenkins: don't build osmo-gsm-manuals
* configure.ac: set -std=gnu11
[ Vadim Yanitskiy ]
* libosmo-mgcp-client: fix use-after-free in mgcp_client_tx()
* libosmo-mgcp-client: fix use-after-free in mgcp_msg_gen()
* libosmo-mgcp: fix unsigned compared against 0 in mgcp_trunk_by_name()
* libosmo-mgcp: fix unused extra argument to printf() in add_fmtp()
* libosmo-mgcp: always check result of msgb_printf() in add_fmtp()
* libosmo-mgcp-client: mgcp_client_tx(): return rc on error
* debian/control: change maintainer to the Osmocom team / mailing list
* vty: use install_lib_element() and install_lib_element_ve()
* main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
* fixup mgcp_trunk: increase default number of virtual endpoints
[ Alexander Couzens ]
* configure.ac: require libosmoabis + libosmotrau >= 1.0.0
-- Pau Espin Pedrol <pespin@sysmocom.de> Tue, 23 Feb 2021 18:28:45 +0100
osmo-mgw (1.7.0) unstable; urgency=medium
[ Neels Hofmeyr ]

13
debian/control vendored
View File

@@ -1,14 +1,15 @@
Source: osmo-mgw
Section: net
Priority: extra
Maintainer: Alexander Couzens <lynxis@fe80.eu>
Maintainer: Osmocom team <openbsc@lists.osmocom.org>
Build-Depends: debhelper (>=9),
dh-autoreconf,
pkg-config,
autotools-dev,
libosmocore-dev,
libosmo-netif-dev,
osmo-gsm-manuals-dev
libosmocore-dev (>= 1.5.0),
libosmo-netif-dev (>= 1.1.0),
libosmo-abis-dev (>= 1.1.0),
osmo-gsm-manuals-dev (>= 1.1.0)
Standards-Version: 3.9.8
Vcs-Git: git://git.osmocom.org/osmo-mgw.git
Vcs-Browser: https://git.osmocom.org/osmo-mgw/
@@ -20,7 +21,7 @@ Multi-Arch: foreign
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: OsmoMGW: Osmocom's Media Gateway for 2G and 3G circuit-switched mobile networks
Package: libosmo-mgcp-client6
Package: libosmo-mgcp-client8
Section: libs
Architecture: any
Multi-Arch: same
@@ -32,7 +33,7 @@ Package: libosmo-mgcp-client-dev
Section: libdevel
Architecture: any
Multi-Arch: same
Depends: libosmo-mgcp-client6 (= ${binary:Version}), ${misc:Depends}
Depends: libosmo-mgcp-client8 (= ${binary:Version}), ${misc:Depends}
Description: libosmo-mgcp-client: Osmocom's Media Gateway Control Protocol client utilities
Package: osmo-mgw-doc

View File

@@ -2,3 +2,4 @@ etc/osmocom/osmo-mgw.cfg
lib/systemd/system/osmo-mgw.service
usr/bin/osmo-mgw
usr/share/doc/osmo-mgw/examples/osmo-mgw/osmo-mgw.cfg
usr/share/doc/osmo-mgw/examples/osmo-mgw/osmo-mgw-abis_e1.cfg

View File

@@ -0,0 +1,25 @@
!
! MGCP configuration example
!
e1_input
e1_line 0 driver dahdi
e1_line 0 port 0
mgcp
bind ip 127.0.0.1
rtp port-range 4002 16000
rtp bind-ip 127.0.0.1
rtp ip-probing
rtp ip-tos 184
bind port 2427
sdp audio payload number 98
sdp audio payload name GSM
number endpoints 512
loop 0
force-realloc 1
rtcp-omit
rtp-patch ssrc
rtp-patch timestamp
trunk 1
rtp keep-alive once
no rtp keep-alive
line 0

View File

@@ -10,7 +10,7 @@ mgcp
bind port 2427
sdp audio payload number 98
sdp audio payload name GSM
number endpoints 31
number endpoints 512
loop 0
force-realloc 1
rtcp-omit

View File

@@ -23,14 +23,13 @@ OsmoMGW(config-mgcp)# local ip 127.0.0.1
=== Configuring the trunk
The first trunk (trunk 0) is considered a virtual trunk in OsmoMGW. All
The first trunk is considered a virtual trunk in OsmoMGW. All
endpoints of type "rtpbridge" are routed here. The virtual trunk is configured
in the config-mgcp context.
All other trunks are configured in the config-mgcp-trunk context, but the
commands used are identical. Right now trunks are considered only for ds/e1
type endpoints which are not yet implemented. Don't use trunks other than the
"virtual" trunk 0.
commands used are identical. Right now trunks are considered only for "ds/e1"
type endpoints.
.Example: MGCP trunk configuration
----
@@ -54,4 +53,72 @@ OsmoMGW(config-mgcp)# rtp-patch timestamp <3>
<2> Hide SSRC changes
<3> Ensure RTP timestamp is aligned with frame duration
NOTE: Changes to trunks that affect resource allocation, such as newly created
trunks or a change of the number of available endpoints, require a full restart
of osmo-mgw!
=== E1 trunk considerations
While the RTP bridge trunks are natively based on IP no special considerations
are required during setup. E1 trunks are mapped on a physical E1 line, which has
to be configured as shown below.
.Example: E1 line setup
----
OsmoMGW(config-e1_input)# e1_line 0 driver dahdi <1>
OsmoMGW(config-e1_input)# e1_line 0 port 2 <2>
----
<1> Name of the libosmo-abis driver implementation ("dahdi")
<2> Port number of the physical E1 port to use (2)
In osmo-mgw the e1_input node is used to configure the physical E1 line. The
line number will be used internally to identify the configured E1 line. The
port number is the physical E1 connector (sometimes called 'span') at the E1
hardware. Per trunk an individual E1 line will be needed. Beware that the E1
driver may also need configuration settings that are not discussed here.
.Example: E1 trunk setup
----
OsmoMGW(config-mgcp)# trunk 0 <1>
OsmoMGW(config-mgcp-trunk)# line 0 <2>
----
<1> Creation of a trunk (0)
<2> Reference to the E1 line to use (0)
The E1 trunk is created along with a number, typically starting at 0, but if
required any number from 0-64 is allowed. The E1 trunk configuration concerning
the IP related aspects is nearly identical to the configuration of the virtual
trunk. However, it is important that the user assigns one of the E1 line numbers
that were configured under the e1_input node.
.Example: A typical configuration with one E1 trunk
----
e1_input
e1_line 0 driver dahdi
e1_line 0 port 2
mgcp
bind ip 127.0.0.1
rtp net-range 6000 6011
rtp net-bind-ip 192.168.100.130
rtp ip-probing
rtp ip-tos 184
no rtp keep-alive
bind port 2428
number endpoints 30
loop 0
force-realloc 1
osmux off
rtp-patch rfc5993hr
trunk 0
rtp keep-alive once
no rtp keep-alive
line 0
----
NOTE: One E1 trunk always covers a whole E1 line. All subslots (I.640) will be mapped
to individual MGCP endpoints. As long as the endpoints remain unused the
underlying E1 timeslot is not used.
NOTE: The E1 trunk implementation also works with T1 lines, however since T1 has
24 instead of 31 usable timeslots only the endpoints that fall into that 1-24 timeslot
range will be useable.

View File

@@ -0,0 +1,94 @@
== MGCP Endpoints
MGCP organizes the switching resources in so called endpoints. Each endpoint is
referenced by its unique identifier. While RFC 3435 specifies a naming scheme, the
actual identifier naming is subject to the implementation and configuration.
=== RTP proxy / RTP bridge endpoints
OsmoMGW implements a freely configurable number of `rtpbridge` endpoints. Those
endpoints are able to host two connections at a time to model the functionality
of a tandem switch.
RTP bridge endpoint identifiers are referenced by the string `rtpbridge/`, a
hexadecimal number without leading zeros and a domain name (configurable).
----
rtpbridge/<number>@<domain>
----
.Example: List of virtual endpoints
----
rtpbridge/1@mgw
rtpbridge/2@mgw
rtpbridge/3@mgw
rtpbridge/4@mgw
rtpbridge/5@mgw
rtpbridge/6@mgw
rtpbridge/7@mgw
rtpbridge/8@mgw
rtpbridge/9@mgw
rtpbridge/a@mgw
rtpbridge/b@mgw
rtpbridge/c@mgw
rtpbridge/d@mgw
rtpbridge/e@mgw
rtpbridge/f@mgw
rtpbridge/10@mgw
----
=== E1/T1 endpoints
OsmoMGW supports E1 subslot multiplexing as specified by I.460. All possible
subslot combinations are mapped on individual endpoints. The endpoint names
are prefixed with `ds/e1-` followed by the trunk number and the E1 timeslot.
The subslot is defined by a bit rate and a bit offset.
----
ds/e1-<trunk>/s-<timeslot>/su<bitrate>-<bitoffset>@<domain>
----
.Example: List of endpoints on E1 trunk 0 at E1 timeslot 2
----
ds/e1-0/s-2/su64-0@mgw
ds/e1-0/s-2/su32-0@mgw
ds/e1-0/s-2/su32-4@mgw
ds/e1-0/s-2/su16-0@mgw
ds/e1-0/s-2/su16-2@mgw
ds/e1-0/s-2/su16-4@mgw
ds/e1-0/s-2/su16-6@mgw
ds/e1-0/s-2/su8-0@mgw
ds/e1-0/s-2/su8-1@mgw
ds/e1-0/s-2/su8-2@mgw
ds/e1-0/s-2/su8-3@mgw
ds/e1-0/s-2/su8-4@mgw
ds/e1-0/s-2/su8-5@mgw
ds/e1-0/s-2/su8-6@mgw
ds/e1-0/s-2/su8-7@mgw
----
When creating connections on endpoints that reside in one E1 timeslot the call
agent must make sure that no overlapping endpoints are used. It is for example
not possible to use `ds/e1-0/s-2/su16-2@mgw` and `ds/e1-0/s-2/su8-3@mgw` at the
same time because they overlap.
.Subslot overlapping
[options="header"]
|===
| Bit offset 4+| Subslots
| 0 | 8k .2+| 16k .4+| 32k .8+| 64k
| 1 | 8k
| 2 | 8k .2+| 16k
| 3 | 8k
| 4 | 8k .2+| 16k .4+| 32k
| 5 | 8k
| 6 | 8k .2+| 16k
| 7 | 8k
|===
NOTE: The current implementation (December 2020) only implements TRAU frame
encoding/decoding for 16K and 8K subslots. Endpoints with other bitrates are
not yet useable.
NOTE: the VTY command "show mgcp" can be used to get a list of all available
endpoints (including identifiers)

View File

@@ -21,10 +21,10 @@ Protocol.
digraph G {
rankdir = LR;
OsmoBTS -> OsmoBSC [label="Abis/IP"];
OsmoBSC -> OsmoMSC [label="3GPP AoIP"];
OsmoBSC -> "core-network" [label="3GPP AoIP"];
OsmoBSC -> OsmoMGW [label="MGCP"];
OsmoBTS -> OsmoMGW [label="RTP",dir=both];
OsmoMGW -> OsmoMSC [label="RTP",dir=both];
OsmoMGW -> "core-network" [label="RTP",dir=both];
{rank=same OsmoBSC OsmoMGW}
OsmoMGW [color=red];
}
@@ -36,10 +36,9 @@ digraph G {
----
digraph G {
rankdir = LR;
BTS -> BSC [label="Abis"];
BSC -> OsmoMSC [label="3GPP AoIP"];
"2G BSS" -> OsmoMSC [label="3GPP AoIP"];
OsmoMSC -> OsmoMGW [label="MGCP"];
BSC -> OsmoMGW [label="RTP",dir=both];
"2G BSS" -> OsmoMGW [label="RTP",dir=both];
OsmoMSC -> OsmoSIP [label="MNCC"];
OsmoSIP -> PBX [label="SIP Trunk"];
OsmoMGW -> PBX [label="RTP",dir=both];
@@ -53,6 +52,22 @@ digraph G {
}
----
[[fig-bsc]]
.Integration of legacy E1 BTS in AoIP network
[graphviz]
----
digraph G {
rankdir = LR;
BTS -> OsmoBSC [label="Abis/E1"];
OsmoBSC -> "core-network" [label="3GPP AoIP"];
OsmoBSC -> OsmoMGW [label="MGCP"];
BTS -> OsmoMGW [label="TRAU/E1",dir=both];
OsmoMGW -> "core-network" [label="RTP",dir=both];
{rank=same OsmoBSC OsmoMGW}
OsmoMGW [color=red];
}
----
=== Software Components
OsmoMGW contains a variety of different software components, which well
@@ -77,14 +92,14 @@ Transcoding is currently not supported in OsmoMGW.
=== Limitations
Osmux is not yet supported in OsmoMGW.
At the moment (July 2018), OsmoMGW only implements RTP proxy / RTP bridge
type endpoints, to each of which two RTP connections can be established.
We are planning to add endpoint types for:
At the moment (November 2020), OsmoMGW implements RTP proxy / RTP bridge
type endpoints and E1/T1 16k/8k sub-slots with TRAU frames for classic BTS
support. To the RTP proxy / RTP bridge endpoints two RTP connections can
be established, which then work as a tandem. E1/T1 endpoints support one
RTP connection at a time that is associated with a sub-slot on an E1 line.
We are planning to add further endpoint types for:
- classic E1/T1 timeslots (64kBps alaw/ulaw)
- classic E1/T1 16k sub-slots with TRAU frames for classic BTS support
- announcement/playout end-points
- conference endpoints

View File

@@ -18,12 +18,16 @@ include::./common/chapters/logging.adoc[]
include::{srcdir}/chapters/configuration.adoc[]
include::{srcdir}/chapters/mgcp_endpoints.adoc[]
include::{srcdir}/chapters/mgcp_extensions.adoc[]
include::./common/chapters/osmux/osmux.adoc[]
//include::{srcdir}/chapters/counters.adoc[]
include::./common/chapters/vty_cpu_sched.adoc[]
include::./common/chapters/port_numbers.adoc[]
include::./common/chapters/bibliography.adoc[]

View File

@@ -23,6 +23,7 @@
#pragma once
#include <osmocom/core/msgb.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/write_queue.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/logging.h>
@@ -94,7 +95,8 @@ typedef void (*mgcp_get_format)(struct mgcp_endpoint *endp,
*/
struct mgcp_port_range {
/* addr or NULL to fall-back to default */
char *bind_addr;
char *bind_addr_v4;
char *bind_addr_v6;
/* dynamically allocated */
int range_start;
@@ -207,4 +209,4 @@ int mgcp_send_reset_all(struct mgcp_config *cfg);
int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port);
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len);
int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, char *buf, int len);

View File

@@ -21,7 +21,6 @@
static const uint8_t e1_rates[] = { 64, 32, 32, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8 };
static const uint8_t e1_offsets[] = { 0, 0, 4, 0, 2, 4, 6, 0, 1, 2, 3, 4, 5, 6, 7 };
int mgcp_e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr);
int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8_t offs);
void mgcp_e1_endp_update(struct mgcp_endpoint *endp);
void mgcp_e1_endp_release(struct mgcp_endpoint *endp);

View File

@@ -26,7 +26,7 @@
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/i460_mux.h>
struct sockaddr_in;
struct sockaddr;
struct mgcp_conn;
struct mgcp_conn_rtp;
struct mgcp_endpoint;
@@ -42,7 +42,7 @@ LOGP(cat, level, "endpoint:%s " fmt, \
struct osmo_rtp_msg_ctx {
int proto;
struct mgcp_conn_rtp *conn_src;
struct sockaddr_in *from_addr;
struct osmo_sockaddr *from_addr;
};
#define OSMO_RTP_MSG_CTX(MSGB) ((struct osmo_rtp_msg_ctx*)(MSGB)->cb)
@@ -139,3 +139,5 @@ struct mgcp_endpoint *mgcp_endp_by_name_trunk(int *cause, const char *epname,
struct mgcp_endpoint *mgcp_endp_by_name(int *cause, const char *epname,
struct mgcp_config *cfg);
bool mgcp_endp_avail(struct mgcp_endpoint *endp);
void mgcp_endp_add_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn);
void mgcp_endp_remove_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn);

View File

@@ -2,6 +2,9 @@
#include <inttypes.h>
#include <stdbool.h>
#include <osmocom/core/socket.h>
#include <osmocom/mgcp/mgcp.h>
#define MGCP_DUMMY_LOAD 0x23
@@ -78,8 +81,8 @@ struct mgcp_rtp_codec {
/* 'mgcp_rtp_end': basically a wrapper around the RTP+RTCP ports */
struct mgcp_rtp_end {
/* local IP address of the RTP socket */
struct in_addr addr;
/* remote IP address of the RTP socket */
struct osmo_sockaddr addr;
/* in network byte order */
int rtp_port, rtcp_port;
@@ -115,18 +118,21 @@ struct mgcp_rtp_end {
/* local UDP port number of the RTP socket; RTCP is +1 */
int local_port;
/* where the endpoint RTP connection binds to, set during CRCX and
* possibly updated during MDCX */
char local_addr[INET6_ADDRSTRLEN];
};
struct mgcp_rtp_tap {
/* is this tap active (1) or not (0) */
int enabled;
/* IP/port to which we're forwarding the tapped data */
struct sockaddr_in forward;
struct osmo_sockaddr forward;
};
struct mgcp_conn;
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr,
struct msgb *msg, struct mgcp_conn_rtp *conn_src,
struct mgcp_conn_rtp *conn_dst);
int mgcp_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn);
@@ -140,7 +146,7 @@ void mgcp_free_rtp_port(struct mgcp_rtp_end *end);
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr, struct msgb *msg);
struct osmo_sockaddr *addr, struct msgb *msg);
void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn);
int mgcp_set_ip_tos(int fd, int tos);

View File

@@ -1,6 +1,7 @@
#pragma once
#include <osmocom/gsm/i460_mux.h>
#include <osmocom/abis/e1_input.h>
#define LOGPTRUNK(trunk, cat, level, fmt, args...) \
LOGP(cat, level, "trunk:%u " fmt, \
@@ -24,7 +25,6 @@ struct mgcp_trunk {
char *audio_fmtp_extra;
int audio_send_ptime;
int audio_send_name;
int audio_loop;
int no_audio_transcoding;
@@ -60,9 +60,11 @@ struct mgcp_trunk {
/* E1 specific */
struct {
unsigned int vty_line_nr;
struct e1inp_line *line;
bool ts_in_use[31];
struct osmo_i460_timeslot i460_ts[31];
bool ts_in_use[NUM_E1_TS-1];
struct osmo_i460_timeslot i460_ts[NUM_E1_TS-1];
/* Note: on an E1 line TS 0 is devoted to framing and
* alignment and therefore only NUM_E1_TS-1 timeslots
* are available for traffic. */
} e1;
};
};

View File

@@ -1,5 +1,6 @@
#pragma once
#include <osmocom/core/socket.h>
#include <osmocom/netif/osmux.h>
struct mgcp_conn_rtp;
@@ -13,7 +14,7 @@ enum {
int osmux_init(int role, struct mgcp_config *cfg);
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
struct in_addr *addr, uint16_t port);
struct osmo_sockaddr *addr, uint16_t port);
void conn_osmux_disable(struct mgcp_conn_rtp *conn);
int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid);
void conn_osmux_release_cid(struct mgcp_conn_rtp *conn);

View File

@@ -6,3 +6,7 @@ enum mgcp_vty_node {
MGCP_NODE = _LAST_OSMOVTY_NODE + 1,
TRUNK_NODE,
};
enum mgw_vty_cmd_attr {
MGW_CMD_ATTR_NEWCONN = 0,
};

View File

@@ -6,7 +6,7 @@
#include <osmocom/mgcp_client/mgcp_common.h>
/* See also: RFC 3435, chapter 3.5 Transmission over UDP */
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT "0.0.0.0"
#define MGCP_CLIENT_LOCAL_ADDR_DEFAULT NULL /* INADDR(6)_ANY */
#define MGCP_CLIENT_LOCAL_PORT_DEFAULT 2727
#define MGCP_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
#define MGCP_CLIENT_REMOTE_PORT_DEFAULT 2427
@@ -75,7 +75,7 @@ struct mgcp_response {
char *body;
struct mgcp_response_head head;
uint16_t audio_port;
char audio_ip[INET_ADDRSTRLEN];
char audio_ip[INET6_ADDRSTRLEN];
unsigned int ptime;
enum mgcp_codecs codecs[MGCP_MAX_CODECS];
unsigned int codecs_len;
@@ -133,7 +133,7 @@ int mgcp_client_connect(struct mgcp_client *mgcp);
const char *mgcp_client_remote_addr_str(struct mgcp_client *mgcp);
uint16_t mgcp_client_remote_port(struct mgcp_client *mgcp);
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp);
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp) OSMO_DEPRECATED("deprecated, returns 0");
const char *mgcp_client_endpoint_domain(const struct mgcp_client *mgcp);
const char *mgcp_client_rtpbridge_wildcard(const struct mgcp_client *mgcp);

View File

@@ -8,14 +8,14 @@
* (either remote or local). It is used to pass parameters (local) to the FSM
* and get responses (remote) from the FSM as pointer attached to the FSM
* event.
*
*
* When modifiying a connection, the endpoint and call_id members may be left
* unpopulated. The call_id field is ignored in this case. If an endpoint
* identifier is supplied it is checked against the internal state to make
* sure it is correct. */
struct mgcp_conn_peer {
/*! RTP connection IP-Address (optional, string e.g. "127.0.0.1") */
char addr[INET_ADDRSTRLEN];
char addr[INET6_ADDRSTRLEN];
/*! RTP connection IP-Port (optional) */
uint16_t port;

View File

@@ -6,7 +6,6 @@
struct mgcp_client {
struct mgcp_client_conf actual;
uint32_t remote_addr;
struct osmo_wqueue wq;
mgcp_trans_id_t next_trans_id;
struct llist_head responses_pending;

View File

@@ -9,6 +9,7 @@ AM_CFLAGS = \
-Wall \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOVTY_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
$(COVERAGE_CFLAGS) \
$(NULL)
@@ -20,7 +21,7 @@ AM_LDFLAGS = \
# This is not at all related to the release version, but a range of supported
# API versions. Read TODO_RELEASE in the source tree's root!
MGCP_CLIENT_LIBVERSION=7:0:1
MGCP_CLIENT_LIBVERSION=8:0:0
lib_LTLIBRARIES = \
libosmo-mgcp-client.la \

View File

@@ -25,10 +25,13 @@
#include <osmocom/core/logging.h>
#include <osmocom/core/byteswap.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/mgcp_client/mgcp_client.h>
#include <osmocom/mgcp_client/mgcp_client_internal.h>
#include <osmocom/abis/e1_input.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -370,22 +373,37 @@ static int mgcp_parse_audio_ptime_rtpmap(struct mgcp_response *r, const char *li
/* Parse a line like "c=IN IP4 10.11.12.13" */
static int mgcp_parse_audio_ip(struct mgcp_response *r, const char *line)
{
struct in_addr ip_test;
struct in6_addr ip_test;
bool is_ipv6;
if (strlen(line) < 16)
if (strncmp("c=IN IP", line, 7) != 0)
goto response_parse_failure;
/* The current implementation strictly supports IPV4 only ! */
if (memcmp("c=IN IP4 ", line, 9) != 0)
line += 7;
if (*line == '6')
is_ipv6 = true;
else if (*line == '4')
is_ipv6 = false;
else
goto response_parse_failure;
/* Extract IP-Address */
osmo_strlcpy(r->audio_ip, line + 9, sizeof(r->audio_ip));
/* Check IP-Address */
if (inet_aton(r->audio_ip, &ip_test) == 0)
line++;
if (*line != ' ')
goto response_parse_failure;
line++;
/* Extract and check IP-Address */
if (is_ipv6) {
/* 45 = INET6_ADDRSTRLEN -1 */
if (sscanf(line, "%45s", r->audio_ip) != 1)
goto response_parse_failure;
if (inet_pton(AF_INET6, r->audio_ip, &ip_test) != 1)
goto response_parse_failure;
} else {
/* 15 = INET_ADDRSTRLEN -1 */
if (sscanf(line, "%15s", r->audio_ip) != 1)
goto response_parse_failure;
if (inet_pton(AF_INET, r->audio_ip, &ip_test) != 1)
goto response_parse_failure;
}
return 0;
response_parse_failure:
@@ -778,7 +796,7 @@ static int init_socket(struct mgcp_client *mgcp)
/* Initalize socket with the currently configured port
* number */
rc = osmo_sock_init2_ofd(&wq->bfd, AF_INET, SOCK_DGRAM, IPPROTO_UDP, mgcp->actual.local_addr,
rc = osmo_sock_init2_ofd(&wq->bfd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, mgcp->actual.local_addr,
mgcp->actual.local_port, mgcp->actual.remote_addr, mgcp->actual.remote_port,
OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT);
if (rc > 0)
@@ -807,7 +825,6 @@ static int init_socket(struct mgcp_client *mgcp)
* \returns 0 on success, -EINVAL on error. */
int mgcp_client_connect(struct mgcp_client *mgcp)
{
struct sockaddr_in addr;
struct osmo_wqueue *wq;
int rc;
@@ -817,6 +834,11 @@ int mgcp_client_connect(struct mgcp_client *mgcp)
}
wq = &mgcp->wq;
osmo_wqueue_init(wq, 1024);
wq->read_cb = mgcp_do_read;
wq->write_cb = mgcp_do_write;
osmo_fd_setup(&wq->bfd, -1, OSMO_FD_READ, osmo_wqueue_bfd_cb, mgcp, 0);
rc = init_socket(mgcp);
if (rc < 0) {
@@ -827,14 +849,6 @@ int mgcp_client_connect(struct mgcp_client *mgcp)
goto error_close_fd;
}
inet_aton(mgcp->actual.remote_addr, &addr.sin_addr);
mgcp->remote_addr = htonl(addr.sin_addr.s_addr);
osmo_wqueue_init(wq, 1024);
wq->bfd.when = OSMO_FD_READ;
wq->bfd.data = mgcp;
wq->read_cb = mgcp_do_read;
wq->write_cb = mgcp_do_write;
LOGP(DLMGCP, LOGL_INFO, "MGCP GW connection: %s\n", osmo_sock_get_name2(wq->bfd.fd));
@@ -861,12 +875,13 @@ uint16_t mgcp_client_remote_port(struct mgcp_client *mgcp)
return mgcp->actual.remote_port;
}
/*! Get the IP-Aaddress of the associated MGW as its numeric representation.
/*! Get the IP-Address of the associated MGW as its numeric representation.
* DEPRECATED, DON'T USE.
* \param[in] mgcp MGCP client descriptor.
* \returns IP-Address as 32 bit integer (network byte order) */
uint32_t mgcp_client_remote_addr_n(struct mgcp_client *mgcp)
{
return mgcp->remote_addr;
return 0;
}
/* To compose endpoint names, usually for CRCX, use this as domain name.
@@ -944,7 +959,7 @@ const char *mgcp_client_e1_epname(void *ctx, const struct mgcp_client *mgcp, uin
/* An E1 line has a maximum of 32 timeslots, while the first (ts=0) is
* reserverd for framing and alignment, so we can not use it here. */
if (ts == 0 || ts > 31) {
if (ts == 0 || ts > NUM_E1_TS-1) {
LOGP(DLMGCP, LOGL_ERROR,
"Cannot compose MGCP e1-endpoint name (%s), E1-timeslot number (%u) is invalid!\n", epname, ts);
talloc_free(epname);
@@ -1121,7 +1136,8 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
{
unsigned int i;
int rc = 0;
char local_ip[INET_ADDRSTRLEN];
char local_ip[INET6_ADDRSTRLEN];
int local_ip_family, audio_ip_family;
const char *codec;
unsigned int pt;
@@ -1138,10 +1154,21 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
msgb_free(msg);
return -2;
}
local_ip_family = osmo_ip_str_type(local_ip);
if (local_ip_family == AF_UNSPEC) {
msgb_free(msg);
return -2;
}
audio_ip_family = osmo_ip_str_type(mgcp_msg->audio_ip);
if (audio_ip_family == AF_UNSPEC) {
msgb_free(msg);
return -2;
}
/* Add owner/creator (SDP) */
rc += msgb_printf(msg, "o=- %x 23 IN IP4 %s\r\n",
mgcp_msg->call_id, local_ip);
rc += msgb_printf(msg, "o=- %x 23 IN IP%c %s\r\n", mgcp_msg->call_id,
local_ip_family == AF_INET6 ? '6' : '4',
local_ip);
/* Add session name (none) */
rc += msgb_printf(msg, "s=-\r\n");
@@ -1159,7 +1186,9 @@ static int add_sdp(struct msgb *msg, struct mgcp_msg *mgcp_msg, struct mgcp_clie
msgb_free(msg);
return -2;
}
rc += msgb_printf(msg, "c=IN IP4 %s\r\n", mgcp_msg->audio_ip);
rc += msgb_printf(msg, "c=IN IP%c %s\r\n",
audio_ip_family == AF_INET6 ? '6' : '4',
mgcp_msg->audio_ip);
/* Add time description, active time (SDP) */
rc += msgb_printf(msg, "t=0 0\r\n");

View File

@@ -27,6 +27,7 @@
#include <osmocom/core/fsm.h>
#include <osmocom/core/byteswap.h>
#include <osmocom/core/tdef.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
@@ -235,8 +236,6 @@ static void fill_event_names()
}
}
/* T_defs is used to obtain an (Osmocom specific) T2427001: timeout for an MGCP response (note, 2427 corresponds to the
* default MGCP port in osmo-mgw). */
static __attribute__((constructor)) void osmo_mgcpc_ep_fsm_init()
{
OSMO_ASSERT(osmo_fsm_register(&osmo_mgcpc_ep_fsm) == 0);
@@ -468,14 +467,12 @@ static void on_success(struct osmo_mgcpc_ep_ci *ci, void *data)
ci->pending = false;
rtp_info = data;
switch (ci->verb) {
case MGCP_VERB_CRCX:
/* If we sent a wildcarded endpoint name on CRCX, we need to store the resulting endpoint
* name here. Also, we receive the MGW's RTP port information. */
rtp_info = data;
OSMO_ASSERT(rtp_info);
ci->got_port_info = true;
ci->rtp_info = *rtp_info;
osmo_strlcpy(ci->mgcp_ci_str, mgcp_conn_get_ci(ci->mgcp_client_fi),
sizeof(ci->mgcp_ci_str));
if (rtp_info->endpoint[0]) {
@@ -485,6 +482,15 @@ static void on_success(struct osmo_mgcpc_ep_ci *ci, void *data)
return;
}
ci->ep->first_crcx_complete = true;
OSMO_ASSERT(rtp_info);
/* fall through */
case MGCP_VERB_MDCX:
/* Always update the received RTP ip/port information, since MGW
* may provide new one after remote end params changed */
if (rtp_info) {
ci->got_port_info = true;
ci->rtp_info = *rtp_info;
}
break;
default:
@@ -517,17 +523,33 @@ const struct mgcp_conn_peer *osmo_mgcpc_ep_ci_get_rtp_info(const struct osmo_mgc
bool osmo_mgcpc_ep_ci_get_crcx_info_to_sockaddr(const struct osmo_mgcpc_ep_ci *ci, struct sockaddr_storage *dest)
{
const struct mgcp_conn_peer *rtp_info;
int family;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
rtp_info = osmo_mgcpc_ep_ci_get_rtp_info(ci);
if (!rtp_info)
return false;
sin = (struct sockaddr_in *)dest;
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = inet_addr(rtp_info->addr);
sin->sin_port = osmo_ntohs(rtp_info->port);
family = osmo_ip_str_type(rtp_info->addr);
switch (family) {
case AF_INET:
sin = (struct sockaddr_in *)dest;
sin->sin_family = AF_INET;
sin->sin_port = osmo_ntohs(rtp_info->port);
if (inet_pton(AF_INET, rtp_info->addr, &sin->sin_addr) != 1)
return false;
break;
case AF_INET6:
sin6 = (struct sockaddr_in6 *)dest;
sin6->sin6_family = AF_INET6;
sin6->sin6_port = osmo_ntohs(rtp_info->port);
if (inet_pton(AF_INET6, rtp_info->addr, &sin6->sin6_addr) != 1)
return false;
break;
default:
return false;
}
return true;
}
@@ -547,7 +569,7 @@ bool osmo_mgcpc_ep_ci_get_crcx_info_to_osmux_cid(const struct osmo_mgcpc_ep_ci *
}
static const struct osmo_tdef_state_timeout osmo_mgcpc_ep_fsm_timeouts[32] = {
[OSMO_MGCPC_EP_ST_WAIT_MGW_RESPONSE] = { .T=2427001 },
[OSMO_MGCPC_EP_ST_WAIT_MGW_RESPONSE] = { .T=-2427 },
};
/* Transition to a state, using the T timer defined in assignment_fsm_timeouts.

View File

@@ -25,6 +25,7 @@
#include <osmocom/core/byteswap.h>
#include <arpa/inet.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/sockaddr_str.h>
/* Context information, this is attached to the priv pointer of the FSM and
* is also handed back when dispatcheing events to the parent FSM. This is
@@ -522,8 +523,8 @@ static void fsm_cleanup_cb(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause ca
* connection. This is not the normal case. The user should always use
* mgcp_conn_delete() to instruct the FSM to perform a graceful exit */
if (strlen(mgcp_ctx->conn_id)) {
LOGPFSML(fi, LOGL_ERROR,
"MGW/DLCX: abrupt FSM termination with connections still present, sending unconditional DLCX...\n");
LOGPFSML(fi, LOGL_NOTICE,
"MGW/DLCX: FSM termination with connections still present, sending unconditional DLCX...\n");
msg = make_dlcx_msg(mgcp_ctx);
if (!msg)
LOGPFSML(fi, LOGL_ERROR, "MGW/DLCX: Error composing DLCX message\n");
@@ -607,14 +608,16 @@ struct osmo_fsm_inst *mgcp_conn_create(struct mgcp_client *mgcp, struct osmo_fsm
{
struct mgcp_ctx *mgcp_ctx;
struct osmo_fsm_inst *fi;
struct in_addr ip_test;
struct in6_addr ip_test;
OSMO_ASSERT(parent_fi);
OSMO_ASSERT(mgcp);
OSMO_ASSERT(conn_peer);
/* Check if IP/Port information in conn info makes sense */
if (conn_peer->port && inet_aton(conn_peer->addr, &ip_test) == 0)
if (conn_peer->port && inet_pton(osmo_ip_str_type(conn_peer->addr),
conn_peer->addr, &ip_test) != 1)
return NULL;
/* Allocate and configure a new fsm instance */
@@ -644,7 +647,7 @@ int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_
{
OSMO_ASSERT(fi);
struct mgcp_ctx *mgcp_ctx = fi->priv;
struct in_addr ip_test;
struct in6_addr ip_test;
OSMO_ASSERT(mgcp_ctx);
OSMO_ASSERT(conn_peer);
@@ -668,8 +671,8 @@ int mgcp_conn_modify(struct osmo_fsm_inst *fi, uint32_t parent_evt, struct mgcp_
LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, port == 0\n");
return -EINVAL;
}
if (inet_aton(conn_peer->addr, &ip_test) == 0) {
LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, IP address == 0.0.0.0\n");
if (inet_pton(osmo_ip_str_type(conn_peer->addr), conn_peer->addr, &ip_test) != 1) {
LOGPFSML(fi, LOGL_ERROR, "Cannot MDCX, IP address %s\n", conn_peer->addr);
return -EINVAL;
}

View File

@@ -36,9 +36,10 @@ void *global_mgcp_client_ctx = NULL;
struct mgcp_client_conf *global_mgcp_client_conf = NULL;
DEFUN(cfg_mgw_local_ip, cfg_mgw_local_ip_cmd,
"mgw local-ip A.B.C.D",
"mgw local-ip " VTY_IPV46_CMD,
MGW_STR "local bind to connect to MGW from\n"
"local bind IP address\n")
"local bind IPv4 address\n"
"local bind IPv6 address\n")
{
if (!global_mgcp_client_conf)
return CMD_ERR_NOTHING_TODO;
@@ -69,9 +70,10 @@ ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
"local bind port\n")
DEFUN(cfg_mgw_remote_ip, cfg_mgw_remote_ip_cmd,
"mgw remote-ip A.B.C.D",
"mgw remote-ip " VTY_IPV46_CMD,
MGW_STR "remote IP address to reach the MGW at\n"
"remote IP address\n")
"remote IPv4 address\n"
"remote IPv6 address\n")
{
if (!global_mgcp_client_conf)
return CMD_ERR_NOTHING_TODO;
@@ -188,21 +190,21 @@ void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *c
global_mgcp_client_ctx = talloc_ctx;
global_mgcp_client_conf = conf;
install_element(node, &cfg_mgw_local_ip_cmd);
install_element(node, &cfg_mgw_local_port_cmd);
install_element(node, &cfg_mgw_remote_ip_cmd);
install_element(node, &cfg_mgw_remote_port_cmd);
install_element(node, &cfg_mgw_endpoint_range_cmd);
install_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
install_element(node, &cfg_mgw_endpoint_domain_name_cmd);
install_lib_element(node, &cfg_mgw_local_ip_cmd);
install_lib_element(node, &cfg_mgw_local_port_cmd);
install_lib_element(node, &cfg_mgw_remote_ip_cmd);
install_lib_element(node, &cfg_mgw_remote_port_cmd);
install_lib_element(node, &cfg_mgw_endpoint_range_cmd);
install_lib_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
install_lib_element(node, &cfg_mgw_endpoint_domain_name_cmd);
/* deprecated 'mgcpgw' commands */
install_element(node, &cfg_mgcpgw_local_ip_cmd);
install_element(node, &cfg_mgcpgw_local_port_cmd);
install_element(node, &cfg_mgcpgw_remote_ip_cmd);
install_element(node, &cfg_mgcpgw_remote_port_cmd);
install_element(node, &cfg_mgcpgw_endpoint_range_cmd);
install_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);
install_lib_element(node, &cfg_mgcpgw_local_port_cmd);
install_lib_element(node, &cfg_mgcpgw_remote_ip_cmd);
install_lib_element(node, &cfg_mgcpgw_remote_port_cmd);
install_lib_element(node, &cfg_mgcpgw_endpoint_range_cmd);
install_lib_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
osmo_fsm_vty_add_cmds();
}

View File

@@ -199,7 +199,7 @@ struct mgcp_conn *mgcp_conn_alloc(void *ctx, struct mgcp_endpoint *endp,
/* Initialize watchdog */
osmo_timer_setup(&conn->watchdog, mgcp_conn_watchdog_cb, conn);
mgcp_conn_watchdog_kick(conn);
llist_add(&conn->entry, &endp->conns);
mgcp_endp_add_conn(endp, conn);
return conn;
}
@@ -289,12 +289,6 @@ void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id)
if (!conn)
return;
/* Run endpoint cleanup action. By this we inform the endpoint about
* the removal of the connection and allow it to clean up its inner
* state accordingly */
if (endp->type->cleanup_cb)
endp->type->cleanup_cb(endp, conn);
switch (conn->type) {
case MGCP_CONN_TYPE_RTP:
aggregate_rtp_conn_stats(endp, &conn->u.rtp);
@@ -308,7 +302,8 @@ void mgcp_conn_free(struct mgcp_endpoint *endp, const char *id)
}
osmo_timer_del(&conn->watchdog);
llist_del(&conn->entry);
mgcp_endp_remove_conn(endp, conn);
/* WARN: endp may have be freed after call to mgcp_endp_remove_conn */
talloc_free(conn);
}
@@ -349,6 +344,7 @@ void mgcp_conn_free_all(struct mgcp_endpoint *endp)
char *mgcp_conn_dump(struct mgcp_conn *conn)
{
static char str[sizeof(conn->name)+sizeof(conn->id)+256];
char ipbuf[INET6_ADDRSTRLEN];
if (!conn) {
snprintf(str, sizeof(str), "(null connection)");
@@ -362,7 +358,7 @@ char *mgcp_conn_dump(struct mgcp_conn *conn)
"rtp:%u rtcp:%u)",
conn->name,
conn->id,
inet_ntoa(conn->u.rtp.end.addr),
osmo_sockaddr_ntop(&conn->u.rtp.end.addr.u.sa, ipbuf),
ntohs(conn->u.rtp.end.rtp_port),
ntohs(conn->u.rtp.end.rtcp_port));
break;

View File

@@ -361,11 +361,7 @@ static void e1_recv_cb(struct e1inp_ts *ts, struct msgb *msg)
e1_send(ts, trunk);
}
/*! Find an endpoint by its name on a specified trunk.
* \param[in] trunk trunk configuration.
* \param[in] ts_nr E1 timeslot number.
* \returns -EINVAL on failure, 0 on success. */
int mgcp_e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr)
static int e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr)
{
/*! Each timeslot needs only to be configured once. The Timeslot then
* stays open and permanently receives data. It is then up to the
@@ -385,26 +381,25 @@ int mgcp_e1_init(struct mgcp_trunk *trunk, uint8_t ts_nr)
}
/* Get E1 line */
if (!trunk->e1.line) {
e1_line = e1inp_line_find(trunk->e1.vty_line_nr);
if (!e1_line) {
LOGPTRUNK(trunk, DE1, LOGL_DEBUG, "no such E1 line %u - check VTY config!\n",
trunk->e1.vty_line_nr);
return -EINVAL;
}
e1inp_line_bind_ops(e1_line, &dummy_e1_line_ops);
} else
e1_line = trunk->e1.line;
if (!e1_line)
e1_line = e1inp_line_find(trunk->e1.vty_line_nr);
if (!e1_line) {
LOGPTRUNK(trunk, DE1, LOGL_DEBUG, "no such E1 line %u - check VTY config!\n",
trunk->e1.vty_line_nr);
return -EINVAL;
}
e1inp_line_bind_ops(e1_line, &dummy_e1_line_ops);
/* Configure E1 timeslot */
rc = e1inp_ts_config_raw(&e1_line->ts[ts_nr - 1], e1_line, e1_recv_cb);
if (rc < 0)
if (rc < 0) {
LOGPTRUNK(trunk, DE1, LOGL_ERROR, "failed to put E1 timeslot %u in raw mode.\n", ts_nr);
return -EINVAL;
e1inp_line_update(e1_line);
if (rc < 0)
}
rc = e1inp_line_update(e1_line);
if (rc < 0) {
LOGPTRUNK(trunk, DE1, LOGL_ERROR, "failed to update E1 timeslot %u.\n", ts_nr);
return -EINVAL;
}
LOGPTRUNK(trunk, DE1, LOGL_DEBUG, "E1 timeslot %u set up successfully.\n", ts_nr);
trunk->e1.ts_in_use[ts_nr - 1] = true;
@@ -518,7 +513,7 @@ int mgcp_e1_endp_equip(struct mgcp_endpoint *endp, uint8_t ts, uint8_t ss, uint8
endp->e1.last_amr_ft = AMR_4_75;
/* Set up E1 line / timeslot */
rc = mgcp_e1_init(endp->trunk, ts);
rc = e1_init(endp->trunk, ts);
if (rc != 0)
return -EINVAL;

View File

@@ -27,9 +27,9 @@
#include <osmocom/mgcp/mgcp_endp.h>
#include <osmocom/mgcp/mgcp_trunk.h>
#include <osmocom/abis/e1_input.h>
#include <osmocom/mgcp/mgcp_e1.h>
#define E1_TIMESLOTS 32
#define E1_RATE_MAX 64
#define E1_OFFS_MAX 8
@@ -375,7 +375,7 @@ static uint8_t e1_ts_nr_from_epname(const char *epname)
if (strncmp(token, "s-", 2) == 0) {
errno = 0;
res = strtoul(token + 2, NULL, 10);
if (errno == ERANGE || res > E1_TIMESLOTS)
if (errno == ERANGE || res > NUM_E1_TS)
return 0xff;
return (uint8_t) res;
}
@@ -641,8 +641,7 @@ int mgcp_endp_claim(struct mgcp_endpoint *endp, const char *callid)
OSMO_ASSERT(false);
}
/* Make sure the endpoint is released when claiming the endpoint
* failes. */
/* Make sure the endpoint is released when claiming the endpoint fails. */
if (rc < 0)
mgcp_endp_release(endp);
@@ -666,3 +665,20 @@ void mgcp_endp_update(struct mgcp_endpoint *endp)
OSMO_ASSERT(false);
}
}
void mgcp_endp_add_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn)
{
llist_add(&conn->entry, &endp->conns);
}
void mgcp_endp_remove_conn(struct mgcp_endpoint *endp, struct mgcp_conn *conn)
{
/* Run endpoint cleanup action. By this we inform the endpoint about
* the removal of the connection and allow it to clean up its inner
* state accordingly */
if (endp->type->cleanup_cb)
endp->type->cleanup_cb(endp, conn);
llist_del(&conn->entry);
if (llist_empty(&endp->conns))
mgcp_endp_release(endp);
}

View File

@@ -107,7 +107,7 @@ int mgcp_parse_conn_mode(const char *mode, struct mgcp_endpoint *endp,
ret = -1;
}
/* Special handling für RTP connections */
/* Special handling for RTP connections */
if (conn->type == MGCP_CONN_TYPE_RTP) {
conn->u.rtp.end.output_enabled =
conn->mode & MGCP_CONN_SEND_ONLY ? 1 : 0;
@@ -245,7 +245,7 @@ int mgcp_check_param(const struct mgcp_endpoint *endp, const char *line)
/*! Check if the specified callid seems plausible.
* \param[in] endp pointer to endpoint
* \param{in] callid to verify
* \returns 1 when callid seems plausible, 0 on error */
* \returns 0 when callid seems plausible, -1 on error */
int mgcp_verify_call_id(struct mgcp_endpoint *endp, const char *callid)
{
/*! This function compares the supplied callid with the called that is

View File

@@ -77,6 +77,16 @@ static void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_end
static int rx_rtp(struct msgb *msg);
static bool addr_is_any(struct osmo_sockaddr *osa) {
if (osa->u.sa.sa_family == AF_INET6) {
struct in6_addr ip6_any = IN6ADDR_ANY_INIT;
return memcmp(&osa->u.sin6.sin6_addr,
&ip6_any, sizeof(ip6_any)) == 0;
} else {
return osa->u.sin.sin_addr.s_addr == 0;
}
}
/*! Determine the local rtp bind IP-address.
* \param[out] addr caller provided memory to store the resulting IP-Address.
* \param[in] endp mgcp endpoint, that holds a copy of the VTY parameters.
@@ -89,39 +99,52 @@ void mgcp_get_local_addr(char *addr, struct mgcp_conn_rtp *conn)
{
struct mgcp_endpoint *endp;
char ipbuf[INET6_ADDRSTRLEN];
int rc;
endp = conn->conn->endp;
bool rem_addr_set = !addr_is_any(&conn->end.addr);
char *bind_addr;
/* Try probing the local IP-Address */
if (endp->cfg->net_ports.bind_addr_probe && conn->end.addr.s_addr != 0) {
rc = osmo_sock_local_ip(addr, inet_ntoa(conn->end.addr));
if (endp->cfg->net_ports.bind_addr_probe && rem_addr_set) {
rc = osmo_sock_local_ip(addr, osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
if (rc < 0)
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"local interface auto detection failed, using configured addresses...\n");
else {
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"selected local rtp bind ip %s by probing using remote ip %s\n",
addr, inet_ntoa(conn->end.addr));
addr, osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
return;
}
}
/* Select from preconfigured IP-Addresses. We don't have bind_addr for Osmux (yet?). */
if (endp->cfg->net_ports.bind_addr) {
if (rem_addr_set) {
/* Check there is a bind IP for the RTP traffic configured,
* if so, use that IP-Address */
osmo_strlcpy(addr, endp->cfg->net_ports.bind_addr, INET_ADDRSTRLEN);
bind_addr = conn->end.addr.u.sa.sa_family == AF_INET6 ?
endp->cfg->net_ports.bind_addr_v6 :
endp->cfg->net_ports.bind_addr_v4;
} else {
/* Choose any of the bind addresses, preferring v6 over v4 */
bind_addr = endp->cfg->net_ports.bind_addr_v6;
if (!bind_addr)
bind_addr = endp->cfg->net_ports.bind_addr_v4;
}
if (bind_addr) {
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"using configured rtp bind ip as local bind ip %s\n",
addr);
bind_addr);
} else {
/* No specific bind IP is configured for the RTP traffic, so
* assume the IP where we listen for incoming MGCP messages
* as bind IP */
osmo_strlcpy(addr, endp->cfg->source_addr, INET_ADDRSTRLEN);
bind_addr = endp->cfg->source_addr;
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"using mgcp bind ip as local rtp bind ip: %s\n", addr);
"using mgcp bind ip as local rtp bind ip: %s\n", bind_addr);
}
osmo_strlcpy(addr, bind_addr, INET6_ADDRSTRLEN);
}
/* This does not need to be a precision timestamp and
@@ -154,19 +177,26 @@ static uint32_t get_current_ts(unsigned codec_rate)
* \param[in] buf buffer that holds the data to be send.
* \param[in] len length of the data to be sent.
* \returns bytes sent, -1 on error. */
int mgcp_udp_send(int fd, struct in_addr *addr, int port, char *buf, int len)
int mgcp_udp_send(int fd, struct osmo_sockaddr *addr, int port, char *buf, int len)
{
struct sockaddr_in out;
char ipbuf[INET6_ADDRSTRLEN];
size_t addr_len;
bool is_ipv6 = addr->u.sa.sa_family == AF_INET6;
LOGP(DRTP, LOGL_DEBUG,
"sending %i bytes length packet to %s:%u ...\n",
len, inet_ntoa(*addr), ntohs(port));
"sending %i bytes length packet to %s:%u ...\n", len,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
ntohs(port));
out.sin_family = AF_INET;
out.sin_port = port;
memcpy(&out.sin_addr, addr, sizeof(*addr));
if (is_ipv6) {
addr->u.sin6.sin6_port = port;
addr_len = sizeof(addr->u.sin6);
} else {
addr->u.sin.sin_port = port;
addr_len = sizeof(addr->u.sin);
}
return sendto(fd, buf, len, 0, (struct sockaddr *)&out, sizeof(out));
return sendto(fd, buf, len, 0, &addr->u.sa, addr_len);
}
/*! send RTP dummy packet (to keep NAT connection open).
@@ -229,12 +259,13 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_stream_state *sstate,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr,
struct osmo_sockaddr *addr,
uint16_t seq, uint32_t timestamp,
const char *text, int32_t * tsdelta_out)
{
int32_t tsdelta;
int32_t timestamp_error;
char ipbuf[INET6_ADDRSTRLEN];
/* Not fully intialized, skip */
if (sstate->last_tsdelta == 0 && timestamp == sstate->last_timestamp)
@@ -251,8 +282,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"from %s:%d\n",
text, seq,
state->patch.timestamp_offset, state->patch.seq_offset,
sstate->ssrc, timestamp, inet_ntoa(addr->sin_addr),
ntohs(addr->sin_port));
sstate->ssrc, timestamp,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
return 0;
}
@@ -267,9 +299,9 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"The %s timestamp delta is %d "
"on SSRC: %u timestamp: %u "
"from %s:%d\n",
text, tsdelta,
sstate->ssrc, timestamp,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
text, tsdelta, sstate->ssrc, timestamp,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
return 0;
}
@@ -281,7 +313,8 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
"on SSRC: %u timestamp: %u from %s:%d\n",
text, sstate->last_tsdelta, tsdelta,
sstate->ssrc, timestamp,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
}
@@ -303,7 +336,8 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
(int16_t)(seq - sstate->last_seq),
(int32_t)(timestamp - sstate->last_timestamp),
tsdelta,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port),
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa),
state->packet_duration);
}
return 1;
@@ -313,12 +347,13 @@ static int check_rtp_timestamp(struct mgcp_endpoint *endp,
static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr,
struct osmo_sockaddr *addr,
int16_t delta_seq, uint32_t in_timestamp)
{
int32_t tsdelta = state->packet_duration;
int timestamp_offset;
uint32_t out_timestamp;
char ipbuf[INET6_ADDRSTRLEN];
if (tsdelta == 0) {
tsdelta = state->out_stream.last_tsdelta;
@@ -327,7 +362,8 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
"A fixed packet duration is not available, "
"using last output timestamp delta instead: %d "
"from %s:%d\n", tsdelta,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
} else {
tsdelta = rtp_end->codec->rate * 20 / 1000;
LOGPENDP(endp, DRTP, LOGL_NOTICE,
@@ -335,7 +371,8 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
"are not available, "
"using fixed 20ms instead: %d "
"from %s:%d\n", tsdelta,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
}
@@ -344,13 +381,13 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
if (state->patch.timestamp_offset != timestamp_offset) {
state->patch.timestamp_offset = timestamp_offset;
LOGPENDP(endp, DRTP, LOGL_NOTICE,
"Timestamp offset change on SSRC: %u "
"SeqNo delta: %d, TS offset: %d, "
"from %s:%d\n", state->in_stream.ssrc,
delta_seq, state->patch.timestamp_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
return timestamp_offset;
@@ -360,9 +397,10 @@ static int adjust_rtp_timestamp_offset(struct mgcp_endpoint *endp,
static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr,
struct osmo_sockaddr *addr,
uint32_t timestamp)
{
char ipbuf[INET6_ADDRSTRLEN];
int ts_error = 0;
int ts_check = 0;
int ptime = state->packet_duration;
@@ -375,14 +413,14 @@ static int align_rtp_timestamp_offset(struct mgcp_endpoint *endp,
/* If there is an alignment error, we have to compensate it */
if (ts_error) {
state->patch.timestamp_offset += ptime - ts_error;
LOGPENDP(endp, DRTP, LOGL_NOTICE,
"Corrected timestamp alignment error of %d on SSRC: %u "
"new TS offset: %d, "
"from %s:%d\n",
ts_error, state->in_stream.ssrc,
state->patch.timestamp_offset, inet_ntoa(addr->sin_addr),
ntohs(addr->sin_port));
state->patch.timestamp_offset,
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
/* Check we really managed to compensate the timestamp
@@ -521,8 +559,9 @@ static int mgcp_patch_pt(struct mgcp_conn_rtp *conn_src,
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr, struct msgb *msg)
struct osmo_sockaddr *addr, struct msgb *msg)
{
char ipbuf[INET6_ADDRSTRLEN];
uint32_t arrival_time;
int32_t transit;
uint16_t seq;
@@ -560,7 +599,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
"pkt-duration: %d, from %s:%d\n",
state->in_stream.ssrc,
state->patch.seq_offset, state->packet_duration,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
if (state->packet_duration == 0) {
state->packet_duration =
rtp_end->codec->rate * 20 / 1000;
@@ -568,14 +608,16 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
"fixed packet duration is not available, "
"using fixed 20ms instead: %d from %s:%d\n",
state->packet_duration,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
} else if (state->in_stream.ssrc != ssrc) {
LOGPENDP(endp, DRTP, LOGL_NOTICE,
"SSRC changed: %u -> %u "
"from %s:%d\n",
state->in_stream.ssrc, rtp_hdr->ssrc,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
state->in_stream.ssrc = ssrc;
if (rtp_end->force_constant_ssrc) {
@@ -604,7 +646,8 @@ void mgcp_patch_and_count(struct mgcp_endpoint *endp,
"SeqNo offset: %d, TS offset: %d "
"from %s:%d\n", state->in_stream.ssrc,
state->patch.seq_offset, state->patch.timestamp_offset,
inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
osmo_sockaddr_ntop(&addr->u.sa, ipbuf),
osmo_sockaddr_port(&addr->u.sa));
}
state->in_stream.last_tsdelta = 0;
@@ -825,7 +868,7 @@ static void gen_rtp_header(struct msgb *msg, struct mgcp_rtp_end *rtp_end,
* \param[in] conn_src associated source connection.
* \param[in] conn_dst associated destination connection.
* \returns 0 on success, -1 on ERROR. */
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct osmo_sockaddr *addr,
struct msgb *msg, struct mgcp_conn_rtp *conn_src,
struct mgcp_conn_rtp *conn_dst)
{
@@ -836,6 +879,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
struct mgcp_trunk *trunk = endp->trunk;
struct mgcp_rtp_end *rtp_end;
struct mgcp_rtp_state *rtp_state;
char ipbuf[INET6_ADDRSTRLEN];
char *dest_name;
int rc;
int len;
@@ -849,10 +893,6 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
LOGPENDP(endp, DRTP, LOGL_DEBUG, "delivering RTCP packet...\n");
}
LOGPENDP(endp, DRTP, LOGL_DEBUG, "loop:%d, mode:%d%s\n",
trunk->audio_loop, conn_src->conn->mode,
conn_src->conn->mode == MGCP_CONN_LOOPBACK ? " (loopback)" : "");
/* FIXME: It is legal that the payload type on the egress connection is
* different from the payload type that has been negotiated on the
* ingress connection. Essentially the codecs are the same so we can
@@ -886,7 +926,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
"output disabled, drop to %s %s "
"rtp_port:%u rtcp_port:%u\n",
dest_name,
inet_ntoa(rtp_end->addr),
osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
);
} else if (is_rtp) {
@@ -932,7 +972,8 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
LOGPENDP(endp, DRTP, LOGL_DEBUG,
"process/send to %s %s "
"rtp_port:%u rtcp_port:%u\n",
dest_name, inet_ntoa(rtp_end->addr),
dest_name,
osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
);
@@ -975,7 +1016,7 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
} else if (!trunk->omit_rtcp) {
LOGPENDP(endp, DRTP, LOGL_DEBUG,
"send to %s %s rtp_port:%u rtcp_port:%u\n",
dest_name, inet_ntoa(rtp_end->addr),
dest_name, osmo_sockaddr_ntop(&rtp_end->addr.u.sa, ipbuf),
ntohs(rtp_end->rtp_port), ntohs(rtp_end->rtcp_port)
);
@@ -995,10 +1036,11 @@ int mgcp_send(struct mgcp_endpoint *endp, int is_rtp, struct sockaddr_in *addr,
/* Check if the origin (addr) matches the address/port data of the RTP
* connections. */
static int check_rtp_origin(struct mgcp_conn_rtp *conn,
struct sockaddr_in *addr)
static int check_rtp_origin(struct mgcp_conn_rtp *conn, struct osmo_sockaddr *addr)
{
if (conn->end.addr.s_addr == 0) {
char ipbuf[INET6_ADDRSTRLEN];
if (addr_is_any(&conn->end.addr)) {
switch (conn->conn->mode) {
case MGCP_CONN_LOOPBACK:
/* HACK: for IuUP, we want to reply with an IuUP Initialization ACK upon the first RTP
@@ -1010,7 +1052,8 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* MGCP port is in loopback mode, allow looping back the packet to any source. */
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"In loopback mode and remote address not set:"
" allowing data from address: %s\n", inet_ntoa(addr->sin_addr));
" allowing data from address: %s\n",
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
return 0;
default:
@@ -1019,18 +1062,25 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* confuse humans with expected errors. */
LOGPCONN(conn->conn, DRTP, LOGL_INFO,
"Rx RTP from %s, but remote address not set:"
" dropping early media\n", inet_ntoa(addr->sin_addr));
" dropping early media\n",
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
return -1;
}
}
/* Note: Check if the inbound RTP data comes from the same host to
* which we send our outgoing RTP traffic. */
if (conn->end.addr.s_addr != addr->sin_addr.s_addr) {
if (conn->end.addr.u.sa.sa_family != addr->u.sa.sa_family ||
(conn->end.addr.u.sa.sa_family == AF_INET &&
conn->end.addr.u.sin.sin_addr.s_addr != addr->u.sin.sin_addr.s_addr) ||
(conn->end.addr.u.sa.sa_family == AF_INET6 &&
memcmp(&conn->end.addr.u.sin6.sin6_addr, &addr->u.sin6.sin6_addr,
sizeof(struct in6_addr)))) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"data from wrong address: %s, ", inet_ntoa(addr->sin_addr));
"data from wrong address: %s, ",
osmo_sockaddr_ntop(&addr->u.sa, ipbuf));
LOGPC(DRTP, LOGL_ERROR, "expected: %s\n",
inet_ntoa(conn->end.addr));
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf));
LOGPCONN(conn->conn, DRTP, LOGL_ERROR, "packet tossed\n");
return -1;
}
@@ -1039,10 +1089,11 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* the same as the remote port where we transmit outgoing RTP traffic
* to (set by MDCX). We use this to check the origin of the data for
* plausibility. */
if (conn->end.rtp_port != addr->sin_port &&
conn->end.rtcp_port != addr->sin_port) {
if (ntohs(conn->end.rtp_port) != osmo_sockaddr_port(&addr->u.sa) &&
ntohs(conn->end.rtcp_port) != osmo_sockaddr_port(&addr->u.sa)) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"data from wrong source port: %d, ", ntohs(addr->sin_port));
"data from wrong source port: %d, ",
osmo_sockaddr_port(&addr->u.sa));
LOGPC(DRTP, LOGL_ERROR,
"expected: %d for RTP or %d for RTCP\n",
ntohs(conn->end.rtp_port), ntohs(conn->end.rtcp_port));
@@ -1057,26 +1108,29 @@ static int check_rtp_origin(struct mgcp_conn_rtp *conn,
* makes sense */
static int check_rtp_destin(struct mgcp_conn_rtp *conn)
{
char ipbuf[INET6_ADDRSTRLEN];
bool ip_is_any = addr_is_any(&conn->end.addr);
/* Note: it is legal to create a connection but never setting a port
* and IP-address for outgoing data. */
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0 && conn->end.rtp_port == 0) {
if (ip_is_any && conn->end.rtp_port == 0) {
LOGPCONN(conn->conn, DRTP, LOGL_DEBUG,
"destination IP-address and rtp port is (not yet) known (%s:%u)\n",
inet_ntoa(conn->end.addr), conn->end.rtp_port);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
return -1;
}
if (strcmp(inet_ntoa(conn->end.addr), "0.0.0.0") == 0) {
if (ip_is_any) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"destination IP-address is invalid (%s:%u)\n",
inet_ntoa(conn->end.addr), conn->end.rtp_port);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
return -1;
}
if (conn->end.rtp_port == 0) {
LOGPCONN(conn->conn, DRTP, LOGL_ERROR,
"destination rtp port is invalid (%s:%u)\n",
inet_ntoa(conn->end.addr), conn->end.rtp_port);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf), conn->end.rtp_port);
return -1;
}
@@ -1147,7 +1201,6 @@ static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
enum rtp_proto proto = mc->proto;
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct sockaddr_in *from_addr = mc->from_addr;
struct mgcp_endpoint *endp = conn_src->conn->endp;
LOGPENDP(endp, DRTP, LOGL_DEBUG, "destin conn:%s\n",
@@ -1167,7 +1220,7 @@ static int mgcp_send_rtp(struct mgcp_conn_rtp *conn_dst, struct msgb *msg)
"endpoint type is MGCP_RTP_DEFAULT, "
"using mgcp_send() to forward data directly\n");
return mgcp_send(endp, proto == MGCP_PROTO_RTP,
from_addr, msg, conn_src, conn_dst);
mc->from_addr, msg, conn_src, conn_dst);
case MGCP_OSMUX_BSC_NAT:
case MGCP_OSMUX_BSC:
LOGPENDP(endp, DRTP, LOGL_DEBUG,
@@ -1197,7 +1250,7 @@ int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct mgcp_conn *conn = conn_src->conn;
struct mgcp_conn *conn_dst;
struct sockaddr_in *from_addr = mc->from_addr;
struct osmo_sockaddr *from_addr = mc->from_addr;
/*! NOTE: This callback function implements the endpoint specific
* dispatch behaviour of an rtp bridge/proxy endpoint. It is assumed
@@ -1216,8 +1269,19 @@ int mgcp_dispatch_rtp_bridge_cb(struct msgb *msg)
* address data from the UDP packet header to patch the
* outgoing address in connection on the fly */
if (conn->u.rtp.end.rtp_port == 0) {
conn->u.rtp.end.addr = from_addr->sin_addr;
conn->u.rtp.end.rtp_port = from_addr->sin_port;
OSMO_ASSERT(conn->u.rtp.end.addr.u.sa.sa_family == from_addr->u.sa.sa_family);
switch (from_addr->u.sa.sa_family) {
case AF_INET:
conn->u.rtp.end.addr.u.sin.sin_addr = from_addr->u.sin.sin_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin.sin_port;
break;
case AF_INET6:
conn->u.rtp.end.addr.u.sin6.sin6_addr = from_addr->u.sin6.sin6_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin6.sin6_port;
break;
default:
OSMO_ASSERT(false);
}
}
return mgcp_send_rtp(conn_src, msg);
}
@@ -1266,7 +1330,7 @@ int mgcp_dispatch_e1_bridge_cb(struct msgb *msg)
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct mgcp_conn *conn = conn_src->conn;
struct sockaddr_in *from_addr = mc->from_addr;
struct osmo_sockaddr *from_addr = mc->from_addr;
/* Check if the connection is in loopback mode, if yes, just send the
* incoming data back to the origin */
@@ -1276,8 +1340,19 @@ int mgcp_dispatch_e1_bridge_cb(struct msgb *msg)
* address data from the UDP packet header to patch the
* outgoing address in connection on the fly */
if (conn->u.rtp.end.rtp_port == 0) {
conn->u.rtp.end.addr = from_addr->sin_addr;
conn->u.rtp.end.rtp_port = from_addr->sin_port;
OSMO_ASSERT(conn->u.rtp.end.addr.u.sa.sa_family == from_addr->u.sa.sa_family);
switch (from_addr->u.sa.sa_family) {
case AF_INET:
conn->u.rtp.end.addr.u.sin.sin_addr = from_addr->u.sin.sin_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin.sin_port;
break;
case AF_INET6:
conn->u.rtp.end.addr.u.sin6.sin6_addr = from_addr->u.sin6.sin6_addr;
conn->u.rtp.end.rtp_port = from_addr->u.sin6.sin6_port;
break;
default:
OSMO_ASSERT(false);
}
}
return mgcp_send_rtp(conn_src, msg);
}
@@ -1300,7 +1375,8 @@ void mgcp_cleanup_rtp_bridge_cb(struct mgcp_endpoint *endp, struct mgcp_conn *co
* connections present when one connection is removed from the
* endpoint. */
llist_for_each_entry(conn_cleanup, &endp->conns, entry) {
conn_cleanup->priv = NULL;
if (conn_cleanup->priv == conn)
conn_cleanup->priv = NULL;
}
}
@@ -1331,8 +1407,9 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
struct mgcp_conn_rtp *conn_src;
struct mgcp_endpoint *endp;
struct sockaddr_in addr;
struct osmo_sockaddr addr;
socklen_t slen = sizeof(addr);
char ipbuf[INET6_ADDRSTRLEN];
int ret;
enum rtp_proto proto;
struct osmo_rtp_msg_ctx *mc;
@@ -1346,7 +1423,7 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
proto = (fd == &conn_src->end.rtp)? MGCP_PROTO_RTP : MGCP_PROTO_RTCP;
ret = recvfrom(fd->fd, msgb_data(msg), msg->data_len, 0, (struct sockaddr *)&addr, &slen);
ret = recvfrom(fd->fd, msgb_data(msg), msg->data_len, 0, (struct sockaddr *)&addr.u.sa, &slen);
if (ret <= 0) {
LOG_CONN_RTP(conn_src, LOGL_ERROR, "recvfrom error: %s\n", strerror(errno));
@@ -1358,7 +1435,8 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "%s: rx %u bytes from %s:%u\n",
proto == MGCP_PROTO_RTP ? "RTP" : "RTPC",
msgb_length(msg), inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
msgb_length(msg), osmo_sockaddr_ntop(&addr.u.sa, ipbuf),
osmo_sockaddr_port(&addr.u.sa));
if ((proto == MGCP_PROTO_RTP && check_rtp(conn_src, msg))
|| (proto == MGCP_PROTO_RTCP && check_rtcp(conn_src, msg))) {
@@ -1383,7 +1461,10 @@ static int rtp_data_net(struct osmo_fd *fd, unsigned int what)
};
LOG_CONN_RTP(conn_src, LOGL_DEBUG, "msg ctx: %d %p %s\n",
mc->proto, mc->conn_src,
osmo_hexdump((void*)mc->from_addr, sizeof(struct sockaddr_in)));
osmo_hexdump((void*)mc->from_addr,
mc->from_addr->u.sa.sa_family == AF_INET6 ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in)));
/* Increment RX statistics */
rate_ctr_inc(&conn_src->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR]);
@@ -1404,7 +1485,7 @@ static int rx_rtp(struct msgb *msg)
{
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
struct mgcp_conn_rtp *conn_src = mc->conn_src;
struct sockaddr_in *from_addr = mc->from_addr;
struct osmo_sockaddr *from_addr = mc->from_addr;
struct mgcp_conn *conn = conn_src->conn;
struct mgcp_trunk *trunk = conn->endp->trunk;
@@ -1456,7 +1537,7 @@ int mgcp_create_bind(const char *source_addr, struct osmo_fd *fd, int port)
{
int rc;
rc = osmo_sock_init2(AF_INET, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
rc = osmo_sock_init2(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, source_addr, port,
NULL, 0, OSMO_SOCK_F_BIND);
if (rc < 0) {
LOGP(DRTP, LOGL_ERROR, "failed to bind UDP port (%s:%i).\n",
@@ -1496,7 +1577,6 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
mgcp_set_ip_tos(rtp_end->rtp.fd, cfg->endp_dscp);
mgcp_set_ip_tos(rtp_end->rtcp.fd, cfg->endp_dscp);
rtp_end->rtp.when = OSMO_FD_READ;
if (osmo_fd_register(&rtp_end->rtp) != 0) {
LOGPENDP(endp, DRTP, LOGL_ERROR,
"failed to register RTP port %d\n",
@@ -1504,7 +1584,6 @@ static int bind_rtp(struct mgcp_config *cfg, const char *source_addr,
goto cleanup2;
}
rtp_end->rtcp.when = OSMO_FD_READ;
if (osmo_fd_register(&rtp_end->rtcp) != 0) {
LOGPENDP(endp, DRTP, LOGL_ERROR,
"failed to register RTCP port %d\n",
@@ -1536,7 +1615,6 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
{
char name[512];
struct mgcp_rtp_end *end;
char local_ip_addr[INET_ADDRSTRLEN];
snprintf(name, sizeof(name), "%s-%s", conn->conn->name, conn->conn->id);
end = &conn->end;
@@ -1554,14 +1632,10 @@ int mgcp_bind_net_rtp_port(struct mgcp_endpoint *endp, int rtp_port,
}
end->local_port = rtp_port;
end->rtp.cb = rtp_data_net;
end->rtp.data = conn;
end->rtcp.data = conn;
end->rtcp.cb = rtp_data_net;
osmo_fd_setup(&end->rtp, -1, OSMO_FD_READ, rtp_data_net, conn, 0);
osmo_fd_setup(&end->rtcp, -1, OSMO_FD_READ, rtp_data_net, conn, 0);
mgcp_get_local_addr(local_ip_addr, conn);
return bind_rtp(endp->cfg, local_ip_addr, end, endp);
return bind_rtp(endp->cfg, conn->end.local_addr, end, endp);
}
/*! free allocated RTP and RTCP ports.

View File

@@ -35,6 +35,7 @@ static LLIST_HEAD(osmux_handle_list);
struct osmux_handle {
struct llist_head head;
struct mgcp_conn_rtp *conn;
struct osmux_in_handle *in;
struct in_addr rem_addr;
int rem_port; /* network byte order */
@@ -47,14 +48,17 @@ static void *osmux;
static void osmux_deliver_cb(struct msgb *batch_msg, void *data)
{
struct osmux_handle *handle = data;
struct sockaddr_in out = {
.sin_family = AF_INET,
.sin_port = handle->rem_port,
};
struct mgcp_conn_rtp *conn = handle->conn;
memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0,
(struct sockaddr *)&out, sizeof(out));
if (conn->end.output_enabled) {
struct sockaddr_in out = {
.sin_family = AF_INET,
.sin_port = handle->rem_port,
};
memcpy(&out.sin_addr, &handle->rem_addr, sizeof(handle->rem_addr));
sendto(osmux_fd.fd, batch_msg->data, batch_msg->len, 0,
(struct sockaddr *)&out, sizeof(out));
}
msgb_free(batch_msg);
}
@@ -109,13 +113,15 @@ static void osmux_handle_put(struct osmux_in_handle *in)
/* Allocate free OSMUX handle */
static struct osmux_handle *
osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
osmux_handle_alloc(struct mgcp_conn_rtp *conn, struct in_addr *addr, int rem_port)
{
struct osmux_handle *h;
struct mgcp_config *cfg = conn->conn->endp->cfg;
h = talloc_zero(osmux, struct osmux_handle);
if (!h)
return NULL;
h->conn = conn;
h->rem_addr = *addr;
h->rem_port = rem_port;
h->refcnt++;
@@ -148,15 +154,20 @@ osmux_handle_alloc(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
/* Lookup existing handle for a specified address, if the handle can not be
* found, the function will automatically allocate one */
static struct osmux_in_handle *
osmux_handle_lookup(struct mgcp_config *cfg, struct in_addr *addr, int rem_port)
osmux_handle_lookup(struct mgcp_conn_rtp *conn, struct osmo_sockaddr *addr, int rem_port)
{
struct osmux_handle *h;
h = osmux_handle_find_get(addr, rem_port);
if (addr->u.sa.sa_family != AF_INET) {
LOGP(DLMGCP, LOGL_DEBUG, "IPv6 not supported in osmux yet!\n");
return NULL;
}
h = osmux_handle_find_get(&addr->u.sin.sin_addr, rem_port);
if (h != NULL)
return h->in;
h = osmux_handle_alloc(cfg, addr, rem_port);
h = osmux_handle_alloc(conn, &addr->u.sin.sin_addr, rem_port);
if (h == NULL)
return NULL;
@@ -236,7 +247,7 @@ static void scheduled_from_osmux_tx_rtp_cb(struct msgb *msg, void *data)
{
struct mgcp_conn_rtp *conn = data;
struct mgcp_endpoint *endp = conn->conn->endp;
struct sockaddr_in addr = { /* FIXME: do we know the source address?? */ };
struct osmo_sockaddr addr = { /* FIXME: do we know the source address?? */ };
struct osmo_rtp_msg_ctx *mc = OSMO_RTP_MSG_CTX(msg);
*mc = (struct osmo_rtp_msg_ctx){
.proto = MGCP_PROTO_RTP,
@@ -275,6 +286,8 @@ static struct msgb *osmux_recv(struct osmo_fd *ofd, struct sockaddr_in *addr)
static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
bool sending)
{
char ipbuf[INET6_ADDRSTRLEN];
switch(conn->osmux.state) {
case OSMUX_STATE_ACTIVATING:
if (osmux_enable_conn(endp, conn, &conn->end.addr, conn->end.rtp_port) < 0) {
@@ -287,7 +300,8 @@ static int endp_osmux_state_check(struct mgcp_endpoint *endp, struct mgcp_conn_r
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
"Osmux %s CID %u towards %s:%u is now enabled\n",
sending ? "sent" : "received",
conn->osmux.cid, inet_ntoa(conn->end.addr),
conn->osmux.cid,
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
ntohs(conn->end.rtp_port));
return 0;
case OSMUX_STATE_ENABLED:
@@ -376,6 +390,8 @@ static int osmux_read_fd_cb(struct osmo_fd *ofd, unsigned int what)
goto out;
}
mgcp_conn_watchdog_kick(conn_src->conn);
/*conn_dst = mgcp_find_dst_conn(conn_src->conn);
if (!conn_dst) {
LOGP(DLMGCP, LOGL_ERROR,
@@ -400,8 +416,7 @@ int osmux_init(int role, struct mgcp_config *cfg)
{
int ret;
osmux_fd.cb = osmux_read_fd_cb;
osmux_fd.data = cfg;
osmo_fd_setup(&osmux_fd, -1, OSMO_FD_READ, osmux_read_fd_cb, cfg, 0);
ret = mgcp_create_bind(cfg->osmux_addr, &osmux_fd, cfg->osmux_port);
if (ret < 0) {
@@ -410,7 +425,6 @@ int osmux_init(int role, struct mgcp_config *cfg)
return ret;
}
mgcp_set_ip_tos(osmux_fd.fd, cfg->endp_dscp);
osmux_fd.when |= OSMO_FD_READ;
ret = osmo_fd_register(&osmux_fd);
if (ret < 0) {
@@ -433,7 +447,7 @@ int osmux_init(int role, struct mgcp_config *cfg)
* \param[in] port portnumber of the remote OSMUX endpoint (in network byte order)
* \returns 0 on success, -1 on ERROR */
int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
struct in_addr *addr, uint16_t port)
struct osmo_sockaddr *addr, uint16_t port)
{
/*! If osmux is enabled, initialize the output handler. This handler is
* used to reconstruct the RTP flow from osmux. The RTP SSRC is
@@ -444,7 +458,7 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
* overlapping RTP SSRC traveling to the BTSes behind the BSC,
* similarly, for flows traveling to the MSC.
*/
struct in_addr addr_unset = {};
struct in6_addr addr_unset = {};
static const uint32_t rtp_ssrc_winlen = UINT32_MAX / (OSMUX_CID_MAX + 1);
uint16_t osmux_dummy = endp->cfg->osmux_dummy;
@@ -457,13 +471,16 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
}
/* Wait until we have the connection information from MDCX */
if (memcmp(&conn->end.addr, &addr_unset, sizeof(addr_unset)) == 0) {
if (memcmp(&conn->end.addr, &addr_unset,
conn->end.addr.u.sa.sa_family == AF_INET6 ?
sizeof(struct in6_addr) :
sizeof(struct in_addr)) == 0) {
LOGPCONN(conn->conn, DLMGCP, LOGL_INFO,
"Osmux remote address/port still unknown\n");
return -1;
}
conn->osmux.in = osmux_handle_lookup(endp->cfg, addr, port);
conn->osmux.in = osmux_handle_lookup(conn, addr, port);
if (!conn->osmux.in) {
LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR,
"Cannot allocate input osmux handle for conn:%s\n",
@@ -559,6 +576,7 @@ int conn_osmux_allocate_cid(struct mgcp_conn_rtp *conn, int osmux_cid)
* \returns bytes sent, -1 on error */
int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
{
char ipbuf[INET6_ADDRSTRLEN];
struct osmux_hdr *osmuxh;
int buf_len;
struct in_addr addr_unset = {};
@@ -588,7 +606,8 @@ int osmux_send_dummy(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn)
LOGPCONN(conn->conn, DLMGCP, LOGL_DEBUG,
"sending OSMUX dummy load to %s:%u CID %u\n",
inet_ntoa(conn->end.addr), ntohs(conn->end.rtp_port), conn->osmux.cid);
osmo_sockaddr_ntop(&conn->end.addr.u.sa, ipbuf),
ntohs(conn->end.rtp_port), conn->osmux.cid);
return mgcp_udp_send(osmux_fd.fd, &conn->end.addr,
conn->end.rtp_port, (char*)osmuxh, buf_len);

View File

@@ -223,24 +223,22 @@ static struct msgb *create_response_with_sdp(struct mgcp_endpoint *endp,
const char *trans_id,
bool add_conn_params)
{
/* TODO: we may want to define another local_ip_osmux var to us for
OSMUX connections. Perhaps adding a new internal API to get it based
on conn type */
const char *addr = endp->cfg->local_ip;
/* cfg->local_ip allows overwritting the announced IP address with
* regards to the one we actually bind to. Useful in behind-NAT
* scenarios.
* TODO: we may want to define another local_ip_osmux var to
* us for OSMUX connections. Perhaps adding a new internal API to get it
* based on conn type.
*/
const char *addr = endp->cfg->local_ip ? : conn->end.local_addr;
struct msgb *sdp;
int rc;
struct msgb *result;
char local_ip_addr[INET_ADDRSTRLEN];
sdp = msgb_alloc_headroom(4096, 128, "sdp record");
if (!sdp)
return NULL;
if (!addr) {
mgcp_get_local_addr(local_ip_addr, conn);
addr = local_ip_addr;
}
/* Attach optional connection parameters */
if (add_conn_params) {
rc = add_params(sdp, endp, conn);
@@ -526,6 +524,7 @@ static int set_local_cx_options(void *ctx, struct mgcp_lco *lco,
{
char *lco_id;
char codec[17];
char nt[17];
int len;
if (!options)
@@ -552,7 +551,7 @@ static int set_local_cx_options(void *ctx, struct mgcp_lco *lco,
lco->pkt_period_max = lco->pkt_period_min;
break;
case 'a':
/* FIXME: LCO also supports the negotiation of more then one codec.
/* FIXME: LCO also supports the negotiation of more than one codec.
* (e.g. a:PCMU;G726-32) But this implementation only supports a single
* codec only. */
if (sscanf(lco_id + 1, ":%16[^,]", codec) == 1) {
@@ -564,6 +563,10 @@ static int set_local_cx_options(void *ctx, struct mgcp_lco *lco,
osmo_str_toupper_buf(lco->codec, len + 1, codec);
}
break;
case 'n':
if (lco_id[1] == 't' && sscanf(lco_id + 2, ":%16[^,]", nt) == 1)
break;
/* else: fall throught to print notice log */
default:
LOGP(DLMGCP, LOGL_NOTICE,
"LCO: unhandled option: '%c'/%d in \"%s\"\n",
@@ -709,7 +712,7 @@ static bool parse_x_osmo_ign(struct mgcp_endpoint *endp, char *line)
{
char *saveptr = NULL;
if (strncmp(line, MGCP_X_OSMO_IGN_HEADER, strlen(MGCP_X_OSMO_IGN_HEADER)))
if (strncasecmp(line, MGCP_X_OSMO_IGN_HEADER, strlen(MGCP_X_OSMO_IGN_HEADER)))
return false;
line += strlen(MGCP_X_OSMO_IGN_HEADER);
@@ -746,8 +749,11 @@ static struct msgb *handle_create_con(struct mgcp_parse_data *p)
int rc;
LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: creating new connection ...\n");
if (!mgcp_endp_avail(endp)) {
rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_AVAIL]);
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"CRCX: selected endpoint not available!\n");
return create_err_response(NULL, 501, "CRCX", p->trans);
}
@@ -940,6 +946,9 @@ mgcp_header_done:
goto error2;
}
/* Find a local address for conn based on policy and initial SDP remote
information, then find a free port for it */
mgcp_get_local_addr(conn->end.local_addr, conn);
if (allocate_port(endp, conn) != 0) {
rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_BIND_PORT]);
goto error2;
@@ -1002,6 +1011,7 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
{
struct mgcp_endpoint *endp = p->endp;
struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.mgcp_mdcx_ctr_group;
char new_local_addr[INET6_ADDRSTRLEN];
int error_code = 500;
int silent = 0;
int have_sdp = 0;
@@ -1017,6 +1027,8 @@ static struct msgb *handle_modify_con(struct mgcp_parse_data *p)
if (!mgcp_endp_avail(endp)) {
rate_ctr_inc(&rate_ctrs->ctr[MGCP_MDCX_FAIL_AVAIL]);
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"MDCX: selected endpoint not available!\n");
return create_err_response(NULL, 501, "MDCX", p->trans);
}
@@ -1164,6 +1176,20 @@ mgcp_header_done:
that conn. */
}
/* MDCX may have provided a new remote address, which means we may need
to update our announced IP addr and re-bind our local end. This can
happen for instance if MGW initially provided an IPv4 during CRCX
ACK, and now MDCX tells us the remote has an IPv6 address. */
mgcp_get_local_addr(new_local_addr, conn);
if (strcmp(new_local_addr, conn->end.local_addr)) {
osmo_strlcpy(conn->end.local_addr, new_local_addr, sizeof(conn->end.local_addr));
mgcp_free_rtp_port(&conn->end);
if (allocate_port(endp, conn) != 0) {
rate_ctr_inc(&rate_ctrs->ctr[MGCP_CRCX_FAIL_BIND_PORT]);
goto error3;
}
}
if (setup_rtp_processing(endp, conn) != 0) {
rate_ctr_inc(&rate_ctrs->ctr[MGCP_MDCX_FAIL_START_RTP]);
goto error3;
@@ -1243,6 +1269,8 @@ static struct msgb *handle_delete_con(struct mgcp_parse_data *p)
if (!mgcp_endp_avail(endp)) {
rate_ctr_inc(&rate_ctrs->ctr[MGCP_DLCX_FAIL_AVAIL]);
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"DLCX: selected endpoint not available!\n");
return create_err_response(NULL, 501, "DLCX", p->trans);
}

View File

@@ -21,6 +21,9 @@
*/
#include <osmocom/core/msgb.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/mgcp/mgcp.h>
#include <osmocom/mgcp/osmux.h>
#include <osmocom/mgcp/mgcp_conn.h>
@@ -259,6 +262,42 @@ error:
return -EINVAL;
}
static int audio_ip_from_sdp(struct osmo_sockaddr *dst_addr, char *sdp)
{
bool is_ipv6;
char ipbuf[INET6_ADDRSTRLEN];
if (strncmp("c=IN IP", sdp, 7) != 0)
return -1;
sdp += 7;
if (*sdp == '6')
is_ipv6 = true;
else if (*sdp == '4')
is_ipv6 = false;
else
return -1;
sdp++;
if (*sdp != ' ')
return -1;
sdp++;
if (is_ipv6) {
/* 45 = INET6_ADDRSTRLEN -1 */
if (sscanf(sdp, "%45s", ipbuf) != 1)
return -1;
if (inet_pton(AF_INET6, ipbuf, &dst_addr->u.sin6.sin6_addr) != 1)
return -1;
dst_addr->u.sa.sa_family = AF_INET6;
} else {
/* 15 = INET_ADDRSTRLEN -1 */
if (sscanf(sdp, "%15s", ipbuf) != 1)
return -1;
if (inet_pton(AF_INET, ipbuf, &dst_addr->u.sin.sin_addr) != 1)
return -1;
dst_addr->u.sa.sa_family = AF_INET;
}
return 0;
}
/* Pick optional fmtp parameters by payload type, if there are no fmtp
* parameters, a nullpointer is returned */
static struct mgcp_codec_param *param_by_pt(int pt, struct sdp_fmtp_param *fmtp_params, unsigned int fmtp_params_len)
@@ -289,6 +328,7 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
struct sdp_fmtp_param fmtp_params[MGCP_MAX_CODECS];
unsigned int fmtp_used = 0;
struct mgcp_codec_param *codec_param;
char ipbuf[INET6_ADDRSTRLEN];
char *line;
unsigned int i;
void *tmp_ctx = talloc_new(NULL);
@@ -298,7 +338,6 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
int ptime, ptime2 = 0;
char audio_name[64];
int port, rc;
char ipv4[16];
OSMO_ASSERT(endp);
OSMO_ASSERT(conn);
@@ -355,10 +394,8 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
codecs_used = rc;
break;
case 'c':
if (sscanf(line, "c=IN IP4 %15s", ipv4) == 1) {
inet_aton(ipv4, &rtp->addr);
}
if (audio_ip_from_sdp(&rtp->addr, line) < 0)
return -1;
break;
default:
if (p->endp)
@@ -393,7 +430,7 @@ int mgcp_parse_sdp_data(const struct mgcp_endpoint *endp,
LOGPCONN(conn->conn, DLMGCP, LOGL_NOTICE,
"Got media info via SDP: port:%d, addr:%s, duration:%d, payload-types:",
ntohs(rtp->rtp_port), inet_ntoa(rtp->addr),
ntohs(rtp->rtp_port), osmo_sockaddr_ntop(&rtp->addr.u.sa, ipbuf),
rtp->packet_duration_ms);
if (codecs_used == 0)
LOGPC(DLMGCP, LOGL_NOTICE, "none");
@@ -529,6 +566,7 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
int local_port;
struct sdp_fmtp_param fmtp_params[1];
unsigned int fmtp_params_len = 0;
bool addr_is_v6;
OSMO_ASSERT(endp);
OSMO_ASSERT(conn);
@@ -543,12 +581,16 @@ int mgcp_write_response_sdp(const struct mgcp_endpoint *endp,
audio_name = codec->audio_name;
payload_type = codec->payload_type;
addr_is_v6 = osmo_ip_str_type(addr) == AF_INET6;
rc = msgb_printf(sdp,
"v=0\r\n"
"o=- %s 23 IN IP4 %s\r\n"
"o=- %s 23 IN IP%c %s\r\n"
"s=-\r\n"
"c=IN IP4 %s\r\n"
"t=0 0\r\n", conn->conn->id, addr, addr);
"c=IN IP%c %s\r\n"
"t=0 0\r\n", conn->conn->id,
addr_is_v6 ? '6' : '4', addr,
addr_is_v6 ? '6' : '4', addr);
if (rc < 0)
goto buffer_too_small;

View File

@@ -50,7 +50,7 @@ struct mgcp_trunk *mgcp_trunk_alloc(struct mgcp_config *cfg, enum mgcp_trunk_typ
trunk->audio_send_ptime = 1;
trunk->audio_send_name = 1;
trunk->v.vty_number_endpoints = 32;
trunk->v.vty_number_endpoints = 512;
trunk->omit_rtcp = 0;
mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
@@ -190,7 +190,7 @@ int e1_trunk_nr_from_epname(const char *epname)
errno = 0;
trunk_nr = strtoul(epname + prefix_len, &str_trunk_nr_end, 10);
if (errno == ERANGE || trunk_nr > 64 || trunk_nr == 0
if (errno == ERANGE || trunk_nr > 64
|| epname + prefix_len == str_trunk_nr_end
|| str_trunk_nr_end[0] != '/')
return -EINVAL;
@@ -217,7 +217,7 @@ struct mgcp_trunk *mgcp_trunk_by_name(const struct mgcp_config *cfg, const char
}
trunk_nr = e1_trunk_nr_from_epname(epname);
if (trunk_nr > 0)
if (trunk_nr >= 0)
return mgcp_trunk_by_num(cfg, MGCP_TRUNK_E1, trunk_nr);
/* Earlier versions of osmo-mgw were accepting endpoint names

View File

@@ -22,6 +22,7 @@
*/
#include <osmocom/core/talloc.h>
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/vty/misc.h>
#include <osmocom/mgcp/mgcp.h>
#include <osmocom/mgcp/mgcp_common.h>
@@ -41,6 +42,7 @@
#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
#define RTP_TS101318_RFC5993_CONV_STR "Convert GSM-HR from TS101318 to RFC5993 and vice versa\n"
#define X(x) (1 << x)
static struct mgcp_config *g_cfg = NULL;
@@ -70,9 +72,12 @@ static int config_write_mgcp(struct vty *vty)
vty_out(vty, " rtp port-range %u %u%s",
g_cfg->net_ports.range_start, g_cfg->net_ports.range_end,
VTY_NEWLINE);
if (g_cfg->net_ports.bind_addr)
if (g_cfg->net_ports.bind_addr_v4)
vty_out(vty, " rtp bind-ip %s%s",
g_cfg->net_ports.bind_addr, VTY_NEWLINE);
g_cfg->net_ports.bind_addr_v4, VTY_NEWLINE);
if (g_cfg->net_ports.bind_addr_v6)
vty_out(vty, " rtp bind-ip-v6 %s%s",
g_cfg->net_ports.bind_addr_v6, VTY_NEWLINE);
if (g_cfg->net_ports.bind_addr_probe)
vty_out(vty, " rtp ip-probing%s", VTY_NEWLINE);
else
@@ -111,7 +116,6 @@ static int config_write_mgcp(struct vty *vty)
trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
vty_out(vty, " %ssdp audio-payload send-name%s",
trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
vty_out(vty, " loop %u%s", ! !trunk->audio_loop, VTY_NEWLINE);
vty_out(vty, " number endpoints %u%s",
trunk->v.vty_number_endpoints, VTY_NEWLINE);
vty_out(vty, " %sallow-transcoding%s",
@@ -405,11 +409,14 @@ DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_local_ip,
cfg_mgcp_local_ip_cmd,
"local ip A.B.C.D",
"Local options for the SDP record\n"
IP_STR "IPv4 Address to use in SDP record\n")
DEFUN_USRATTR(cfg_mgcp_local_ip,
cfg_mgcp_local_ip_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"local ip " VTY_IPV46_CMD,
"Local options for the SDP record\n"
IP_STR
"IPv4 Address to use in SDP record\n"
"IPv6 Address to use in SDP record\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
return CMD_SUCCESS;
@@ -418,7 +425,10 @@ DEFUN(cfg_mgcp_local_ip,
#define BIND_STR "Listen/Bind related socket option\n"
DEFUN(cfg_mgcp_bind_ip,
cfg_mgcp_bind_ip_cmd,
"bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
"bind ip " VTY_IPV46_CMD,
BIND_STR IP_STR
"IPv4 Address to bind to\n"
"IPv6 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
return CMD_SUCCESS;
@@ -434,14 +444,13 @@ DEFUN(cfg_mgcp_bind_port,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_bind_early,
cfg_mgcp_bind_early_cmd,
"bind early (0|1)",
BIND_STR
"Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
DEFUN_DEPRECATED(cfg_mgcp_bind_early,
cfg_mgcp_bind_early_cmd,
"bind early (0|1)",
BIND_STR
"Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
{
vty_out(vty, "bind early is deprecated, remove it from the config.\n");
return CMD_WARNING;
return CMD_SUCCESS;
}
#define RTP_STR "RTP configuration\n"
@@ -492,12 +501,14 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
RTP_STR "Range of ports to use for the NET side\n"
RANGE_START_STR RANGE_END_STR)
DEFUN(cfg_mgcp_rtp_bind_ip,
cfg_mgcp_rtp_bind_ip_cmd,
"rtp bind-ip A.B.C.D",
RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
DEFUN_USRATTR(cfg_mgcp_rtp_bind_ip,
cfg_mgcp_rtp_bind_ip_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp bind-ip A.B.C.D",
RTP_STR "Bind endpoints facing the Network\n"
"IPv4 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr_v4, argv[0]);
return CMD_SUCCESS;
}
ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
@@ -505,14 +516,15 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
"rtp net-bind-ip A.B.C.D",
RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
DEFUN(cfg_mgcp_rtp_no_bind_ip,
cfg_mgcp_rtp_no_bind_ip_cmd,
"no rtp bind-ip",
NO_STR RTP_STR "Bind endpoints facing the Network\n"
"Address to bind to\n")
DEFUN_USRATTR(cfg_mgcp_rtp_no_bind_ip,
cfg_mgcp_rtp_no_bind_ip_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp bind-ip",
NO_STR RTP_STR "Bind endpoints facing the Network\n"
"Address to bind to\n")
{
talloc_free(g_cfg->net_ports.bind_addr);
g_cfg->net_ports.bind_addr = NULL;
talloc_free(g_cfg->net_ports.bind_addr_v4);
g_cfg->net_ports.bind_addr_v4 = NULL;
return CMD_SUCCESS;
}
ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
@@ -521,29 +533,55 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
NO_STR RTP_STR "Bind endpoints facing the Network\n"
"Address to bind to\n")
DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
cfg_mgcp_rtp_net_bind_ip_probing_cmd,
"rtp ip-probing",
RTP_STR "automatic rtp bind ip selection\n")
DEFUN_USRATTR(cfg_mgcp_rtp_bind_ip_v6,
cfg_mgcp_rtp_bind_ip_v6_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp bind-ip-v6 " VTY_IPV6_CMD,
RTP_STR "Bind endpoints facing the Network\n"
"IPv6 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr_v6, argv[0]);
return CMD_SUCCESS;
}
DEFUN_USRATTR(cfg_mgcp_rtp_no_bind_ip_v6,
cfg_mgcp_rtp_no_bind_ip_v6_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp bind-ip-v6",
NO_STR RTP_STR "Bind endpoints facing the Network\n"
"Address to bind to\n")
{
talloc_free(g_cfg->net_ports.bind_addr_v6);
g_cfg->net_ports.bind_addr_v6 = NULL;
return CMD_SUCCESS;
}
DEFUN_USRATTR(cfg_mgcp_rtp_net_bind_ip_probing,
cfg_mgcp_rtp_net_bind_ip_probing_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp ip-probing",
RTP_STR "automatic rtp bind ip selection\n")
{
g_cfg->net_ports.bind_addr_probe = true;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
"no rtp ip-probing",
NO_STR RTP_STR "no automatic rtp bind ip selection\n")
DEFUN_USRATTR(cfg_mgcp_rtp_no_net_bind_ip_probing,
cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp ip-probing",
NO_STR RTP_STR "no automatic rtp bind ip selection\n")
{
g_cfg->net_ports.bind_addr_probe = false;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_rtp_ip_dscp,
cfg_mgcp_rtp_ip_dscp_cmd,
"rtp ip-dscp <0-255>",
RTP_STR
"Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
DEFUN_USRATTR(cfg_mgcp_rtp_ip_dscp,
cfg_mgcp_rtp_ip_dscp_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp ip-dscp <0-255>",
RTP_STR
"Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
{
int dscp = atoi(argv[0]);
g_cfg->endp_dscp = dscp;
@@ -555,29 +593,32 @@ ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
RTP_STR
"Apply IP_TOS to the audio stream\n" "The DSCP value\n")
#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
DEFUN(cfg_mgcp_rtp_force_ptime,
cfg_mgcp_rtp_force_ptime_cmd,
"rtp force-ptime (10|20|40)",
RTP_STR FORCE_PTIME_STR
"The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
DEFUN_USRATTR(cfg_mgcp_rtp_force_ptime,
cfg_mgcp_rtp_force_ptime_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp force-ptime (10|20|40)",
RTP_STR FORCE_PTIME_STR
"The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
{
g_cfg->force_ptime = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_rtp_force_ptime,
cfg_mgcp_no_rtp_force_ptime_cmd,
"no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
DEFUN_USRATTR(cfg_mgcp_no_rtp_force_ptime,
cfg_mgcp_no_rtp_force_ptime_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
{
g_cfg->force_ptime = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_sdp_fmtp_extra,
cfg_mgcp_sdp_fmtp_extra_cmd,
"sdp audio fmtp-extra .NAME",
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
"Extra Information\n")
DEFUN_USRATTR(cfg_mgcp_sdp_fmtp_extra,
cfg_mgcp_sdp_fmtp_extra_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"sdp audio fmtp-extra .NAME",
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
"Extra Information\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -590,9 +631,10 @@ DEFUN(cfg_mgcp_sdp_fmtp_extra,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_allow_transcoding,
cfg_mgcp_allow_transcoding_cmd,
"allow-transcoding", "Allow transcoding\n")
DEFUN_USRATTR(cfg_mgcp_allow_transcoding,
cfg_mgcp_allow_transcoding_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"allow-transcoding", "Allow transcoding\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -600,9 +642,10 @@ DEFUN(cfg_mgcp_allow_transcoding,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_allow_transcoding,
cfg_mgcp_no_allow_transcoding_cmd,
"no allow-transcoding", NO_STR "Allow transcoding\n")
DEFUN_USRATTR(cfg_mgcp_no_allow_transcoding,
cfg_mgcp_no_allow_transcoding_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no allow-transcoding", NO_STR "Allow transcoding\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -637,10 +680,11 @@ ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
"sdp audio payload name NAME",
SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
DEFUN(cfg_mgcp_sdp_payload_send_ptime,
cfg_mgcp_sdp_payload_send_ptime_cmd,
"sdp audio-payload send-ptime",
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
DEFUN_USRATTR(cfg_mgcp_sdp_payload_send_ptime,
cfg_mgcp_sdp_payload_send_ptime_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"sdp audio-payload send-ptime",
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -648,10 +692,11 @@ DEFUN(cfg_mgcp_sdp_payload_send_ptime,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
cfg_mgcp_no_sdp_payload_send_ptime_cmd,
"no sdp audio-payload send-ptime",
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
DEFUN_USRATTR(cfg_mgcp_no_sdp_payload_send_ptime,
cfg_mgcp_no_sdp_payload_send_ptime_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no sdp audio-payload send-ptime",
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -659,10 +704,11 @@ DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_sdp_payload_send_name,
cfg_mgcp_sdp_payload_send_name_cmd,
"sdp audio-payload send-name",
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
DEFUN_USRATTR(cfg_mgcp_sdp_payload_send_name,
cfg_mgcp_sdp_payload_send_name_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"sdp audio-payload send-name",
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -670,10 +716,11 @@ DEFUN(cfg_mgcp_sdp_payload_send_name,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_sdp_payload_send_name,
cfg_mgcp_no_sdp_payload_send_name_cmd,
"no sdp audio-payload send-name",
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
DEFUN_USRATTR(cfg_mgcp_no_sdp_payload_send_name,
cfg_mgcp_no_sdp_payload_send_name_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no sdp audio-payload send-name",
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -681,26 +728,20 @@ DEFUN(cfg_mgcp_no_sdp_payload_send_name,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_loop,
cfg_mgcp_loop_cmd,
"loop (0|1)",
"Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
DEFUN_DEPRECATED(cfg_mgcp_loop,
cfg_mgcp_loop_cmd,
"loop (0|1)",
"Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
if (g_cfg->osmux) {
vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
return CMD_WARNING;
}
trunk->audio_loop = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_force_realloc,
cfg_mgcp_force_realloc_cmd,
"force-realloc (0|1)",
"Force endpoint reallocation when the endpoint is still seized\n"
"Don't force reallocation\n" "force reallocation\n")
DEFUN_USRATTR(cfg_mgcp_force_realloc,
cfg_mgcp_force_realloc_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"force-realloc (0|1)",
"Force endpoint reallocation when the endpoint is still seized\n"
"Don't force reallocation\n" "force reallocation\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -708,11 +749,12 @@ DEFUN(cfg_mgcp_force_realloc,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_rtp_accept_all,
cfg_mgcp_rtp_accept_all_cmd,
"rtp-accept-all (0|1)",
"Accept all RTP packets, even when the originating IP/Port does not match\n"
"enable filter\n" "disable filter\n")
DEFUN_ATTR(cfg_mgcp_rtp_accept_all,
cfg_mgcp_rtp_accept_all_cmd,
"rtp-accept-all (0|1)",
"Accept all RTP packets, even when the originating IP/Port does not match\n"
"enable filter\n" "disable filter\n",
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -731,15 +773,21 @@ DEFUN(cfg_mgcp_number_endp,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
DEFUN_ATTR(cfg_mgcp_omit_rtcp,
cfg_mgcp_omit_rtcp_cmd,
"rtcp-omit", RTCP_OMIT_STR,
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
trunk->omit_rtcp = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_omit_rtcp,
cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
DEFUN_ATTR(cfg_mgcp_no_omit_rtcp,
cfg_mgcp_no_omit_rtcp_cmd,
"no rtcp-omit",
NO_STR RTCP_OMIT_STR,
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -747,9 +795,10 @@ DEFUN(cfg_mgcp_no_omit_rtcp,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_patch_rtp_ssrc,
cfg_mgcp_patch_rtp_ssrc_cmd,
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
DEFUN_USRATTR(cfg_mgcp_patch_rtp_ssrc,
cfg_mgcp_patch_rtp_ssrc_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -757,9 +806,10 @@ DEFUN(cfg_mgcp_patch_rtp_ssrc,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
cfg_mgcp_no_patch_rtp_ssrc_cmd,
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp_ssrc,
cfg_mgcp_no_patch_rtp_ssrc_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -767,9 +817,10 @@ DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_patch_rtp_ts,
cfg_mgcp_patch_rtp_ts_cmd,
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
DEFUN_USRATTR(cfg_mgcp_patch_rtp_ts,
cfg_mgcp_patch_rtp_ts_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -777,9 +828,10 @@ DEFUN(cfg_mgcp_patch_rtp_ts,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_patch_rtp_ts,
cfg_mgcp_no_patch_rtp_ts_cmd,
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp_ts,
cfg_mgcp_no_patch_rtp_ts_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -787,9 +839,10 @@ DEFUN(cfg_mgcp_no_patch_rtp_ts,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
cfg_mgcp_patch_rtp_rfc5993hr_cmd,
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
DEFUN_USRATTR(cfg_mgcp_patch_rtp_rfc5993hr,
cfg_mgcp_patch_rtp_rfc5993hr_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -797,9 +850,10 @@ DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp_rfc5993hr,
cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -807,8 +861,10 @@ DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_patch_rtp,
cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
DEFUN_USRATTR(cfg_mgcp_no_patch_rtp,
cfg_mgcp_no_patch_rtp_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch", NO_STR RTP_PATCH_STR)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -818,10 +874,11 @@ DEFUN(cfg_mgcp_no_patch_rtp,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_rtp_keepalive,
cfg_mgcp_rtp_keepalive_cmd,
"rtp keep-alive <1-120>",
RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
DEFUN_ATTR(cfg_mgcp_rtp_keepalive,
cfg_mgcp_rtp_keepalive_cmd,
"rtp keep-alive <1-120>",
RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n",
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -829,10 +886,11 @@ DEFUN(cfg_mgcp_rtp_keepalive,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_rtp_keepalive_once,
cfg_mgcp_rtp_keepalive_once_cmd,
"rtp keep-alive once",
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
DEFUN_ATTR(cfg_mgcp_rtp_keepalive_once,
cfg_mgcp_rtp_keepalive_once_cmd,
"rtp keep-alive once",
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n",
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -840,9 +898,10 @@ DEFUN(cfg_mgcp_rtp_keepalive_once,
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_no_rtp_keepalive,
cfg_mgcp_no_rtp_keepalive_cmd,
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
DEFUN_ATTR(cfg_mgcp_no_rtp_keepalive,
cfg_mgcp_no_rtp_keepalive_cmd,
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR,
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_VIRTUAL, MGCP_VIRT_TRUNK_ID);
OSMO_ASSERT(trunk);
@@ -850,11 +909,13 @@ DEFUN(cfg_mgcp_no_rtp_keepalive,
return CMD_SUCCESS;
}
#define CALL_AGENT_STR "Callagent information\n"
#define CALL_AGENT_STR "Call agent information\n"
DEFUN(cfg_mgcp_agent_addr,
cfg_mgcp_agent_addr_cmd,
"call-agent ip A.B.C.D",
CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
"call-agent ip " VTY_IPV46_CMD,
CALL_AGENT_STR IP_STR
"IPv4 Address of the call agent\n"
"IPv6 Address of the call agent\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
return CMD_SUCCESS;
@@ -866,16 +927,11 @@ ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
"IPv4 Address of the callagent\n")
DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
"trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
"trunk <0-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
{
struct mgcp_trunk *trunk;
int index = atoi(argv[0]);
/* Due to historical reasons, the trunk id number 0 is reserved for the
* virtual trunk. This trunk is configured with separate VTY
* parameters, so we restrict the access to trunks with id numbers
* greater than 0. */
trunk = mgcp_trunk_by_num(g_cfg, MGCP_TRUNK_E1, index);
if (!trunk) {
trunk = mgcp_trunk_alloc(g_cfg, MGCP_TRUNK_E1, index);
@@ -902,7 +958,8 @@ static int config_write_trunk(struct vty *vty)
config of trunk 0 here. The configuration for the virtual
trunk is written by config_write_mgcp(). */
if (trunk->trunk_nr == MGCP_VIRT_TRUNK_ID)
if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL
&& trunk->trunk_nr == MGCP_VIRT_TRUNK_ID)
continue;
vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
@@ -919,7 +976,6 @@ static int config_write_trunk(struct vty *vty)
trunk->keepalive_interval, VTY_NEWLINE);
else
vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
vty_out(vty, " force-realloc %d%s",
trunk->force_realloc, VTY_NEWLINE);
vty_out(vty, " rtp-accept-all %d%s",
@@ -951,11 +1007,12 @@ static int config_write_trunk(struct vty *vty)
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_sdp_fmtp_extra,
cfg_trunk_sdp_fmtp_extra_cmd,
"sdp audio fmtp-extra .NAME",
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
"Extra Information\n")
DEFUN_USRATTR(cfg_trunk_sdp_fmtp_extra,
cfg_trunk_sdp_fmtp_extra_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"sdp audio fmtp-extra .NAME",
"Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
"Extra Information\n")
{
struct mgcp_trunk *trunk = vty->index;
char *txt = argv_concat(argv, argc, 0);
@@ -991,132 +1048,168 @@ ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
"sdp audio payload name NAME",
SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
DEFUN(cfg_trunk_loop,
cfg_trunk_loop_cmd,
"loop (0|1)",
"Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
DEFUN_DEPRECATED(cfg_trunk_loop,
cfg_trunk_loop_cmd,
"loop (0|1)",
"Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
{
struct mgcp_trunk *trunk = vty->index;
if (g_cfg->osmux) {
vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
return CMD_WARNING;
}
trunk->audio_loop = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_sdp_payload_send_ptime,
cfg_trunk_sdp_payload_send_ptime_cmd,
"sdp audio-payload send-ptime",
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
DEFUN_USRATTR(cfg_trunk_force_realloc,
cfg_trunk_force_realloc_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"force-realloc (0|1)",
"Force endpoint reallocation when the endpoint is still seized\n"
"Don't force reallocation\n" "force reallocation\n")
{
struct mgcp_trunk *trunk = vty->index;
OSMO_ASSERT(trunk);
trunk->force_realloc = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_ATTR(cfg_trunk_rtp_accept_all,
cfg_trunk_rtp_accept_all_cmd,
"rtp-accept-all (0|1)",
"Accept all RTP packets, even when the originating IP/Port does not match\n"
"enable filter\n" "disable filter\n",
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = vty->index;
OSMO_ASSERT(trunk);
trunk->rtp_accept_all = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN_USRATTR(cfg_trunk_sdp_payload_send_ptime,
cfg_trunk_sdp_payload_send_ptime_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"sdp audio-payload send-ptime",
SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->audio_send_ptime = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
cfg_trunk_no_sdp_payload_send_ptime_cmd,
"no sdp audio-payload send-ptime",
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
DEFUN_USRATTR(cfg_trunk_no_sdp_payload_send_ptime,
cfg_trunk_no_sdp_payload_send_ptime_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no sdp audio-payload send-ptime",
NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->audio_send_ptime = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_sdp_payload_send_name,
cfg_trunk_sdp_payload_send_name_cmd,
"sdp audio-payload send-name",
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
DEFUN_USRATTR(cfg_trunk_sdp_payload_send_name,
cfg_trunk_sdp_payload_send_name_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"sdp audio-payload send-name",
SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->audio_send_name = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_sdp_payload_send_name,
cfg_trunk_no_sdp_payload_send_name_cmd,
"no sdp audio-payload send-name",
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
DEFUN_USRATTR(cfg_trunk_no_sdp_payload_send_name,
cfg_trunk_no_sdp_payload_send_name_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no sdp audio-payload send-name",
NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->audio_send_name = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
DEFUN_ATTR(cfg_trunk_omit_rtcp,
cfg_trunk_omit_rtcp_cmd,
"rtcp-omit", RTCP_OMIT_STR,
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = vty->index;
trunk->omit_rtcp = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_omit_rtcp,
cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
DEFUN_ATTR(cfg_trunk_no_omit_rtcp,
cfg_trunk_no_omit_rtcp_cmd,
"no rtcp-omit", NO_STR RTCP_OMIT_STR,
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = vty->index;
trunk->omit_rtcp = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_patch_rtp_ssrc,
cfg_trunk_patch_rtp_ssrc_cmd,
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
DEFUN_USRATTR(cfg_trunk_patch_rtp_ssrc,
cfg_trunk_patch_rtp_ssrc_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->force_constant_ssrc = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_patch_rtp_ssrc,
cfg_trunk_no_patch_rtp_ssrc_cmd,
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
DEFUN_USRATTR(cfg_trunk_no_patch_rtp_ssrc,
cfg_trunk_no_patch_rtp_ssrc_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->force_constant_ssrc = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_patch_rtp_ts,
cfg_trunk_patch_rtp_ts_cmd,
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
DEFUN_USRATTR(cfg_trunk_patch_rtp_ts,
cfg_trunk_patch_rtp_ts_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->force_aligned_timing = 1;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_patch_rtp_ts,
cfg_trunk_no_patch_rtp_ts_cmd,
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
DEFUN_USRATTR(cfg_trunk_no_patch_rtp_ts,
cfg_trunk_no_patch_rtp_ts_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->force_aligned_timing = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_patch_rtp_rfc5993hr,
cfg_trunk_patch_rtp_rfc5993hr_cmd,
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
DEFUN_USRATTR(cfg_trunk_patch_rtp_rfc5993hr,
cfg_trunk_patch_rtp_rfc5993hr_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
{
struct mgcp_trunk *trunk = vty->index;
trunk->rfc5993_hr_convert = true;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_patch_rtp_rfc5993hr,
cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
DEFUN_USRATTR(cfg_trunk_no_patch_rtp_rfc5993hr,
cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
{
struct mgcp_trunk *trunk = vty->index;
trunk->rfc5993_hr_convert = false;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_patch_rtp,
cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
DEFUN_USRATTR(cfg_trunk_no_patch_rtp,
cfg_trunk_no_patch_rtp_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no rtp-patch", NO_STR RTP_PATCH_STR)
{
struct mgcp_trunk *trunk = vty->index;
trunk->force_constant_ssrc = 0;
@@ -1125,47 +1218,52 @@ DEFUN(cfg_trunk_no_patch_rtp,
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_rtp_keepalive,
cfg_trunk_rtp_keepalive_cmd,
"rtp keep-alive <1-120>",
RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
DEFUN_ATTR(cfg_trunk_rtp_keepalive,
cfg_trunk_rtp_keepalive_cmd,
"rtp keep-alive <1-120>",
RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n",
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = vty->index;
mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_rtp_keepalive_once,
cfg_trunk_rtp_keepalive_once_cmd,
"rtp keep-alive once",
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
DEFUN_ATTR(cfg_trunk_rtp_keepalive_once,
cfg_trunk_rtp_keepalive_once_cmd,
"rtp keep-alive once",
RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n",
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = vty->index;
mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_rtp_keepalive,
cfg_trunk_no_rtp_keepalive_cmd,
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
DEFUN_ATTR(cfg_trunk_no_rtp_keepalive,
cfg_trunk_no_rtp_keepalive_cmd,
"no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR,
CMD_ATTR_IMMEDIATE)
{
struct mgcp_trunk *trunk = vty->index;
mgcp_trunk_set_keepalive(trunk, 0);
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_allow_transcoding,
cfg_trunk_allow_transcoding_cmd,
"allow-transcoding", "Allow transcoding\n")
DEFUN_USRATTR(cfg_trunk_allow_transcoding,
cfg_trunk_allow_transcoding_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"allow-transcoding", "Allow transcoding\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->no_audio_transcoding = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_trunk_no_allow_transcoding,
cfg_trunk_no_allow_transcoding_cmd,
"no allow-transcoding", NO_STR "Allow transcoding\n")
DEFUN_USRATTR(cfg_trunk_no_allow_transcoding,
cfg_trunk_no_allow_transcoding_cmd,
X(MGW_CMD_ATTR_NEWCONN),
"no allow-transcoding", NO_STR "Allow transcoding\n")
{
struct mgcp_trunk *trunk = vty->index;
trunk->no_audio_transcoding = 1;
@@ -1241,13 +1339,15 @@ DEFUN(loop_conn,
DEFUN(tap_rtp,
tap_rtp_cmd,
"tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
"tap-rtp <0-64> ENDPOINT CONN (in|out) " VTY_IPV46_CMD " <0-65534>",
"Forward data on endpoint to a different system\n" "Trunk number\n"
"The endpoint in hex\n"
"The connection id in hex\n"
"Forward incoming data\n"
"Forward leaving data\n"
"destination IP of the data\n" "destination port\n")
"Destination IPv4 of the data\n"
"Destination IPv6 of the data\n"
"Destination port\n")
{
struct mgcp_rtp_tap *tap;
struct mgcp_trunk *trunk;
@@ -1295,8 +1395,22 @@ DEFUN(tap_rtp,
}
memset(&tap->forward, 0, sizeof(tap->forward));
inet_aton(argv[4], &tap->forward.sin_addr);
tap->forward.sin_port = htons(atoi(argv[5]));
tap->forward.u.sa.sa_family = osmo_ip_str_type(argv[4]);
switch (tap->forward.u.sa.sa_family) {
case AF_INET:
if (inet_pton(AF_INET, argv[4], &tap->forward.u.sin.sin_addr) != 1)
return CMD_WARNING;
tap->forward.u.sin.sin_port = htons(atoi(argv[5]));
break;
case AF_INET6:
if (inet_pton(AF_INET6, argv[4], &tap->forward.u.sin6.sin6_addr) != 1)
return CMD_WARNING;
tap->forward.u.sin6.sin6_port = htons(atoi(argv[5]));
break;
default:
return CMD_WARNING;
}
tap->enabled = 1;
return CMD_SUCCESS;
}
@@ -1401,18 +1515,16 @@ DEFUN(cfg_mgcp_osmux,
else if (strcmp(argv[0], "only") == 0)
g_cfg->osmux = OSMUX_USAGE_ONLY;
if (trunk->audio_loop) {
vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(cfg_mgcp_osmux_ip,
cfg_mgcp_osmux_ip_cmd,
"osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
"osmux bind-ip " VTY_IPV46_CMD,
OSMUX_STR IP_STR
"IPv4 Address to bind to\n"
"IPv6 Address to bind to\n")
{
osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
return CMD_SUCCESS;
@@ -1503,8 +1615,10 @@ int mgcp_vty_init(void)
install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_v6_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_v6_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
@@ -1559,6 +1673,8 @@ int mgcp_vty_init(void)
install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
install_element(TRUNK_NODE, &cfg_trunk_force_realloc_cmd);
install_element(TRUNK_NODE, &cfg_trunk_rtp_accept_all_cmd);
install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);

View File

@@ -60,6 +60,8 @@
#include <osmocom/vty/command.h>
#include <osmocom/vty/stats.h>
#include <osmocom/vty/misc.h>
#include <osmocom/vty/cpu_sched_vty.h>
#include <osmocom/abis/abis.h>
#include "../../bscconfig.h"
@@ -91,17 +93,45 @@ const char *osmomgw_copyright =
static char *config_file = "osmo-mgw.cfg";
/* used by msgb and mgcp */
void *tall_bsc_ctx = NULL;
void *tall_mgw_ctx = NULL;
static void print_help()
{
printf("Some useful help...\n");
printf("Some useful options:\n");
printf(" -h --help is printing this text.\n");
printf(" -c --config-file filename The config file to use.\n");
printf(" -s --disable-color\n");
printf(" -D --daemonize Fork the process into a background daemon\n");
printf(" -V --version Print the version number\n");
printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
printf("\nVTY reference generation:\n");
printf(" --vty-ref-mode MODE VTY reference generation mode (e.g. 'expert').\n");
printf(" --vty-ref-xml Generate the VTY reference XML output and exit.\n");
}
static void handle_long_options(const char *prog_name, const int long_option)
{
static int vty_ref_mode = VTY_REF_GEN_MODE_DEFAULT;
switch (long_option) {
case 1:
vty_ref_mode = get_string_value(vty_ref_gen_mode_names, optarg);
if (vty_ref_mode < 0) {
fprintf(stderr, "%s: Unknown VTY reference generation "
"mode '%s'\n", prog_name, optarg);
exit(2);
}
break;
case 2:
fprintf(stderr, "Generating the VTY reference in mode '%s' (%s)\n",
get_value_string(vty_ref_gen_mode_names, vty_ref_mode),
get_value_string(vty_ref_gen_mode_desc, vty_ref_mode));
vty_dump_xml_ref_mode(stdout, (enum vty_ref_gen_mode) vty_ref_mode);
exit(0);
default:
fprintf(stderr, "%s: error parsing cmdline options\n", prog_name);
exit(2);
}
}
static void handle_options(int argc, char **argv)
@@ -115,7 +145,8 @@ static void handle_options(int argc, char **argv)
{"daemonize", 0, 0, 'D'},
{"version", 0, 0, 'V'},
{"disable-color", 0, 0, 's'},
{"vty-ref-xml", 0, &long_option, 1},
{"vty-ref-mode", 1, &long_option, 1},
{"vty-ref-xml", 0, &long_option, 2},
{0, 0, 0, 0},
};
@@ -130,16 +161,10 @@ static void handle_options(int argc, char **argv)
exit(0);
break;
case 0:
switch (long_option) {
case 1:
vty_dump_xml_ref(stdout);
exit(0);
default:
fprintf(stderr, "error parsing cmdline options\n");
exit(2);
}
handle_long_options(argv[0], long_option);
break;
case 'c':
config_file = talloc_strdup(tall_bsc_ctx, optarg);
config_file = talloc_strdup(tall_mgw_ctx, optarg);
break;
case 's':
log_set_use_color(osmo_stderr_target, 0);
@@ -177,7 +202,7 @@ static int mgcp_rsip_cb(struct mgcp_trunk *trunk)
static int read_call_agent(struct osmo_fd *fd, unsigned int what)
{
struct sockaddr_in addr;
struct osmo_sockaddr addr;
socklen_t slen = sizeof(addr);
struct msgb *msg;
struct msgb *resp;
@@ -203,7 +228,7 @@ static int read_call_agent(struct osmo_fd *fd, unsigned int what)
msgb_reset(msg);
if (resp) {
sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr));
sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, &addr.u.sa, sizeof(addr));
msgb_free(resp);
}
@@ -290,20 +315,24 @@ int main(int argc, char **argv)
unsigned int flags;
int rc;
tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent");
vty_info.tall_ctx = tall_bsc_ctx;
tall_mgw_ctx = talloc_named_const(NULL, 1, "mgcp-callagent");
vty_info.tall_ctx = tall_mgw_ctx;
msgb_talloc_ctx_init(tall_bsc_ctx, 0);
msgb_talloc_ctx_init(tall_mgw_ctx, 0);
osmo_init_ignore_signals();
osmo_init_logging2(tall_bsc_ctx, &log_info);
libosmo_abis_init(tall_bsc_ctx);
osmo_init_logging2(tall_mgw_ctx, &log_info);
libosmo_abis_init(tall_mgw_ctx);
cfg = mgcp_config_alloc();
if (!cfg)
return -1;
vty_info.copyright = osmomgw_copyright;
vty_info.usr_attr_desc[MGW_CMD_ATTR_NEWCONN] = \
"This command applies when a new connection is created";
vty_info.usr_attr_letters[MGW_CMD_ATTR_NEWCONN] = 'n';
vty_init(&vty_info);
logging_vty_add_cmds();
osmo_talloc_vty_add_cmds();
@@ -311,18 +340,19 @@ int main(int argc, char **argv)
mgcp_vty_init();
ctrl_vty_init(cfg);
e1inp_vty_init();
osmo_cpu_sched_vty_init(tall_mgw_ctx);
handle_options(argc, argv);
rate_ctr_init(tall_bsc_ctx);
osmo_stats_init(tall_bsc_ctx);
rate_ctr_init(tall_mgw_ctx);
osmo_stats_init(tall_mgw_ctx);
rc = mgcp_parse_config(config_file, cfg, MGCP_BSC);
if (rc < 0)
return rc;
/* start telnet after reading config for vty_get_bind_addr() */
rc = telnet_init_dynif(tall_bsc_ctx, NULL,
rc = telnet_init_dynif(tall_mgw_ctx, NULL,
vty_get_bind_addr(), OSMO_VTY_PORT_MGW);
if (rc < 0)
return rc;
@@ -342,7 +372,7 @@ int main(int argc, char **argv)
if (cfg->call_agent_addr)
flags |= OSMO_SOCK_F_CONNECT;
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
rc = osmo_sock_init2_ofd(&cfg->gw_fd.bfd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
cfg->source_addr, cfg->source_port,
cfg->call_agent_addr, cfg->call_agent_addr ? 2727 : 0, flags);
if (rc < 0) {

View File

@@ -34,6 +34,7 @@
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <string.h>
#include <limits.h>
#include <dlfcn.h>
@@ -1262,7 +1263,7 @@ struct rtp_packet_info test_rtp_packets1[] = {
void mgcp_patch_and_count(struct mgcp_endpoint *endp,
struct mgcp_rtp_state *state,
struct mgcp_rtp_end *rtp_end,
struct sockaddr_in *addr, struct msgb *msg);
struct osmo_sockaddr *addr, struct msgb *msg);
static void test_packet_error_detection(int patch_ssrc, int patch_ts)
{
@@ -1274,7 +1275,7 @@ static void test_packet_error_detection(int patch_ssrc, int patch_ts)
struct mgcp_config cfg = {0};
struct mgcp_rtp_state state;
struct mgcp_rtp_end *rtp;
struct sockaddr_in addr = { 0 };
struct osmo_sockaddr addr = { 0 };
uint32_t last_ssrc = 0;
uint32_t last_timestamp = 0;
uint32_t last_seqno = 0;
@@ -1486,7 +1487,8 @@ static void test_multilple_codec(void)
OSMO_ASSERT(conn->end.rtp_port == htons(16434));
memset(&addr, 0, sizeof(addr));
inet_aton("8.8.8.8", &addr);
OSMO_ASSERT(conn->end.addr.s_addr == addr.s_addr);
OSMO_ASSERT(conn->end.addr.u.sa.sa_family == AF_INET);
OSMO_ASSERT(conn->end.addr.u.sin.sin_addr.s_addr == addr.s_addr);
/* Check what happens without that flag */
@@ -2124,6 +2126,8 @@ void test_e1_trunk_nr_from_epname()
/* Note: e1_trunk_nr_from_epname does not check the text
* after the E1 trunk number, after the delimiter
* character "/" arbitrary text may follow. */
trunk_nr = e1_trunk_nr_from_epname("ds/e1-0/s-1/su16-0");
OSMO_ASSERT(trunk_nr == 0);
trunk_nr = e1_trunk_nr_from_epname("ds/e1-1/s-1/su16-0");
OSMO_ASSERT(trunk_nr == 1);
trunk_nr = e1_trunk_nr_from_epname("ds/e1-2/s-2/su16-0");
@@ -2141,8 +2145,6 @@ void test_e1_trunk_nr_from_epname()
* trunk number exceeds the valid range or the trunk prefix
* is wrong. Also when the delimiter character "/" at the
* end of the trunk is wrong the parsing should fail. */
trunk_nr = e1_trunk_nr_from_epname("ds/e1-0/s-1/su16-0");
OSMO_ASSERT(trunk_nr == -EINVAL);
trunk_nr = e1_trunk_nr_from_epname("ds/e1-65/s-1/su16-0");
OSMO_ASSERT(trunk_nr == -EINVAL);
trunk_nr = e1_trunk_nr_from_epname("ds/e1--1/s-1/su16-0");

View File

@@ -294,11 +294,23 @@ void test_mgcp_msg(void)
MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
memset(audio_ip_overflow, 'X', sizeof(audio_ip_overflow));
audio_ip_overflow[1] = '.';
audio_ip_overflow[sizeof(audio_ip_overflow) - 1] = '\0';
mgcp_msg.audio_ip = audio_ip_overflow;
msg = mgcp_msg_gen(mgcp, &mgcp_msg);
OSMO_ASSERT(msg == NULL);
printf("IPv6 test:\n");
mgcp_msg.verb = MGCP_VERB_MDCX;
mgcp_msg.presence =
(MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID |
MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE |
MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT);
mgcp_msg.audio_ip = "2001:db8:1::ab9:c0a8:102";
mgcp->actual.remote_addr = "::1";
msg = mgcp_msg_gen(mgcp, &mgcp_msg);
printf("%s\n", (char *)msg->data);
printf("\n");
msgb_free(msg);
}
@@ -413,6 +425,66 @@ static struct sdp_section_start_test sdp_section_start_tests[] = {
"m=audio 23\r\n",
.expect_rc = 0,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 1.2.3.4\r\n",
.expect_params = {
.audio_ip = "1.2.3.4",
},
.expect_rc = 0,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP6 2001:db8:1::ab9:c0a8:102\r\n",
.expect_params = {
.audio_ip = "2001:db8:1::ab9:c0a8:102",
},
.expect_rc = 0,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP6 1.2.3.4\r\n",
.expect_rc = -22,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 ::1\r\n",
.expect_rc = -22,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 notanip\r\n",
.expect_rc = -22,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 1.2.3.4.5.6\r\n",
.expect_rc = -22,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 1.2 .3\r\n",
.expect_rc = -22,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 1.2 .3\r\n",
.expect_rc = -22,
},
{
.body = "some mgcp header data\r\nand header params"
"\r\n\r\n"
"c=IN IP4 \r\n",
.expect_rc = -22,
},
};
void test_sdp_section_start()
@@ -443,7 +515,12 @@ void test_sdp_section_start()
continue;
}
fprintf(stderr, "got audio_port=%u\n", t->expect_params.audio_port);
fprintf(stderr, "got audio_ip=\"%s\"\n", r->audio_ip);
if (strcmp(r->audio_ip, t->expect_params.audio_ip)) {
fprintf(stderr, "FAIL: Expected audio_ip=\"%s\"\n", t->expect_params.audio_ip);
failures++;
}
fprintf(stderr, "got audio_port=%u\n", r->audio_port);
if (r->audio_port != t->expect_params.audio_port) {
fprintf(stderr, "FAIL: Expected audio_port=%u\n", t->expect_params.audio_port);
failures++;
@@ -612,9 +689,10 @@ int main(int argc, char **argv)
ctx = talloc_named_const(NULL, 1, "mgcp_client_test");
msgb_talloc_ctx_init(ctx, 0);
osmo_init_logging2(ctx, &log_info);
log_set_print_filename(osmo_stderr_target, 0);
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
log_set_print_timestamp(osmo_stderr_target, 0);
log_set_use_color(osmo_stderr_target, 0);
log_set_print_category_hex(osmo_stderr_target, 0);
log_set_print_category(osmo_stderr_target, 1);
log_set_category_filter(osmo_stderr_target, DLMGCP, 1, LOGL_DEBUG);

View File

@@ -19,55 +19,112 @@ test_sdp_section_start() test [0]:
body: ""
DLMGCP MGCP response contains no SDP parameters
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [1]:
body: "\n\n"
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [2]:
body: "\r\n\r\n"
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [3]:
body: "\n\r\n\r"
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [4]:
body: "some mgcp header data\r\nand header params\n\nm=audio 23\r\n"
got rc=0
got audio_ip=""
got audio_port=23
test_sdp_section_start() test [5]:
body: "some mgcp header data\r\nand header params\r\n\r\nm=audio 23\r\n"
got rc=0
got audio_ip=""
got audio_port=23
test_sdp_section_start() test [6]:
body: "some mgcp header data\r\nand header params\n\r\n\rm=audio 23\r\n"
got rc=0
got audio_ip=""
got audio_port=23
test_sdp_section_start() test [7]:
body: "some mgcp header data\r\nand header params\n\r\nm=audio 23\r\n"
DLMGCP MGCP response contains no SDP parameters
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [8]:
body: "some mgcp header data\r\nand header params\r\n\rm=audio 23\r\n"
DLMGCP MGCP response contains no SDP parameters
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [9]:
body: "some mgcp header data\r\nand header params\n\r\rm=audio 23\r\n"
DLMGCP MGCP response contains no SDP parameters
got rc=0
got audio_ip=""
got audio_port=0
test_sdp_section_start() test [10]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2.3.4\r\n"
got rc=0
got audio_ip="1.2.3.4"
got audio_port=0
test_sdp_section_start() test [11]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP6 2001:db8:1::ab9:c0a8:102\r\n"
got rc=0
got audio_ip="2001:db8:1::ab9:c0a8:102"
got audio_port=0
test_sdp_section_start() test [12]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP6 1.2.3.4\r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
test_sdp_section_start() test [13]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 ::1\r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
test_sdp_section_start() test [14]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 notanip\r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
test_sdp_section_start() test [15]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2.3.4.5.6\r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
test_sdp_section_start() test [16]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2 .3\r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
test_sdp_section_start() test [17]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 1.2 .3\r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
test_sdp_section_start() test [18]:
body: "some mgcp header data\r\nand header params\r\n\r\nc=IN IP4 \r\n"
DLMGCP Failed to parse MGCP response header (audio ip)
got rc=-22
DLMGCP ptmap contains illegal mapping: codec=113 maps to pt=2
DLMGCP ptmap contains illegal mapping: codec=0 maps to pt=100
DLMGCP ptmap contains illegal mapping: codec=113 maps to pt=2

View File

@@ -109,6 +109,20 @@ M: sendrecv
X-Osmux: 2
Overfolow test:
IPv6 test:
MDCX 19 23@mgw MGCP 1.0
C: 2f
I: 11
M: sendrecv
v=0
o=- 2f 23 IN IP6 ::1
s=-
c=IN IP6 2001:db8:1::ab9:c0a8:102
t=0 0
m=audio 1234 RTP/AVP 3
a=ptime:20
test_mgcp_client_cancel():
@@ -149,6 +163,24 @@ test_sdp_section_start() test [7]:
test_sdp_section_start() test [8]:
test_sdp_section_start() test [9]:
test_sdp_section_start() test [10]:
test_sdp_section_start() test [11]:
test_sdp_section_start() test [12]:
test_sdp_section_start() test [13]:
test_sdp_section_start() test [14]:
test_sdp_section_start() test [15]:
test_sdp_section_start() test [16]:
test_sdp_section_start() test [17]:
test_sdp_section_start() test [18]:
110 => 96
111 => 97
112 => 98