Beispiel #1
0
static int forward_ussd(struct nat_sccp_connection *con, const struct ussd_request *req,
			struct msgb *input)
{
	struct msgb *msg, *copy;
	struct ipac_msgt_sccp_state *state;
	struct bsc_nat_ussd_con *ussd;
	uint16_t lac, ci;

	if (!con->bsc->nat->ussd_con)
		return -1;

	msg = msgb_alloc_headroom(4096, 128, "forward ussd");
	if (!msg) {
		LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
		return -1;
	}

	copy = msgb_alloc_headroom(4096, 128, "forward bts");
	if (!copy) {
		LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
		msgb_free(msg);
		return -1;
	}

	copy->l2h = msgb_put(copy, msgb_l2len(input));
	memcpy(copy->l2h, input->l2h, msgb_l2len(input));

	msg->l2h = msgb_put(msg, 1);
	msg->l2h[0] = IPAC_MSGT_SCCP_OLD;

	/* fill out the data */
	state = (struct ipac_msgt_sccp_state *) msgb_put(msg, sizeof(*state));
	state->trans_id = req->transaction_id;
	state->invoke_id = req->invoke_id;
	memcpy(&state->src_ref, &con->remote_ref, sizeof(con->remote_ref));
	memcpy(&state->dst_ref, &con->real_ref, sizeof(con->real_ref));
	memcpy(state->imsi, con->filter_state.imsi, strlen(con->filter_state.imsi));

	/* add additional tag/values */
	lac = htons(con->lac);
	ci = htons(con->ci);
	msgb_tv_fixed_put(msg, USSD_LAC_IE, sizeof(lac), (const uint8_t *) &lac);
	msgb_tv_fixed_put(msg, USSD_CI_IE, sizeof(ci), (const uint8_t *) &ci);

	ussd = con->bsc->nat->ussd_con;
	bsc_do_write(&ussd->queue, msg, IPAC_PROTO_IPACCESS);
	bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);

	return 0;
}
/*
 * handle incoming messages:
 *   - this can be a command (four letters, space, transaction id)
 *   - or a response (three numbers, space, transaction id)
 */
struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct msgb *msg)
{
    int code;
    struct msgb *resp = NULL;

    if (msgb_l2len(msg) < 4) {
        LOGP(DMGCP, LOGL_ERROR, "mgs too short: %d\n", msg->len);
        return NULL;
    }

    /* attempt to treat it as a response */
    if (sscanf((const char *)&msg->l2h[0], "%3d %*s", &code) == 1) {
        LOGP(DMGCP, LOGL_DEBUG, "Response: Code: %d\n", code);
    } else {
        int i, handled = 0;
        msg->l3h = &msg->l2h[4];
        for (i = 0; i < ARRAY_SIZE(mgcp_requests); ++i)
            if (strncmp(mgcp_requests[i].name, (const char *) &msg->l2h[0], 4) == 0) {
                handled = 1;
                resp = mgcp_requests[i].handle_request(cfg, msg);
                break;
            }
        if (!handled) {
            LOGP(DMGCP, LOGL_NOTICE, "MSG with type: '%.4s' not handled\n", &msg->l2h[0]);
        }
    }

    return resp;
}
Beispiel #3
0
void ipa_msg_push_header(struct msgb *msg, uint8_t proto)
{
	struct ipaccess_head *hh;

	msg->l2h = msg->data;
	hh = (struct ipaccess_head *) msgb_push(msg, sizeof(*hh));
	hh->proto = proto;
	hh->len = htons(msgb_l2len(msg));
}
static int send(struct msgb *in_msg, struct lapdm_channel *chan)
{
	struct osmo_phsap_prim pp;
	struct msgb *msg;
	int rc;

	msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
	osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
			PRIM_OP_INDICATION, msg);
	/* copy over actual MAC block */
	msg->l2h = msgb_put(msg, msgb_l2len(in_msg));
	memcpy(msg->l2h, in_msg->l2h, msgb_l2len(in_msg));

	/* LAPDm requires those... */
	pp.u.data.chan_nr = 0;
	pp.u.data.link_id = 0;
        /* feed into the LAPDm code of libosmogsm */
        rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
	ASSERT(rc == 0 || rc == -EBUSY);
	return 0;
}
static struct msgb *create_mm_id_req(void)
{
	struct msgb *msg;

	msg = msgb_from_array(mm, sizeof(mm));
	msg->l2h = msg->data + 3;
	ASSERT(msgb_l2len(msg) == 12);
	msg->l3h = msg->l2h + 6;
	ASSERT(msgb_l3len(msg) == 6);

	return msg;
}
Beispiel #6
0
static int
loader_read_cb(struct osmo_fd *fd, unsigned int flags) {
	struct msgb *msg;
	uint16_t len;
	int rc;

	msg = msgb_alloc(MSGB_MAX, "loader");
	if (!msg) {
		fprintf(stderr, "Failed to allocate msg.\n");
		return -1;
	}

	rc = read(fd->fd, &len, sizeof(len));
	if (rc < sizeof(len)) {
		fprintf(stderr, "Short read. Error.\n");
		exit(2);
	}

	if (ntohs(len) > MSGB_MAX) {
		fprintf(stderr, "Length is too big: %u\n", ntohs(len));
		msgb_free(msg);
		return -1;
	}

	/* blocking read for the poor... we can starve in here... */
	msg->l2h = msgb_put(msg, ntohs(len));
	rc = read(fd->fd, msg->l2h, msgb_l2len(msg));
	if (rc != msgb_l2len(msg)) {
		fprintf(stderr, "Can not read data: rc: %d errno: %d\n", rc, errno);
		msgb_free(msg);
		return -1;
	}

	loader_handle_reply(msg);

	msgb_free(msg);

	return 0;
}
Beispiel #7
0
static int ussd_read_cb(struct osmo_fd *bfd)
{
	struct bsc_nat_ussd_con *conn = bfd->data;
	struct msgb *msg = NULL;
	struct ipaccess_head *hh;
	int ret;

	ret = ipa_msg_recv_buffered(bfd->fd, &msg, &conn->pending_msg);
	if (ret <= 0) {
		if (ret == -EAGAIN)
			return 0;
		LOGP(DNAT, LOGL_ERROR, "USSD Connection was lost.\n");
		bsc_nat_ussd_destroy(conn);
		return -1;
	}

	LOGP(DNAT, LOGL_NOTICE, "MSG from USSD: %s proto: %d\n",
		osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
	hh = (struct ipaccess_head *) msg->data;

	if (hh->proto == IPAC_PROTO_IPACCESS) {
		if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
			struct tlv_parsed tvp;
			int ret;
			ret = ipa_ccm_idtag_parse(&tvp,
					     (unsigned char *) msg->l2h + 2,
					     msgb_l2len(msg) - 2);
			if (ret < 0) {
				LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
					"message with malformed TLVs\n");
				msgb_free(msg);
				return ret;
			}
			if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
				ussd_auth_con(&tvp, conn);
		} else if (msg->l2h[0] == IPAC_MSGT_PING) {
			LOGP(DNAT, LOGL_DEBUG, "Got USSD ping request.\n");
			ussd_pong(conn);
		} else {
			LOGP(DNAT, LOGL_NOTICE, "Got unknown IPACCESS message 0x%02x.\n", msg->l2h[0]);
		}

		msgb_free(msg);
	} else if (hh->proto == IPAC_PROTO_SCCP) {
		forward_sccp(conn->nat, msg);
	} else {
		msgb_free(msg);
	}

	return 0;
}
Beispiel #8
0
/**
 * \brief Verify the structure of the OML message and set l3h
 *
 * This function verifies that the data in \param in msg is a proper
 * OML message. This code assumes that msg->l2h points to the
 * beginning of the OML message. In the successful case the msg->l3h
 * will be set and will point to the FOM header. The value is undefined
 * in all other cases.
 *
 * \param msg The message to analyze starting from msg->l2h.
 * \return In case the structure is correct a positive number will be
 * returned and msg->l3h will point to the FOM. The number is a
 * classification of the vendor type of the message.
 */
int msg_verify_oml_structure(struct msgb *msg)
{
	struct abis_om_hdr *omh;

	if (msgb_l2len(msg) < sizeof(*omh)) {
		LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n",
		     msgb_l2len(msg), sizeof(*omh));
		return -1;
	}

	omh = (struct abis_om_hdr *) msg->l2h;
	if (omh->mdisc != ABIS_OM_MDISC_FOM &&
	    omh->mdisc != ABIS_OM_MDISC_MANUF) {
		LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n",
		     omh->mdisc);
		return -1;
	}

	if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
		LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n",
		     omh->placement, ABIS_OM_PLACEMENT_ONLY);
		return -1;
	}

	if (omh->sequence != 0) {
		LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n",
		     omh->sequence);
		return -1;
	}

	if (omh->mdisc == ABIS_OM_MDISC_MANUF)
		return check_manuf(msg, omh, msgb_l2len(msg) - sizeof(*omh));

	msg->l3h = omh->data;
	if (check_fom(omh, msgb_l3len(msg)) != 0)
		return -1;
	return OML_MSG_TYPE_ETSI;
}
Beispiel #9
0
static int __handle_ts1_write(struct osmo_fd *bfd, struct e1inp_line *line)
{
    unsigned int ts_nr = bfd->priv_nr;
    struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
    struct e1inp_sign_link *sign_link;
    struct msgb *msg;
    int ret;

    bfd->when &= ~BSC_FD_WRITE;

    /* get the next msg for this timeslot */
    msg = e1inp_tx_ts(e1i_ts, &sign_link);
    if (!msg) {
        /* no message after tx delay timer */
        return 0;
    }

    switch (sign_link->type) {
    case E1INP_SIGN_OML:
#ifdef HSL_SR_1_0
        /* HSL uses 0x81 for FOM for some reason */
        if (msg->data[0] == ABIS_OM_MDISC_FOM)
            msg->data[0] = ABIS_OM_MDISC_FOM | 0x01;
#endif
        break;
    case E1INP_SIGN_RSL:
        break;
    default:
        msgb_free(msg);
        bfd->when |= BSC_FD_WRITE; /* come back for more msg */
        return -EINVAL;
    }

    msg->l2h = msg->data;
    ipaccess_prepend_header(msg, sign_link->tei);

    DEBUGP(DLMI, "TX %u: %s\n", ts_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg)));

    ret = send(bfd->fd, msg->data, msg->len, 0);
    msgb_free(msg);

    /* set tx delay timer for next event */
    e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
    e1i_ts->sign.tx_timer.data = e1i_ts;

    /* Reducing this might break the nanoBTS 900 init. */
    osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);

    return ret;
}
Beispiel #10
0
static int forward_ussd_simple(struct sccp_connections *con, struct msgb *input)
{
	struct msgb *copy;
	struct bsc_nat_ussd_con *ussd;

	if (!con->bsc->nat->ussd_con)
		return -1;

	copy = msgb_alloc_headroom(4096, 128, "forward bts");
	if (!copy) {
		LOGP(DNAT, LOGL_ERROR, "Allocation failed, not forwarding.\n");
		return -1;
	}

	/* copy the data into the copy */
	copy->l2h = msgb_put(copy, msgb_l2len(input));
	memcpy(copy->l2h, input->l2h, msgb_l2len(input));

	/* send it out */
	ussd = con->bsc->nat->ussd_con;
	bsc_do_write(&ussd->queue, copy, IPAC_PROTO_SCCP);
	return 0;
}
Beispiel #11
0
/* Append padding (if required) */
static void lapdm_pad_msgb(struct msgb *msg, uint8_t n201)
{
	int pad_len = n201 - msgb_l2len(msg);
	uint8_t *data;

	if (pad_len < 0) {
		LOGP(DLLAPD, LOGL_ERROR,
		     "cannot pad message that is already too big!\n");
		return;
	}

	data = msgb_put(msg, pad_len);
	memset(data, 0x2B, pad_len);
}
void lapd_rx_cb(struct osmo_dlsap_prim *dp, uint8_t tei, uint8_t sapi,
		void *rx_cbdata)
{
	struct msgb *msg = dp->oph.msg;

	switch (dp->oph.primitive) {
	case PRIM_DL_EST:
		DEBUGP(DLAPDTEST, "DL_EST: sapi(%d) tei(%d)\n", sapi, tei);
		break;
	case PRIM_DL_REL:
		DEBUGP(DLAPDTEST, "DL_REL: sapi(%d) tei(%d)\n", sapi, tei);
		break;
	case PRIM_DL_DATA:
	case PRIM_DL_UNIT_DATA:
		if (dp->oph.operation == PRIM_OP_INDICATION) {
			struct msgb *nmsg;
			char *ptr;
			int x;

			msg->l2h = msg->l3h;

			DEBUGP(DLAPDTEST, "RX: %s sapi=%d tei=%d\n",
				osmo_hexdump(msgb_l2(msg), msgb_l2len(msg)),
				sapi, tei);

			LOGP(DLAPDTEST, LOGL_DEBUG, "forwarding message\n");

                        nmsg = msgb_alloc(1024, "LAPD/test");
                        if (nmsg == NULL) {
                                LOGP(DLAPDTEST, LOGL_ERROR, "cannot alloc msg\n");
                                return;
                        }
                        ptr = (char *)msgb_put(nmsg, sizeof(int));

                        x = *((int *)msg->data);
                        memcpy(ptr, &x, sizeof(int));

			/* send the message back to client over LAPD */
			lapd_transmit(lapd, tei, sapi, msg);
			return;
		}
		break;
	case PRIM_MDL_ERROR:
		DEBUGP(DLMI, "MDL_EERROR: cause(%d)\n", dp->u.error_ind.cause);
		break;
	default:
		printf("ERROR: unknown prim\n");
		break;
	}
}
Beispiel #13
0
static void l1ctl_rx_data_tbf_req(struct l1_model_ms *ms, struct msgb *msg)
{
	struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
	struct l1ctl_info_ul_tbf *udt = (struct l1ctl_info_ul_tbf *) l1h->data;
	enum osmo_gprs_cs osmo_cs;
	int block_size;

	msg->l2h = udt->payload;

	LOGPMS(DL1P, LOGL_ERROR, ms, "Rx L1CTL_DATA_TBF_REQ (tbf_id=%d, data=%s)\n",
		udt->tbf_nr, osmo_hexdump(msg->l2h, msgb_l2len(msg)));
	if (udt->tbf_nr != 0) {
		LOGPMS(DL1C, LOGL_ERROR, ms, "TBF_NR != 0 not supported yet!\n");
		return;
	}

	if (ms->state.state != MS_STATE_TBF) {
		LOGPMS(DL1P, LOGL_ERROR, ms, "DATA_TBF_REQ in state != TBF\n");
		return;
	}

	osmo_cs = get_l1ctl_cs_by_osmo(udt->coding_scheme);
	if (osmo_cs < 0) {
		LOGPMS(DL1P, LOGL_ERROR, ms, "DATA_RBF_REQ with invalid CS\n");
		return;
	}
	block_size = osmo_gprs_ul_block_size_bytes(osmo_cs);

	if (msgb_l2len(msg) < block_size) {
		int pad_len = block_size - msgb_l2len(msg);
		uint8_t *pad = msgb_put(msg, pad_len);
		memset(pad, GSM_MACBLOCK_PADDING, pad_len);
	}

	msgb_enqueue(&ms->state.tbf.ul.tx_queue, msg);
}
int chan_conf(struct osmocom_ms *ms, struct msgb *msg)
{
	struct abis_rsl_cchan_hdr *ch = msgb_l2(msg);
	struct gsm48_req_ref *ref = (struct gsm48_req_ref *) (ch->data + 1);

	if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) {
		LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n");
		return -EINVAL;
	}

	rach_ref.valid = 1;
	rach_ref.t1 = ref->t1;
	rach_ref.t2 = ref->t2;
	rach_ref.t3 = ref->t3_low | (ref->t3_high << 3);

	return 0;
}
Beispiel #15
0
/* FIXME: read from a B channel TS */
static int handle_tsX_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 msgb *msg = msgb_alloc(TSX_ALLOC_SIZE, "mISDN TSx");
	struct mISDNhead *hh;
	int ret;

	if (!msg)
		return -ENOMEM;

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

	ret = recv(bfd->fd, msg->data, TSX_ALLOC_SIZE, 0);
	if (ret < 0) {
		fprintf(stderr, "recvfrom error  %s\n", strerror(errno));
		return ret;
	}

	msgb_put(msg, ret);

	if (hh->prim != PH_CONTROL_IND)
		DEBUGP(DLMIB, "<= BCHAN 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 PH_DATA_IND:
		msg->l2h = msg->data + MISDN_HEADER_LEN;
		DEBUGP(DLMIB, "BCHAN RX: %s\n",
			osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
		/* the number of bytes received indicates that data to send */
		handle_tsX_write(bfd, msgb_l2len(msg));
		return e1inp_rx_ts(e1i_ts, msg, 0, 0);
	case PH_ACTIVATE_IND:
	case PH_DATA_CNF:
		break;
	default:
		break;
	}
	/* FIXME: why do we free signalling msgs in the caller, and trau not? */
	msgb_free(msg);

	return ret;
}
Beispiel #16
0
static int read_call_agent(struct osmo_fd *fd, unsigned int what)
{
	struct sockaddr_in addr;
	socklen_t slen = sizeof(addr);
	struct msgb *msg;
	struct msgb *resp;
	int i;

	msg = (struct msgb *) fd->data;

	/* read one less so we can use it as a \0 */
	int rc = recvfrom(cfg->gw_fd.bfd.fd, msg->data, msg->data_len - 1, 0,
		(struct sockaddr *) &addr, &slen);
	if (rc < 0) {
		perror("Gateway failed to read");
		return -1;
	} else if (slen > sizeof(addr)) {
		fprintf(stderr, "Gateway received message from outerspace: %zu %zu\n",
			(size_t) slen, sizeof(addr));
		return -1;
	}

	/* handle message now */
	msg->l2h = msgb_put(msg, rc);
	resp = mgcp_handle_message(cfg, msg);
	msgb_reset(msg);

	if (resp) {
		sendto(cfg->gw_fd.bfd.fd, resp->l2h, msgb_l2len(resp), 0, (struct sockaddr *) &addr, sizeof(addr));
		msgb_free(resp);
	}

	if (reset_endpoints) {
		LOGP(DMGCP, LOGL_NOTICE,
		     "Asked to reset endpoints: %d/%d\n",
		     reset_trunk->trunk_nr, reset_trunk->trunk_type);
		reset_endpoints = 0;

		/* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */
		for (i = 1; i < reset_trunk->number_endpoints; ++i)
			mgcp_release_endp(&reset_trunk->endpoints[i]);
	}

	return 0;
}
Beispiel #17
0
static int ph_data_req(struct gsm_bts_trx *trx, struct msgb *msg,
		       struct osmo_phsap_prim *l1sap, bool use_cache)
{
	struct lc15l1_hdl *fl1 = trx_lc15l1_hdl(trx);
	struct msgb *l1msg = l1p_msgb_alloc();
	struct gsm_lchan *lchan;
	uint32_t u32Fn;
	uint8_t u8Tn, subCh, u8BlockNbr = 0, sapi = 0;
	uint8_t chan_nr, link_id;
	int len;

	if (!msg) {
		LOGP(DL1C, LOGL_FATAL, "PH-DATA.req without msg. "
			"Please fix!\n");
		abort();
	}

	len = msgb_l2len(msg);

	chan_nr = l1sap->u.data.chan_nr;
	link_id = l1sap->u.data.link_id;
	u32Fn = l1sap->u.data.fn;
	u8Tn = L1SAP_CHAN2TS(chan_nr);
	subCh = 0x1f;
	lchan = get_lchan_by_chan_nr(trx, chan_nr);
	if (L1SAP_IS_LINK_SACCH(link_id)) {
		sapi = GsmL1_Sapi_Sacch;
		if (!L1SAP_IS_CHAN_TCHF(chan_nr))
			subCh = l1sap_chan2ss(chan_nr);
	} else if (L1SAP_IS_CHAN_TCHF(chan_nr)) {
		if (ts_is_pdch(&trx->ts[u8Tn])) {
			if (L1SAP_IS_PTCCH(u32Fn)) {
				sapi = GsmL1_Sapi_Ptcch;
				u8BlockNbr = L1SAP_FN2PTCCHBLOCK(u32Fn);
			} else {
				sapi = GsmL1_Sapi_Pdtch;
				u8BlockNbr = L1SAP_FN2MACBLOCK(u32Fn);
			}
		} else {
			sapi = GsmL1_Sapi_FacchF;
			u8BlockNbr = (u32Fn % 13) >> 2;
		}
	} else if (L1SAP_IS_CHAN_TCHH(chan_nr)) {
Beispiel #18
0
static int ussd_read_cb(struct osmo_fd *bfd)
{
	int error;
	struct bsc_nat_ussd_con *conn = bfd->data;
	struct msgb *msg = ipaccess_read_msg(bfd, &error);
	struct ipaccess_head *hh;

	if (!msg) {
		LOGP(DNAT, LOGL_ERROR, "USSD Connection was lost.\n");
		bsc_nat_ussd_destroy(conn);
		return -1;
	}

	LOGP(DNAT, LOGL_NOTICE, "MSG from USSD: %s proto: %d\n",
		osmo_hexdump(msg->data, msg->len), msg->l2h[0]);
	hh = (struct ipaccess_head *) msg->data;

	if (hh->proto == IPAC_PROTO_IPACCESS) {
		if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
			struct tlv_parsed tvp;
			int ret;
			ret = ipaccess_idtag_parse(&tvp,
					     (unsigned char *) msg->l2h + 2,
					     msgb_l2len(msg) - 2);
			if (ret < 0) {
				LOGP(DNAT, LOGL_ERROR, "ignoring IPA response "
					"message with malformed TLVs\n");
				return ret;
			}
			if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
				ussd_auth_con(&tvp, conn);
		}

		msgb_free(msg);
	} else if (hh->proto == IPAC_PROTO_SCCP) {
		forward_sccp(conn->nat, msg);
	} else {
		msgb_free(msg);
	}

	return 0;
}
static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
	struct tlv_parsed tv;
	uint8_t ch_type, ch_subch, ch_ts;
	
	DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
		rllh->chan_nr, rllh->link_id);

	rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
	if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
		DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
		return -EIO;
	}
	msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);

	if (state != SCAN_STATE_READ && state != SCAN_STATE_RACH) {
	 	return -EINVAL;
	}

	rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
	switch (ch_type) {
	case RSL_CHAN_PCH_AGCH:
		return pch_agch(ms, msg);
	case RSL_CHAN_BCCH:
		return bcch(ms, msg);
#if 0
	case RSL_CHAN_Bm_ACCHs:
	case RSL_CHAN_Lm_ACCHs:
	case RSL_CHAN_SDCCH4_ACCH:
	case RSL_CHAN_SDCCH8_ACCH:
		return rx_acch(ms, msg);
#endif
	default:
		LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",
			rllh->chan_nr);
		return -EINVAL;
	}
}
Beispiel #20
0
static int rslms_rx_udata_ind(struct msgb *msg, struct osmocom_ms *ms)
{
	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
	struct tlv_parsed tv;
	int rc = 0;
	
	DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
		rllh->chan_nr, rllh->link_id);

	rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
	if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
		DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
		return -EIO;
	}
	msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);

	if (rllh->chan_nr == RSL_CHAN_PCH_AGCH) {
		rc = gsm48_rx_ccch(msg, ms);
	} else if (rllh->chan_nr == RSL_CHAN_BCCH) {
		rc = gsm48_rx_bcch(msg, ms);
	}

	return rc;
}
static int unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
{
	struct abis_rsl_rll_hdr *rllh = msgb_l2(msg);
	struct tlv_parsed tv;
	uint8_t ch_type, ch_subch, ch_ts;

	DEBUGP(DRSL, "RSLms UNIT DATA IND chan_nr=0x%02x link_id=0x%02x\n",
		rllh->chan_nr, rllh->link_id);

	rsl_tlv_parse(&tv, rllh->data, msgb_l2len(msg)-sizeof(*rllh));
	if (!TLVP_PRESENT(&tv, RSL_IE_L3_INFO)) {
		DEBUGP(DRSL, "UNIT_DATA_IND without L3 INFO ?!?\n");
		return -EIO;
	}
	msg->l3h = (uint8_t *) TLVP_VAL(&tv, RSL_IE_L3_INFO);

	rsl_dec_chan_nr(rllh->chan_nr, &ch_type, &ch_subch, &ch_ts);
	switch (ch_type) {
	case RSL_CHAN_BCCH:
		return bcch(ms, msg);
	default:
		return 0;
	}
}
Beispiel #22
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;
}
Beispiel #23
0
int oap_client_handle(struct oap_client_state *state,
		      const struct msgb *msg_rx, struct msgb **msg_tx)
{
	uint8_t *data = msgb_l2(msg_rx);
	size_t data_len = msgb_l2len(msg_rx);
	struct osmo_oap_message oap_msg = {0};
	int rc = 0;

	*msg_tx = NULL;

	OSMO_ASSERT(data);

	rc = osmo_oap_decode(&oap_msg, data, data_len);
	if (rc < 0) {
		LOGP(DLOAP, LOGL_ERROR,
		     "Decoding OAP message failed with error '%s' (%d)\n",
		     get_value_string(gsm48_gmm_cause_names, -rc), -rc);
		return -10;
	}

	switch (state->state) {
	case OAP_UNINITIALIZED:
		LOGP(DLOAP, LOGL_ERROR,
		     "Received OAP message %d, but the OAP client is"
		     " not initialized\n", oap_msg.message_type);
		return -ENOTCONN;
	case OAP_DISABLED:
		LOGP(DLOAP, LOGL_ERROR,
		     "Received OAP message %d, but the OAP client is"
		     " disabled\n", oap_msg.message_type);
		return -ENOTCONN;
	default:
		break;
	}

	switch (oap_msg.message_type) {
	case OAP_MSGT_CHALLENGE_REQUEST:
		return handle_challenge(state, &oap_msg, msg_tx);

	case OAP_MSGT_REGISTER_RESULT:
		/* successfully registered */
		state->state = OAP_REGISTERED;
		break;

	case OAP_MSGT_REGISTER_ERROR:
		LOGP(DLOAP, LOGL_ERROR,
		     "OAP registration failed\n");
		state->state = OAP_INITIALIZED;
		if (state->registration_failures < 3) {
			state->registration_failures ++;
			return oap_client_register(state, msg_tx);
		}
		return -11;

	case OAP_MSGT_REGISTER_REQUEST:
	case OAP_MSGT_CHALLENGE_RESULT:
		LOGP(DLOAP, LOGL_ERROR,
		     "Received invalid OAP message type for OAP client side: %d\n",
		     (int)oap_msg.message_type);
		return -12;

	default:
		LOGP(DLOAP, LOGL_ERROR,
		     "Unknown OAP message type: %d\n",
		     (int)oap_msg.message_type);
		return -13;
	}

	return 0;
}
Beispiel #24
0
int ipa_server_conn_ccm(struct ipa_server_conn *conn, struct msgb *msg)
{
	struct tlv_parsed tlvp;
	uint8_t msg_type = *(msg->l2h);
	struct ipaccess_unit unit_data = {};
	char *unitid;
	int len, rc;

	/* shared CCM handling on both server and client */
	rc = ipa_ccm_rcvmsg_base(msg, &conn->ofd);
	switch (rc) {
	case -1:
		/* error in IPA CCM processing */
		goto err;
	case 1:
		/* IPA CCM message that was handled in _base */
		return 0;
	case 0:
		/* IPA CCM message that we need to handle */
		break;
	default:
		/* Error */
		LOGIPA(conn, LOGL_ERROR, "Unexpected return from "
		     "ipa_ccm_rcvmsg_base: %d\n", rc);
		goto err;
	}

	switch (msg_type) {
	case IPAC_MSGT_ID_RESP:
		rc = ipa_ccm_id_resp_parse(&tlvp, (const uint8_t *)msg->l2h+1, msgb_l2len(msg)-1);
		if (rc < 0) {
			LOGIPA(conn, LOGL_ERROR, "IPA CCM RESPonse with "
				"malformed TLVs\n");
			goto err;
		}
		if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
			LOGIPA(conn, LOGL_ERROR, "IPA CCM RESP without "
				"unit ID\n");
			goto err;
		}
		len = TLVP_LEN(&tlvp, IPAC_IDTAG_UNIT);
		if (len < 1) {
			LOGIPA(conn, LOGL_ERROR, "IPA CCM RESP with short"
				"unit ID\n");
			goto err;
		}
		unitid = (char *) TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT);
		unitid[len-1] = '\0';
		ipa_parse_unitid(unitid, &unit_data);

		/* FIXME */
		rc = conn->ccm_cb(conn, msg, &tlvp, &unit_data);
		if (rc < 0)
			goto err;
		break;
	default:
		LOGIPA(conn, LOGL_ERROR, "Unknown IPA message type\n");
		break;
	}
	return 0;
err:
	/* in case of any error, we close the connection */
	ipa_server_conn_destroy(conn);
	return -1;
}
Beispiel #25
0
int ipa_msg_recv_buffered(int fd, struct msgb **rmsg, struct msgb **tmp_msg)
{
	struct msgb *msg = tmp_msg ? *tmp_msg : NULL;
	struct ipaccess_head *hh;
	int len, ret;
	int needed;

	if (msg == NULL) {
		msg = ipa_msg_alloc(0);
		if (msg == NULL) {
			ret = -ENOMEM;
			goto discard_msg;
		}
		msg->l1h = msg->tail;
	}

	if (msg->l2h == NULL) {
		/* first read our 3-byte header */
		needed = sizeof(*hh) - msg->len;
		ret = recv(fd, msg->tail, needed, 0);
		if (ret == 0)
		       goto discard_msg;

		if (ret < 0) {
			if (errno == EAGAIN || errno == EINTR)
				ret = 0;
			else {
				ret = -errno;
				goto discard_msg;
			}
		}

		msgb_put(msg, ret);

		if (ret < needed) {
			if (msg->len == 0) {
				ret = -EAGAIN;
				goto discard_msg;
			}

			LOGP(DLINP, LOGL_INFO,
			     "Received part of IPA message header (%d/%zu)\n",
			     msg->len, sizeof(*hh));
			if (!tmp_msg) {
				ret = -EIO;
				goto discard_msg;
			}
			*tmp_msg = msg;
			return -EAGAIN;
		}

		msg->l2h = msg->tail;
	}

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

	/* then read the length as specified in header */
	len = ntohs(hh->len);

	if (len < 0 || IPA_ALLOC_SIZE < len + sizeof(*hh)) {
		LOGP(DLINP, LOGL_ERROR, "bad message length of %d bytes, "
					"received %d bytes\n", len, msg->len);
		ret = -EIO;
		goto discard_msg;
	}

	needed = len - msgb_l2len(msg);

	if (needed > 0) {
		ret = recv(fd, msg->tail, needed, 0);

		if (ret == 0)
			goto discard_msg;

		if (ret < 0) {
			if (errno == EAGAIN || errno == EINTR)
				ret = 0;
			else {
				ret = -errno;
				goto discard_msg;
			}
		}

		msgb_put(msg, ret);

		if (ret < needed) {
			LOGP(DLINP, LOGL_INFO,
			     "Received part of IPA message L2 data (%d/%d)\n",
			    msgb_l2len(msg), len);
			if (!tmp_msg) {
				ret = -EIO;
				goto discard_msg;
			}
			*tmp_msg = msg;
			return -EAGAIN;
		}
	}

	ret = msgb_l2len(msg);

	if (ret == 0) {
		LOGP(DLINP, LOGL_INFO,
		     "Discarding IPA message without payload\n");
		ret = -EAGAIN;
		goto discard_msg;
	}

	if (tmp_msg)
		*tmp_msg = NULL;
	*rmsg = msg;
	return ret;

discard_msg:
	if (tmp_msg)
		*tmp_msg = NULL;
	msgb_free(msg);
	return ret;
}