mncc: Support IPv6 addresses (new version mncc 7)
Apparently commit 06b859ca314f53a902329ed95848dbafef1d4f87 forgot to
bump the MNCC_SOCK_VERSION field from 5 to 6.
Change-Id: I5448ff931ec33f24f4837a51376f1703fe97683b
diff --git a/library/MNCC_Emulation.ttcn b/library/MNCC_Emulation.ttcn
index be087ec..49b1249 100644
--- a/library/MNCC_Emulation.ttcn
+++ b/library/MNCC_Emulation.ttcn
@@ -38,7 +38,7 @@
import from UD_Types all;
modulepar {
- int mp_mncc_version := 6;
+ int mp_mncc_version := 7;
}
/* General "base class" component definition, of which specific implementations
@@ -266,6 +266,11 @@
function main(MnccOps ops, charstring id, charstring sock, boolean role_server := false)
runs on MNCC_Emulation_CT {
+ if (not set_MNCC_version(mp_mncc_version)) {
+ setverdict(fail, "Failed configuring MNCC enc/dec to version ", mp_mncc_version);
+ return;
+ }
+
if (role_server) {
f_listen(sock);
MNCC.send(t_SD_MNCC(g_mncc_ud_id, ts_MNCC_HELLO(version := mp_mncc_version)));
diff --git a/library/MNCC_EncDec.cc b/library/MNCC_EncDec.cc
index f2692d7..be5d01a 100644
--- a/library/MNCC_EncDec.cc
+++ b/library/MNCC_EncDec.cc
@@ -5,6 +5,16 @@
namespace MNCC__Types {
+static int mncc_sock_version = MNCC_SOCK_VERSION;
+
+BOOLEAN set__MNCC__version(INTEGER const& version)
+{
+ if (version != 6 && version != 7)
+ return false;
+ mncc_sock_version = version;
+ return true;
+}
+
static void enc_bcap(struct gsm_mncc_bearer_cap *out, const MNCC__bearer__cap& in)
{
out->transfer = in.transfer();
@@ -76,6 +86,7 @@
{
struct gsm_mncc mncc;
OCTETSTRING ret_val;
+ TTCN_Buffer ttcn_buffer;
memset(&mncc, 0, sizeof(mncc));
mncc.msg_type = in.msg__type();
@@ -184,15 +195,46 @@
ret_val = ret_val & in.u().data().data();
break;
case MNCC__MsgUnion::ALT_rtp:
- struct gsm_mncc_rtp rtp;
- memset(&rtp, 0, sizeof(rtp));
- rtp.msg_type = in.msg__type();
- rtp.callref = in.u().rtp().callref();
- rtp.ip = in.u().rtp().ip();
- rtp.port = in.u().rtp().rtp__port();
- rtp.payload_type = in.u().rtp().payload__type();
- rtp.payload_msg_type = in.u().rtp().payload__msg__type();
- ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
+ switch (mncc_sock_version) {
+ case 6:
+ struct gsm_mncc_rtp_mncc6 rtp_old;
+ memset(&rtp_old, 0, sizeof(rtp_old));
+ rtp_old.msg_type = in.msg__type();
+ rtp_old.callref = in.u().rtp().callref();
+ ttcn_buffer.put_string(in.u().rtp().ip());
+ if (!in.u().rtp().is__ipv6()) {
+ memcpy(&rtp_old.ip, ttcn_buffer.get_data(), sizeof(struct in_addr));
+ rtp_old.ip = ntohl(rtp_old.ip);
+ } /* else: ipv6 not supported in MNCCv6 */
+ rtp_old.port = in.u().rtp().rtp__port();
+ rtp_old.payload_type = in.u().rtp().payload__type();
+ rtp_old.payload_msg_type = in.u().rtp().payload__msg__type();
+ ret_val = OCTETSTRING(sizeof(rtp_old), (uint8_t *) &rtp_old);
+ break;
+ case 7:
+ struct gsm_mncc_rtp rtp;
+ memset(&rtp, 0, sizeof(rtp));
+ rtp.msg_type = in.msg__type();
+ rtp.callref = in.u().rtp().callref();
+ ttcn_buffer.put_string(in.u().rtp().ip());
+ if (in.u().rtp().is__ipv6()) {
+ // if(in.u().rtp().ip().lengthof() != 16) print error
+ rtp.addr.ss_family = AF_INET6;
+ memcpy(&((struct sockaddr_in6*)&rtp.addr)->sin6_addr, ttcn_buffer.get_data(),
+ sizeof(struct in6_addr));
+ ((struct sockaddr_in6*)&rtp.addr)->sin6_port = htons(in.u().rtp().rtp__port());
+ } else {
+ // if(in.u().rtp().ip().lengthof() != 4) print error
+ rtp.addr.ss_family = AF_INET;
+ memcpy(&((struct sockaddr_in*)&rtp.addr)->sin_addr, ttcn_buffer.get_data(),
+ sizeof(struct in_addr));
+ ((struct sockaddr_in*)&rtp.addr)->sin_port = htons(in.u().rtp().rtp__port());
+ }
+ rtp.payload_type = in.u().rtp().payload__type();
+ rtp.payload_msg_type = in.u().rtp().payload__msg__type();
+ ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
+ break;
+ }
break;
case MNCC__MsgUnion::ALT_hello:
struct gsm_mncc_hello hello;
@@ -222,8 +264,12 @@
const struct gsm_data_frame *in_data;
MNCC__PDU__Data data;
const struct gsm_mncc_rtp *in_rtp;
+ const struct gsm_mncc_rtp_mncc6 *in_rtp_old;
MNCC__PDU__Rtp rtp;
MNCC__MsgUnion u;
+ bool is_ipv6;
+ OCTETSTRING ip;
+ uint16_t port;
in_mncc = (struct gsm_mncc *) ttcn_buffer.get_read_data();
@@ -257,10 +303,40 @@
case MNCC_RTP_CREATE:
case MNCC_RTP_CONNECT:
case MNCC_RTP_FREE:
- in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
- rtp = MNCC__PDU__Rtp(in_rtp->callref, in_rtp->ip, in_rtp->port, in_rtp->payload_type,
- in_rtp->payload_msg_type, in_rtp->sdp);
- u.rtp() = rtp;
+ switch (mncc_sock_version) {
+ case 6:
+ struct in_addr inaddr;
+ in_rtp_old = (const struct gsm_mncc_rtp_mncc6 *) in_mncc;
+ inaddr.s_addr = htonl(in_rtp_old->ip);
+ ip = OCTETSTRING(sizeof(struct in_addr),
+ (const unsigned char*)&inaddr);
+ rtp = MNCC__PDU__Rtp(in_rtp_old->callref, false, ip, in_rtp_old->port, in_rtp_old->payload_type,
+ in_rtp_old->payload_msg_type, in_rtp_old->sdp);
+ u.rtp() = rtp;
+ break;
+ case 7:
+ in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
+ switch (in_rtp->addr.ss_family) {
+ case AF_INET6:
+ is_ipv6 = true;
+ port = ntohs(((struct sockaddr_in6*)&in_rtp->addr)->sin6_port);
+ ip = OCTETSTRING(sizeof(struct in6_addr),
+ (const unsigned char*)&((struct sockaddr_in6*)&in_rtp->addr)->sin6_addr);
+
+ break;
+ case AF_UNSPEC: //RTP_CREATE and RTP_FREE can contain fully zeroed addr
+ case AF_INET:
+ is_ipv6 = false;
+ port = ntohs(((struct sockaddr_in*)&in_rtp->addr)->sin_port);
+ ip = OCTETSTRING(sizeof(struct in_addr),
+ (const unsigned char*)&((struct sockaddr_in*)&in_rtp->addr)->sin_addr);
+ break;
+ }
+ rtp = MNCC__PDU__Rtp(in_rtp->callref, is_ipv6, ip, port, in_rtp->payload_type,
+ in_rtp->payload_msg_type, in_rtp->sdp);
+ u.rtp() = rtp;
+ break;
+ }
break;
default:
sign.callref() = in_mncc->callref;
diff --git a/library/MNCC_Types.ttcn b/library/MNCC_Types.ttcn
index 0a8e7d9..bd233ce 100644
--- a/library/MNCC_Types.ttcn
+++ b/library/MNCC_Types.ttcn
@@ -373,7 +373,8 @@
type record MNCC_PDU_Rtp {
uint32_t callref,
- uint32_t ip,
+ boolean is_ipv6,
+ octetstring ip,
uint16_t rtp_port,
uint32_t payload_type,
uint32_t payload_msg_type,
@@ -421,6 +422,8 @@
external function dec_MNCC_PDU(in octetstring stream) return MNCC_PDU;
+external function set_MNCC_version(in integer version) return boolean;
+
template (value) MNCC_PDU ts_MNCC_HELLO(uint32_t version := 5) := {
msg_type := MNCC_SOCKET_HELLO,
u := {
@@ -1921,7 +1924,8 @@
u := {
rtp := {
callref := call_id,
- ip := 0,
+ is_ipv6 := false,
+ ip := '00000000'O,
rtp_port := 0,
payload_type := 0,
payload_msg_type := 0,
@@ -1935,13 +1939,14 @@
/* MSC -> MNCC: RTP_CREATE.rsp; acknowledge creation of RTP (stating MSC side IP/Port) */
template MNCC_PDU tr_MNCC_RTP_CREATE(template uint32_t call_id := ?,
- template uint32_t ip := ?,
- template uint32_t rtp_port := ?,
+ template octetstring ip := ?,
+ template uint16_t rtp_port := ?,
template uint32_t payload_type := ?) := {
msg_type := MNCC_RTP_CREATE,
u := {
rtp := {
callref := call_id,
+ is_ipv6 := ?,
ip := ip,
rtp_port := rtp_port,
payload_type := payload_type,
@@ -1952,11 +1957,12 @@
}
/* MSC <- MNCC: RTP_CONNECT.req; request connect of RTP */
-template MNCC_PDU ts_MNCC_RTP_CONNECT(uint32_t call_id, uint32_t ip, uint32_t rtp_port, uint32_t pt) := {
+template MNCC_PDU ts_MNCC_RTP_CONNECT(uint32_t call_id, boolean is_ipv6, octetstring ip, uint16_t rtp_port, uint32_t pt) := {
msg_type := MNCC_RTP_CONNECT,
u := {
rtp := {
callref := call_id,
+ is_ipv6 := is_ipv6,
ip := ip,
rtp_port := rtp_port,
payload_type := pt,
@@ -1966,13 +1972,14 @@
}
}
template MNCC_PDU tr_MNCC_RTP_CONNECT(template uint32_t call_id,
- template uint32_t ip := ?,
- template uint32_t rtp_port := ?,
+ template octetstring ip := ?,
+ template uint16_t rtp_port := ?,
template uint32_t pt := ?) := {
msg_type := MNCC_RTP_CONNECT,
u := {
rtp := {
callref := call_id,
+ is_ipv6 := ?,
ip := ip,
rtp_port := rtp_port,
payload_type := pt,
diff --git a/library/mncc.h b/library/mncc.h
index 9aff948..a55d155 100644
--- a/library/mncc.h
+++ b/library/mncc.h
@@ -5,6 +5,7 @@
*/
#include <stdint.h>
+#include <netinet/in.h>
/* GSM 04.08 Bearer Capability: Rate Adaption */
enum gsm48_bcap_ra {
@@ -275,7 +276,7 @@
unsigned char data[0];
};
-#define MNCC_SOCK_VERSION 5
+#define MNCC_SOCK_VERSION 7
struct gsm_mncc_hello {
uint32_t msg_type;
uint32_t version;
@@ -291,11 +292,22 @@
uint32_t lchan_type_offset;
};
+/* Use this one in MNCCv6 */
+struct gsm_mncc_rtp_mncc6 {
+ uint32_t msg_type;
+ uint32_t callref;
+ uint32_t ip;
+ uint16_t port;
+ uint32_t payload_type;
+ uint32_t payload_msg_type;
+
+ char sdp[1024];
+};
+
struct gsm_mncc_rtp {
uint32_t msg_type;
uint32_t callref;
- uint32_t ip;
- uint16_t port;
+ struct sockaddr_storage addr;
uint32_t payload_type;
uint32_t payload_msg_type;
diff --git a/msc/BSC_ConnectionHandler.ttcn b/msc/BSC_ConnectionHandler.ttcn
index 24a56b2..9218c76 100644
--- a/msc/BSC_ConnectionHandler.ttcn
+++ b/msc/BSC_ConnectionHandler.ttcn
@@ -15,6 +15,7 @@
import from General_Types all;
import from Osmocom_Types all;
import from Native_Functions all;
+import from Misc_Helpers all;
import from GSM_Types all;
import from IPL4asp_Types all;
import from SCCPasp_Types all;
@@ -813,6 +814,8 @@
/* MNCC related parameters */
uint32_t mncc_callref optional, /* call reference on the MNCC side */
MNCC_bearer_cap mncc_bearer_cap optional, /* MNCC-side bearer capabilities */
+ HostName mncc_rtp_ip optional, /* MNCC Side RTP IP */
+ PortNumber mncc_rtp_port optional, /* MNCC Side RTP port */
/* RTP related parameters */
HostName bss_rtp_ip optional, /* BSS Side RTP IP */
@@ -845,6 +848,8 @@
emergency := false,
mncc_callref := omit,
mncc_bearer_cap := valueof(ts_MNCC_bcap_voice),
+ mncc_rtp_ip := "42.23.11.5",
+ mncc_rtp_port := 423,
bss_rtp_ip := "9.8.7.6",
bss_rtp_port := 9000,
mss_rtp_ip := omit,
@@ -979,9 +984,16 @@
[] MNCC.receive(tr_MNCC_SETUP_cnf(cpars.mncc_callref)) {
log("f_mt_call_complete 7");
+ var octetstring ip;
+ var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
+ if (is_ipv6) {
+ ip := f_inet6_addr(cpars.mncc_rtp_ip);
+ } else {
+ ip := f_inet_addr(cpars.mncc_rtp_ip);
+ }
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
- /* ip 42.23.11.5 */ hex2int('42231105'H),
- /* port 423 */ 423,
+ is_ipv6, ip,
+ cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
}
@@ -1064,9 +1076,16 @@
[] MNCC.receive(tr_MNCC_SETUP_cnf(cpars.mncc_callref)) {
log("f_mt_call_complete 7.iu");
+ var octetstring ip;
+ var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
+ if (is_ipv6) {
+ ip := f_inet6_addr(cpars.mncc_rtp_ip);
+ } else {
+ ip := f_inet_addr(cpars.mncc_rtp_ip);
+ }
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
- /* ip 42.23.11.5 */ hex2int('42231105'H),
- /* port 423 */ 423,
+ is_ipv6, ip,
+ cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
}
@@ -1458,9 +1477,16 @@
cpars.mncc_callref := mncc.u.signal.callref;
/* Call Proceeding */
+ var octetstring ip;
+ var boolean is_ipv6 := f_addr_is_ipv6(cpars.mncc_rtp_ip);
+ if (is_ipv6) {
+ ip := f_inet6_addr(cpars.mncc_rtp_ip);
+ } else {
+ ip := f_inet_addr(cpars.mncc_rtp_ip);
+ }
MNCC.send(ts_MNCC_RTP_CONNECT(cpars.mncc_callref,
- /* ip 42.23.11.5 */ hex2int('42231105'H),
- /* port 423 */ 423,
+ is_ipv6, ip,
+ cpars.mncc_rtp_port,
/* payload type 3 = GSM FR */ 3));
MNCC.send(ts_MNCC_SETUP_rsp(cpars.mncc_callref));
}
diff --git a/msc/MSC_Tests.ttcn b/msc/MSC_Tests.ttcn
index fb2a46e..5129c5b 100644
--- a/msc/MSC_Tests.ttcn
+++ b/msc/MSC_Tests.ttcn
@@ -1979,6 +1979,7 @@
cpars.mgw_conn_1.mgw_rtp_ip := "::1";
cpars.mgw_conn_2.mgw_rtp_ip := "::2";
cpars.bss_rtp_ip := "::3";
+ cpars.mncc_rtp_ip := "::9";
f_perform_lu();
f_mt_call(cpars);
}
diff --git a/sip/SIP_Tests.default b/sip/SIP_Tests.default
index faf87c8..1c8c2dd 100644
--- a/sip/SIP_Tests.default
+++ b/sip/SIP_Tests.default
@@ -25,7 +25,7 @@
[MODULE_PARAMETERS]
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoSIPcon";
-MNCC_Emulation.mp_mncc_version := 6;
+MNCC_Emulation.mp_mncc_version := 7;
[MAIN_CONTROLLER]