Esempio n. 1
0
static int hsl_bts_process(struct ipa_client_conn *link, struct msgb *msg)
{
    struct ipaccess_head *hh;
    struct e1inp_sign_link *sign_link;
    struct e1inp_ts *e1i_ts = &link->line->ts[0];

    hh = (struct ipaccess_head *) msg->data;
    if (hh->proto == HSL_PROTO_DEBUG) {
        LOGP(DLINP, LOGL_NOTICE, "HSL debug: %s\n",
             msg->data + sizeof(*hh));
        msgb_free(msg);
        return 0;
    }
    sign_link = e1inp_lookup_sign_link(e1i_ts, hh->proto, 0);
    if (!sign_link) {
        LOGP(DLINP, LOGL_ERROR, "no matching signalling link for "
             "hh->proto=0x%02x\n", hh->proto);
        msgb_free(msg);
        return -EIO;
    }
    msg->dst = sign_link;

    /* XXX better use e1inp_ts_rx? */
    if (!link->line->ops->sign_link) {
        LOGP(DLINP, LOGL_ERROR, "Fix your application, "
             "no action set for signalling messages.\n");
        return -ENOENT;
    }
    link->line->ops->sign_link(msg);
    return 0;
}
Esempio n. 2
0
static int handle_ts1_read(struct osmo_fd *bfd)
{
	struct e1inp_line *line = bfd->data;
	struct misdn_line *mline = line->driver_data;
	unsigned int ts_nr = bfd->priv_nr;
	struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
	struct e1inp_sign_link *link;
	struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "mISDN TS1");
	struct sockaddr_mISDN l2addr;
	struct mISDNhead *hh;
	socklen_t alen;
	int ret;

	if (!msg)
		return -ENOMEM;

	hh = (struct mISDNhead *) msg->data;

	alen = sizeof(l2addr);
	ret = recvfrom(bfd->fd, msg->data, 300, 0,
		       (struct sockaddr *) &l2addr, &alen);
	if (ret < 0) {
		fprintf(stderr, "recvfrom error  %s\n", strerror(errno));
		msgb_free(msg);
		return ret;
	}

	if (alen != sizeof(l2addr)) {
		fprintf(stderr, "%s error len\n", __func__);
		msgb_free(msg);
		return -EINVAL;
	}

	msgb_put(msg, ret);

	DEBUGP(DLMI, "alen =%d, dev(%d) channel(%d) sapi(%d) tei(%d)\n",
		alen, l2addr.dev, l2addr.channel, l2addr.sapi, l2addr.tei);

	DEBUGP(DLMI, "<= len = %d, prim(0x%x) id(0x%x): %s\n",
		ret, hh->prim, hh->id, get_value_string(prim_names, hh->prim));

	switch (hh->prim) {
	case DL_INFORMATION_IND:
		/* mISDN tells us which channel number is allocated for this
		 * tuple of (SAPI, TEI). */
		DEBUGP(DLMI, "DL_INFORMATION_IND: use channel(%d) sapi(%d) tei(%d) for now\n",
			l2addr.channel, l2addr.sapi, l2addr.tei);
		link = e1inp_lookup_sign_link(e1i_ts, l2addr.tei, l2addr.sapi);
		if (!link) {
			DEBUGPC(DLMI, "mISDN message for unknown sign_link\n");
			msgb_free(msg);
			return -EINVAL;
		}
		/* save the channel number in the driver private struct */
		link->driver.misdn.channel = l2addr.channel;
		msgb_free(msg);
		break;
	case DL_ESTABLISH_IND:
		DEBUGP(DLMI, "DL_ESTABLISH_IND: channel(%d) sapi(%d) tei(%d)\n",
			l2addr.channel, l2addr.sapi, l2addr.tei);
		/* For some strange reason, sometimes the DL_INFORMATION_IND tells
		 * us the wrong channel, and we only get the real channel number
		 * during the DL_ESTABLISH_IND */
		link = e1inp_lookup_sign_link(e1i_ts, l2addr.tei, l2addr.sapi);
		if (!link) {
			DEBUGPC(DLMI, "mISDN message for unknown sign_link\n");
			msgb_free(msg);
			return -EINVAL;
		}
		/* save the channel number in the driver private struct */
		link->driver.misdn.channel = l2addr.channel;
		ret = e1inp_event(e1i_ts, S_L_INP_TEI_UP, l2addr.tei, l2addr.sapi);
		msgb_free(msg);
		break;
	case DL_RELEASE_IND:
		DEBUGP(DLMI, "DL_RELEASE_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		ret = e1inp_event(e1i_ts, S_L_INP_TEI_DN, l2addr.tei, l2addr.sapi);
		msgb_free(msg);
		break;
	case DL_DATA_IND:
	case DL_UNITDATA_IND:
		msg->l2h = msg->data + MISDN_HEADER_LEN;
		DEBUGP(DLMI, "RX: %s\n", osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
		if (mline->use_userspace_lapd) {
			LOGP(DLMI, LOGL_ERROR, "DL_DATA_IND but userspace LAPD ?!?\n");
			msgb_free(msg);
			return -EIO;
		}
		ret = e1inp_rx_ts(e1i_ts, msg, l2addr.tei, l2addr.sapi);
		break;
	case PH_ACTIVATE_IND:
		DEBUGP(DLMI, "PH_ACTIVATE_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		msgb_free(msg);
		break;
	case PH_DEACTIVATE_IND:
		DEBUGP(DLMI, "PH_DEACTIVATE_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		msgb_free(msg);
		break;
	case PH_DATA_IND:
		if (!mline->use_userspace_lapd) {
			LOGP(DLMI, LOGL_ERROR, "PH_DATA_IND but kernel LAPD ?!?\n");
			return -EIO;
		}
		/* remove the Misdn Header */
		msgb_pull(msg, MISDN_HEADER_LEN);
		/* hand into the LAPD code */
		DEBUGP(DLMI, "RX: %s\n", osmo_hexdump(msg->data, msg->len));
		ret = e1inp_rx_ts_lapd(e1i_ts, msg);
		break;
	default:
		msgb_free(msg);
		break;
	}
	return ret;
}
Esempio n. 3
0
static int handle_ts1_read(struct bsc_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 msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "mISDN TS1");
	struct sockaddr_mISDN l2addr;
	struct mISDNhead *hh;
	socklen_t alen;
	int ret;

	if (!msg)
		return -ENOMEM;

	hh = (struct mISDNhead *) msg->data;

	alen = sizeof(l2addr);
	ret = recvfrom(bfd->fd, msg->data, 300, 0,
		       (struct sockaddr *) &l2addr, &alen);
	if (ret < 0) {
		fprintf(stderr, "recvfrom error  %s\n", strerror(errno));
		return ret;
	}

	if (alen != sizeof(l2addr)) {
		fprintf(stderr, "%s error len\n", __func__);
		return -EINVAL;
	}

	msgb_put(msg, ret);

	DEBUGP(DMI, "alen =%d, dev(%d) channel(%d) sapi(%d) tei(%d)\n",
		alen, l2addr.dev, l2addr.channel, l2addr.sapi, l2addr.tei);

	DEBUGP(DMI, "<= len = %d, prim(0x%x) id(0x%x): %s\n",
		ret, hh->prim, hh->id, get_prim_name(hh->prim));

	switch (hh->prim) {
	case DL_INFORMATION_IND:
		/* mISDN tells us which channel number is allocated for this
		 * tuple of (SAPI, TEI). */
		DEBUGP(DMI, "DL_INFORMATION_IND: use channel(%d) sapi(%d) tei(%d) for now\n",
			l2addr.channel, l2addr.sapi, l2addr.tei);
		link = e1inp_lookup_sign_link(e1i_ts, l2addr.tei, l2addr.sapi);
		if (!link) {
			DEBUGPC(DMI, "mISDN message for unknown sign_link\n");
			msgb_free(msg);
			return -EINVAL;
		}
		/* save the channel number in the driver private struct */
		link->driver.misdn.channel = l2addr.channel;
		break;
	case DL_ESTABLISH_IND:
		DEBUGP(DMI, "DL_ESTABLISH_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		ret = e1inp_event(e1i_ts, EVT_E1_TEI_UP, l2addr.tei, l2addr.sapi);
		break;
	case DL_RELEASE_IND:
		DEBUGP(DMI, "DL_RELEASE_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		ret = e1inp_event(e1i_ts, EVT_E1_TEI_DN, l2addr.tei, l2addr.sapi);
		break;
	case DL_DATA_IND:
	case DL_UNITDATA_IND:
		msg->l2h = msg->data + MISDN_HEADER_LEN;
		DEBUGP(DMI, "RX: %s\n", hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
		ret = e1inp_rx_ts(e1i_ts, msg, l2addr.tei, l2addr.sapi);
		break;
	case PH_ACTIVATE_IND:
		DEBUGP(DMI, "PH_ACTIVATE_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		break;
	case PH_DEACTIVATE_IND:
		DEBUGP(DMI, "PH_DEACTIVATE_IND: channel(%d) sapi(%d) tei(%d)\n",
		l2addr.channel, l2addr.sapi, l2addr.tei);
		break;
	default:
		break;
	}
	return ret;
}
Esempio n. 4
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;

    error = ipa_msg_recv(bfd->fd, &msg);
    if (error < 0)
        return error;
    else if (error == 0) {
        hsl_drop(e1i_ts->line, bfd);
        LOGP(DLINP, LOGL_NOTICE, "Sign link vanished, dead socket\n");
        return error;
    }
    DEBUGP(DLMI, "RX %u: %s\n", ts_nr, osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)));

    hh = (struct ipaccess_head *) msg->data;
    if (hh->proto == HSL_PROTO_DEBUG) {
        LOGP(DLINP, 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)) {
        ret = process_hsl_rsl(msg, line, bfd);
        if (ret < 0) {
            hsl_drop(e1i_ts->line, bfd);
            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(DLINP, 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(DLINP, LOGL_ERROR, "Fix your application, "
             "no action set for signalling messages.\n");
        return -ENOENT;
    }
    e1i_ts->line->ops->sign_link(msg);

    return ret;
}