diff options
author | Pablo Neira Ayuso <pablo@gnumonks.org> | 2011-08-09 23:15:38 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2011-08-10 10:51:02 +0200 |
commit | cd98656315c4e81816866823920fc1951f0c2a0b (patch) | |
tree | 280e0576a65721134a0bdf8a9f0f0a324b1c511f /openbsc/src/libabis/input/lapd.c | |
parent | 1045697c349a432ef4b0a8dfd5ad20549afe2f39 (diff) |
LAPD: Propagate lapd_receive() errors to the E1 driver
Scenario: BTS are configured and working, then the BSC stops working
for some reason (crash or administrative stop).
If the BSC comes back to life, LAPD among other things does not know
about the previous existing TEIs. Instead of ignoring these frames,
we notify the driver that we are seeing frames with unknown TEIs, so
it can try to recover, e.g. by resending the SABM message.
Diffstat (limited to 'openbsc/src/libabis/input/lapd.c')
-rw-r--r-- | openbsc/src/libabis/input/lapd.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/openbsc/src/libabis/input/lapd.c b/openbsc/src/libabis/input/lapd.c index 66ff05e09..2934b58ca 100644 --- a/openbsc/src/libabis/input/lapd.c +++ b/openbsc/src/libabis/input/lapd.c @@ -310,8 +310,9 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len) }; /* General input function for any data received for this LAPD instance */ -uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len, - int *ilen, lapd_mph_type *prim) +uint8_t * +lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len, + int *ilen, lapd_mph_type *prim, int *error) { uint8_t sapi, cr, tei, command; int pf, ns, nr; @@ -327,12 +328,14 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len if (len < 2) { LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 2, ignoring\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; }; if ((data[0] & 1) != 0 || (data[1] & 1) != 1) { LOGP(DMI, LOGL_ERROR, "LAPD address field %x/%x not well formed\n", data[0], data[1]); + *error = LAPD_ERR_BAD_ADDR; return NULL; }; @@ -344,6 +347,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len if (len < 3) { LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 3, ignoring\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; }; @@ -356,6 +360,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len typ = LAPD_TYPE_I; if (len < 4) { LOGP(DMI, LOGL_ERROR, "LAPD I frame, len %d < 4\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; } ns = data[2] >> 1; @@ -366,6 +371,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len typ = LAPD_TYPE_S; if (len < 4) { LOGP(DMI, LOGL_ERROR, "LAPD S frame, len %d < 4\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; } nr = data[3] >> 1; @@ -382,6 +388,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len break; default: LOGP(DMI, LOGL_ERROR, "LAPD unknown S cmd %x\n", data[2]); + *error = LAPD_ERR_UNKNOWN_S_CMD; return NULL; }; } else if ((data[2] & 3) == 3) { @@ -414,6 +421,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len default: LOGP(DMI, LOGL_ERROR, "LAPD unknown U cmd %x " "(pf %x data %x)\n", val, pf, data[2]); + *error = LAPD_ERR_UNKNOWN_U_CMD; return NULL; }; }; @@ -429,6 +437,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len teip = teip_from_tei(li, tei); if (!teip) { LOGP(DMI, LOGL_NOTICE, "LAPD Unknown TEI %u\n", tei); + *error = LAPD_ERR_UNKNOWN_TEI; return NULL; } @@ -587,6 +596,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len return contents; } + *error = LAPD_ERR_BAD_CMD; return NULL; }; |