From 5a4b7c54c699889b3255e578ef75c0989622b541 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 7 Jun 2011 14:07:48 +0200 Subject: e1input: rework generic (virtual and real) E1 line operations struct e1inp_line_ops { int (*sign_link_up)(struct msgb *msg, struct e1inp_line *line); int (*sign_link)(struct msgb *msg, struct e1inp_sign_link *link); int (*error)(struct msgb *msg, int error); }; The description of the operations is the following: * sign_link_up is invoked if the signalling link becomes up. In A-bis over IP, we have to wait until the other peer identifies itself as a BTS/BSC device, then this function is invoked. This function is not used by ISDN drivers, the signalling link can be set up just after the line is created. * sign_link is called if we receive OML/RSL message. This function is used both by ISDN and A-bis over IP drivers. * error is called if we receive a malformed message. It is used both by ISDN and A-bis over IP drivers. --- src/e1_input.c | 16 +++++------ src/input/dahdi.c | 8 ++++-- src/input/hsl.c | 56 +++++++++++++++++++++++++++++++++---- src/input/ipaccess.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/input/misdn.c | 5 +++- 5 files changed, 143 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/e1_input.c b/src/e1_input.c index 1c3d3b0..7904f61 100644 --- a/src/e1_input.c +++ b/src/e1_input.c @@ -305,8 +305,7 @@ struct e1inp_line *e1inp_line_get(uint8_t e1_nr) struct e1inp_line * e1inp_line_create(uint8_t e1_nr, const char *driver_name, - int (*rx)(struct msgb *msgb, struct e1inp_ts *ts), - int (*rx_err)(int error)) + const struct e1inp_line_ops *ops) { struct e1inp_driver *driver; struct e1inp_line *line; @@ -331,8 +330,7 @@ e1inp_line_create(uint8_t e1_nr, const char *driver_name, return NULL; line->driver = driver; - line->rx = rx; - line->rx_err = rx_err; + memcpy(&line->ops, ops, sizeof(struct e1inp_line_ops)); line->num = e1_nr; for (i = 0; i < NUM_E1_TS; i++) { @@ -467,10 +465,12 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg, "tei %d, sapi %d\n", tei, sapi); return -EINVAL; } - if (!ts->line->rx) - printf("XXX Error, horror\n"); - - ts->line->rx(msg, ts); + if (!ts->line->ops.sign_link) { + LOGP(DINP, LOGL_ERROR, "Fix your application, " + "no action set for signalling messages.\n"); + return -ENOENT; + } + ts->line->ops.sign_link(msg, link); break; case E1INP_TS_TYPE_TRAU: ret = subch_demux_in(&ts->trau.demux, msg->l2h, msgb_l2len(msg)); diff --git a/src/input/dahdi.c b/src/input/dahdi.c index ba8ce02..8e5e635 100644 --- a/src/input/dahdi.c +++ b/src/input/dahdi.c @@ -121,8 +121,11 @@ static int handle_ts1_read(struct osmo_fd *bfd) DEBUGP(DMI, "<= len = %d, sapi(%d) tei(%d)", ret, sapi, tei); idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim); - if (!idata && prim == 0) + if (!idata && prim == 0) { + if (line->ops.error) + line->ops.error(NULL, -EBADMSG); return -EIO; + } msgb_pull(msg, 2); @@ -149,7 +152,8 @@ static int handle_ts1_read(struct osmo_fd *bfd) ret = e1inp_rx_ts(e1i_ts, msg, tei, sapi); break; default: - printf("ERROR: unknown prim\n"); + if (line->ops.error) + line->ops.error(NULL, -EBADMSG); break; } diff --git a/src/input/hsl.c b/src/input/hsl.c index b7c7897..97475cf 100644 --- a/src/input/hsl.c +++ b/src/input/hsl.c @@ -77,13 +77,15 @@ static int handle_ts1_read(struct osmo_fd *bfd) struct e1inp_line *line = bfd->data; unsigned int ts_nr = bfd->priv_nr; struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1]; + struct e1inp_sign_link *link; + struct ipaccess_head *hh; struct msgb *msg; int ret = 0, error; msg = ipaccess_read_msg(bfd, &error); if (!msg) { - if (e1i_ts->line->rx_err) - e1i_ts->line->rx_err(error); + if (e1i_ts->line->ops.error) + e1i_ts->line->ops.error(NULL, error); if (error == 0) { osmo_fd_unregister(bfd); close(bfd->fd); @@ -93,9 +95,53 @@ static int handle_ts1_read(struct osmo_fd *bfd) } DEBUGP(DMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg))); - /* XXX better use e1inp_rx_ts. */ - if (e1i_ts->line->rx) - e1i_ts->line->rx(msg, e1i_ts); + hh = (struct ipaccess_head *) msg->data; + if (hh->proto == HSL_PROTO_DEBUG) { + LOGP(DINP, LOGL_NOTICE, "HSL debug: %s\n", msg->data + sizeof(*hh)); + msgb_free(msg); + return ret; + } + + /* HSL proprietary RSL extension */ + if (hh->proto == 0 && (msg->l2h[0] == 0x81 || msg->l2h[0] == 0x80)) { + if (!line->ops.sign_link_up) { + LOGP(DINP, LOGL_ERROR, "Fix your application, no " + "action set if the signalling link " + "becomes ready.\n"); + return -EINVAL; + } + ret = line->ops.sign_link_up(msg, line); + if (ret < 0) { + /* FIXME: close connection */ + if (line->ops.error) + line->ops.error(msg, -EBADMSG); + return ret; + } else if (ret == 1) + return 0; + /* else: continue... */ + } + +#ifdef HSL_SR_1_0 + /* HSL for whatever reason chose to use 0x81 instead of 0x80 for FOM */ + if (hh->proto == 255 && msg->l2h[0] == (ABIS_OM_MDISC_FOM | 0x01)) + msg->l2h[0] = ABIS_OM_MDISC_FOM; +#endif + link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0); + if (!link) { + LOGP(DINP, LOGL_ERROR, "no matching signalling link for " + "hh->proto=0x%02x\n", hh->proto); + msgb_free(msg); + return -EIO; + } + msg->dst = link; + + /* XXX: better use e1inp_ts_rx? */ + if (!e1i_ts->line->ops.sign_link) { + LOGP(DINP, LOGL_ERROR, "Fix your application, " + "no action set for signalling messages.\n"); + return -ENOENT; + } + e1i_ts->line->ops.sign_link(msg, link); return ret; } diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c index ef773ba..92819ac 100644 --- a/src/input/ipaccess.c +++ b/src/input/ipaccess.c @@ -170,18 +170,65 @@ struct msgb *ipaccess_read_msg(struct osmo_fd *bfd, int *error) return msg; } +/* base handling of the ip.access protocol */ +int ipaccess_rcvmsg_base(struct msgb *msg, + struct osmo_fd *bfd) +{ + uint8_t msg_type = *(msg->l2h); + int ret = 0; + + switch (msg_type) { + case IPAC_MSGT_PING: + ret = ipaccess_send_pong(bfd->fd); + break; + case IPAC_MSGT_PONG: + DEBUGP(DMI, "PONG!\n"); + break; + case IPAC_MSGT_ID_ACK: + DEBUGP(DMI, "ID_ACK? -> ACK!\n"); + ret = ipaccess_send_id_ack(bfd->fd); + break; + } + return 0; +} + +static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg, + struct osmo_fd *bfd) +{ + uint8_t msg_type = *(msg->l2h); + + /* handle base messages */ + ipaccess_rcvmsg_base(msg, bfd); + + switch (msg_type) { + case IPAC_MSGT_ID_RESP: + DEBUGP(DMI, "ID_RESP\n"); + if (!line->ops.sign_link_up) { + LOGP(DINP, LOGL_ERROR, "Fix your application, " + "no action set if the signalling link " + "becomes ready\n"); + return -EINVAL; + } + line->ops.sign_link_up(msg, line); + break; + } + return 0; +} + static int handle_ts1_read(struct osmo_fd *bfd) { struct e1inp_line *line = bfd->data; unsigned int ts_nr = bfd->priv_nr; struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1]; + struct e1inp_sign_link *link; + struct ipaccess_head *hh; struct msgb *msg; int ret = 0, error; msg = ipaccess_read_msg(bfd, &error); if (!msg) { - if (e1i_ts->line->rx_err) - e1i_ts->line->rx_err(error); + if (e1i_ts->line->ops.error) + e1i_ts->line->ops.error(NULL, error); if (error == 0) { osmo_fd_unregister(bfd); close(bfd->fd); @@ -191,10 +238,32 @@ static int handle_ts1_read(struct osmo_fd *bfd) } DEBUGP(DMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg))); - /* XXX better use e1inp_ts_rx. */ + hh = (struct ipaccess_head *) msg->data; + if (hh->proto == IPAC_PROTO_IPACCESS) { + ipaccess_rcvmsg(line, msg, bfd); + msgb_free(msg); + return ret; + } + /* BIG FAT WARNING: bfd might no longer exist here, since ipaccess_rcvmsg() + * might have free'd it !!! */ + + link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0); + if (!link) { + LOGP(DINP, LOGL_ERROR, "no matching signalling link for " + "hh->proto=0x%02x\n", hh->proto); + msgb_free(msg); + return -EIO; + } + msg->dst = link; + + /* XXX better use e1inp_ts_rx? */ + if (!e1i_ts->line->ops.sign_link) { + LOGP(DINP, LOGL_ERROR, "Fix your application, " + "no action set for signalling messages.\n"); + return -ENOENT; + } + e1i_ts->line->ops.sign_link(msg, link); - if (e1i_ts->line->rx) - e1i_ts->line->rx(msg, e1i_ts); return ret; } diff --git a/src/input/misdn.c b/src/input/misdn.c index c97169a..afa9032 100644 --- a/src/input/misdn.c +++ b/src/input/misdn.c @@ -115,7 +115,8 @@ static int handle_ts1_read(struct osmo_fd *bfd) } if (alen != sizeof(l2addr)) { - fprintf(stderr, "%s error len\n", __func__); + if (line->ops.error) + line->ops.error(NULL, -EBADMSG); return -EINVAL; } @@ -178,6 +179,8 @@ static int handle_ts1_read(struct osmo_fd *bfd) l2addr.channel, l2addr.sapi, l2addr.tei); break; default: + if (line->ops.error) + line->ops.error(NULL, -EBADMSG); break; } return ret; -- cgit v1.2.3-55-g7522