add X-Osmo-IGN MGCP header to ignore CallID
The format is
CRCX ...
C: ...
M: ...
X-Osmo-IGN: C
So far the only ignorable element is C, i.e. the CallID. Any other items may be
added in the future.
(I initially intended to also add '@' to ignore the endpoint name's domain
part, but in the osmo-mgw code base the domain part is verified long before any
additional headers are even parsed, so sparing that refactoring for now.)
The intention is that osmo-bsc will issue "X-Osmo-IGN: C" for all SCCPlite
calls, because we are unable to retrieve the CallID that the MSC sends to
osmo-mgw for the network side of the endpoint.
Testing with a specific SCCPlite MSC, I actually observe that all CallIDs are
1, even for concurrent calls. So, an alternative hacky solution would have been
to always pass CallID == 1 for SCCPlite connections from osmo-bsc.
Related: I257ad574d8060fef19afce9798bd8a5a7f8c99fe (osmo-bsc)
Change-Id: Id7ae275ffde8ea9389270cfe3db087ee8db00b51
diff --git a/include/osmocom/mgcp/mgcp_common.h b/include/osmocom/mgcp/mgcp_common.h
index eb6564f..b2c7370 100644
--- a/include/osmocom/mgcp/mgcp_common.h
+++ b/include/osmocom/mgcp/mgcp_common.h
@@ -49,6 +49,14 @@
MGCP_CONN_LOOPBACK = 4 | MGCP_CONN_RECV_SEND,
};
+#define MGCP_X_OSMO_IGN_HEADER "X-Osmo-IGN:"
+
+/* Values should be bitwise-OR-able */
+enum mgcp_x_osmo_ign {
+ MGCP_X_OSMO_IGN_NONE = 0,
+ MGCP_X_OSMO_IGN_CALLID = 1,
+};
+
/* Ensure that the msg->l2h is NUL terminated. */
static inline int mgcp_msg_terminate_nul(struct msgb *msg)
{
diff --git a/include/osmocom/mgcp/mgcp_endp.h b/include/osmocom/mgcp/mgcp_endp.h
index 3876794..d834c09 100644
--- a/include/osmocom/mgcp/mgcp_endp.h
+++ b/include/osmocom/mgcp/mgcp_endp.h
@@ -90,6 +90,9 @@
/*! Memorize if this endpoint was choosen by the MGW (wildcarded, true)
* or if the user has choosen the particular endpoint explicitly. */
bool wildcarded_req;
+
+ /*! MGCP_X_OSMO_IGN_* flags from 'X-Osmo-IGN:' header */
+ uint32_t x_osmo_ign;
};
/*! Extract endpoint number for a given endpoint */
diff --git a/include/osmocom/mgcp_client/mgcp_client.h b/include/osmocom/mgcp_client/mgcp_client.h
index ed2dfb0..6c478e8 100644
--- a/include/osmocom/mgcp_client/mgcp_client.h
+++ b/include/osmocom/mgcp_client/mgcp_client.h
@@ -11,6 +11,8 @@
#define MGCP_CLIENT_REMOTE_ADDR_DEFAULT "127.0.0.1"
#define MGCP_CLIENT_REMOTE_PORT_DEFAULT 2427
+#define MGCP_CLIENT_MGW_STR "Configure MGCP connection to Media Gateway\n"
+
struct msgb;
struct vty;
struct mgcp_client;
@@ -88,6 +90,7 @@
#define MGCP_MSG_PRESENCE_AUDIO_IP 0x0008
#define MGCP_MSG_PRESENCE_AUDIO_PORT 0x0010
#define MGCP_MSG_PRESENCE_CONN_MODE 0x0020
+#define MGCP_MSG_PRESENCE_X_OSMO_IGN 0x8000
struct mgcp_msg {
enum mgcp_verb verb;
@@ -104,6 +107,7 @@
unsigned int codecs_len;
struct ptmap ptmap[MGCP_MAX_CODECS];
unsigned int ptmap_len;
+ uint32_t x_osmo_ign;
};
void mgcp_client_conf_init(struct mgcp_client_conf *conf);
diff --git a/include/osmocom/mgcp_client/mgcp_client_fsm.h b/include/osmocom/mgcp_client/mgcp_client_fsm.h
index 81d3dea..bb07872 100644
--- a/include/osmocom/mgcp_client/mgcp_client_fsm.h
+++ b/include/osmocom/mgcp_client/mgcp_client_fsm.h
@@ -42,6 +42,11 @@
/*! RTP payload type map length (optional, only needed when payload
* types are used that differ from what IANA/3GPP defines) */
unsigned int ptmap_len;
+
+ /*! If nonzero, send 'X-Osmo-IGN:' header. This is useful e.g. for SCCPlite MSCs where the MSC is
+ * known to issue incoherent or unknown CallIDs / to issue CRCX commands with a different domain
+ * name than the BSC. An OsmoMGW will then ignore these and not fail on mismatches. */
+ uint32_t x_osmo_ign;
};
struct osmo_fsm_inst *mgcp_conn_create(struct mgcp_client *mgcp, struct osmo_fsm_inst *parent_fi, uint32_t parent_term_evt,
diff --git a/src/libosmo-mgcp-client/mgcp_client.c b/src/libosmo-mgcp-client/mgcp_client.c
index c10abc9..e9d7b3f 100644
--- a/src/libosmo-mgcp-client/mgcp_client.c
+++ b/src/libosmo-mgcp-client/mgcp_client.c
@@ -1313,6 +1313,13 @@
msgb_printf(msg, "M: %s\r\n",
mgcp_client_cmode_name(mgcp_msg->conn_mode));
+ /* Add X-Osmo-IGN */
+ if ((mgcp_msg->presence & MGCP_MSG_PRESENCE_X_OSMO_IGN)
+ && (mgcp_msg->x_osmo_ign != 0))
+ rc +=
+ msgb_printf(msg, MGCP_X_OSMO_IGN_HEADER "%s\r\n",
+ mgcp_msg->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID ? " C": "");
+
/* Add session description protocol (SDP) */
if (use_sdp
&& (mgcp_msg->verb == MGCP_VERB_CRCX
diff --git a/src/libosmo-mgcp-client/mgcp_client_fsm.c b/src/libosmo-mgcp-client/mgcp_client_fsm.c
index 770db5e..0b5a251 100644
--- a/src/libosmo-mgcp-client/mgcp_client_fsm.c
+++ b/src/libosmo-mgcp-client/mgcp_client_fsm.c
@@ -119,6 +119,11 @@
osmo_strlcpy(mgcp_msg->endpoint, info->endpoint, MGCP_ENDPOINT_MAXLEN);
memcpy(mgcp_msg->codecs, info->codecs, sizeof(mgcp_msg->codecs));
memcpy(mgcp_msg->ptmap, info->ptmap, sizeof(mgcp_msg->ptmap));
+
+ if (info->x_osmo_ign) {
+ mgcp_msg->x_osmo_ign = info->x_osmo_ign;
+ mgcp_msg->presence |= MGCP_MSG_PRESENCE_X_OSMO_IGN;
+ }
}
static void add_audio(struct mgcp_msg *mgcp_msg, struct mgcp_conn_peer *info)
diff --git a/src/libosmo-mgcp-client/mgcp_client_vty.c b/src/libosmo-mgcp-client/mgcp_client_vty.c
index 10d078a..48fcd70 100644
--- a/src/libosmo-mgcp-client/mgcp_client_vty.c
+++ b/src/libosmo-mgcp-client/mgcp_client_vty.c
@@ -30,7 +30,7 @@
#include <osmocom/mgcp_client/mgcp_client.h>
-#define MGW_STR "Configure MGCP connection to Media Gateway\n"
+#define MGW_STR MGCP_CLIENT_MGW_STR
void *global_mgcp_client_ctx = NULL;
struct mgcp_client_conf *global_mgcp_client_conf = NULL;
diff --git a/src/libosmo-mgcp/mgcp_msg.c b/src/libosmo-mgcp/mgcp_msg.c
index a5bef7b..a7c8b47 100644
--- a/src/libosmo-mgcp/mgcp_msg.c
+++ b/src/libosmo-mgcp/mgcp_msg.c
@@ -407,6 +407,11 @@
if (!endp)
return -1;
+
+ /* Accept any CallID for "X-Osmo-IGN: C" */
+ if (endp->x_osmo_ign & MGCP_X_OSMO_IGN_CALLID)
+ return 0;
+
if (!callid)
return -1;
if (!endp->callid)
diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c
index ea80907..cb2c965 100644
--- a/src/libosmo-mgcp/mgcp_protocol.c
+++ b/src/libosmo-mgcp/mgcp_protocol.c
@@ -715,12 +715,31 @@
mode = (const char *)line + 3;
break;
case 'X':
- /* If osmoux is disabled, just skip setting it up */
- if (!p->endp->cfg->osmux)
- break;
- if (strncmp("Osmux: ", line + 2, strlen("Osmux: ")) ==
- 0)
+ if (strncmp("Osmux: ", line + 2, strlen("Osmux: ")) == 0) {
+ /* If osmux is disabled, just skip setting it up */
+ if (!p->endp->cfg->osmux)
+ break;
osmux_cid = mgcp_osmux_setup(endp, line);
+ break;
+ }
+
+ /* Parse X-Osmo-IGN header */
+ if (!strncmp(line, MGCP_X_OSMO_IGN_HEADER,
+ strlen(MGCP_X_OSMO_IGN_HEADER))) {
+ int i;
+ int line_len = strlen(line);
+ for (i = strlen(MGCP_X_OSMO_IGN_HEADER); i < line_len; i++) {
+ switch (line[i]) {
+ case 'C':
+ endp->x_osmo_ign |= MGCP_X_OSMO_IGN_CALLID;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ /* Ignore unknown X-headers */
break;
case '\0':
have_sdp = 1;
diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c
index ea79485..2d1e28a 100644
--- a/tests/mgcp/mgcp_test.c
+++ b/tests/mgcp/mgcp_test.c
@@ -309,6 +309,32 @@
"a=rtpmap:97 GSM-EFR/8000\r\n" \
"a=ptime:20\r\n"
+#define CRCX_X_OSMO_IGN \
+ "CRCX 2 1@mgw MGCP 1.0\r\n" \
+ "M: recvonly\r\n" \
+ "C: 2\r\n" \
+ "L: p:20\r\n" \
+ "X-Osmo-IGN: C\r\n" \
+ "\r\n" \
+ "v=0\r\n" \
+ "c=IN IP4 123.12.12.123\r\n" \
+ "m=audio 5904 RTP/AVP 97\r\n" \
+ "a=rtpmap:97 GSM-EFR/8000\r\n" \
+ "a=ptime:40\r\n"
+
+#define CRCX_X_OSMO_IGN_RET \
+ "200 2 OK\r\n" \
+ "I: %s\r\n" \
+ "\r\n" \
+ "v=0\r\n" \
+ "o=- %s 23 IN IP4 0.0.0.0\r\n" \
+ "s=-\r\n" \
+ "c=IN IP4 0.0.0.0\r\n" \
+ "t=0 0\r\n" \
+ "m=audio 16010 RTP/AVP 97\r\n" \
+ "a=rtpmap:97 GSM-EFR/8000\r\n" \
+ "a=ptime:40\r\n"
+
#define DLCX \
"DLCX 7 1@mgw MGCP 1.0\r\n" \
"I: %s\r\n" \
@@ -482,6 +508,7 @@
"a=fmtp:126 0/1/2"},
{"DLCX", DLCX, DLCX_RET, PTYPE_IGNORE,.extra_fmtp = "a=fmtp:126 0/1/2"},
{"CRCX", CRCX_NO_LCO_NO_SDP, CRCX_NO_LCO_NO_SDP_RET, 97},
+ {"CRCX", CRCX_X_OSMO_IGN, CRCX_X_OSMO_IGN_RET, 97},
};
static const struct mgcp_test retransmit[] = {
diff --git a/tests/mgcp/mgcp_test.ok b/tests/mgcp/mgcp_test.ok
index 9838f4d..bdaf5d7 100644
--- a/tests/mgcp/mgcp_test.ok
+++ b/tests/mgcp/mgcp_test.ok
Binary files differ
diff --git a/tests/mgcp_client/mgcp_client_test.c b/tests/mgcp_client/mgcp_client_test.c
index 9978f79..2662fc1 100644
--- a/tests/mgcp_client/mgcp_client_test.c
+++ b/tests/mgcp_client/mgcp_client_test.c
@@ -180,7 +180,8 @@
.codecs_len = 1,
.ptmap[0].codec = CODEC_GSMEFR_8000_1,
.ptmap[0].pt = 96,
- .ptmap_len = 1
+ .ptmap_len = 1,
+ .x_osmo_ign = MGCP_X_OSMO_IGN_CALLID,
};
if (mgcp)
@@ -268,6 +269,16 @@
msg = mgcp_msg_gen(mgcp, &mgcp_msg);
printf("%s\n", (char *)msg->data);
+ printf("Generate X-Osmo-IGN message:\n");
+ msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+ mgcp_msg.verb = MGCP_VERB_CRCX;
+ 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_X_OSMO_IGN);
+ msg = mgcp_msg_gen(mgcp, &mgcp_msg);
+ printf("%s\n", (char *)msg->data);
+
printf("Overfolow test:\n");
mgcp_msg.verb = MGCP_VERB_MDCX;
mgcp_msg.presence =
diff --git a/tests/mgcp_client/mgcp_client_test.ok b/tests/mgcp_client/mgcp_client_test.ok
index 454ee3d..58c4b82 100644
--- a/tests/mgcp_client/mgcp_client_test.ok
+++ b/tests/mgcp_client/mgcp_client_test.ok
@@ -117,6 +117,14 @@
Generated RSIP message:
RSIP 9 23@mgw MGCP 1.0
+Generate X-Osmo-IGN message:
+CRCX 11 23@mgw MGCP 1.0
+C: 2f
+I: 11
+L: p:20, a:GSM, nt:IN
+M: sendrecv
+X-Osmo-IGN: C
+
Overfolow test: