aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/libbsc/abis_nm.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2012-11-22 14:59:46 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2012-12-19 16:37:55 +0100
commitbce5675e5fa1eb4bcbe0dd24d503456eaeb58a0d (patch)
tree338b2407a776d4112de78486892b281407e06a3e /openbsc/src/libbsc/abis_nm.c
parentc751cf92cbc25a5cfca8041ef3fdcc16ed5865ad (diff)
abis: Create a routine that can parse all SW Descriptions of a SW Config
Be able to parse the entire SW Config IE. Parse the SW Descruption into a struct provided by the caller.
Diffstat (limited to 'openbsc/src/libbsc/abis_nm.c')
-rw-r--r--openbsc/src/libbsc/abis_nm.c87
1 files changed, 55 insertions, 32 deletions
diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c
index e95c0a905..7485a6cce 100644
--- a/openbsc/src/libbsc/abis_nm.c
+++ b/openbsc/src/libbsc/abis_nm.c
@@ -359,7 +359,8 @@ static int ipacc_sw_activate(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0,
return abis_nm_sendmsg(bts, msg);
}
-static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
+int abis_nm_parse_sw_config(const uint8_t *sw_descr, const size_t sw_descr_len,
+ struct abis_nm_sw_descr *desc, const int res_len)
{
static const struct tlv_definition sw_descr_def = {
.def = {
@@ -368,38 +369,56 @@ static int abis_nm_parse_sw_descr(const uint8_t *sw_descr, int sw_descr_len)
},
};
- uint8_t tag;
- uint16_t tag_len;
- const uint8_t *val;
- int ofs = 0, len;
+ size_t pos = 0;
+ int desc_pos = 0;
- /* Classic TLV parsing doesn't work well with SW_DESCR because of it's
- * nested nature and the fact you have to assume it contains only two sub
- * tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
+ for (pos = 0; pos < sw_descr_len && desc_pos < res_len; ++desc_pos) {
+ uint8_t tag;
+ uint16_t tag_len;
+ const uint8_t *val;
+ int len;
- if (sw_descr[0] != NM_ATT_SW_DESCR) {
- DEBUGP(DNM, "SW_DESCR attribute identifier not found!\n");
- return -1;
- }
- ofs += 1;
+ memset(&desc[desc_pos], 0, sizeof(desc[desc_pos]));
+ desc[desc_pos].start = &sw_descr[pos];
- len = tlv_parse_one(&tag, &tag_len, &val,
- &sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
- if (len < 0 || (tag != NM_ATT_FILE_ID)) {
- DEBUGP(DNM, "FILE_ID attribute identifier not found!\n");
- return -2;
- }
- ofs += len;
+ /* Classic TLV parsing doesn't work well with SW_DESCR because of it's
+ * nested nature and the fact you have to assume it contains only two sub
+ * tags NM_ATT_FILE_VERSION & NM_ATT_FILE_ID to parse it */
+ if (sw_descr[pos] != NM_ATT_SW_DESCR) {
+ LOGP(DNM, LOGL_ERROR,
+ "SW_DESCR attribute identifier not found!\n");
+ return -1;
+ }
- len = tlv_parse_one(&tag, &tag_len, &val,
- &sw_descr_def, &sw_descr[ofs], sw_descr_len-ofs);
- if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
- DEBUGP(DNM, "FILE_VERSION attribute identifier not found!\n");
- return -3;
+ pos += 1;
+ len = tlv_parse_one(&tag, &tag_len, &val,
+ &sw_descr_def, &sw_descr[pos], sw_descr_len - pos);
+ if (len < 0 || (tag != NM_ATT_FILE_ID)) {
+ LOGP(DNM, LOGL_ERROR,
+ "FILE_ID attribute identifier not found!\n");
+ return -2;
+ }
+ desc[desc_pos].file_id = val;
+ desc[desc_pos].file_id_len = tag_len;
+ pos += len;
+
+
+ len = tlv_parse_one(&tag, &tag_len, &val,
+ &sw_descr_def, &sw_descr[pos], sw_descr_len - pos);
+ if (len < 0 || (tag != NM_ATT_FILE_VERSION)) {
+ LOGP(DNM, LOGL_ERROR,
+ "FILE_VERSION attribute identifier not found!\n");
+ return -3;
+ }
+ desc[desc_pos].file_ver = val;
+ desc[desc_pos].file_ver_len = tag_len;
+ pos += len;
+
+ /* final size */
+ desc[desc_pos].len = &sw_descr[pos] - desc[desc_pos].start;
}
- ofs += len;
- return ofs;
+ return desc_pos;
}
static int abis_nm_rx_sw_act_req(struct msgb *mb)
@@ -409,7 +428,8 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
struct e1inp_sign_link *sign_link = mb->dst;
struct tlv_parsed tp;
const uint8_t *sw_config;
- int ret, sw_config_len, sw_descr_len;
+ int ret, sw_config_len;
+ struct abis_nm_sw_descr sw_descr[1];
abis_nm_debugp_foh(DNM, foh);
@@ -439,16 +459,19 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
DEBUGP(DNM, "Found SW config: %s\n", osmo_hexdump(sw_config, sw_config_len));
}
- /* Use the first SW_DESCR present in SW config */
- sw_descr_len = abis_nm_parse_sw_descr(sw_config, sw_config_len);
- if (sw_descr_len < 0)
+ /* Parse up to two sw descriptions from the data */
+ ret = abis_nm_parse_sw_config(sw_config, sw_config_len,
+ &sw_descr[0], ARRAY_SIZE(sw_descr));
+ if (ret <= 0) {
+ LOGP(DNM, LOGL_ERROR, "Failed to parse SW Config.\n");
return -EINVAL;
+ }
return ipacc_sw_activate(sign_link->trx->bts, foh->obj_class,
foh->obj_inst.bts_nr,
foh->obj_inst.trx_nr,
foh->obj_inst.ts_nr,
- sw_config, sw_descr_len);
+ sw_descr[0].start, sw_descr[0].len);
}
/* Receive a CHANGE_ADM_STATE_ACK, parse the TLV and update local state */