diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2012-11-22 14:59:46 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2012-12-19 16:37:55 +0100 |
commit | bce5675e5fa1eb4bcbe0dd24d503456eaeb58a0d (patch) | |
tree | 338b2407a776d4112de78486892b281407e06a3e /openbsc/src/libbsc/abis_nm.c | |
parent | c751cf92cbc25a5cfca8041ef3fdcc16ed5865ad (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.c | 87 |
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 */ |