mgcp_protocol: add support for wildcarded DLCX

The request handler handle_delete_con currently rejects wildcarded DLCX
requests even though a wildcarded DLCX would be a valuable tool to
remove lingering connections from the trunk in case osmo-bsc has to be
restarted.

Change-Id: I5c2de6b2b61ee64ba9c0618fd20e8fc2fe6a5ed3
Related: SYS#5535
This commit is contained in:
Philipp Maier 2021-07-19 14:56:29 +02:00 committed by dexter
parent 268568593e
commit f486e741a4
3 changed files with 53 additions and 19 deletions

View File

@ -53,7 +53,6 @@ enum {
/* Trunk-global MCGP DLCX related rate counters */
enum {
MGCP_DLCX_SUCCESS,
MGCP_DLCX_FAIL_WILDCARD,
MGCP_DLCX_FAIL_NO_CONN,
MGCP_DLCX_FAIL_INVALID_CALLID,
MGCP_DLCX_FAIL_INVALID_CONNID,

View File

@ -46,6 +46,16 @@
#include <osmocom/mgcp/mgcp_codec.h>
#include <osmocom/mgcp/mgcp_conn.h>
/* A combination of LOGPENDP and LOGPTRUNK that automatically falls back to
* LOGPTRUNK when the endp parameter is NULL */
#define LOGPEPTR(endp, trunk, cat, level, fmt, args...) \
do { \
if (endp) \
LOGPENDP(endp, cat, level, fmt, ## args); \
else \
LOGPTRUNK(trunk, cat, level, fmt, ## args); \
} while (0)
/* Request data passed to the request handler */
struct mgcp_request_data {
/* request name (e.g. "MDCX") */
@ -102,7 +112,7 @@ static const struct mgcp_request mgcp_requests[] = {
{ .name = "DLCX",
.handle_request = handle_delete_con,
.debug_name = "DeleteConnection",
.require_endp = true },
.require_endp = false },
{ .name = "MDCX",
.handle_request = handle_modify_con,
.debug_name = "ModifiyConnection",
@ -1351,26 +1361,21 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
char stats[1048];
const char *conn_id = NULL;
struct mgcp_conn_rtp *conn = NULL;
unsigned int i;
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
"DLCX: deleting connection ...\n");
/* NOTE: In this handler we can not take it for granted that the endp
* pointer will be populated, however a trunk is always guaranteed. */
if (!mgcp_endp_avail(endp)) {
LOGPEPTR(endp, trunk, DLMGCP, LOGL_NOTICE, "DLCX: deleting connection(s) ...\n");
if (endp && !mgcp_endp_avail(endp)) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_AVAIL));
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"DLCX: selected endpoint not available!\n");
return create_err_response(NULL, 501, "DLCX", pdata->trans);
}
/* Prohibit wildcarded requests */
if (endp->wildcarded_req) {
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"DLCX: wildcarded endpoint names not supported.\n");
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_WILDCARD));
return create_err_response(endp, 507, "DLCX", pdata->trans);
}
if (llist_count(&endp->conns) <= 0) {
if (endp && !rq->wildcarded && llist_empty(&endp->conns)) {
LOGPENDP(endp, DLMGCP, LOGL_ERROR,
"DLCX: endpoint is not holding a connection.\n");
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_NO_CONN));
@ -1383,6 +1388,15 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
switch (toupper(line[0])) {
case 'C':
/* If we have no endpoint, but a call id in the request,
then this request cannot be handled */
if (!endp) {
LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
"cannot handle requests with call-id (C) without endpoint -- abort!");
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
return create_err_response(NULL, 539, "DLCX", pdata->trans);
}
if (mgcp_verify_call_id(endp, line + 3) != 0) {
error_code = 516;
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CALLID));
@ -1390,6 +1404,15 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
}
break;
case 'I':
/* If we have no endpoint, but a connection id in the request,
then this request cannot be handled */
if (!endp) {
LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE,
"cannot handle requests with conn-id (I) without endpoint -- abort!");
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
return create_err_response(NULL, 539, "DLCX", pdata->trans);
}
conn_id = (const char *)line + 3;
if ((error_code = mgcp_verify_ci(endp, conn_id))) {
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CONNID));
@ -1400,8 +1423,7 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
silent = strcasecmp("noanswer", line + 3) == 0;
break;
default:
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,
"DLCX: Unhandled MGCP option: '%c'/%d\n",
LOGPEPTR(endp, trunk, DLMGCP, LOGL_NOTICE, "DLCX: Unhandled MGCP option: '%c'/%d\n",
line[0], line[0]);
rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM));
return create_err_response(NULL, 539, "DLCX", pdata->trans);
@ -1432,9 +1454,23 @@ static struct msgb *handle_delete_con(struct mgcp_request_data *rq)
}
}
/* Handle wildcarded DLCX that refers to the whole trunk. This means
* that we walk over all endpoints on the trunk in order to drop all
* connections on the trunk. (see also RFC3435 Annex F.7) */
if (rq->wildcarded) {
int num_conns = 0;
for (i = 0; i < trunk->number_endpoints; i++) {
num_conns += llist_count(&trunk->endpoints[i]->conns);
mgcp_endp_release(trunk->endpoints[i]);
}
rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns);
return create_ok_response(NULL, 200, "DLCX", pdata->trans);
}
/* When no connection id is supplied, we will interpret this as a
* wildcarded DLCX and drop all connections at once. (See also
* RFC3435 Section F.7) */
* wildcarded DLCX that refers to the selected endpoint. This means
* that we drop all connections on that specific endpoint at once.
* (See also RFC3435 Section F.7) */
if (!conn_id) {
int num_conns = llist_count(&endp->conns);
LOGPENDP(endp, DLMGCP, LOGL_NOTICE,

View File

@ -106,7 +106,6 @@ const static struct rate_ctr_group_desc mgcp_mdcx_ctr_group_desc = {
static const struct rate_ctr_desc mgcp_dlcx_ctr_desc[] = {
[MGCP_DLCX_SUCCESS] = { "dlcx:success", "DLCX command processed successfully." },
[MGCP_DLCX_FAIL_WILDCARD] = { "dlcx:wildcard", "wildcard names in DLCX commands are unsupported." },
[MGCP_DLCX_FAIL_NO_CONN] = { "dlcx:no_conn", "endpoint specified in DLCX command has no active connections." },
[MGCP_DLCX_FAIL_INVALID_CALLID] =
{ "dlcx:callid", "CallId specified in DLCX command mismatches endpoint's CallId ." },