mirror of https://gerrit.osmocom.org/osmo-tetra
Added basic link FCS validation in LLC
tetra_llc_pdu.c now parses the FCS (Frame Check Sequence) for basic link pdus that use it. Some changes were made to the tetra_resrc_decoded struct definition. The have_fcs field designates the FCS was present, while the FCS field holds the extracted FCS, and FCS_invalid designates an FCS was present but differs from the computed value. Change-Id: I81941110801d00ca06bdafdcc0a7afaf7b7617d3
This commit is contained in:
parent
a5bc24792b
commit
3fba49ead4
|
@ -82,42 +82,98 @@ const char *tetra_get_llc_pdut_dec_name(enum tllc_pdut_dec pdut)
|
|||
return get_value_string(pdut_dec_names, pdut);
|
||||
}
|
||||
|
||||
static uint32_t tetra_llc_compute_fcs(const uint8_t *buf, int len)
|
||||
{
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
if (len < 32) {
|
||||
crc <<= (32 - len);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint8_t bit = (buf[i] ^ (crc >> 31)) & 1;
|
||||
crc <<= 1;
|
||||
if (bit) {
|
||||
crc = crc ^ 0x04C11DB7;
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
static int tetra_llc_check_fcs(struct tetra_llc_pdu *lpp, uint8_t *buf, int len)
|
||||
{
|
||||
uint32_t computed_fcs = tetra_llc_compute_fcs(buf, len);
|
||||
return lpp->fcs == computed_fcs;
|
||||
}
|
||||
|
||||
int tetra_llc_pdu_parse(struct tetra_llc_pdu *lpp, uint8_t *buf, int len)
|
||||
{
|
||||
uint8_t *cur = buf;
|
||||
uint8_t pdu_type;
|
||||
lpp->have_fcs = 0;
|
||||
lpp->fcs = 0;
|
||||
|
||||
pdu_type = bits_to_uint(cur, 4);
|
||||
cur += 4;
|
||||
|
||||
switch (pdu_type) {
|
||||
case TLLC_PDUT_BL_ADATA_FCS:
|
||||
/* FIXME */
|
||||
len -= 32;
|
||||
|
||||
case TLLC_PDUT_BL_ADATA:
|
||||
case TLLC_PDUT_BL_ADATA_FCS:
|
||||
lpp->nr = *cur++;
|
||||
lpp->ns = *cur++;
|
||||
lpp->tl_sdu = cur;
|
||||
lpp->tl_sdu_len = len - (cur - buf);
|
||||
lpp->pdu_type = TLLC_PDUT_DEC_BL_ADATA;
|
||||
|
||||
if (pdu_type == TLLC_PDUT_BL_ADATA_FCS) {
|
||||
if (lpp->tl_sdu_len < 32) {
|
||||
printf("\nWARNING frame too small for FCS (%d)\n", lpp->tl_sdu_len);
|
||||
return cur-buf;
|
||||
}
|
||||
lpp->tl_sdu_len -= 32;
|
||||
lpp->have_fcs = 1;
|
||||
lpp->fcs = bits_to_uint(buf + len - 32, 32);
|
||||
lpp->fcs_invalid = !tetra_llc_check_fcs(lpp, cur, lpp->tl_sdu_len);
|
||||
}
|
||||
break;
|
||||
case TLLC_PDUT_BL_DATA_FCS:
|
||||
/* FIXME */
|
||||
len -= 32;
|
||||
|
||||
case TLLC_PDUT_BL_DATA:
|
||||
case TLLC_PDUT_BL_DATA_FCS:
|
||||
lpp->ns = *cur++;
|
||||
lpp->tl_sdu = cur;
|
||||
lpp->tl_sdu_len = len - (cur - buf);
|
||||
lpp->pdu_type = TLLC_PDUT_DEC_BL_DATA;
|
||||
|
||||
if (pdu_type == TLLC_PDUT_BL_DATA_FCS) {
|
||||
if (lpp->tl_sdu_len < 32) {
|
||||
printf("\nWARNING frame too small for FCS (%d)\n", lpp->tl_sdu_len);
|
||||
return cur-buf;
|
||||
}
|
||||
lpp->tl_sdu_len -= 32;
|
||||
lpp->have_fcs = 1;
|
||||
lpp->fcs = bits_to_uint(buf + len - 32, 32);
|
||||
lpp->fcs_invalid = !tetra_llc_check_fcs(lpp, cur, lpp->tl_sdu_len);
|
||||
}
|
||||
break;
|
||||
case TLLC_PDUT_BL_UDATA_FCS:
|
||||
/* FIXME */
|
||||
len -= 32;
|
||||
|
||||
case TLLC_PDUT_BL_UDATA:
|
||||
case TLLC_PDUT_BL_UDATA_FCS:
|
||||
lpp->tl_sdu = cur;
|
||||
lpp->tl_sdu_len = len - (cur - buf);
|
||||
lpp->pdu_type = TLLC_PDUT_DEC_BL_UDATA;
|
||||
|
||||
if (pdu_type == TLLC_PDUT_BL_UDATA_FCS) {
|
||||
if (lpp->tl_sdu_len < 32) {
|
||||
printf("\nWARNING frame too small for FCS (%d)\n", lpp->tl_sdu_len);
|
||||
return cur-buf;
|
||||
}
|
||||
lpp->tl_sdu_len -= 32;
|
||||
lpp->have_fcs = 1;
|
||||
lpp->fcs = bits_to_uint(buf + len - 32, 32);
|
||||
lpp->fcs_invalid = !tetra_llc_check_fcs(lpp, cur, lpp->tl_sdu_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case TLLC_PDUT_AL_DATA_FINAL:
|
||||
if (*cur++) {
|
||||
/* FINAL */
|
||||
|
|
|
@ -72,8 +72,11 @@ struct tetra_llc_pdu {
|
|||
uint8_t nr; /* N(R) PDU number (receive) */
|
||||
uint8_t ns; /* N(S) PDU number (sent) */
|
||||
uint8_t ss; /* S(S) Segment (sent) */
|
||||
uint32_t _fcs;
|
||||
uint32_t *fcs;
|
||||
|
||||
uint8_t have_fcs; /* 1 if LLC PDU defines FCS is present */
|
||||
uint32_t fcs; /* FCS value extracted from pdu */
|
||||
uint8_t fcs_invalid; /* 1 if extracted FCS does not match computed FCS */
|
||||
|
||||
uint8_t *tl_sdu; /* pointer to bitbuf */
|
||||
uint8_t tl_sdu_len; /* in bits */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue