Exemple #1
0
/**
 * Return 0 in case the IPA structure is okay and in this
 * case the l2h will be set to the beginning of the data.
 */
int msg_verify_ipa_structure(struct msgb *msg)
{
	struct ipaccess_head *hh;

	if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
		LOGP(DL1C, LOGL_ERROR,
			"Ipa header insufficient space %d %d\n",
			msgb_l1len(msg), sizeof(struct ipaccess_head));
		return -1;
	}

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

	if (hh->proto != IPAC_PROTO_OML) {
		LOGP(DL1C, LOGL_ERROR,
			"Incorrect ipa header protocol 0x%x 0x%x\n",
			hh->proto, IPAC_PROTO_OML);
		return -1;
	}

	if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
		LOGP(DL1C, LOGL_ERROR,
			"Incorrect ipa header msg size %d %d\n",
			ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
		return -1;
	}

	msg->l2h = hh->data;
	return 0;
}
Exemple #2
0
/**
 * Return 0 in case the IPA structure is okay and in this
 * case the l2h will be set to the beginning of the data.
 */
int msg_verify_ipa_structure(struct msgb *msg)
{
	struct ipaccess_head *hh;

	if (msgb_l1len(msg) < sizeof(struct ipaccess_head)) {
		LOGP(DL1C, LOGL_ERROR,
			"Ipa header insufficient space %d %zu\n",
			msgb_l1len(msg), sizeof(struct ipaccess_head));
		return -1;
	}

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

	if (ntohs(hh->len) != msgb_l1len(msg) - sizeof(struct ipaccess_head)) {
		LOGP(DL1C, LOGL_ERROR,
			"Incorrect ipa header msg size %d %zu\n",
			ntohs(hh->len), msgb_l1len(msg) - sizeof(struct ipaccess_head));
		return -1;
	}

	if (hh->proto == IPAC_PROTO_OSMO) {
		struct ipaccess_head_ext *hh_ext = (struct ipaccess_head_ext *) hh->data;
		if (ntohs(hh->len) < sizeof(*hh_ext)) {
			LOGP(DL1C, LOGL_ERROR, "IPA length shorter than OSMO header\n");
			return -1;
		}
		msg->l2h = hh_ext->data;
	} else
		msg->l2h = hh->data;

	return 0;
}
Exemple #3
0
/* callback when we can write to the UDP socket */
static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg)
{
	int rc;
	struct l1fwd_hdl *l1fh = ofd->data;

	DEBUGP(DL1C, "UDP: Writing %u bytes for queue %d\n", msgb_l1len(msg),
		ofd->priv_nr);

	rc = sendto(ofd->fd, msg->l1h, msgb_l1len(msg), 0,
		    (const struct sockaddr *)&l1fh->remote_sa[ofd->priv_nr], l1fh->remote_sa_len[ofd->priv_nr]);
	if (rc < 0) {
		LOGP(DL1C, LOGL_ERROR, "error writing to L1 msg_queue: %s\n",
			strerror(errno));
		return rc;
	} else if (rc < msgb_l1len(msg)) {
		LOGP(DL1C, LOGL_ERROR, "short write to L1 msg_queue: "
			"%u < %u\n", rc, msgb_l1len(msg));
		return -EIO;
	}

	return 0;
}
Exemple #4
0
static void rx_resrc(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
	struct msgb *msg = tmvp->oph.msg;
	struct tetra_resrc_decoded rsd;
	int tmpdu_offset;

	memset(&rsd, 0, sizeof(rsd));
	tmpdu_offset = macpdu_decode_resource(&rsd, msg->l1h);
	msg->l2h = msg->l1h + tmpdu_offset;

	printf("RESOURCE Encr=%u, Length=%d Addr=%s ",
		rsd.encryption_mode, rsd.macpdu_length,
		tetra_addr_dump(&rsd.addr));

	if (rsd.addr.type == ADDR_TYPE_NULL)
		goto out;

	if (rsd.chan_alloc_pres)
		printf("ChanAlloc=%s ", tetra_alloc_dump(&rsd.cad, tms));

	if (rsd.slot_granting.pres)
		printf("SlotGrant=%u/%u ", rsd.slot_granting.nr_slots,
			rsd.slot_granting.delay);

	if (rsd.macpdu_length > 0 && rsd.encryption_mode == 0) {
		int len_bits = rsd.macpdu_length*8;
		if (msg->l2h + len_bits > msg->l1h + msgb_l1len(msg))
			len_bits = msgb_l1len(msg) - tmpdu_offset;
		rx_tm_sdu(tms, msg, len_bits);
	}

  ssi = rsd.addr.ssi;

out:
	printf("\n");
}
Exemple #5
0
/* callback when we can write to one of the l1 msg_queue devices */
static int l1fd_write_cb(struct osmo_fd *ofd, struct msgb *msg)
{
	int rc;

	rc = write(ofd->fd, msg->l1h, msgb_l1len(msg));
	if (rc < 0) {
		LOGP(DL1IF, LOGL_ERROR, "error writing to L1 msg_queue: %s\n",
			strerror(errno));
		return rc;
	} else if (rc < msg->len) {
		LOGP(DL1IF, LOGL_ERROR, "short write to L1 msg_queue: "
			"%u < %u\n", rc, msg->len);
		return -EIO;
	}

	return 0;
}
Exemple #6
0
static int rx_tmv_unitdata_ind(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms)
{
	struct tmv_unitdata_param *tup = &tmvp->u.unitdata;
	struct msgb *msg = tmvp->oph.msg;
	uint8_t pdu_type = bits_to_uint(msg->l1h, 2);
	const char *pdu_name;
	struct msgb *gsmtap_msg;

	if (tup->lchan == TETRA_LC_BSCH)
		pdu_name = "SYNC";
	else if (tup->lchan == TETRA_LC_AACH)
		pdu_name = "ACCESS-ASSIGN";
	else {
		pdu_type = bits_to_uint(msg->l1h, 2);
		pdu_name = tetra_get_macpdu_name(pdu_type);
	}

	printf("TMV-UNITDATA.ind %s %s CRC=%u %s\n",
		tetra_tdma_time_dump(&tup->tdma_time),
		tetra_get_lchan_name(tup->lchan),
		tup->crc_ok, pdu_name);

	if (!tup->crc_ok)
		return 0;

	gsmtap_msg = tetra_gsmtap_makemsg(&tup->tdma_time, tup->lchan,
					  tup->tdma_time.tn,
					  /* FIXME: */ 0, 0, 0,
					msg->l1h, msgb_l1len(msg));
	if (gsmtap_msg)
		tetra_gsmtap_sendmsg(gsmtap_msg);

	switch (tup->lchan) {
	case TETRA_LC_AACH:
		rx_aach(tmvp, tms);
		break;
	case TETRA_LC_BNCH:
	case TETRA_LC_UNKNOWN:
	case TETRA_LC_SCH_F:
		switch (pdu_type) {
		case TETRA_PDU_T_BROADCAST:
			rx_bcast(tmvp, tms);
			break;
		case TETRA_PDU_T_MAC_RESOURCE:
			rx_resrc(tmvp, tms);
			break;
		case TETRA_PDU_T_MAC_SUPPL:
			rx_suppl(tmvp, tms);
			break;
		case TETRA_PDU_T_MAC_FRAG_END:
			if (msg->l1h[3] == TETRA_MAC_FRAGE_FRAG) {
				printf("FRAG/END FRAG: ");
				msg->l2h = msg->l1h+4;
				rx_tm_sdu(tms, msg, 100 /*FIXME*/);
				printf("\n");
			} else
				printf("FRAG/END END\n");
			break;
		default:
			printf("STRANGE pdu=%u\n", pdu_type);
			break;
		}
		break;
	case TETRA_LC_BSCH:
		break;
	default:
		printf("STRANGE lchan=%u\n", tup->lchan);
		break;
	}

	return 0;
}