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; }
static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { struct msgb *msg; uint8_t amr_if2_len = payload_len - 2; uint8_t *cur; msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); if (!msg) return NULL; cur = msgb_put(msg, amr_if2_len); memcpy(cur, l1_payload+2, amr_if2_len); /* * Audiocode's MGW doesn't like receiving CMRs that are not * the same as the previous one. This means we need to patch * the content here. */ if ((cur[0] & 0xF0) == 0xF0) cur[0]= lchan->tch.last_cmr << 4; else lchan->tch.last_cmr = cur[0] >> 4; return msg; }
/* data has arrived on the udp socket */ static int udp_read_cb(struct osmo_fd *ofd) { struct msgb *msg = msgb_alloc_headroom(SYSMOBTS_PRIM_SIZE, 128, "udp_rx"); struct l1fwd_hdl *l1fh = ofd->data; struct femtol1_hdl *fl1h = l1fh->fl1h; int rc; if (!msg) return -ENOMEM; msg->l1h = msg->data; l1fh->remote_sa_len[ofd->priv_nr] = sizeof(l1fh->remote_sa[ofd->priv_nr]); rc = recvfrom(ofd->fd, msg->l1h, msgb_tailroom(msg), 0, (struct sockaddr *) &l1fh->remote_sa[ofd->priv_nr], &l1fh->remote_sa_len[ofd->priv_nr]); if (rc < 0) { perror("read from udp"); msgb_free(msg); return rc; } else if (rc == 0) { perror("len=0 read from udp"); msgb_free(msg); return rc; } msgb_put(msg, rc); DEBUGP(DL1C, "UDP: Received %u bytes for queue %d\n", rc, ofd->priv_nr); /* put the message into the right queue */ rc = osmo_wqueue_enqueue(&fl1h->write_q[ofd->priv_nr], msg); return rc; }
struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg) { struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); OSMO_ASSERT(msg); osmo_oap_encode(msg, oap_msg); return msg; }
static struct msgb *msgb_from_array(const uint8_t *data, int len) { struct msgb *msg = msgb_alloc_headroom(4096, 128, "data"); msg->l3h = msgb_put(msg, len); memcpy(msg->l3h, data, len); return msg; }
struct msgb *m3ua_msgb_alloc(const char *name) { if (!name) name = "M3UA"; return msgb_alloc_headroom(M3UA_MSG_SIZE+M3UA_MSG_HEADROOM, M3UA_MSG_HEADROOM, name); }
static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { struct msgb *msg; uint8_t *cur; msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); if (!msg) return NULL; #ifdef USE_L1_RTP_MODE /* new L1 can deliver bits like we need them */ cur = msgb_put(msg, GSM_EFR_BYTES); memcpy(cur, l1_payload, GSM_EFR_BYTES); #else /* step1: reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, payload_len); cur = msgb_put(msg, GSM_EFR_BYTES); /* step 2: we need to shift the entire L1 payload by 4 bits right */ osmo_nibble_shift_right(cur, l1_payload, GSM_EFR_BITS/4); cur[0] |= 0xC0; #endif /* USE_L1_RTP_MODE */ enum osmo_amr_type ft; enum osmo_amr_quality bfi; uint8_t cmr; int8_t sti, cmi; osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan); return msg; }
static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { struct msgb *msg; uint8_t *cur; msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); if (!msg) return NULL; if (payload_len != GSM_HR_BYTES) { LOGP(DL1C, LOGL_ERROR, "L1 HR frame length %u != expected %u\n", payload_len, GSM_HR_BYTES); return NULL; } cur = msgb_put(msg, GSM_HR_BYTES); memcpy(cur, l1_payload, GSM_HR_BYTES); #ifndef USE_L1_RTP_MODE /* reverse the bit-order of each payload byte */ osmo_revbytebits_buf(cur, GSM_HR_BYTES); #endif /* USE_L1_RTP_MODE */ lchan_set_marker(osmo_hr_check_sid(l1_payload, payload_len), lchan); return msg; }
int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr, const uint8_t *phys_conf, unsigned int phys_conf_len) { struct msgb *msg; if (trx->ipaccess.test_state != IPAC_TEST_S_IDLE) { fprintf(stderr, "Cannot start test in state %u\n", trx->ipaccess.test_state); return -EINVAL; } switch (testnr) { case NM_IPACC_TESTNO_CHAN_USAGE: case NM_IPACC_TESTNO_BCCH_CHAN_USAGE: rxlev_stat_reset(&trx->ipaccess.rxlev_stat); break; } msg = msgb_alloc_headroom(phys_conf_len+256, 128, "OML"); if (phys_conf && phys_conf_len) { uint8_t *payload; /* first put the phys conf header */ msgb_tv16_put(msg, NM_ATT_PHYS_CONF, phys_conf_len); payload = msgb_put(msg, phys_conf_len); memcpy(payload, phys_conf, phys_conf_len); } abis_nm_perform_test(trx->bts, NM_OC_RADIO_CARRIER, 0, trx->nr, 0xff, testnr, 1, msg); trx->ipaccess.test_nr = testnr; /* FIXME: start safety timer until when test is supposed to complete */ return 0; }
static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { struct msgb *msg; uint8_t *cur; msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP"); if (!msg) return NULL; #ifdef USE_L1_RTP_MODE /* new L1 can deliver bits like we need them */ cur = msgb_put(msg, GSM_FR_BYTES); memcpy(cur, l1_payload, GSM_FR_BYTES); #else /* step1: reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, payload_len); cur = msgb_put(msg, GSM_FR_BYTES); /* step2: we need to shift the entire L1 payload by 4 bits right */ osmo_nibble_shift_right(cur, l1_payload, GSM_FR_BITS/4); cur[0] |= 0xD0; #endif /* USE_L1_RTP_MODE */ lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan); return msg; }
/* Called whenever we recive a DATA packet */ static int cb_data_ind(struct pdp_t *lib, void *packet, unsigned int len) { struct bssgp_paging_info pinfo; struct sgsn_pdp_ctx *pdp; struct sgsn_mm_ctx *mm; struct msgb *msg; uint8_t *ud; int rc; DEBUGP(DGPRS, "GTP DATA IND from GGSN, length=%u\n", len); pdp = lib->priv; if (!pdp) { DEBUGP(DGPRS, "GTP DATA IND from GGSN for unknown PDP\n"); return -EIO; } mm = pdp->mm; msg = msgb_alloc_headroom(len+256, 128, "GTP->SNDCP"); ud = msgb_put(msg, len); memcpy(ud, packet, len); msgb_tlli(msg) = mm->tlli; msgb_bvci(msg) = mm->bvci; msgb_nsei(msg) = mm->nsei; switch (mm->mm_state) { case GMM_REGISTERED_SUSPENDED: /* initiate PS PAGING procedure */ memset(&pinfo, 0, sizeof(pinfo)); pinfo.mode = BSSGP_PAGING_PS; pinfo.scope = BSSGP_PAGING_BVCI; pinfo.bvci = mm->bvci; pinfo.imsi = mm->imsi; pinfo.ptmsi = &mm->p_tmsi; pinfo.drx_params = mm->drx_parms; pinfo.qos[0] = 0; // FIXME rc = gprs_bssgp_tx_paging(mm->nsei, 0, &pinfo); rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PAGING_PS]); /* FIXME: queue the packet we received from GTP */ break; case GMM_REGISTERED_NORMAL: break; default: LOGP(DGPRS, LOGL_ERROR, "GTP DATA IND for TLLI %08X in state " "%u\n", mm->tlli, mm->mm_state); msgb_free(msg); return -1; } rate_ctr_inc(&pdp->ctrg->ctr[PDP_CTR_PKTS_UDATA_OUT]); rate_ctr_add(&pdp->ctrg->ctr[PDP_CTR_BYTES_UDATA_OUT], len); rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_UDATA_OUT]); rate_ctr_add(&mm->ctrg->ctr[GMM_CTR_BYTES_UDATA_OUT], len); return sndcp_unitdata_req(msg, &mm->llme->lle[pdp->sapi], pdp->nsapi, mm); }
struct msgb *gsm411_msgb_alloc(void){ struct msgb *msg; msg = msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM, "GSM 04.11"); if (!msg) return NULL; return msg; }
static struct msgb *create_auep2() { struct msgb *msg; msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); int len = sprintf((char *)msg->data, "AUEP 18983213 ds/e1-2/[email protected] MGCP 1.0\r\n"); msg->l2h = msgb_put(msg, len); return msg; }
static struct msgb *create_msg(const char *str) { struct msgb *msg; msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); int len = sprintf((char *)msg->data, str); msg->l2h = msgb_put(msg, len); return msg; }
static struct msgb *mgcp_msgb_alloc(void) { struct msgb *msg; msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); if (!msg) LOGP(DMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n"); return msg; }
struct msgb *bssgp_msgb_alloc(void) { struct msgb *msg = msgb_alloc_headroom(4096, 128, "BSSGP"); /* TODO: Add handling of msg == NULL to this function and to all callers */ OSMO_ASSERT(msg != NULL); msgb_bssgph(msg) = msg->data; return msg; }
static void start_rach(void) { struct gsm48_sysinfo *s = &sysinfo; uint8_t chan_req_val, chan_req_mask; struct msgb *nmsg; struct abis_rsl_cchan_hdr *ncch; if (rach_count == RACH_MAX) { log_sysinfo(); start_sync(); return; } state = SCAN_STATE_RACH; if (s->neci) { chan_req_mask = 0x0f; chan_req_val = 0x01; LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x " "(OTHER with NECI)\n", chan_req_val); } else { chan_req_mask = 0x1f; chan_req_val = 0xe0; LOGP(DRR, LOGL_INFO, "CHANNEL REQUEST: %02x (OTHER no NECI)\n", chan_req_val); } rach_ref.valid = 0; rach_ref.cr = random(); rach_ref.cr &= chan_req_mask; rach_ref.cr |= chan_req_val; nmsg = msgb_alloc_headroom(RSL_ALLOC_SIZE+RSL_ALLOC_HEADROOM, RSL_ALLOC_HEADROOM, "GSM 04.06 RSL"); if (!nmsg) return; nmsg->l2h = nmsg->data; ncch = (struct abis_rsl_cchan_hdr *) msgb_put(nmsg, sizeof(*ncch) + 4 + 2 + 2); rsl_init_cchan_hdr(ncch, RSL_MT_CHAN_RQD); ncch->chan_nr = RSL_CHAN_RACH; ncch->data[0] = RSL_IE_REQ_REFERENCE; ncch->data[1] = rach_ref.cr; ncch->data[2] = (s->ccch_conf == 1) << 7; ncch->data[3] = 0; ncch->data[4] = RSL_IE_ACCESS_DELAY; ncch->data[5] = 0; /* no delay */ ncch->data[6] = RSL_IE_MS_POWER; ncch->data[7] = 0; /* full power */ start_timer(RACH_WAIT); lapdm_rslms_recvmsg(nmsg, &ms->lapdm_channel); }
struct msgb *gsm48_l3_msgb_alloc(void) { struct msgb *msg; msg = msgb_alloc_headroom(L3_ALLOC_SIZE+L3_ALLOC_HEADROOM, L3_ALLOC_HEADROOM, "GSM 04.08 L3"); if (!msg) return NULL; msg->l3h = msg->data; return msg; }
struct msgb *ipa_msg_alloc(int headroom) { struct msgb *nmsg; headroom += sizeof(struct ipaccess_head); nmsg = msgb_alloc_headroom(1200 + headroom, headroom, "Abis/IP"); if (!nmsg) return NULL; return nmsg; }
/* * send voice */ int gsm_send_voice(struct osmocom_ms *ms, struct gsm_data_frame *data) { struct msgb *nmsg; nmsg = msgb_alloc_headroom(33 + 64, 64, "TCH/F"); if (!nmsg) return -ENOMEM; nmsg->l2h = msgb_put(nmsg, 33); memcpy(nmsg->l2h, data->data, 33); return gsm48_rr_tx_voice(ms, nmsg); }
static void ussd_pong(struct bsc_nat_ussd_con *conn) { struct msgb *msg; msg = msgb_alloc_headroom(4096, 128, "pong message"); if (!msg) { LOGP(DNAT, LOGL_ERROR, "Failed to allocate pong msg\n"); return; } msgb_v_put(msg, IPAC_MSGT_PONG); bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS); }
/** * @brief Allocates a msgb with set l1ctl header and room for a l3 header. * * @param [in] msg_type L1CTL primitive message type set to l1ctl_hdr. * @return the allocated message. * * The message looks as follows: * # headers * [l1ctl_hdr] : initialized. msgb->l1h points here * [spare-bytes] : L3_MSG_HEAD bytes reserved for l3 header * # data * [spare-bytes] : L3_MSG_DATA bytes reserved for data. msgb->tail points here. msgb->data points here. */ struct msgb *l1ctl_msgb_alloc(uint8_t msg_type) { struct msgb *msg; struct l1ctl_hdr *l1h; msg = msgb_alloc_headroom(L3_MSG_SIZE, L3_MSG_HEAD, "l1ctl"); OSMO_ASSERT(msg); l1h = (struct l1ctl_hdr *) msgb_put(msg, sizeof(*l1h)); l1h->msg_type = msg_type; l1h->flags = 0; msg->l1h = (uint8_t *)l1h; return msg; }
static void ussd_start_auth(struct bsc_nat_ussd_con *conn) { struct msgb *msg; conn->auth_timeout.data = conn; conn->auth_timeout.cb = ussd_auth_cb; osmo_timer_schedule(&conn->auth_timeout, conn->nat->auth_timeout, 0); msg = msgb_alloc_headroom(4096, 128, "auth message"); if (!msg) { LOGP(DNAT, LOGL_ERROR, "Failed to allocate auth msg\n"); return; } msgb_v_put(msg, IPAC_MSGT_ID_GET); bsc_do_write(&conn->queue, msg, IPAC_PROTO_IPACCESS); }
static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { struct msgb *msg; uint8_t *cur; msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); if (!msg) return NULL; /* new L1 can deliver bits like we need them */ cur = msgb_put(msg, GSM_FR_BYTES); memcpy(cur, l1_payload, GSM_FR_BYTES); lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan); return msg; }
/* callback when there's something to read from the l1 msg_queue */ static int l1if_fd_cb(struct osmo_fd *ofd, unsigned int what) { //struct msgb *msg = l1p_msgb_alloc(); struct msgb *msg = msgb_alloc_headroom(sizeof(SuperFemto_Prim_t) + 128, 128, "1l_fd"); struct femtol1_hdl *fl1h = ofd->data; int rc; msg->l1h = msg->data; rc = read(ofd->fd, msg->l1h, msgb_tailroom(msg)); if (rc < 0) { if (rc != -1) LOGP(DL1IF, LOGL_ERROR, "error reading from L1 msg_queue: %s\n", strerror(errno)); msgb_free(msg); return rc; } msgb_put(msg, rc); switch (ofd->priv_nr) { case MQ_SYS_WRITE: if (rc != sizeof(SuperFemto_Prim_t)) LOGP(DL1IF, LOGL_NOTICE, "%u != " "sizeof(SuperFemto_Prim_t)\n", rc); return l1if_handle_sysprim(fl1h, msg); case MQ_L1_WRITE: #ifndef HW_SYSMOBTS_V1 case MQ_TCH_WRITE: case MQ_PDTCH_WRITE: #endif if (rc != sizeof(GsmL1_Prim_t)) LOGP(DL1IF, LOGL_NOTICE, "%u != " "sizeof(GsmL1_Prim_t)\n", rc); return l1if_handle_l1prim(ofd->priv_nr, fl1h, msg); default: /* The compiler can't know that priv_nr is an enum. Assist. */ LOGP(DL1IF, LOGL_FATAL, "writing on a wrong queue: %d\n", ofd->priv_nr); exit(0); break; } };
/* send location updating request * (as part of RSLms EST IND / LAPDm SABME) */ static int gsm48_tx_loc_upd_req(struct osmocom_ms *ms, uint8_t chan_nr) { struct msgb *msg = msgb_alloc_headroom(256, 16, "loc_upd_req"); struct gsm48_hdr *gh; struct gsm48_loc_upd_req *lu_r; DEBUGP(DMM, "chan_nr=%u\n", chan_nr); msg->l3h = msgb_put(msg, sizeof(*gh)); gh = (struct gsm48_hdr *) msg->l3h; gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_LOC_UPD_REQUEST; lu_r = (struct gsm48_loc_upd_req *) msgb_put(msg, sizeof(*lu_r)); lu_r->type = GSM48_LUPD_IMSI_ATT; lu_r->key_seq = 0; /* FIXME: set LAI and CM1 */ /* FIXME: set MI */ lu_r->mi_len = 0; return rslms_tx_rll_req_l3(ms, RSL_MT_EST_REQ, chan_nr, 0, 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; }
struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len) { struct msgb *msg; if (!token) { LOGP(DMSC, LOGL_ERROR, "No token specified.\n"); return NULL; } msg = msgb_alloc_headroom(4096, 128, "id resp"); if (!msg) { LOGP(DMSC, LOGL_ERROR, "Failed to create the message.\n"); return NULL; } /* * The situation is bizarre. The encoding doesn't follow the * TLV structure. It is more like a LV and old versions had * it wrong but we want new versions to old servers so we * introduce the quirk here. */ msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP); if (fixed) { msgb_put_u8(msg, 0); msgb_put_u8(msg, strlen(token) + 2); msgb_tv_fixed_put(msg, IPAC_IDTAG_UNITNAME, strlen(token) + 1, (uint8_t *) token); if (len > 0) { msgb_put_u8(msg, 0); msgb_put_u8(msg, len + 1); msgb_tv_fixed_put(msg, 0x24, len, res); } } else { msgb_l16tv_put(msg, strlen(token) + 1, IPAC_IDTAG_UNITNAME, (uint8_t *) token); } return msg; }
static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, uint8_t payload_len, struct gsm_lchan *lchan) { struct msgb *msg; uint8_t *cur; msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP"); if (!msg) return NULL; /* new L1 can deliver bits like we need them */ cur = msgb_put(msg, GSM_EFR_BYTES); memcpy(cur, l1_payload, GSM_EFR_BYTES); enum osmo_amr_type ft; enum osmo_amr_quality bfi; uint8_t cmr; int8_t sti, cmi; osmo_amr_rtp_dec(l1_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); lchan_set_marker(ft == AMR_GSM_EFR_SID, lchan); return msg; }
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; }