aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libbsc
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/libbsc')
-rw-r--r--openbsc/src/libbsc/arfcn_range_encode.c4
-rw-r--r--openbsc/src/libbsc/rest_octets.c21
-rw-r--r--openbsc/src/libbsc/system_information.c66
3 files changed, 54 insertions, 37 deletions
diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c
index 99188384d..9ca48407e 100644
--- a/openbsc/src/libbsc/arfcn_range_encode.c
+++ b/openbsc/src/libbsc/arfcn_range_encode.c
@@ -27,6 +27,8 @@
#include <osmocom/core/utils.h>
+#include <errno.h>
+
static inline int greatest_power_of_2_lesser_or_equal_to(int index)
{
int power_of_2 = 1;
@@ -109,6 +111,8 @@ int range_enc_arfcns(enum gsm48_range range,
/* Now do the processing */
split_at = range_enc_find_index(range, arfcns, size);
+ if (split_at < 0)
+ return -EINVAL;
/* we now know where to split */
out[index] = 1 + arfcns[split_at];
diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c
index 1a5e43525..fc0282e06 100644
--- a/openbsc/src/libbsc/rest_octets.c
+++ b/openbsc/src/libbsc/rest_octets.c
@@ -180,10 +180,10 @@ static inline void append_earfcn(struct bitvec *bv,
bitvec_set_bit(bv, L);
}
-static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u,
+static inline int append_uarfcn(struct bitvec *bv, const uint16_t *u,
const uint16_t *sc, size_t length)
{
- int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length];
+ int f0_inc, i, w[RANGE_ENC_MAX_ARFCNS] = { 0 }, a[length];
uint8_t chan_list[16] = {0};
/* 3G Neighbour Cell Description */
@@ -211,9 +211,9 @@ static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u,
/* Note: we do not support multiple UARFCN values ATM: */
bitvec_set_uint(bv, u[0], 14);
- arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc);
- range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0);
- range_enc_range1024(chan_list, 0, f0_inc, w);
+ f0_inc = range_encode(ARFCN_RANGE_1024, a, length, w, 0, chan_list);
+ if (f0_inc < 0)
+ return f0_inc;
/* FDD_Indic0: parameter value '0000000000' is not a member of the set */
bitvec_set_bit(bv, f0_inc);
@@ -229,12 +229,15 @@ static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u,
/* UTRAN TDD Description */
bitvec_set_bit(bv, 0);
+
+ return 0;
}
/* generate SI2quater rest octets: 3GPP TS 44.018 ยง 10.5.2.33b */
int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
const uint16_t *u, const uint16_t *sc, size_t u_len)
{
+ int rc;
unsigned sz;
struct bitvec bv;
bv.data = data;
@@ -279,7 +282,13 @@ int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
SI2Q_MAX_LEN);
return -ENOMEM;
}
- append_uarfcn(&bv, u, sc, u_len);
+ rc = append_uarfcn(&bv, u, sc, u_len);
+ if (rc < 0) {
+ LOGP(DRR, LOGL_ERROR, "SI2quater: failed to append %zu "
+ "UARFCNs due to range encoding failure: %s\n",
+ u_len, strerror(-rc));
+ return rc;
+ }
} else { /* No 3G Neighbour Cell Description */
bitvec_set_bit(&bv, 0);
}
diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c
index 3d55d1a73..20c3915e2 100644
--- a/openbsc/src/libbsc/system_information.c
+++ b/openbsc/src/libbsc/system_information.c
@@ -316,6 +316,38 @@ static inline int enc_freq_lst_var_bitmap(uint8_t *chan_list,
return 0;
}
+int range_encode(enum gsm48_range r, int *arfcns, int arfcns_used, int *w,
+ int f0, uint8_t *chan_list)
+{
+ /*
+ * Manipulate the ARFCN list according to the rules in J4 depending
+ * on the selected range.
+ */
+ int rc, f0_included;
+
+ range_enc_filter_arfcns(arfcns, arfcns_used, f0, &f0_included);
+
+ rc = range_enc_arfcns(r, arfcns, arfcns_used, w, 0);
+ if (rc < 0)
+ return rc;
+
+ /* Select the range and the amount of bits needed */
+ switch (r) {
+ case ARFCN_RANGE_128:
+ return range_enc_range128(chan_list, f0, w);
+ case ARFCN_RANGE_256:
+ return range_enc_range256(chan_list, f0, w);
+ case ARFCN_RANGE_512:
+ return range_enc_range512(chan_list, f0, w);
+ case ARFCN_RANGE_1024:
+ return range_enc_range1024(chan_list, f0, f0_included, w);
+ default:
+ return -ERANGE;
+ };
+
+ return f0_included;
+}
+
/* generate a frequency list with the range 512 format */
static inline int enc_freq_lst_range(uint8_t *chan_list,
struct bitvec *bv, const struct gsm_bts *bts,
@@ -323,9 +355,8 @@ static inline int enc_freq_lst_range(uint8_t *chan_list,
{
int arfcns[RANGE_ENC_MAX_ARFCNS];
int w[RANGE_ENC_MAX_ARFCNS];
- int f0_included = 0;
int arfcns_used = 0;
- int i, rc, range, f0;
+ int i, range, f0;
/*
* Select ARFCNs according to the rules in bitvec2freq_list
@@ -346,35 +377,8 @@ static inline int enc_freq_lst_range(uint8_t *chan_list,
if (range == ARFCN_RANGE_INVALID)
return -2;
- /*
- * Manipulate the ARFCN list according to the rules in J4 depending
- * on the selected range.
- */
- arfcns_used = range_enc_filter_arfcns(arfcns, arfcns_used,
- f0, &f0_included);
-
memset(w, 0, sizeof(w));
- rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
- if (rc != 0)
- return -3;
-
- /* Select the range and the amount of bits needed */
- switch (range) {
- case ARFCN_RANGE_128:
- return range_enc_range128(chan_list, f0, w);
- break;
- case ARFCN_RANGE_256:
- return range_enc_range256(chan_list, f0, w);
- break;
- case ARFCN_RANGE_512:
- return range_enc_range512(chan_list, f0, w);
- break;
- case ARFCN_RANGE_1024:
- return range_enc_range1024(chan_list, f0, f0_included, w);
- break;
- default:
- return -4;
- };
+ return range_encode(range, arfcns, arfcns_used, w, f0, chan_list);
}
/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
@@ -447,7 +451,7 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
/* Attempt to do the range encoding */
rc = enc_freq_lst_range(chan_list, bv, bts, bis, ter, pgsm);
- if (rc == 0)
+ if (rc >= 0)
return 0;
LOGP(DRR, LOGL_ERROR, "min_arfcn=%u, max_arfcn=%u, arfcns=%d "