diff options
Diffstat (limited to 'openbsc/src/libbsc')
-rw-r--r-- | openbsc/src/libbsc/arfcn_range_encode.c | 4 | ||||
-rw-r--r-- | openbsc/src/libbsc/rest_octets.c | 21 | ||||
-rw-r--r-- | openbsc/src/libbsc/system_information.c | 66 |
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 " |