neels has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-pfcp/+/30406 )
Change subject: fix coding of Network Instance IE
......................................................................
fix coding of Network Instance IE
Network instance names should be coded like in DNS, where each label is
preceded by a length byte.
Add static functions to converting between dotted and DNS notation.
These qualify for moving to libosmocore utils, but giving them a spin
here in libosmo-pfcp first (main aim is to speed up the fix now).
Related: SYS#6192
Change-Id: I9d67464ef0f92b0512cfd6e48d203f8828a82a19
---
M src/libosmo-pfcp/pfcp_ies_custom.c
M tests/libosmo-pfcp/pfcp_test.ok
2 files changed, 107 insertions(+), 8 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-pfcp refs/changes/06/30406/1
diff --git a/src/libosmo-pfcp/pfcp_ies_custom.c b/src/libosmo-pfcp/pfcp_ies_custom.c
index 1891902..ac1f6f0 100644
--- a/src/libosmo-pfcp/pfcp_ies_custom.c
+++ b/src/libosmo-pfcp/pfcp_ies_custom.c
@@ -81,6 +81,97 @@
tlv->len - ((POS) - tlv->val)); \
} while (0)
+/* TODO: this probably qualifies for a libosmocore utils.c function */
+/* A memcpy that can be used by OSMO_STRBUF_APPEND(). */
+static int strncpy_buf(char *buf, size_t buflen, const char *src, size_t len)
+{
+ size_t cpylen = len;
+ if (cpylen < SIZE_MAX)
+ cpylen++;
+ cpylen = OSMO_MIN(buflen, cpylen);
+ osmo_strlcpy(buf, src, cpylen);
+ return len;
+}
+
+/* TODO: this probably qualifies for a libosmocore utils.c function */
+/*! Decode a domain string from a qname (RFC 1035 4.1.2).
+ * \param[out] buf Output buffer to write the dotted domain name to.
+ * \param[in] buflen memory available in buf.
+ * \param[in] qname buffer with length-value pairs for each label (e.g. 0x03
"sip" 0x05 "voice" ...)
+ * \param[in] qname_len amount of bytes that can be read at most from the memory
location that qname points to.
+ * \returns number of chars that would be written, like snprintf(), negative on error.
+ */
+static int qname_decode(char *buf, size_t buflen, const uint8_t *qname, size_t
qname_len)
+{
+ struct osmo_strbuf sb = { .buf = buf, .len = buflen };
+ const uint8_t *qname_pos = qname;
+ const uint8_t *qname_end = qname + qname_len;
+
+ /* zero input bytes? */
+ if (qname_len < 1) {
+ if (buflen)
+ buf[0] = '\0';
+ return 0;
+ }
+
+ while (qname_pos < qname_end) {
+ size_t len = *qname_pos;
+ qname_pos++;
+
+ /* Two dots in a row is not allowed */
+ if (!len)
+ return -EINVAL;
+ /* label must not exceed length of input data */
+ if (qname_pos + len > qname_end)
+ return -EINVAL;
+
+ /* Place a dot before each label, but not at the start. */
+ if (sb.chars_needed)
+ OSMO_STRBUF_PRINTF(sb, ".");
+ /* Copy label */
+ OSMO_STRBUF_APPEND(sb, strncpy_buf, (const char *)qname_pos, len);
+ qname_pos += len;
+ }
+
+ return sb.chars_needed;
+}
+
+/* TODO: this probably qualifies for a libosmocore utils.c function */
+/*! Encode a domain string as qname (RFC 1035 4.1.2).
+ * Encode each label as length-value pairs (e.g. 0x03 "sip" 0x05
"voice" ...).
+ * No final '\0' character is written.
+ * \param[out] dst Encode qname to this memory location.
+ * \param[in] dst_maxlen Memory available at dst.
+ * \param[in] domain multiple labels separated by dots, e.g.
"sip.voice.1234.msisdn".
+ * \returns nr of bytes written, negative on error.
+ */
+int qname_encode(uint8_t *dst, size_t dst_maxlen, const char *domain)
+{
+ uint8_t *dst_pos = dst;
+ uint8_t *dst_end = dst_pos + dst_maxlen;
+ const char *pos = domain;
+
+ while (*pos) {
+ const char *next_dot = strchr(pos, '.');
+ size_t len = next_dot ? next_dot - pos : strlen(pos);
+
+ if (len < 1 || len > UINT8_MAX)
+ return -EINVAL;
+
+ if (dst_pos + 1 + len > dst_end)
+ return -ENOSPC;
+ *dst_pos = len;
+ dst_pos++;
+ memcpy(dst_pos, pos, len);
+ dst_pos += len;
+
+ if (!next_dot)
+ break;
+ pos = next_dot + 1;
+ }
+ return dst_pos - dst;
+}
+
void osmo_pfcp_ie_f_seid_set(struct osmo_pfcp_ie_f_seid *f_seid, uint64_t seid, const
struct osmo_sockaddr *remote_addr)
{
*f_seid = (struct osmo_pfcp_ie_f_seid) {
@@ -698,16 +789,24 @@
int osmo_pfcp_dec_network_inst(void *decoded_struct, void *decode_to, const struct
osmo_gtlv_load *tlv)
{
struct osmo_pfcp_ie_network_inst *network_inst = decode_to;
- osmo_strlcpy(network_inst->str, (const char *)tlv->val,
OSMO_MIN(sizeof(network_inst->str), tlv->len+1));
+ int rc;
+
+ rc = qname_decode(network_inst->str, sizeof(network_inst->str), tlv->val,
tlv->len);
+ if (rc < 0)
+ RETURN_ERROR(rc ? : -EINVAL, "decoding qname (RFC 1035 4.1.2) failed");
return 0;
}
int osmo_pfcp_enc_network_inst(struct osmo_gtlv_put *tlv, const void *decoded_struct,
const void *encode_from)
{
const struct osmo_pfcp_ie_network_inst *network_inst = encode_from;
- unsigned int l = strlen(network_inst->str);
- if (l)
- memcpy(msgb_put(tlv->dst, l), network_inst->str, l);
+ int rc;
+
+ rc = qname_encode(tlv->dst->tail, msgb_tailroom(tlv->dst),
network_inst->str);
+ if (rc <= 0)
+ RETURN_ERROR(rc ? : -EINVAL, "encoding qname (RFC 1035 4.1.2) from '%s'
failed",
+ (const char *)encode_from);
+ msgb_put(tlv->dst, rc);
return 0;
}
diff --git a/tests/libosmo-pfcp/pfcp_test.ok b/tests/libosmo-pfcp/pfcp_test.ok
index b8eddb9..02424cd 100644
--- a/tests/libosmo-pfcp/pfcp_test.ok
+++ b/tests/libosmo-pfcp/pfcp_test.ok
@@ -69,8 +69,8 @@
encoding: SESSION_EST_REQ
PFCPv1 SESSION_EST_REQ hdr={seq=7 SEID=0x0} ies={ 'Node ID'=v4:127.0.0.1
'F-SEID'=0x1234567890abcdef,v4:10.9.8.7 'Create PDR'={ { 'PDR
ID'=1 'Precedence'=255 'PDI'={ 'Source Interface'=Core
'Network Instance'="foo" 'UE IP Address'=,dst,v4:192.168.0.23 }
'FAR ID'=1 }, { 'PDR ID'=2 'Precedence'=255 'PDI'={
'Source Interface'=Access 'F-TEID'=CHOOSE-v4 'Network
Instance'="bar" } 'Outer Header Removal'=GTP_U_UDP_IPV4 'FAR
ID'=2 } } 'Create FAR'={ { 'FAR ID'=1 'Apply Action'=( FORW )
'Forwarding Parameters'={ 'Destination Interface'=Access 'Outer Header
Creation'=( GTP_U_UDP_IPV4 ),TEID:0xabcdef,v4:10.9.8.7 } }, { 'FAR ID'=2
'Apply Action'=( FORW ) 'Forwarding Parameters'={ 'Destination
Interface'=Core } } } }
osmo_pfcp_msg_encode() rc = 0
-21 32 00 d1 00 00 00 00 00 00 00 00 00 00 07 00 00 3c 00 05 00 7f 00 00 01 00 39 00 0d 02
12 34 56 78 90 ab cd ef 0a 09 08 07 00 01 00 2f 00 38 00 02 00 01 00 1d 00 04 00 00 00 ff
00 02 00 15 00 14 00 01 01 00 16 00 03 66 6f 6f 00 5d 00 05 06 c0 a8 00 17 00 6c 00 04 00
00 00 01 00 01 00 30 00 38 00 02 00 02 00 1d 00 04 00 00 00 ff 00 02 00 11 00 14 00 01 00
00 15 00 01 05 00 16 00 03 62 61 72 00 5f 00 01 00 00 6c 00 04 00 00 00 02 00 03 00 25 00
6c 00 04 00 00 00 01 00 2c 00 02 02 00 00 04 00 13 00 2a 00 01 00 00 54 00 0a 01 00 00 ab
cd ef 0a 09 08 07 00 03 00 17 00 6c 00 04 00 00 00 02 00 2c 00 02 02 00 00 04 00 05 00 2a
00 01 01 .
-osmo_pfcp_msg_decode_header() rc = 213
+21 32 00 d3 00 00 00 00 00 00 00 00 00 00 07 00 00 3c 00 05 00 7f 00 00 01 00 39 00 0d 02
12 34 56 78 90 ab cd ef 0a 09 08 07 00 01 00 30 00 38 00 02 00 01 00 1d 00 04 00 00 00 ff
00 02 00 16 00 14 00 01 01 00 16 00 04 03 66 6f 6f 00 5d 00 05 06 c0 a8 00 17 00 6c 00 04
00 00 00 01 00 01 00 31 00 38 00 02 00 02 00 1d 00 04 00 00 00 ff 00 02 00 12 00 14 00 01
00 00 15 00 01 05 00 16 00 04 03 62 61 72 00 5f 00 01 00 00 6c 00 04 00 00 00 02 00 03 00
25 00 6c 00 04 00 00 00 01 00 2c 00 02 02 00 00 04 00 13 00 2a 00 01 00 00 54 00 0a 01 00
00 ab cd ef 0a 09 08 07 00 03 00 17 00 6c 00 04 00 00 00 02 00 2c 00 02 02 00 00 04 00 05
00 2a 00 01 01 .
+osmo_pfcp_msg_decode_header() rc = 215
rc == msgb_length()
osmo_pfcp_msg_decode_tlv() rc = 0
parsed == orig
@@ -91,8 +91,8 @@
encoding: SESSION_MOD_REQ
PFCPv1 SESSION_MOD_REQ hdr={seq=9 SEID=0x0} ies={ 'Remove PDR'={ { 'PDR
ID'=1 } } 'Remove FAR'={ { 'FAR ID'=1 } } 'Create PDR'={ {
'PDR ID'=3 'Precedence'=255 'PDI'={ 'Source
Interface'=Access 'F-TEID'=CHOOSE-v4 'Network
Instance'="baz" } 'Outer Header Removal'=GTP_U_UDP_IPV4 'FAR
ID'=3 } } 'Create FAR'={ { 'FAR ID'=3 'Apply Action'=( FORW )
'Forwarding Parameters'={ 'Destination Interface'=Access 'Outer Header
Creation'=( GTP_U_UDP_IPV4 ),TEID:0xabcdef,v4:10.9.8.7 } } } 'Update PDR'={ {
'PDR ID'=1 'Outer Header Removal'=GTP_U_UDP_IPV4 'PDI'={
'Source Interface'=Access 'F-TEID'=CHOOSE-v4 'Network
Instance'="moo" } 'FAR ID'=1 } } 'Update FAR'={ { 'FAR
ID'=1 'Update Forwarding Parameters'={ 'Network
Instance'="internet" } } } }
osmo_pfcp_msg_encode() rc = 0
-21 34 00 c7 00 00 00 00 00 00 00 00 00 00 09 00 00 0f 00 06 00 38 00 02 00 01 00 10 00 08
00 6c 00 04 00 00 00 01 00 01 00 30 00 38 00 02 00 03 00 1d 00 04 00 00 00 ff 00 02 00 11
00 14 00 01 00 00 15 00 01 05 00 16 00 03 62 61 7a 00 5f 00 01 00 00 6c 00 04 00 00 00 03
00 03 00 25 00 6c 00 04 00 00 00 03 00 2c 00 02 02 00 00 04 00 13 00 2a 00 01 00 00 54 00
0a 01 00 00 ab cd ef 0a 09 08 07 00 09 00 28 00 38 00 02 00 01 00 5f 00 01 00 00 02 00 11
00 14 00 01 00 00 15 00 01 05 00 16 00 03 6d 6f 6f 00 6c 00 04 00 00 00 01 00 0a 00 18 00
6c 00 04 00 00 00 01 00 0b 00 0c 00 16 00 08 69 6e 74 65 72 6e 65 74 .
-osmo_pfcp_msg_decode_header() rc = 203
+21 34 00 ca 00 00 00 00 00 00 00 00 00 00 09 00 00 0f 00 06 00 38 00 02 00 01 00 10 00 08
00 6c 00 04 00 00 00 01 00 01 00 31 00 38 00 02 00 03 00 1d 00 04 00 00 00 ff 00 02 00 12
00 14 00 01 00 00 15 00 01 05 00 16 00 04 03 62 61 7a 00 5f 00 01 00 00 6c 00 04 00 00 00
03 00 03 00 25 00 6c 00 04 00 00 00 03 00 2c 00 02 02 00 00 04 00 13 00 2a 00 01 00 00 54
00 0a 01 00 00 ab cd ef 0a 09 08 07 00 09 00 29 00 38 00 02 00 01 00 5f 00 01 00 00 02 00
12 00 14 00 01 00 00 15 00 01 05 00 16 00 04 03 6d 6f 6f 00 6c 00 04 00 00 00 01 00 0a 00
19 00 6c 00 04 00 00 00 01 00 0b 00 0d 00 16 00 09 08 69 6e 74 65 72 6e 65 74 .
+osmo_pfcp_msg_decode_header() rc = 206
rc == msgb_length()
osmo_pfcp_msg_decode_tlv() rc = 0
parsed == orig
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-pfcp/+/30406
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-pfcp
Gerrit-Branch: master
Gerrit-Change-Id: I9d67464ef0f92b0512cfd6e48d203f8828a82a19
Gerrit-Change-Number: 30406
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange