From c0a0b2562bd65188b6d70d308cc7f595764deb97 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Mon, 10 Jan 2022 13:54:57 +0100 Subject: [PATCH] iu_helpers: add function ranap_transp_layer_addr_decode2 Add ranap_transp_layer_addr_decode2 as AF agnostic version of ranap_transp_layer_addr_decode. Change-Id: Ia60e0ab671fc4185815a880377ab88fcf1b30ac9 --- include/osmocom/ranap/iu_helpers.h | 2 + src/iu_helpers.c | 50 ++++++++++++++++++++++++ src/tests/test-helpers.c | 61 ++++++++++++++++++++++++++++++ src/tests/test-helpers.ok | 9 +++++ 4 files changed, 122 insertions(+) diff --git a/include/osmocom/ranap/iu_helpers.h b/include/osmocom/ranap/iu_helpers.h index d8246468..bf2a5803 100644 --- a/include/osmocom/ranap/iu_helpers.h +++ b/include/osmocom/ranap/iu_helpers.h @@ -15,6 +15,8 @@ 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); +int ranap_transp_layer_addr_decode2(struct osmo_sockaddr *addr, bool *uses_x213_nsap, + 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); diff --git a/src/iu_helpers.c b/src/iu_helpers.c index 62f5c227..1591f7d0 100644 --- a/src/iu_helpers.c +++ b/src/iu_helpers.c @@ -126,6 +126,56 @@ int ranap_transp_layer_addr_decode(char *addr, unsigned int addr_len, return 0; } +/* (same as ranap_transp_layer_addr_decode, but AF agnostic) */ +int ranap_transp_layer_addr_decode2(struct osmo_sockaddr *addr, bool *uses_x213_nsap, + const RANAP_TransportLayerAddress_t *trasp_layer_addr) +{ + unsigned char *buf; + int len; + bool x213_nsap = false; + uint16_t icp; + + buf = trasp_layer_addr->buf; + len = trasp_layer_addr->size; + + memset(addr, 0, sizeof(*addr)); + + if (len == 20 && buf[0] == 0x35) { + /* For an X.213 NSAP encoded address we expect a buffer of exactly 20 bytes (3 bytes IDP + 17 bytes + * DSP). we also expect AFI = 0x35, which means that two byte IDI and an IP address follows. (see also + * comments in function new_transp_layer_addr below) */ + x213_nsap = true; + icp = osmo_load16be(&buf[1]); + switch (icp) { + case 0x0000: + addr->u.sa.sa_family = AF_INET6; + memcpy(addr->u.sin6.sin6_addr.s6_addr, buf + 3, sizeof(addr->u.sin6.sin6_addr.s6_addr)); + break; + case 0x0001: + addr->u.sa.sa_family = AF_INET; + memcpy((uint8_t *) &addr->u.sin.sin_addr.s_addr, buf + 3, sizeof(addr->u.sin.sin_addr.s_addr)); + break; + default: + return -EINVAL; + } + } else if (len == 4) { + /* A non X.213 NSAP encoded IPv4 address is 4 bytes long */ + addr->u.sa.sa_family = AF_INET; + memcpy((uint8_t *) &addr->u.sin.sin_addr.s_addr, buf, sizeof(addr->u.sin.sin_addr.s_addr)); + } else if (len == 16) { + /* A non X.213 NSAP encoded IPv6 address is 16 bytes long */ + addr->u.sa.sa_family = AF_INET6; + memcpy(addr->u.sin6.sin6_addr.s6_addr, buf, sizeof(addr->u.sin6.sin6_addr.s6_addr)); + } else + return -EINVAL; + + /* In case the caller is interested in the encoding method that was used */ + if (uses_x213_nsap) + *uses_x213_nsap = x213_nsap; + + return 0; +} + static int new_transp_layer_addr(BIT_STRING_t *out, struct osmo_sockaddr *addr, bool use_x213_nsap) { uint8_t *buf; diff --git a/src/tests/test-helpers.c b/src/tests/test-helpers.c index 5b5004a7..42e8b26b 100644 --- a/src/tests/test-helpers.c +++ b/src/tests/test-helpers.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -347,6 +348,65 @@ void test_ranap_transp_layer_addr_decode(void) OSMO_ASSERT(rc == 0); } +void test_ranap_transp_layer_addr_decode2(void) +{ + int rc; + struct osmo_sockaddr addr; + struct osmo_sockaddr_str sockaddr_str; + bool uses_x213_nsap; + RANAP_TransportLayerAddress_t trasp_layer_addr = { 0 }; + uint8_t encoded_ipv4_addr_x213_nsap[] = { + 0x35, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + uint8_t encoded_ipv4_addr[] = { 0x01, 0x02, 0x03, 0x04 }; + uint8_t encoded_ipv6_addr_x213_nsap[] = { + 0x35, 0x00, 0x00, 0xf1, 0x1f, 0xf2, 0x2f, 0xf3, + 0x3f, 0xf4, 0x4f, 0xf5, 0x5f, 0xf6, 0x6f, 0xf7, + 0x7f, 0xf8, 0x8f, 0x00 }; + uint8_t encoded_ipv6_addr[] = { + 0xf1, 0x1f, 0xf2, 0x2f, 0xf3, 0x3f, 0xf4, 0x4f, + 0xf5, 0x5f, 0xf6, 0x6f, 0xf7, 0x7f, 0xf8, 0x8f }; + + printf("Testing function ranap_transp_layer_addr_decode2()\n"); + + printf(" ipv4, x213_nsap\n"); + trasp_layer_addr.buf = encoded_ipv4_addr_x213_nsap; + trasp_layer_addr.size = sizeof(encoded_ipv4_addr_x213_nsap); + rc = ranap_transp_layer_addr_decode2(&addr, &uses_x213_nsap, &trasp_layer_addr); + OSMO_ASSERT(rc == 0); + memset(&sockaddr_str, 0, sizeof(sockaddr_str)); + osmo_sockaddr_str_from_sockaddr_in(&sockaddr_str, &addr.u.sin); + printf(" addr=%s, af=%d, x213_nsap=%u\n", sockaddr_str.ip, sockaddr_str.af, uses_x213_nsap); + + printf(" ipv4\n"); + trasp_layer_addr.buf = encoded_ipv4_addr; + trasp_layer_addr.size = sizeof(encoded_ipv4_addr); + rc = ranap_transp_layer_addr_decode2(&addr, &uses_x213_nsap, &trasp_layer_addr); + OSMO_ASSERT(rc == 0); + memset(&sockaddr_str, 0, sizeof(sockaddr_str)); + osmo_sockaddr_str_from_sockaddr_in(&sockaddr_str, &addr.u.sin); + printf(" addr=%s, af=%d, x213_nsap=%u\n", sockaddr_str.ip, sockaddr_str.af, uses_x213_nsap); + + printf(" ipv6, x213_nsap\n"); + trasp_layer_addr.buf = encoded_ipv6_addr_x213_nsap; + trasp_layer_addr.size = sizeof(encoded_ipv6_addr_x213_nsap); + rc = ranap_transp_layer_addr_decode2(&addr, &uses_x213_nsap, &trasp_layer_addr); + OSMO_ASSERT(rc == 0); + memset(&sockaddr_str, 0, sizeof(sockaddr_str)); + osmo_sockaddr_str_from_sockaddr_in6(&sockaddr_str, &addr.u.sin6); + printf(" addr=%s, af=%d, x213_nsap=%u\n", sockaddr_str.ip, sockaddr_str.af, uses_x213_nsap); + + printf(" ipv6\n"); + trasp_layer_addr.buf = encoded_ipv6_addr; + trasp_layer_addr.size = sizeof(encoded_ipv6_addr); + rc = ranap_transp_layer_addr_decode2(&addr, &uses_x213_nsap, &trasp_layer_addr); + OSMO_ASSERT(rc == 0); + memset(&sockaddr_str, 0, sizeof(sockaddr_str)); + osmo_sockaddr_str_from_sockaddr_in6(&sockaddr_str, &addr.u.sin6); + printf(" addr=%s, af=%d, x213_nsap=%u\n", sockaddr_str.ip, sockaddr_str.af, uses_x213_nsap); +} + int main(int argc, char **argv) { asn1_xer_print = 0; @@ -360,6 +420,7 @@ int main(int argc, char **argv) test_ranap_new_transp_info_gtp(); test_ranap_new_transp_info_rtp(); test_ranap_transp_layer_addr_decode(); + test_ranap_transp_layer_addr_decode2(); test_common_cleanup(); return 0; diff --git a/src/tests/test-helpers.ok b/src/tests/test-helpers.ok index fe082878..0626413d 100644 --- a/src/tests/test-helpers.ok +++ b/src/tests/test-helpers.ok @@ -56,3 +56,12 @@ Testing function ranap_transp_layer_addr_decode() addr=1.2.3.4 ipv4 addr=1.2.3.4 +Testing function ranap_transp_layer_addr_decode2() + ipv4, x213_nsap + addr=1.2.3.4, af=2, x213_nsap=1 + ipv4 + addr=1.2.3.4, af=2, x213_nsap=0 + ipv6, x213_nsap + addr=f11f:f22f:f33f:f44f:f55f:f66f:f77f:f88f, af=10, x213_nsap=1 + ipv6 + addr=f11f:f22f:f33f:f44f:f55f:f66f:f77f:f88f, af=10, x213_nsap=0