This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Holger Freyther zecke at selfish.orgOn Friday 10 July 2009 19:08:40 Holger Freyther wrote: > On Thursday 02 July 2009 06:45:48 Harald Welte wrote: > Things that I think I should do: > - Maybe nuke the PARSE_FLAG and flag attribute? If we get a response that > contains an attribute that should not be there our tlvp_parse will have > already parsed it. Does it hurt to copy the value to the gsm_mncc? In one > way we would like to be strict, in another it can be nice to see what > incorrect messages we receive? > > - Kill the enum with the PARSE_ flags, I can use the MNCC ones > directly.. to reply to myself... i think I have fixed the above and think the patch is good enough to be merged? what should I change? From 6de565798996dfc18de0c2fda98e7365d13fd3bc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther <zecke at selfish.org> Date: Mon, 29 Jun 2009 17:21:37 +0200 Subject: [PATCH] Generic data derived informations parsing... Parse everything that was found during the tlvp_parse and assign it to members of the gsm_mncc. This would even parse elements that are not present/part of the specification. --- openbsc/include/openbsc/mncc.h | 46 +++++-- openbsc/src/msc_mncc.c | 294 ++++++++++------------------------------ 2 files changed, 107 insertions(+), 233 deletions(-) diff --git a/openbsc/include/openbsc/mncc.h b/openbsc/include/openbsc/mncc.h index 6aa1917..d6df502 100644 --- a/openbsc/include/openbsc/mncc.h +++ b/openbsc/include/openbsc/mncc.h @@ -93,20 +93,38 @@ struct gsm_call { #define GSM_MAX_SSVERSION 128 #define GSM_MAX_USERUSER 128 -#define MNCC_F_BEARER_CAP 0x0001 -#define MNCC_F_CALLED 0x0002 -#define MNCC_F_CALLING 0x0004 -#define MNCC_F_REDIRECTING 0x0008 -#define MNCC_F_CONNECTED 0x0010 -#define MNCC_F_CAUSE 0x0020 -#define MNCC_F_USERUSER 0x0040 -#define MNCC_F_PROGRESS 0x0080 -#define MNCC_F_EMERGENCY 0x0100 -#define MNCC_F_FACILITY 0x0200 -#define MNCC_F_SSVERSION 0x0400 -#define MNCC_F_CCCAP 0x0800 -#define MNCC_F_KEYPAD 0x1000 -#define MNCC_F_SIGNAL 0x2000 +enum { + _MNCC_E_BEARER_CAP, + _MNCC_E_CALLED, + _MNCC_E_CALLING, + _MNCC_E_REDIRECTING, + _MNCC_E_CONNECTED, + _MNCC_E_CAUSE, + _MNCC_E_USERUSER, + _MNCC_E_PROGRESS, + _MNCC_E_EMERGENCY, + _MNCC_E_FACILITY, + _MNCC_E_SSVERSION, + _MNCC_E_CCCAP, + _MNCC_E_KEYPAD, + _MNCC_E_SIGNAL, + _MNCC_E_LAST_ITEM, +}; + +#define MNCC_F_BEARER_CAP (1 << _MNCC_E_BEARER_CAP) +#define MNCC_F_CALLED (1 << _MNCC_E_CALLED) +#define MNCC_F_CALLING (1 << _MNCC_E_CALLING) +#define MNCC_F_REDIRECTING (1 << _MNCC_E_REDIRECTING) +#define MNCC_F_CONNECTED (1 << _MNCC_E_CONNECTED) +#define MNCC_F_CAUSE (1 << _MNCC_E_CAUSE) +#define MNCC_F_USERUSER (1 << _MNCC_E_USERUSER) +#define MNCC_F_PROGRESS (1 << _MNCC_E_PROGRESS) +#define MNCC_F_EMERGENCY (1 << _MNCC_E_EMERGENCY) +#define MNCC_F_FACILITY (1 << _MNCC_E_FACILITY) +#define MNCC_F_SSVERSION (1 << _MNCC_E_SSVERSION) +#define MNCC_F_CCCAP (1 << _MNCC_E_CCCAP) +#define MNCC_F_KEYPAD (1 << _MNCC_E_KEYPAD) +#define MNCC_F_SIGNAL (1 << _MNCC_E_SIGNAL) struct gsm_mncc_bearer_cap { int transfer; diff --git a/openbsc/src/msc_mncc.c b/openbsc/src/msc_mncc.c index 90354c0..41ffcc0 100644 --- a/openbsc/src/msc_mncc.c +++ b/openbsc/src/msc_mncc.c @@ -587,6 +587,55 @@ static int encode_more(struct msgb *msg) return 0; } +#define DECLARE_DECODER3(IE_NAME, M_NAME, name) \ + [_MNCC_E_##M_NAME] = \ + { .information_element = GSM48_IE_##IE_NAME, \ + .mncc_field = MNCC_F_##M_NAME, \ + .offset = offsetof(struct gsm_mncc, name), \ + .decoder = (dd_decoder)decode_##name, \ + } + +#define DECLARE_DECODER(NAME, name) \ + DECLARE_DECODER3(NAME, NAME, name) + +typedef int (*dd_decoder)(void* data, const u_int8_t *lv); + +struct dd_parser { + int information_element; + int mncc_field; + int offset; + dd_decoder decoder; +}; + +static const struct dd_parser dd_parsers [_MNCC_E_LAST_ITEM] = { + DECLARE_DECODER(CAUSE, cause), + DECLARE_DECODER(FACILITY, facility), + DECLARE_DECODER3(USER_USER, USERUSER, useruser), + DECLARE_DECODER3(SS_VERS, SSVERSION, ssversion), + DECLARE_DECODER3(KPD_FACILITY, KEYPAD, keypad), + DECLARE_DECODER(BEARER_CAP, bearer_cap), + DECLARE_DECODER3(CALLED_BCD, CALLED, called), + DECLARE_DECODER3(CC_CAP, CCCAP, cccap), + DECLARE_DECODER3(PROGR_IND, PROGRESS, progress), +}; + +static void parse_data_derived_information(struct tlv_parsed *tp, struct gsm_mncc *rel, int flags) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dd_parsers); ++i) { + if ((flags & (1<<i)) == (1<<i) && + TLVP_PRESENT(tp, dd_parsers[i].information_element) && + dd_parsers[i].decoder) { + + rel->fields |= dd_parsers[i].mncc_field; + dd_parsers[i].decoder(rel + dd_parsers[i].offset, + TLVP_VAL(tp, dd_parsers[i].information_element)-1); + } + } +} + + /* map two ipaccess RTP streams onto each other */ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) { @@ -1013,48 +1062,17 @@ static int msc_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) strncpy(setup.imsi, trans->subscr->imsi, sizeof(setup.imsi)-1); } - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - setup.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&setup.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - setup.fields |= MNCC_F_FACILITY; - decode_facility(&setup.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* called party bcd number */ - if (TLVP_PRESENT(&tp, GSM48_IE_CALLED_BCD)) { - setup.fields |= MNCC_F_CALLED; - decode_called(&setup.called, - TLVP_VAL(&tp, GSM48_IE_CALLED_BCD)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - setup.fields |= MNCC_F_USERUSER; - decode_useruser(&setup.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - setup.fields |= MNCC_F_SSVERSION; - decode_ssversion(&setup.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + + parse_data_derived_information(&tp, &setup, MNCC_F_BEARER_CAP | MNCC_F_FACILITY | + MNCC_F_CALLED | MNCC_F_USERUSER | + MNCC_F_SSVERSION | MNCC_F_CCCAP); + /* CLIR suppression */ if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_SUPP)) setup.clir.sup = 1; /* CLIR invocation */ if (TLVP_PRESENT(&tp, GSM48_IE_CLIR_INVOC)) setup.clir.inv = 1; - /* cc cap */ - if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) { - setup.fields |= MNCC_F_CCCAP; - decode_cccap(&setup.cccap, - TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); - } if (is_ipaccess_bts(msg->trx->bts)) rsl_ipacc_bind(msg->lchan); @@ -1171,24 +1189,9 @@ static int msc_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg) if (TLVP_PRESENT(&tp, GSM48_IE_REPEAT_SEQ)) call_conf.repeat = 2; #endif - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - call_conf.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&call_conf.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - call_conf.fields |= MNCC_F_CAUSE; - decode_cause(&call_conf.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* cc cap */ - if (TLVP_PRESENT(&tp, GSM48_IE_CC_CAP)) { - call_conf.fields |= MNCC_F_CCCAP; - decode_cccap(&call_conf.cccap, - TLVP_VAL(&tp, GSM48_IE_CC_CAP)-1); - } + + parse_data_derived_information(&tp, &call_conf, MNCC_F_BEARER_CAP | + MNCC_F_CAUSE | MNCC_F_CCCAP); new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF); @@ -1233,25 +1236,8 @@ static int msc_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg) memset(&alerting, 0, sizeof(struct gsm_mncc)); alerting.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - alerting.fields |= MNCC_F_FACILITY; - decode_facility(&alerting.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - - /* progress */ - if (TLVP_PRESENT(&tp, GSM48_IE_PROGR_IND)) { - alerting.fields |= MNCC_F_PROGRESS; - decode_progress(&alerting.progress, - TLVP_VAL(&tp, GSM48_IE_PROGR_IND)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - alerting.fields |= MNCC_F_SSVERSION; - decode_ssversion(&alerting.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &alerting, MNCC_F_FACILITY | + MNCC_F_PROGRESS | MNCC_F_SSVERSION); new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED); @@ -1353,25 +1339,9 @@ static int msc_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg) strncpy(connect.imsi, trans->subscr->imsi, sizeof(connect.imsi)-1); } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - connect.fields |= MNCC_F_FACILITY; - decode_facility(&connect.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - connect.fields |= MNCC_F_USERUSER; - decode_useruser(&connect.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - connect.fields |= MNCC_F_SSVERSION; - decode_ssversion(&connect.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &connect, MNCC_F_FACILITY | + MNCC_F_USERUSER | MNCC_F_SSVERSION); new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST); return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect); @@ -1420,31 +1390,9 @@ static int msc_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg) memset(&disc, 0, sizeof(struct gsm_mncc)); disc.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_CAUSE, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - disc.fields |= MNCC_F_CAUSE; - decode_cause(&disc.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - disc.fields |= MNCC_F_FACILITY; - decode_facility(&disc.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - disc.fields |= MNCC_F_USERUSER; - decode_useruser(&disc.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - disc.fields |= MNCC_F_SSVERSION; - decode_ssversion(&disc.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } - + parse_data_derived_information(&tp, &disc, MNCC_F_CAUSE | + MNCC_F_FACILITY | MNCC_F_USERUSER | + MNCC_F_SSVERSION); return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc); } @@ -1509,30 +1457,8 @@ static int msc_cc_rx_release(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &rel, MNCC_F_CAUSE | MNCC_F_FACILITY | + MNCC_F_USERUSER | MNCC_F_SSVERSION); if (trans->state == GSM_CSTATE_RELEASE_REQ) { /* release collision 5.4.5 */ @@ -1598,30 +1524,8 @@ static int msc_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg) memset(&rel, 0, sizeof(struct gsm_mncc)); rel.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - rel.fields |= MNCC_F_CAUSE; - decode_cause(&rel.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - rel.fields |= MNCC_F_FACILITY; - decode_facility(&rel.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - rel.fields |= MNCC_F_USERUSER; - decode_useruser(&rel.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - rel.fields |= MNCC_F_SSVERSION; - decode_ssversion(&rel.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } + parse_data_derived_information(&tp, &rel, MNCC_F_CAUSE | MNCC_F_FACILITY | + MNCC_F_USERUSER | MNCC_F_SSVERSION); if (trans->callref) { switch (trans->state) { @@ -1684,19 +1588,7 @@ static int msc_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg) memset(&fac, 0, sizeof(struct gsm_mncc)); fac.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_FACILITY, 0); - /* facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_FACILITY)) { - fac.fields |= MNCC_F_FACILITY; - decode_facility(&fac.facility, - TLVP_VAL(&tp, GSM48_IE_FACILITY)-1); - } - /* ss-version */ - if (TLVP_PRESENT(&tp, GSM48_IE_SS_VERS)) { - fac.fields |= MNCC_F_SSVERSION; - decode_ssversion(&fac.ssversion, - TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1); - } - + parse_data_derived_information(&tp, &fac, MNCC_F_FACILITY | MNCC_F_SSVERSION); return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac); } @@ -1806,13 +1698,7 @@ static int msc_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg) memset(&dtmf, 0, sizeof(struct gsm_mncc)); dtmf.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, 0, 0); - /* keypad facility */ - if (TLVP_PRESENT(&tp, GSM48_IE_KPD_FACILITY)) { - dtmf.fields |= MNCC_F_KEYPAD; - decode_keypad(&dtmf.keypad, - TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1); - } - + parse_data_derived_information(&tp, &dtmf, MNCC_F_KEYPAD); return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf); } @@ -1884,15 +1770,8 @@ static int msc_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - + parse_data_derived_information(&tp, &modify, MNCC_F_BEARER_CAP); new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify); } @@ -1928,15 +1807,8 @@ static int msc_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, 0); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= MNCC_F_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - + parse_data_derived_information(&tp, &modify, MNCC_F_BEARER_CAP); new_cc_state(trans, GSM_CSTATE_ACTIVE); - return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify); } @@ -1970,19 +1842,7 @@ static int msc_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg) memset(&modify, 0, sizeof(struct gsm_mncc)); modify.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_BEARER_CAP, GSM48_IE_CAUSE); - /* bearer capability */ - if (TLVP_PRESENT(&tp, GSM48_IE_BEARER_CAP)) { - modify.fields |= GSM48_IE_BEARER_CAP; - decode_bearer_cap(&modify.bearer_cap, - TLVP_VAL(&tp, GSM48_IE_BEARER_CAP)-1); - } - /* cause */ - if (TLVP_PRESENT(&tp, GSM48_IE_CAUSE)) { - modify.fields |= MNCC_F_CAUSE; - decode_cause(&modify.cause, - TLVP_VAL(&tp, GSM48_IE_CAUSE)-1); - } - + parse_data_derived_information(&tp, &modify, MNCC_F_BEARER_CAP | MNCC_F_CAUSE); new_cc_state(trans, GSM_CSTATE_ACTIVE); return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify); @@ -2070,12 +1930,8 @@ static int msc_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg) memset(&user, 0, sizeof(struct gsm_mncc)); user.callref = trans->callref; tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USER_USER, 0); - /* user-user */ - if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) { - user.fields |= MNCC_F_USERUSER; - decode_useruser(&user.useruser, - TLVP_VAL(&tp, GSM48_IE_USER_USER)-1); - } + parse_data_derived_information(&tp, &user, MNCC_F_USERUSER); + /* more data */ if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA)) user.more = 1; -- 1.6.3.3