iu_helpers: make new_transp_info_(rtp|gtp) public

The functions new_transp_info_rtp and new_transp_info_gtp are needed to
generate the transport layer information struct. The functions are currently
not public since they are only used in ranap_msg_factory.c but to
reqwrite the RANAP RAB AssignmentReqtest / AssignmentResponse messages we
can reuse this code, so lets make them public.

Change-Id: I1e369718de8c4c7db1f1af1e6864562164ada6cf
Related: OS#5152
This commit is contained in:
Philipp Maier 2022-01-06 13:23:50 +01:00 committed by laforge
parent 48b8af2bde
commit ed1537e9cb
5 changed files with 267 additions and 59 deletions

View File

@ -1,13 +1,20 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
#include <osmocom/ranap/RANAP_IuTransportAssociation.h>
#include <osmocom/ranap/RANAP_TransportLayerAddress.h>
#include <osmocom/ranap/RANAP_TransportLayerInformation.h>
struct osmo_sockaddr;
int ranap_bcd_decode(char *out, size_t out_len, const uint8_t *in, size_t in_len);
int ranap_imsi_encode(uint8_t *out, size_t out_len, const char *in);
int ranap_transp_assoc_decode(uint16_t *port, const RANAP_IuTransportAssociation_t *transp_assoc);
int ranap_transp_layer_addr_decode(char *addr, unsigned int addr_len,
const RANAP_TransportLayerAddress_t *trasp_layer_addr);
RANAP_TransportLayerInformation_t *ranap_new_transp_info_rtp(struct osmo_sockaddr *addr, bool use_x213_nsap);
RANAP_TransportLayerInformation_t *ranap_new_transp_info_gtp(struct osmo_sockaddr *addr, uint32_t tei,
bool use_x213_nsap);

View File

@ -24,8 +24,12 @@
#include <arpa/inet.h>
#include "asn1helpers.h"
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/bit16gen.h>
#include <osmocom/ranap/RANAP_IuTransportAssociation.h>
#include <osmocom/ranap/RANAP_TransportLayerAddress.h>
#include <osmocom/ranap/RANAP_TransportLayerInformation.h>
/* decode a BCD-string as used inside ASN.1 encoded Iu interface protocols */
int ranap_bcd_decode(char *out, size_t out_len, const uint8_t *in, size_t in_len)
@ -121,3 +125,102 @@ int ranap_transp_layer_addr_decode(char *addr, unsigned int addr_len,
return 0;
}
static int new_transp_layer_addr(BIT_STRING_t *out, struct osmo_sockaddr *addr, bool use_x213_nsap)
{
uint8_t *buf;
unsigned int len;
size_t ip_len;
uint8_t *ip_addr;
uint16_t icp;
switch (addr->u.sa.sa_family) {
case AF_INET:
ip_len = sizeof(addr->u.sin.sin_addr.s_addr);
ip_addr = (uint8_t *) &addr->u.sin.sin_addr.s_addr;
icp = 0x0001; /* See X.213, section A.5.2.1.2.7 */
break;
case AF_INET6:
ip_len = sizeof(addr->u.sin6.sin6_addr.s6_addr);
ip_addr = addr->u.sin6.sin6_addr.s6_addr;
icp = 0x0000; /* See X.213, section A.5.2.1.2.7 */
break;
default:
return -EINVAL;
}
if (use_x213_nsap) {
/* 3 bytes IDP (AFI+ICP) + 17 bytes DSP */
len = 3 + 17;
buf = CALLOC(len, sizeof(uint8_t));
/* 1 byte AFI to announce IANA ICP, see also X.213, table A.4 */
buf[0] = 0x35;
/* 2 byte IANA ICP IDI, see also X.213, A.5.2.1.2.7 */
osmo_store16be(icp, &buf[1]);
/* 17 byte DSP, see also X.213, table A.5 and A.5.2.1.2.7 */
memcpy(&buf[3], ip_addr, ip_len);
} else {
len = ip_len;
buf = CALLOC(len, sizeof(uint8_t));
memcpy(buf, ip_addr, ip_len);
}
out->buf = buf;
out->size = len;
out->bits_unused = 0;
return 0;
}
RANAP_TransportLayerInformation_t *ranap_new_transp_info_rtp(struct osmo_sockaddr *addr, bool use_x213_nsap)
{
RANAP_TransportLayerInformation_t *tli;
uint8_t binding_id[4] = { 0 };
int rc;
switch (addr->u.sin.sin_family) {
case AF_INET:
osmo_store16be(ntohs(addr->u.sin.sin_port), binding_id);
break;
case AF_INET6:
osmo_store16be(ntohs(addr->u.sin6.sin6_port), binding_id);
break;
default:
return NULL;
}
tli = CALLOC(1, sizeof(*tli));
rc = new_transp_layer_addr(&tli->transportLayerAddress, addr, use_x213_nsap);
if (rc < 0) {
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
return NULL;
}
tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_bindingID;
OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID,
(const char *)binding_id, sizeof(binding_id));
return tli;
}
RANAP_TransportLayerInformation_t *ranap_new_transp_info_gtp(struct osmo_sockaddr *addr, uint32_t tei,
bool use_x213_nsap)
{
RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
uint32_t binding_buf = htonl(tei);
int rc;
rc = new_transp_layer_addr(&tli->transportLayerAddress, addr, use_x213_nsap);
if (rc < 0) {
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
return NULL;
}
tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_gTP_TEI;
OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.gTP_TEI,
(const char *)&binding_buf, sizeof(binding_buf));
return tli;
}

View File

@ -20,6 +20,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/socket.h>
#include "asn1helpers.h"
#include <osmocom/ranap/iu_helpers.h>
@ -691,61 +692,6 @@ static RANAP_RAB_Parameters_t *new_rab_par_data(uint32_t dl_max_bitrate, uint32_
return rab;
}
static void new_transp_layer_addr(BIT_STRING_t *out, uint32_t ip, bool use_x213_nsap)
{
uint8_t *buf;
unsigned int len;
uint32_t ip_h = ntohl(ip);
if (use_x213_nsap) {
len = 160/8;
buf = CALLOC(len, sizeof(uint8_t));
buf[0] = 0x35; /* AFI For IANA ICP */
buf[1] = 0x00; /* See A.5.2.1.2.7 of X.213 */
buf[2] = 0x01;
memcpy(&buf[3], &ip_h, sizeof(ip_h));
} else {
len = sizeof(ip_h);
buf = CALLOC(len, sizeof(uint8_t));
memcpy(buf, &ip_h, sizeof(ip_h));
}
out->buf = buf;
out->size = len;
out->bits_unused = 0;
}
static RANAP_TransportLayerInformation_t *new_transp_info_rtp(uint32_t ip, uint16_t port,
bool use_x213_nsap)
{
RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
uint8_t binding_id[4];
binding_id[0] = port >> 8;
binding_id[1] = port & 0xff;
binding_id[2] = binding_id[3] = 0;
new_transp_layer_addr(&tli->transportLayerAddress, ip, use_x213_nsap);
tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_bindingID;
OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.bindingID,
(const char *) binding_id, sizeof(binding_id));
return tli;
}
static RANAP_TransportLayerInformation_t *new_transp_info_gtp(uint32_t ip, uint32_t tei,
bool use_x213_nsap)
{
RANAP_TransportLayerInformation_t *tli = CALLOC(1, sizeof(*tli));
uint32_t binding_buf = htonl(tei);
new_transp_layer_addr(&tli->transportLayerAddress, ip, use_x213_nsap);
tli->iuTransportAssociation.present = RANAP_IuTransportAssociation_PR_gTP_TEI;
OCTET_STRING_fromBuf(&tli->iuTransportAssociation.choice.gTP_TEI,
(const char *) &binding_buf, sizeof(binding_buf));
return tli;
}
static RANAP_UserPlaneInformation_t *new_upi(long mode, uint8_t mode_versions)
{
RANAP_UserPlaneInformation_t *upi = CALLOC(1, sizeof(*upi));
@ -786,6 +732,7 @@ struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip,
RANAP_RAB_AssignmentRequest_t out;
struct msgb *msg;
int rc;
struct osmo_sockaddr rtp_addr;
memset(&ies, 0, sizeof(ies));
memset(&out, 0, sizeof(out));
@ -800,8 +747,11 @@ struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id, uint32_t rtp_ip,
first.nAS_SynchronisationIndicator = new_rab_nas_sync_ind(60);
first.rAB_Parameters = new_rab_par_voice(6700, 12200);
first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_support_mode_for_predefined_SDU_sizes, 1); /* 2? */
first.transportLayerInformation = new_transp_info_rtp(rtp_ip, rtp_port,
use_x213_nsap);
rtp_addr.u.sin.sin_family = AF_INET;
rtp_addr.u.sin.sin_port = htons(rtp_port);
rtp_addr.u.sin.sin_addr.s_addr = htonl(rtp_ip);
first.transportLayerInformation = ranap_new_transp_info_rtp(&rtp_addr, use_x213_nsap);
/* put together the 'Second' part */
RANAP_RAB_SetupOrModifyItemSecond_t second;
@ -855,6 +805,7 @@ struct msgb *ranap_new_msg_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip,
RANAP_DataVolumeReportingIndication_t *dat_vol_ind;
struct msgb *msg;
int rc;
struct osmo_sockaddr gtp_addr;
memset(&ies, 0, sizeof(ies));
memset(&out, 0, sizeof(out));
@ -870,8 +821,10 @@ struct msgb *ranap_new_msg_rab_assign_data(uint8_t rab_id, uint32_t gtp_ip,
first.rAB_Parameters = new_rab_par_data(1600000, 800000);
first.userPlaneInformation = new_upi(RANAP_UserPlaneMode_transparent_mode, 1);
first.transportLayerInformation = new_transp_info_gtp(gtp_ip, gtp_tei,
use_x213_nsap);
gtp_addr.u.sin.sin_family = AF_INET;
gtp_addr.u.sin.sin_addr.s_addr = htonl(gtp_ip);
first.transportLayerInformation = ranap_new_transp_info_gtp(&gtp_addr, gtp_tei, use_x213_nsap);
/* put together the 'Second' part */
RANAP_RAB_SetupOrModifyItemSecond_t second;

View File

@ -28,6 +28,7 @@
#define ASSERT(x) assert(x)
#include <osmocom/core/utils.h>
#include <osmocom/core/socket.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/ranap/RANAP_LAI.h>
@ -204,6 +205,120 @@ void test_ranap_common(void)
OSMO_ASSERT(rc == -1);
}
void test_ranap_new_transp_info_rtp(void)
{
RANAP_TransportLayerInformation_t *tli;
printf("Testing function ranap_new_transp_info_rtp()\n");
struct osmo_sockaddr addr;
addr.u.sin.sin_family = AF_INET;
addr.u.sin.sin_port = htons(0x1122);
inet_pton(AF_INET, "1.2.3.4", &addr.u.sin.sin_addr);
printf(" ipv4, x213_nsap\n");
tli = ranap_new_transp_info_rtp(&addr, true);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" bindingID = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.bindingID.buf,
tli->iuTransportAssociation.choice.bindingID.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
printf(" ipv4\n");
tli = ranap_new_transp_info_rtp(&addr, false);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" bindingID = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.bindingID.buf,
tli->iuTransportAssociation.choice.bindingID.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
addr.u.sin.sin_family = AF_INET6;
addr.u.sin.sin_port = htons(0x1122);
inet_pton(AF_INET6, "f11f:f22f:f33f:f44f:f55f:f66f:f77f:f88f", &addr.u.sin6.sin6_addr);
printf(" ipv6, x213_nsap\n");
tli = ranap_new_transp_info_rtp(&addr, true);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" bindingID = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.bindingID.buf,
tli->iuTransportAssociation.choice.bindingID.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
printf(" ipv6\n");
tli = ranap_new_transp_info_rtp(&addr, false);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" bindingID = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.bindingID.buf,
tli->iuTransportAssociation.choice.bindingID.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
addr.u.sin.sin_family = AF_X25;
printf(" unsupported address family\n");
tli = ranap_new_transp_info_rtp(&addr, false);
OSMO_ASSERT(tli == NULL);
}
void test_ranap_new_transp_info_gtp(void)
{
RANAP_TransportLayerInformation_t *tli;
printf("Testing function ranap_new_transp_info_gtp()\n");
struct osmo_sockaddr addr;
addr.u.sin.sin_family = AF_INET;
inet_pton(AF_INET, "1.2.3.4", &addr.u.sin.sin_addr);
printf(" ipv4, x213_nsap\n");
tli = ranap_new_transp_info_gtp(&addr, 0x11223344, true);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" gTP_TEI = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.gTP_TEI.buf,
tli->iuTransportAssociation.choice.gTP_TEI.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
printf(" ipv4\n");
tli = ranap_new_transp_info_gtp(&addr, 0x11223344, false);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" gTP_TEI = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.gTP_TEI.buf,
tli->iuTransportAssociation.choice.gTP_TEI.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
addr.u.sin.sin_family = AF_INET6;
inet_pton(AF_INET6, "f11f:f22f:f33f:f44f:f55f:f66f:f77f:f88f", &addr.u.sin6.sin6_addr);
printf(" ipv6, x213_nsap\n");
tli = ranap_new_transp_info_gtp(&addr, 0x11223344, true);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" gTP_TEI = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.gTP_TEI.buf,
tli->iuTransportAssociation.choice.gTP_TEI.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
printf(" ipv6\n");
tli = ranap_new_transp_info_gtp(&addr, 0x11223344, false);
printf(" transportLayerAddress = %s\n",
osmo_hexdump_nospc(tli->transportLayerAddress.buf, tli->transportLayerAddress.size));
printf(" gTP_TEI = %s\n",
osmo_hexdump_nospc(tli->iuTransportAssociation.choice.gTP_TEI.buf,
tli->iuTransportAssociation.choice.gTP_TEI.size));
ASN_STRUCT_FREE(asn_DEF_RANAP_TransportLayerInformation, tli);
addr.u.sin.sin_family = AF_X25;
printf(" unsupported address family\n");
tli = ranap_new_transp_info_gtp(&addr, 0x11223344, false);
OSMO_ASSERT(tli == NULL);
}
int main(int argc, char **argv)
{
asn1_xer_print = 0;
@ -214,6 +329,8 @@ int main(int argc, char **argv)
test_iu_helpers();
test_asn1_helpers();
test_ranap_common();
test_ranap_new_transp_info_gtp();
test_ranap_new_transp_info_rtp();
test_common_cleanup();
return 0;

View File

@ -23,3 +23,31 @@ PLMN-Id [ 21 43 ], LAC [ ab cd ]
rc == -1
PLMN-Id [ 21 43 65 ], LAC [ ab ]
rc == -1
Testing function ranap_new_transp_info_gtp()
ipv4, x213_nsap
transportLayerAddress = 3500010102030400000000000000000000000000
gTP_TEI = 11223344
ipv4
transportLayerAddress = 01020304
gTP_TEI = 11223344
ipv6, x213_nsap
transportLayerAddress = 350000f11ff22ff33ff44ff55ff66ff77ff88f00
gTP_TEI = 11223344
ipv6
transportLayerAddress = f11ff22ff33ff44ff55ff66ff77ff88f
gTP_TEI = 11223344
unsupported address family
Testing function ranap_new_transp_info_rtp()
ipv4, x213_nsap
transportLayerAddress = 3500010102030400000000000000000000000000
bindingID = 11220000
ipv4
transportLayerAddress = 01020304
bindingID = 11220000
ipv6, x213_nsap
transportLayerAddress = 350000f11ff22ff33ff44ff55ff66ff77ff88f00
bindingID = 11220000
ipv6
transportLayerAddress = f11ff22ff33ff44ff55ff66ff77ff88f
bindingID = 11220000
unsupported address family