gprs: Use shift functions instead of manual parsing
Currently the patching code directly accesses the single bytes to
parse the LLC/DTAP messages.
This patch uses the shift functions instead to parse tlv and similar
structures.
Sponsored-by: On-Waves ehf
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index bf79444..412b215 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -941,31 +941,30 @@
struct gbprox_peer *peer,
int to_bss, int *len_change)
{
- /* Check minimum length, always includes the RAI */
- if (data_len < 23)
- return 0;
+ uint8_t *value;
+ size_t value_len;
/* Skip MS network capability */
- if (data[0] < 1 || data[0] > 2)
+ if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
+ value_len < 1 || value_len > 2)
/* invalid */
- return 0;
- data_len -= data[0] + 1;
- data += data[0] + 1;
+ return 0;;
/* Skip Attach type */
/* Skip Ciphering key sequence number */
/* Skip DRX parameter */
- data_len -= 3;
- data += 3;
+ v_fixed_shift(&data, &data_len, 3, NULL);
/* Skip Mobile identity */
- if (data[0] < 5 || data[0] > 8)
+ if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
+ value_len < 5 || value_len > 8)
/* invalid */
- return 0;
- data_len -= data[0] + 1;
- data += data[0] + 1;
+ return 0;;
- gbprox_patch_raid(data, peer, to_bss, "LLC/ATTACH_REQ");
+ if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
+ return 0;
+
+ gbprox_patch_raid(value, peer, to_bss, "LLC/ATTACH_REQ");
return 1;
}
@@ -975,19 +974,19 @@
struct gbprox_peer *peer,
int to_bss, int *len_change)
{
- /* Check minimum length, always includes the RAI */
- if (data_len < 9)
- return 0;
+ uint8_t *value;
/* Skip Attach result */
/* Skip Force to standby */
/* Skip Periodic RA update timer */
/* Skip Radio priority for SMS */
/* Skip Spare half octet */
- data_len -= 3;
- data += 3;
+ v_fixed_shift(&data, &data_len, 3, NULL);
- gbprox_patch_raid(data, peer, to_bss, "LLC/ATTACH_ACK");
+ if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
+ return 0;
+
+ gbprox_patch_raid(value, peer, to_bss, "LLC/ATTACH_ACK");
return 1;
}
@@ -997,16 +996,16 @@
struct gbprox_peer *peer,
int to_bss, int *len_change)
{
- /* Check minimum length, always includes the RAI */
- if (data_len < 13)
- return 0;
+ uint8_t *value;
/* Skip Update type */
/* Skip GPRS ciphering key sequence number */
- data_len -= 1;
- data += 1;
+ v_fixed_shift(&data, &data_len, 1, NULL);
- gbprox_patch_raid(data, peer, to_bss, "LLC/RA_UPD_REQ");
+ if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
+ return 0;
+
+ gbprox_patch_raid(value, peer, to_bss, "LLC/RA_UPD_REQ");
return 1;
}
@@ -1016,17 +1015,18 @@
struct gbprox_peer *peer,
int to_bss, int *len_change)
{
- /* Check minimum length, always includes the RAI */
- if (data_len < 8)
- return 0;
+ uint8_t *value;
/* Skip Force to standby */
/* Skip Update result */
/* Skip Periodic RA update timer */
- data_len -= 2;
- data += 2;
+ v_fixed_shift(&data, &data_len, 2, NULL);
- gbprox_patch_raid(data, peer, to_bss, "LLC/RA_UPD_ACK");
+ if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
+ return 0;
+
+ gbprox_patch_raid(value, peer, to_bss, "LLC/RA_UPD_ACK");
+
return 1;
}
@@ -1036,18 +1036,18 @@
struct gbprox_peer *peer,
int to_bss, int *len_change)
{
- /* Check minimum length, always includes the RAI */
- if (data_len < 12)
- return 0;
+ uint8_t *value;
+ size_t value_len;
/* Skip Allocated P-TMSI */
- if (data[0] != 5)
+ if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 || value_len != 5)
/* invalid */
return 0;
- data_len -= 6;
- data += 6;
- gbprox_patch_raid(data, peer, to_bss, "LLC/PTMSI_REALL_CMD");
+ if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
+ return 0;
+
+ gbprox_patch_raid(value, peer, to_bss, "LLC/PTMSI_REALL_CMD");
return 1;
}
@@ -1057,53 +1057,42 @@
struct gbprox_peer *peer,
int to_bss, int *len_change)
{
- size_t new_len, old_len;
-
- /* Check minimum length, always contains length field of
- * Requested QoS */
- if (data_len < 9)
- return 0;
+ size_t new_len;
+ ssize_t old_len;
+ uint8_t *value;
+ size_t value_len;
+ int have_patched = 0;
/* Skip Requested NSAPI */
/* Skip Requested LLC SAPI */
- data_len -= 2;
- data += 2;
+ v_fixed_shift(&data, &data_len, 2, NULL);
/* Skip Requested QoS (support 04.08 and 24.008) */
- if (data[0] < 4 || data[0] > 14 ||
- data_len - (data[0] + 1) < 0)
+ if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
+ value_len < 4 || value_len > 14)
/* invalid */
- return 0;
- data_len -= data[0] + 1;
- data += data[0] + 1;
+ return 0;;
/* Skip Requested PDP address */
- if (data_len < 1 ||
- data[0] < 2 || data[0] > 18 ||
- data_len - (data[0] + 1) < 0)
+ if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
+ value_len < 2 || value_len > 18)
/* invalid */
return 0;
- data_len -= data[0] + 1;
- data += data[0] + 1;
/* Access point name */
- if (data_len < 2 || data[0] != GSM48_IE_GSM_APN)
- return 0;
+ old_len = tlv_match(&data, &data_len,
+ GSM48_IE_GSM_APN, &value, &value_len);
- if (data[1] < 1 || data[1] > 100 ||
- data_len - (data[1] + 2) < 0)
- /* invalid */
- return 0;
+ if (old_len > 0 && value_len >=1 && value_len <= 100) {
+ gbprox_patch_apn_ie(msg, data - old_len, old_len, peer,
+ &new_len, "LLC/ACT_PDP_REQ");
+ *len_change += (int)new_len - (int)old_len;
+ data += *len_change;
- old_len = data[1] + 2;
+ have_patched = 1;
+ }
- gbprox_patch_apn_ie(msg, data, old_len, peer, &new_len, "LLC/ACT_PDP_REQ");
-
- *len_change += (int)new_len - (int)old_len;
- data_len -= old_len;
- data += new_len;
-
- return 1;
+ return have_patched;
}
struct gbprox_peer *peer_by_bssgp_tlv(struct tlv_parsed *tp)
@@ -1140,14 +1129,9 @@
*len_change = 0;
- if (data_len < 2)
+ if (v_fixed_shift(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
return 0;
- g48h = (struct gsm48_hdr *)data;
-
- data += sizeof(struct gsm48_hdr);
- data_len -= sizeof(struct gsm48_hdr);
-
if ((g48h->proto_discr & 0x0f) != GSM48_PDISC_MM_GPRS &&
(g48h->proto_discr & 0x0f) != GSM48_PDISC_SM_GPRS)
return 0;