aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gprs/gprs_sndcp_xid.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gprs/gprs_sndcp_xid.c')
-rw-r--r--openbsc/src/gprs/gprs_sndcp_xid.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/openbsc/src/gprs/gprs_sndcp_xid.c b/openbsc/src/gprs/gprs_sndcp_xid.c
index bb43eab68..37551e462 100644
--- a/openbsc/src/gprs/gprs_sndcp_xid.c
+++ b/openbsc/src/gprs/gprs_sndcp_xid.c
@@ -549,26 +549,29 @@ static int gprs_sndcp_pack_fields(const struct llist_head *comp_fields,
/* Transform a list with compression fields into an SNDCP-XID message (dst) */
int gprs_sndcp_compile_xid(uint8_t *dst, unsigned int dst_maxlen,
- const struct llist_head *comp_fields)
+ const struct llist_head *comp_fields, int version)
{
int rc;
int byte_counter = 0;
uint8_t comp_bytes[512];
- uint8_t xid_version_number[1] = { CURRENT_SNDCP_VERSION };
+ uint8_t xid_version_number[1];
OSMO_ASSERT(comp_fields);
OSMO_ASSERT(dst);
OSMO_ASSERT(dst_maxlen >= 2 + sizeof(xid_version_number));
- /* Bail if there is no input */
- if (llist_empty(comp_fields))
- return -EINVAL;
+ /* Prepend header with version number */
+ if (version >= 0) {
+ xid_version_number[0] = (uint8_t) (version & 0xff);
+ dst =
+ tlv_put(dst, SNDCP_XID_VERSION_NUMBER,
+ sizeof(xid_version_number), xid_version_number);
+ byte_counter += (sizeof(xid_version_number) + 2);
+ }
- /* Prepend header */
- dst =
- tlv_put(dst, SNDCP_XID_VERSION_NUMBER,
- sizeof(xid_version_number), xid_version_number);
- byte_counter += (sizeof(xid_version_number) + 2);
+ /* Stop if there is no compression fields supplied */
+ if (llist_empty(comp_fields))
+ return byte_counter;
/* Add data compression fields */
rc = gprs_sndcp_pack_fields(comp_fields, comp_bytes,
@@ -1283,11 +1286,10 @@ static int decode_xid_block(struct llist_head *comp_fields, uint8_t tag,
}
/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
-static int gprs_sndcp_decode_xid(struct llist_head *comp_fields,
+static int gprs_sndcp_decode_xid(int *version, struct llist_head *comp_fields,
const uint8_t *src, unsigned int src_len,
- const struct
- entity_algo_table
- *lt, unsigned int lt_len)
+ const struct entity_algo_table *lt,
+ unsigned int lt_len)
{
int src_pos = 0;
uint8_t tag;
@@ -1297,6 +1299,10 @@ static int gprs_sndcp_decode_xid(struct llist_head *comp_fields,
int rc;
int tlv_count = 0;
+ /* Preset version value as invalid */
+ if(version)
+ *version = -1;
+
/* Valid TLV-Tag and types */
static const struct tlv_definition sndcp_xid_def = {
.def = {
@@ -1327,6 +1333,10 @@ static int gprs_sndcp_decode_xid(struct llist_head *comp_fields,
return -EINVAL;
}
+ /* Decode sndcp xid version number */
+ if (version && tag == SNDCP_XID_VERSION_NUMBER)
+ *version = val[0];
+
/* Decode compression parameters */
if ((tag == SNDCP_XID_PROTOCOL_COMPRESSION)
|| (tag == SNDCP_XID_DATA_COMPRESSION)) {
@@ -1548,7 +1558,8 @@ static int gprs_sndcp_complete_comp_fields(struct llist_head
}
/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
-struct llist_head *gprs_sndcp_parse_xid(const void *ctx,
+struct llist_head *gprs_sndcp_parse_xid(int *version,
+ const void *ctx,
const uint8_t *src,
unsigned int src_len,
const struct llist_head
@@ -1559,6 +1570,12 @@ struct llist_head *gprs_sndcp_parse_xid(const void *ctx,
struct llist_head *comp_fields;
struct entity_algo_table lt[MAX_ENTITIES * 2];
+ /* In case of a zero length field, just exit */
+ if(src_len == 0)
+ return NULL;
+
+ /* We should go any further if we have a field length greater
+ * zero and a null pointer as buffer! */
OSMO_ASSERT(src);
comp_fields = talloc_zero(ctx, struct llist_head);
@@ -1575,8 +1592,8 @@ struct llist_head *gprs_sndcp_parse_xid(const void *ctx,
}
/* Parse SNDCP-CID XID-Field */
- rc = gprs_sndcp_decode_xid(comp_fields, src, src_len, lt,
- lt_len);
+ rc = gprs_sndcp_decode_xid(version, comp_fields, src, src_len,
+ lt, lt_len);
if (rc < 0) {
talloc_free(comp_fields);
return NULL;
@@ -1591,7 +1608,8 @@ struct llist_head *gprs_sndcp_parse_xid(const void *ctx,
} else {
/* Parse SNDCP-CID XID-Field */
- rc = gprs_sndcp_decode_xid(comp_fields, src, src_len, NULL, 0);
+ rc = gprs_sndcp_decode_xid(version, comp_fields, src, src_len,
+ NULL, 0);
if (rc < 0) {
talloc_free(comp_fields);
return NULL;