aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/system_information.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/system_information.c')
-rw-r--r--openbsc/src/system_information.c63
1 files changed, 43 insertions, 20 deletions
diff --git a/openbsc/src/system_information.c b/openbsc/src/system_information.c
index 7625da637..a9df0ba26 100644
--- a/openbsc/src/system_information.c
+++ b/openbsc/src/system_information.c
@@ -31,13 +31,29 @@
#include <openbsc/gsm_data.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/rest_octets.h>
-#include <openbsc/bitvec.h>
+#include <osmocore/bitvec.h>
#include <openbsc/debug.h>
#define GSM48_CELL_CHAN_DESC_SIZE 16
#define GSM_MACBLOCK_LEN 23
#define GSM_MACBLOCK_PADDING 0x2b
+/* verify the sizes of the system information type structs */
+
+/* rest octets are not part of the struct */
+static_assert(sizeof(struct gsm48_system_information_type_header) == 3, _si_header_size);
+static_assert(sizeof(struct gsm48_rach_control) == 3, _si_rach_control);
+static_assert(sizeof(struct gsm48_system_information_type_1) == 22, _si1_size);
+static_assert(sizeof(struct gsm48_system_information_type_2) == 23, _si2_size);
+static_assert(sizeof(struct gsm48_system_information_type_3) == 19, _si3_size);
+static_assert(sizeof(struct gsm48_system_information_type_4) == 13, _si4_size);
+
+/* bs11 forgot the l2 len, 0-6 rest octets */
+static_assert(sizeof(struct gsm48_system_information_type_5) == 18, _si5_size);
+static_assert(sizeof(struct gsm48_system_information_type_6) == 11, _si6_size);
+
+static_assert(sizeof(struct gsm48_system_information_type_13) == 3, _si13_size);
+
/* Frequency Lists as per TS 04.08 10.5.2.13 */
/* 10.5.2.13.2: Bit map 0 format */
@@ -98,7 +114,7 @@ static int freq_list_bmrel_set_arfcn(u_int8_t *chan_list, unsigned int arfcn)
static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
const struct gsm_bts *bts)
{
- int i, rc, min = 1024, max = 0;
+ int i, rc, min = 1024, max = -1;
memset(chan_list, 0, 16);
@@ -128,6 +144,12 @@ static int bitvec2freq_list(u_int8_t *chan_list, struct bitvec *bv,
}
}
+ if (max == -1) {
+ /* Empty set, use 'bit map 0 format' */
+ chan_list[0] = 0;
+ return 0;
+ }
+
if ((max - min) > 111) {
LOGP(DRR, LOGL_ERROR, "min_arfcn=%u, max_arfcn=%u, "
"distance > 111\n", min, max);
@@ -200,9 +222,8 @@ static int generate_si1(u_int8_t *output, struct gsm_bts *bts)
si1->rach_control = bts->si_common.rach_control;
/* SI1 Rest Octets (10.5.2.32), contains NCH position */
- rest_octets_si1(si1->rest_octets, NULL);
-
- return GSM_MACBLOCK_LEN;
+ rc = rest_octets_si1(si1->rest_octets, NULL);
+ return sizeof(*si1) + rc;
}
static int generate_si2(u_int8_t *output, struct gsm_bts *bts)
@@ -225,7 +246,7 @@ static int generate_si2(u_int8_t *output, struct gsm_bts *bts)
si2->ncc_permitted = bts->si_common.ncc_permitted;
si2->rach_control = bts->si_common.rach_control;
- return GSM_MACBLOCK_LEN;
+ return sizeof(*si2);
}
struct gsm48_si_ro_info si_info = {
@@ -254,6 +275,7 @@ struct gsm48_si_ro_info si_info = {
static int generate_si3(u_int8_t *output, struct gsm_bts *bts)
{
+ int rc;
struct gsm48_system_information_type_3 *si3 =
(struct gsm48_system_information_type_3 *) output;
@@ -265,9 +287,9 @@ static int generate_si3(u_int8_t *output, struct gsm_bts *bts)
si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
si3->cell_identity = htons(bts->cell_identity);
- gsm0408_generate_lai(&si3->lai, bts->network->country_code,
- bts->network->network_code,
- bts->location_area_code);
+ gsm48_generate_lai(&si3->lai, bts->network->country_code,
+ bts->network->network_code,
+ bts->location_area_code);
si3->control_channel_desc = bts->si_common.chan_desc;
si3->cell_options = bts->si_common.cell_options;
si3->cell_sel_par = bts->si_common.cell_sel_par;
@@ -277,13 +299,14 @@ static int generate_si3(u_int8_t *output, struct gsm_bts *bts)
CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
Power Offset, 2ter Indicator, Early Classmark Sending,
Scheduling if and WHERE, GPRS Indicator, SI13 position */
- rest_octets_si3(si3->rest_octets, &si_info);
+ rc = rest_octets_si3(si3->rest_octets, &si_info);
- return GSM_MACBLOCK_LEN;
+ return sizeof(*si3) + rc;
}
static int generate_si4(u_int8_t *output, struct gsm_bts *bts)
{
+ int rc;
struct gsm48_system_information_type_4 *si4 =
(struct gsm48_system_information_type_4 *) output;
@@ -296,9 +319,9 @@ static int generate_si4(u_int8_t *output, struct gsm_bts *bts)
si4->header.skip_indicator = 0;
si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
- gsm0408_generate_lai(&si4->lai, bts->network->country_code,
- bts->network->network_code,
- bts->location_area_code);
+ gsm48_generate_lai(&si4->lai, bts->network->country_code,
+ bts->network->network_code,
+ bts->location_area_code);
si4->cell_sel_par = bts->si_common.cell_sel_par;
si4->rach_control = bts->si_common.rach_control;
@@ -309,9 +332,9 @@ static int generate_si4(u_int8_t *output, struct gsm_bts *bts)
/* SI4 Rest Octets (10.5.2.35), containing
Optional Power offset, GPRS Indicator,
Cell Identity, LSA ID, Selection Parameter */
- rest_octets_si4(si4->data, &si_info);
+ rc = rest_octets_si4(si4->data, &si_info);
- return GSM_MACBLOCK_LEN;
+ return sizeof(*si4) + rc;
}
static int generate_si5(u_int8_t *output, struct gsm_bts *bts)
@@ -361,9 +384,9 @@ static int generate_si6(u_int8_t *output, struct gsm_bts *bts)
si6->skip_indicator = 0;
si6->system_information = GSM48_MT_RR_SYSINFO_6;
si6->cell_identity = htons(bts->cell_identity);
- gsm0408_generate_lai(&si6->lai, bts->network->country_code,
- bts->network->network_code,
- bts->location_area_code);
+ gsm48_generate_lai(&si6->lai, bts->network->country_code,
+ bts->network->network_code,
+ bts->location_area_code);
si6->cell_options = bts->si_common.cell_options;
si6->ncc_permitted = bts->si_common.ncc_permitted;
@@ -418,7 +441,7 @@ static int generate_si13(u_int8_t *output, struct gsm_bts *bts)
si13->header.l2_plen = ret & 0xff;
- return GSM_MACBLOCK_LEN;
+ return sizeof (*si13) + ret;
}
int gsm_generate_si(u_int8_t *output, struct gsm_bts *bts, int type)