/** * 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; }
/** * 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; }
/* 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; }
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"); }
/* 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; }
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; }