mncc: Support IPv6 addresses (new version mncc 7)

Apparently commit 06b859ca31 forgot to
bump the MNCC_SOCK_VERSION field from 5 to 6.

Change-Id: I5448ff931ec33f24f4837a51376f1703fe97683b
changes/56/20056/5
Pau Espin 2 years ago committed by pespin
parent 28aa466dd9
commit 563b3d013b
  1. 7
      library/MNCC_Emulation.ttcn
  2. 102
      library/MNCC_EncDec.cc
  3. 21
      library/MNCC_Types.ttcn
  4. 18
      library/mncc.h
  5. 38
      msc/BSC_ConnectionHandler.ttcn
  6. 1
      msc/MSC_Tests.ttcn
  7. 2
      sip/SIP_Tests.default

@ -38,7 +38,7 @@ import from MNCC_Types all;
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 @@ type record MnccOps {
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)));

@ -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 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
{
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 @@ OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
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 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
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 @@ MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
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;

@ -373,7 +373,8 @@ type record MNCC_PDU_Data {
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 enc_MNCC_PDU(in MNCC_PDU pdu) return octetstring;
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 @@ template MNCC_PDU ts_MNCC_SIMPLE_RTP(MNCC_MsgType msg_type, uint32_t call_id) :=
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 @@ template MNCC_PDU ts_MNCC_RTP_CREATE(uint32_t call_id) := ts_MNCC_SIMPLE_RTP(MNC
/* 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 @@ template MNCC_PDU tr_MNCC_RTP_CREATE(template uint32_t call_id := ?,
}
/* 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 ts_MNCC_RTP_CONNECT(uint32_t call_id, uint32_t ip, uint32_t rt
}
}
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,

@ -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 @@ struct gsm_data_frame {
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 @@ struct gsm_mncc_hello {
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;

@ -15,6 +15,7 @@ module BSC_ConnectionHandler {
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 @@ type record CallParameters {
/* 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 @@ template (value) CallParameters t_CallParams(hexstring called := '12345'H, integ
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 @@ runs on BSC_ConnHdlr {
[] 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 @@ runs on BSC_ConnHdlr {
[] 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 @@ runs on BSC_ConnHdlr {
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));
}

@ -1979,6 +1979,7 @@ friend function f_tc_lu_and_mt_call_ipv6(charstring id, BSC_ConnHdlrPars pars) r
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);
}

@ -25,7 +25,7 @@ mtc.FileMask := ERROR | WARNING | PARALLEL | VERDICTOP;
[MODULE_PARAMETERS]
Osmocom_VTY_Functions.mp_prompt_prefix := "OsmoSIPcon";
MNCC_Emulation.mp_mncc_version := 6;
MNCC_Emulation.mp_mncc_version := 7;
[MAIN_CONTROLLER]

Loading…
Cancel
Save