示例#1
0
static void test_wqueue_limit(void)
{
	struct msgb *msg;
	struct osmo_wqueue wqueue;
	int rc;

	osmo_wqueue_init(&wqueue, 0);
	OSMO_ASSERT(wqueue.max_length == 0);
	OSMO_ASSERT(wqueue.current_length == 0);
	OSMO_ASSERT(wqueue.read_cb == NULL);
	OSMO_ASSERT(wqueue.write_cb == NULL);
	OSMO_ASSERT(wqueue.except_cb == NULL);

	/* try to add and fail */
	msg = msgb_alloc(4096, "msg1");
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc < 0);

	/* add one and fail on the second */
	wqueue.max_length = 1;
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc == 0);
	OSMO_ASSERT(wqueue.current_length == 1);
	msg = msgb_alloc(4096, "msg2");
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc < 0);

	/* add one more */
	wqueue.max_length = 2;
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc == 0);
	OSMO_ASSERT(wqueue.current_length == 2);

	/* release everything */
	osmo_wqueue_clear(&wqueue);
	OSMO_ASSERT(wqueue.current_length == 0);
	OSMO_ASSERT(wqueue.max_length == 2);

	/* Add two, fail on the third, free it and the queue */
	msg = msgb_alloc(4096, "msg3");
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc == 0);
	OSMO_ASSERT(wqueue.current_length == 1);
	msg = msgb_alloc(4096, "msg4");
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc == 0);
	OSMO_ASSERT(wqueue.current_length == 2);
	msg = msgb_alloc(4096, "msg5");
	rc = osmo_wqueue_enqueue(&wqueue, msg);
	OSMO_ASSERT(rc < 0);
	OSMO_ASSERT(wqueue.current_length == 2);
	msgb_free(msg);
	osmo_wqueue_clear(&wqueue);
}
示例#2
0
/*! \brief Copy an msgb.
 *
 *  This function allocates a new msgb, copies the data buffer of msg,
 *  and adjusts the pointers (incl l1h-l4h) accordingly. The cb part
 *  is not copied.
 *  \param[in] msg  The old msgb object
 *  \param[in] name Human-readable name to be associated with msgb
 */
struct msgb *msgb_copy(const struct msgb *msg, const char *name)
{
	struct msgb *new_msg;

	new_msg = msgb_alloc(msg->data_len, name);
	if (!new_msg)
		return NULL;

	/* copy data */
	memcpy(new_msg->_data, msg->_data, new_msg->data_len);

	/* copy header */
	new_msg->len = msg->len;
	new_msg->data += msg->data - msg->_data;
	new_msg->head += msg->head - msg->_data;
	new_msg->tail += msg->tail - msg->_data;

	if (msg->l1h)
		new_msg->l1h = new_msg->_data + (msg->l1h - msg->_data);
	if (msg->l2h)
		new_msg->l2h = new_msg->_data + (msg->l2h - msg->_data);
	if (msg->l3h)
		new_msg->l3h = new_msg->_data + (msg->l3h - msg->_data);
	if (msg->l4h)
		new_msg->l4h = new_msg->_data + (msg->l4h - msg->_data);

	return new_msg;
}
示例#3
0
/* receive a message from L1/L2 and put it in GSMTAP */
struct msgb *gsmtap_makemsg(uint16_t arfcn, uint8_t ts, uint8_t chan_type,
			    uint8_t ss, uint32_t fn, int8_t signal_dbm,
			    uint8_t snr, const uint8_t *data, unsigned int len)
{
	struct msgb *msg;
	struct gsmtap_hdr *gh;
	uint8_t *dst;

	msg = msgb_alloc(sizeof(*gh) + len, "gsmtap_tx");
	if (!msg)
		return NULL;

	gh = (struct gsmtap_hdr *) msgb_put(msg, sizeof(*gh));

	gh->version = GSMTAP_VERSION;
	gh->hdr_len = sizeof(*gh)/4;
	gh->type = GSMTAP_TYPE_UM;
	gh->timeslot = ts;
	gh->sub_slot = ss;
	gh->arfcn = htons(arfcn);
	gh->snr_db = snr;
	gh->signal_dbm = signal_dbm;
	gh->frame_number = htonl(fn);
	gh->sub_type = chan_type;
	gh->antenna_nr = 0;

	dst = msgb_put(msg, len);
	memcpy(dst, data, len);

	return msg;
}
示例#4
0
static int read_cb(struct osmo_rs232 *r)
{
	struct msgb *msg;

	LOGP(DRS232TEST, LOGL_DEBUG, "received data from rs232\n");

	msg = msgb_alloc(1024, "rs232/test");
	if (msg == NULL) {
		LOGP(DRS232TEST, LOGL_ERROR, "cannot allocate message\n");
		return 0;
	}
	if (osmo_rs232_read(r, msg) < 0) {
		LOGP(DRS232TEST, LOGL_ERROR, "cannot receive message\n");
		return 0;
	}
	LOGP(DRS232TEST, LOGL_DEBUG, "received %d bytes\n", msg->len);

	printf("received %d bytes ", msg->len);

	int i;
	printf("(");
	for (i=0; i<msg->len; i++)
		printf("\\x%.2x", 0xff & msg->data[i]);
	printf(") %s\n", msg->data);

	msgb_free(msg);

	return 0;
}
示例#5
0
/* allocate a msgb containing a Litecell15_Prim_t */
struct msgb *sysp_msgb_alloc(void)
{
	struct msgb *msg = msgb_alloc(sizeof(Litecell15_Prim_t), "sys_prim");

	if (msg)
		msg->l1h = msgb_put(msg, sizeof(Litecell15_Prim_t));

	return msg;
}
示例#6
0
/* allocate a msgb containing a GsmL1_Prim_t */
struct msgb *l1p_msgb_alloc(void)
{
	struct msgb *msg = msgb_alloc(sizeof(GsmL1_Prim_t), "l1_prim");

	if (msg)
		msg->l1h = msgb_put(msg, sizeof(GsmL1_Prim_t));

	return msg;
}
示例#7
0
static void
loader_send_simple(uint8_t command) {
	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
	msgb_put_u8(msg, command);
	loader_send_request(msg);
	msgb_free(msg);

	osmoload.command = command;
}
示例#8
0
static void
loader_start_jump(uint32_t address) {
	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
	msgb_put_u8(msg, LOADER_JUMP);
	msgb_put_u32(msg, address);
	loader_send_request(msg);
	msgb_free(msg);

	osmoload.state = STATE_QUERY_PENDING;
	osmoload.command = LOADER_JUMP;
}
示例#9
0
static void
loader_send_flash_query(uint8_t command, uint8_t chip, uint32_t address) {
	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
	msgb_put_u8(msg, command);
	msgb_put_u8(msg, chip);
	msgb_put_u32(msg, address);
	loader_send_request(msg);
	msgb_free(msg);

	osmoload.command = command;
}
示例#10
0
static void
loader_start_memget(uint8_t length, uint32_t address) {
	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
	msgb_put_u8(msg, LOADER_MEM_READ);
	msgb_put_u8(msg, length);
	msgb_put_u32(msg, address);
	loader_send_request(msg);
	msgb_free(msg);

	osmoload.state = STATE_QUERY_PENDING;
	osmoload.command = LOADER_MEM_READ;
}
示例#11
0
int main(void)
{
	struct tcp_client *c;
	struct tcp_conf conf = {
		.ipproto	= AF_INET,
		.port		= 1234,
		.client		= {
			.inet_addr	= { inet_addr("127.0.0.1") },
		},
	};
	struct nft_sync_hdr *hdr;
	struct msg_buff *msgb;
	char buf[1024];
	fd_set fds;

	msgb = msgb_alloc(NFTS_MAX_REQUEST);
	if (msgb == NULL) {
		perror("msgb_alloc");
		exit(EXIT_FAILURE);
	}

	hdr = msgb_put(msgb, sizeof(struct nft_sync_hdr) + strlen("fetch"));
	hdr->len = htonl(sizeof(struct nft_sync_hdr) + strlen("fetch"));
	memcpy(hdr->data, "fetch", strlen("fetch"));

	c = tcp_client_create(&conf);
	if (c == NULL) {
		fprintf(stderr, "cannot initialize TCP client\n");
		exit(EXIT_FAILURE);
	}

	FD_ZERO(&fds);
	FD_SET(tcp_client_get_fd(c), &fds);
	/* Wait for connection ... */
	select(tcp_client_get_fd(c) + 1, NULL, &fds, NULL, NULL);

	if (tcp_client_send(c, msgb_data(msgb), msgb_len(msgb)) < 0) {
		perror("cannot send to socket");
		exit(EXIT_FAILURE);
	}

	FD_ZERO(&fds);
	FD_SET(tcp_client_get_fd(c), &fds);
	/* Wait to receive data after sending request ... */
	select(tcp_client_get_fd(c) + 1, &fds, NULL, NULL, NULL);

	if (tcp_client_recv(c, buf, sizeof(buf)) < 0) {
		perror("cannot send to socket");
		exit(EXIT_FAILURE);
	}
	printf("[TEST OK] Received: %s\n", buf + sizeof(struct nft_sync_hdr));
	tcp_client_destroy(c);
}
示例#12
0
/* forward a RUA message to the SCCP User API to SCCP/SUA */
static int rua_to_scu(struct hnb_context *hnb, struct hnbgw_cnlink *cn,
		      enum osmo_scu_prim_type type,
		      uint32_t context_id, uint32_t cause,
		      const uint8_t *data, unsigned int len)
{
	struct msgb *msg = msgb_alloc(1500, "rua_to_sua");
	struct osmo_scu_prim *prim;
	struct hnbgw_context_map *map;
	int rc;

	if (!cn) {
		DEBUGP(DRUA, "CN=NULL, discarding message\n");
		return 0;
	}

	prim = (struct osmo_scu_prim *) msgb_put(msg, sizeof(*prim));
	osmo_prim_init(&prim->oph, SCCP_SAP_USER, type, PRIM_OP_REQUEST, msg);

	map = context_map_alloc_by_hnb(hnb, context_id, cn);

	/* add primitive header */
	switch (type) {
	case OSMO_SCU_PRIM_N_CONNECT:
		prim->u.connect.called_addr;
		prim->u.connect.calling_addr;
		prim->u.connect.sccp_class = 2;
		prim->u.connect.conn_id = map->scu_conn_id;
		break;
	case OSMO_SCU_PRIM_N_DATA:
		prim->u.data.conn_id = map->scu_conn_id;
		break;
	case OSMO_SCU_PRIM_N_DISCONNECT:
		prim->u.disconnect.conn_id = map->scu_conn_id;
		prim->u.disconnect.cause = cause;
		break;
	case OSMO_SCU_PRIM_N_UNITDATA:
		prim->u.unitdata.called_addr;
		prim->u.unitdata.calling_addr;
		break;
	default:
		return -EINVAL;
	}

	/* add optional data section, if needed */
	if (data && len) {
		msg->l2h = msgb_put(msg, len);
		memcpy(msg->l2h, data, len);
	}

	rc = osmo_sua_user_link_down(cn->sua_link, &prim->oph);

	return rc;
}
示例#13
0
static int test_bearer_cap()
{
	struct gsm_mncc_bearer_cap bc;
	int i, rc;

	for (i = 0; i < ARRAY_SIZE(bcap_tests); i++) {
		struct msgb *msg = msgb_alloc(100, "test");
		int lv_len;

		memset(&bc, 0, sizeof(bc));

		/* test decoding */
		rc = gsm48_decode_bearer_cap(&bc, bcap_tests[i].lv);
		if (rc < 0) {
			fprintf(stderr, "Error decoding %s\n",
				bcap_tests[i].name);
			return rc;
		}
		if (memcmp(&bc, bcap_tests[i].bc, sizeof(bc))) {
			fprintf(stderr, "Incorrect decoded result of %s:\n",
				bcap_tests[i].name);
			fprintf(stderr, " should: %s\n",
				osmo_hexdump((uint8_t *) bcap_tests[i].bc, sizeof(bc)));
			fprintf(stderr, " is:     %s\n",
				osmo_hexdump((uint8_t *) &bc, sizeof(bc)));
			return -1;
		}

		/* also test re-encode? */
		rc = gsm48_encode_bearer_cap(msg, 1, &bc);
		if (rc < 0) {
			fprintf(stderr, "Error encoding %s\n",
				bcap_tests[i].name);
			return rc;
		}
		lv_len = bcap_tests[i].lv[0]+1;
		if (memcmp(msg->data, bcap_tests[i].lv, lv_len)) {
			fprintf(stderr, "Incorrect encoded result of %s:\n",
				bcap_tests[i].name);
			fprintf(stderr, " should: %s\n",
				osmo_hexdump(bcap_tests[i].lv, lv_len));
			fprintf(stderr, " is:     %s\n",
				osmo_hexdump(msg->data, msg->len));
			return -1;
		}

		printf("Test `%s' passed\n", bcap_tests[i].name);
		msgb_free(msg);
	}

	return 0;
}
示例#14
0
static void
loader_do_memdump(uint16_t crc, void *data, size_t length) {
	int rc;

	if(data && length) {
		osmoload.memcrc = osmo_crc16(0, data, length);
		if(osmoload.memcrc != crc) {
			osmoload.memoff -= osmoload.memreq;
			printf("\nbad crc %4.4x (not %4.4x) at offset 0x%8.8x", crc, osmoload.memcrc, osmoload.memoff);
		} else {
			putchar('.');
		}

		memcpy(osmoload.binbuf + osmoload.memoff, data, length);
		osmoload.memoff += length;
	}

	uint32_t rembytes = osmoload.memlen - osmoload.memoff;

	if(!rembytes) {
		puts("done.");
		osmoload.quit = 1;

		unsigned c = osmoload.memlen;
		char *p = osmoload.binbuf;
		while(c) {
			rc = fwrite(p, 1, c, osmoload.binfile);
			if(ferror(osmoload.binfile)) {
				printf("Could not read from file: %s\n", strerror(errno));
				exit(1);
			}
			c -= rc;
			p += rc;
		}
		fclose(osmoload.binfile);
		osmoload.binfile = NULL;

		free(osmoload.binbuf);

		return;
	}

	uint8_t reqbytes = (rembytes < MEM_MSG_MAX) ? rembytes : MEM_MSG_MAX;

	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");

	msgb_put_u8(msg, LOADER_MEM_READ);
	msgb_put_u8(msg, reqbytes);
	msgb_put_u32(msg, osmoload.membase + osmoload.memoff);
	loader_send_request(msg);
	msgb_free(msg);
}
示例#15
0
static int fc_in(struct bssgp_flow_control *fc, unsigned int pdu_len)
{
	struct msgb *msg;
	unsigned int csecs = get_centisec_diff();
	csecs = round_decisec(csecs);

	msg = msgb_alloc(1, "fc test");
	msg->cb[0] = in_ctr++;

	printf("%u: FC IN Nr %lu\n", csecs, msg->cb[0]);
	bssgp_fc_in(fc, msg, pdu_len, NULL);
	return 0;
}
示例#16
0
static void
loader_start_memput(uint8_t length, uint32_t address, void *data) {
	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");
	msgb_put_u8(msg, LOADER_MEM_WRITE);
	msgb_put_u8(msg, length);
	msgb_put_u16(msg, osmo_crc16(0, data, length));
	msgb_put_u32(msg, address);
	memcpy(msgb_put(msg, length), data, length);
	loader_send_request(msg);
	msgb_free(msg);

	osmoload.state = STATE_QUERY_PENDING;
	osmoload.command = LOADER_MEM_WRITE;
}
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;
	}
}
示例#18
0
static int process_meas_rep(struct gsm_meas_rep *mr)
{
	struct msgb *msg;
	struct meas_feed_meas *mfm;
	struct gsm_subscriber *subscr;

	/* ignore measurements as long as we don't know who it is */
	if (!mr->lchan || !mr->lchan->conn || !mr->lchan->conn->subscr)
		return 0;

	subscr = mr->lchan->conn->subscr;

	msg = msgb_alloc(sizeof(struct meas_feed_meas), "Meas. Feed");
	if (!msg)
		return 0;

	/* fill in the header */
	mfm = (struct meas_feed_meas *) msgb_put(msg, sizeof(*mfm));
	mfm->hdr.msg_type = MEAS_FEED_MEAS;
	mfm->hdr.version = MEAS_FEED_VERSION;

	/* fill in MEAS_FEED_MEAS specific header */
	strncpy(mfm->imsi, subscr->imsi, sizeof(mfm->imsi)-1);
	mfm->imsi[sizeof(mfm->imsi)-1] = '\0';
	strncpy(mfm->name, subscr->name, sizeof(mfm->name)-1);
	mfm->name[sizeof(mfm->name)-1] = '\0';
	strncpy(mfm->scenario, g_mfs.scenario, sizeof(mfm->scenario));
	mfm->scenario[sizeof(mfm->scenario)-1] = '\0';

	/* copy the entire measurement report */
	memcpy(&mfm->mr, mr, sizeof(mfm->mr));

	/* copy channel information */
	/* we assume that the measurement report always belong to some timeslot */
	mfm->lchan_type = (uint8_t)mr->lchan->type;
	mfm->pchan_type = (uint8_t)mr->lchan->ts->pchan;
	mfm->bts_nr = mr->lchan->ts->trx->bts->nr;
	mfm->trx_nr = mr->lchan->ts->trx->nr;
	mfm->ts_nr = mr->lchan->ts->nr;
	mfm->ss_nr = mr->lchan->nr;

	/* and send it to the socket */
	if (osmo_wqueue_enqueue(&g_mfs.wqueue, msg) != 0)
		msgb_free(msg);

	return 0;
}
示例#19
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;
}
示例#20
0
static int pack_and_send(struct esme *esme, uint32_t type, void *ptr)
{
	struct msgb *msg = msgb_alloc(4096, "SMPP_Tx");
	int rc, rlen;
	if (!msg)
		return -ENOMEM;

	rc = smpp34_pack(type, msg->tail, msgb_tailroom(msg), &rlen, ptr);
	if (rc != 0) {
		LOGP(DSMPP, LOGL_ERROR, "[%s] Error during smpp34_pack(): %s\n",
		     esme->system_id, smpp34_strerror);
		msgb_free(msg);
		return -EINVAL;
	}
	msgb_put(msg, rlen);

	return osmo_wqueue_enqueue(&esme->wqueue, msg);
}
示例#21
0
static void
loader_do_fprogram() {
	uint32_t rembytes = osmoload.memlen - osmoload.memoff;

	if(!rembytes) {
		puts("done.");
		osmoload.quit = 1;
		return;
	}

	osmo_timer_schedule(&osmoload.timeout, 0, 10000000);

	uint8_t reqbytes = (rembytes < MEM_MSG_MAX) ? rembytes : MEM_MSG_MAX;

	osmoload.memcrc = osmo_crc16(0, (uint8_t *) osmoload.binbuf + osmoload.memoff, reqbytes);
	osmoload.memreq = reqbytes;

	struct msgb *msg = msgb_alloc(MSGB_MAX, "loader");

	msgb_put_u8(msg, LOADER_FLASH_PROGRAM);
	msgb_put_u8(msg, reqbytes);
	msgb_put_u16(msg, osmoload.memcrc);
	msgb_put_u8(msg, 0); // XXX: align data to 16bit
	msgb_put_u8(msg, osmoload.memchip);
	msgb_put_u32(msg, osmoload.membase + osmoload.memoff);

	unsigned char *p = msgb_put(msg, reqbytes);
	memcpy(p, osmoload.binbuf + osmoload.memoff, reqbytes);

#if 0
	printf("Sending %u bytes at offset %u to address %x with crc %x\n",
		   reqbytes, osmoload.memoff, osmoload.membase + osmoload.memoff,
		   osmoload.memcrc);
#endif

	loader_send_request(msg);

	msgb_free(msg);

	osmoload.memoff += reqbytes;
}
示例#22
0
/**
 * @brief L1CTL socket file descriptor callback function.
 *
 * @param ofd The osmocom file descriptor.
 * @param what Indicates if the fd has a read, write or exception request. See select.h.
 *
 * Will be called by osmo_select_main() if data on fd is pending.
 */
static int l1ctl_sock_data_cb(struct osmo_fd *ofd, unsigned int what)
{
	struct l1ctl_sock_client *lsc = ofd->data;
	struct l1ctl_hdr *l1h;
	struct msgb *msg;
	uint16_t len;
	int rc;

	/* Check if request is really read request */
	if (!(what & BSC_FD_READ))
		return 0;

	msg = msgb_alloc(L1CTL_SOCK_MSGB_SIZE, "L1CTL sock rx");

	/* read length of the message first and convert to host byte order */
	rc = read(ofd->fd, &len, sizeof(len));
	if (rc < sizeof(len))
		goto err_close;

	/* convert to host byte order */
	len = ntohs(len);
	if (len <= 0 || len > L1CTL_SOCK_MSGB_SIZE)
		goto err_close;

	rc = read(ofd->fd, msgb_data(msg), len);
	if (rc == len) {
		msgb_put(msg, rc);
		l1h = (void *) msgb_data(msg);
		msg->l1h = (void *) l1h;
		lsc->l1ctl_sock->recv_cb(lsc, msg);
		return 0;
	}
err_close:
	LOGP(DL1C, LOGL_ERROR, "Failed to receive msg from l2. Connection will be closed.\n");
	l1ctl_client_destroy(lsc);

	return 0;

}
示例#23
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;
}
int read_cb(struct osmo_dgram *conn)
{
	int error;
	struct msgb *msg;

	LOGP(DLAPDTEST, LOGL_DEBUG, "received message from datagram\n");

	msg = msgb_alloc(1200, "LAPD/test");
	if (msg == NULL) {
		LOGP(DLAPDTEST, LOGL_ERROR, "cannot allocate message\n");
		return -1;
	}
	if (osmo_dgram_recv(conn, msg) < 0) {
		LOGP(DLAPDTEST, LOGL_ERROR, "cannot receive message\n");
		return -1;
	}
	if (lapd_receive(lapd, msg, &error) < 0) {
		LOGP(DLAPDTEST, LOGL_ERROR, "lapd_receive returned error!\n");
		return -1;
	}

	return 0;
}
示例#25
0
static int pcu_sock_read(struct osmo_fd *bfd)
{
	struct pcu_sock_state *state = (struct pcu_sock_state *)bfd->data;
	struct gsm_pcu_if *pcu_prim;
	struct msgb *msg;
	int rc;

	msg = msgb_alloc(sizeof(*pcu_prim), "pcu_sock_rx");
	if (!msg)
		return -ENOMEM;

	pcu_prim = (struct gsm_pcu_if *) msg->tail;

	rc = recv(bfd->fd, msg->tail, msgb_tailroom(msg), 0);
	if (rc == 0)
		goto close;

	if (rc < 0) {
		if (errno == EAGAIN)
			return 0;
		goto close;
	}

	rc = pcu_rx(pcu_prim->msg_type, pcu_prim);

	/* as we always synchronously process the message in pcu_rx() and
	 * its callbacks, we can free the message here. */
	msgb_free(msg);

	return rc;

close:
	msgb_free(msg);
	pcu_sock_close(state, 1);
	return -1;
}
示例#26
0
/* FIXME: merge with smpp_smsc.c */
static int esme_read_cb(struct osmo_fd *ofd)
{
	struct esme *esme = ofd->data;
	uint32_t len;
	uint8_t *lenptr = (uint8_t *) &len;
	uint8_t *cur;
	struct msgb *msg;
	int rdlen;
	int rc;

	switch (esme->read_state) {
	case READ_ST_IN_LEN:
		rdlen = sizeof(uint32_t) - esme->read_idx;
		rc = read(ofd->fd, lenptr + esme->read_idx, rdlen);
		if (rc < 0) {
			LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %d\n",
			     esme->system_id, rc);
		} else if (rc == 0) {
			goto dead_socket;
		} else
			esme->read_idx += rc;
		if (esme->read_idx >= sizeof(uint32_t)) {
			esme->read_len = ntohl(len);
			msg = msgb_alloc(esme->read_len, "SMPP Rx");
			if (!msg)
				return -ENOMEM;
			esme->read_msg = msg;
			cur = msgb_put(msg, sizeof(uint32_t));
			memcpy(cur, lenptr, sizeof(uint32_t));
			esme->read_state = READ_ST_IN_MSG;
			esme->read_idx = sizeof(uint32_t);
		}
		break;
	case READ_ST_IN_MSG:
		msg = esme->read_msg;
		rdlen = esme->read_len - esme->read_idx;
		rc = read(ofd->fd, msg->tail, OSMO_MIN(rdlen, msgb_tailroom(msg)));
		if (rc < 0) {
			LOGP(DSMPP, LOGL_ERROR, "[%s] read returned %d\n",
				esme->system_id, rc);
		} else if (rc == 0) {
			goto dead_socket;
		} else {
			esme->read_idx += rc;
			msgb_put(msg, rc);
		}

		if (esme->read_idx >= esme->read_len) {
			rc = smpp_pdu_rx(esme, esme->read_msg);
			esme->read_msg = NULL;
			esme->read_idx = 0;
			esme->read_len = 0;
			esme->read_state = READ_ST_IN_LEN;
		}
		break;
	}

	return 0;
dead_socket:
	msgb_free(esme->read_msg);
	osmo_fd_unregister(&esme->wqueue.bfd);
	close(esme->wqueue.bfd.fd);
	esme->wqueue.bfd.fd = -1;
	exit(2342);

	return 0;
}
示例#27
0
/* read from incoming RTP/RTCP socket */
static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
{
	int rc;
	struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP");
	struct msgb *new_msg;
	struct rtp_sub_socket *other_rss;

	if (!msg)
		return -ENOMEM;

	rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE);
	if (rc <= 0) {
		rss->bfd.when &= ~BSC_FD_READ;
		return rc;
	}

	msgb_put(msg, rc);

	switch (rs->rx_action) {
	case RTP_PROXY:
		if (!rs->proxy.other_sock) {
			rc = -EIO;
			goto out_free;
		}
		if (rss->bfd.priv_nr == RTP_PRIV_RTP)
			other_rss = &rs->proxy.other_sock->rtp;
		else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
			other_rss = &rs->proxy.other_sock->rtcp;
			/* modify RTCP SDES CNAME */
			rc = rtcp_mangle(msg, rs);
			if (rc < 0)
				goto out_free;
		} else {
			rc = -EINVAL;
			goto out_free;
		}
		msgb_enqueue(&other_rss->tx_queue, msg);
		other_rss->bfd.when |= BSC_FD_WRITE;
		break;

	case RTP_RECV_UPSTREAM:
		if (!rs->receive.callref || !rs->receive.net) {
			rc = -EIO;
			goto out_free;
		}
		if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
			if (!mangle_rtcp_cname) {
				msgb_free(msg);
				break;
			}
			/* modify RTCP SDES CNAME */
			rc = rtcp_mangle(msg, rs);
			if (rc < 0)
				goto out_free;
			msgb_enqueue(&rss->tx_queue, msg);
			rss->bfd.when |= BSC_FD_WRITE;
			break;
		}
		if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
			rc = -EINVAL;
			goto out_free;
		}
		rc = rtp_decode(msg, rs->receive.callref, &new_msg);
		if (rc < 0)
			goto out_free;
		msgb_free(msg);
		msgb_enqueue(&rs->receive.net->upqueue, new_msg);
		break;

	case RTP_NONE: /* if socket exists, but disabled by app */
		msgb_free(msg);
		break;
	}

	return 0;

out_free:
	msgb_free(msg);
	return rc;
}
示例#28
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;
}
示例#29
0
static void test_agch_queue(void)
{
	int rc;
	uint8_t out_buf[GSM_MACBLOCK_LEN];
	struct gsm_time g_time;
	const int num_rounds = 40;
	const int num_ima_per_round = 2;
	const int num_rej_per_round = 16;

	int round, idx;
	int count = 0;
	struct msgb *msg = NULL;
	int multiframes = 0;
	int imm_ass_count = 0;
	int imm_ass_rej_count = 0;
	int imm_ass_rej_ref_count = 0;

	g_time.fn = 0;
	g_time.t1 = 0;
	g_time.t2 = 0;
	g_time.t3 = 6;

	printf("Testing AGCH messages queue handling.\n");
	btsb->agch_max_queue_length = 32;

	btsb->agch_queue_low_level = 30;
	btsb->agch_queue_high_level = 30;
	btsb->agch_queue_thresh_level = 60;

	for (round = 1; round <= num_rounds; round++) {
		for (idx = 0; idx < num_ima_per_round; idx++) {
			msg = msgb_alloc(GSM_MACBLOCK_LEN, __FUNCTION__);
			put_imm_ass(msg, ++count);
			bts_agch_enqueue(bts, msg);
			imm_ass_count++;
		}
		for (idx = 0; idx < num_rej_per_round; idx++) {
			msg = msgb_alloc(GSM_MACBLOCK_LEN, __FUNCTION__);
			put_imm_ass_rej(msg, ++count, 10);
			bts_agch_enqueue(bts, msg);
			imm_ass_rej_count++;
			imm_ass_rej_ref_count++;
		}
	}

	printf("AGCH filled: count %u, imm.ass %d, imm.ass.rej %d (refs %d), "
	       "queue limit %u, occupied %d, "
	       "dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", "
	       "ag-res %"PRIu64", non-res %"PRIu64"\n",
	       count, imm_ass_count, imm_ass_rej_count, imm_ass_rej_ref_count,
	       btsb->agch_max_queue_length, btsb->agch_queue_length,
	       btsb->agch_queue_dropped_msgs, btsb->agch_queue_merged_msgs,
	       btsb->agch_queue_rejected_msgs, btsb->agch_queue_agch_msgs,
	       btsb->agch_queue_pch_msgs);

	imm_ass_count = 0;
	imm_ass_rej_count = 0;
	imm_ass_rej_ref_count = 0;

	for (idx = 0; 1; idx++) {
		struct gsm48_imm_ass *ima;
		int is_agch = (idx % 3) == 0; /* 1 AG reserved, 2 PCH */
		if (is_agch)
			multiframes++;

		rc = bts_ccch_copy_msg(bts, out_buf, &g_time, is_agch);
		ima = (struct gsm48_imm_ass *)out_buf;
		switch (ima->msg_type) {
		case GSM48_MT_RR_IMM_ASS:
			imm_ass_count++;
			break;
		case GSM48_MT_RR_IMM_ASS_REJ:
			imm_ass_rej_count++;
			imm_ass_rej_ref_count +=
				count_imm_ass_rej_refs((struct gsm48_imm_ass_rej *)ima);
			break;
		default:
			break;
		}
		if (is_agch && rc <= 0)
			break;

	}

	printf("AGCH drained: multiframes %u, imm.ass %d, imm.ass.rej %d (refs %d), "
	       "queue limit %u, occupied %d, "
	       "dropped %"PRIu64", merged %"PRIu64", rejected %"PRIu64", "
	       "ag-res %"PRIu64", non-res %"PRIu64"\n",
	       multiframes, imm_ass_count, imm_ass_rej_count, imm_ass_rej_ref_count,
	       btsb->agch_max_queue_length, btsb->agch_queue_length,
	       btsb->agch_queue_dropped_msgs, btsb->agch_queue_merged_msgs,
	       btsb->agch_queue_rejected_msgs, btsb->agch_queue_agch_msgs,
	       btsb->agch_queue_pch_msgs);
}
示例#30
0
/* decode an rtp frame and create a new buffer with payload */
static int rtp_decode(struct msgb *msg, u_int32_t callref, struct msgb **data)
{
	struct msgb *new_msg;
	struct gsm_data_frame *frame;
	struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data;
	struct rtp_x_hdr *rtpxh;
	u_int8_t *payload;
	int payload_len;
	int msg_type;
	int x_len;

	if (msg->len < 12) {
		DEBUGPC(DMUX, "received RTP frame too short (len = %d)\n",
			msg->len);
		return -EINVAL;
	}
	if (rtph->version != RTP_VERSION) {
		DEBUGPC(DMUX, "received RTP version %d not supported.\n",
			rtph->version);
		return -EINVAL;
	}
	payload = msg->data + sizeof(struct rtp_hdr) + (rtph->csrc_count << 2);
	payload_len = msg->len - sizeof(struct rtp_hdr) - (rtph->csrc_count << 2);
	if (payload_len < 0) {
		DEBUGPC(DMUX, "received RTP frame too short (len = %d, "
			"csrc count = %d)\n", msg->len, rtph->csrc_count);
		return -EINVAL;
	}
	if (rtph->extension) {
		if (payload_len < sizeof(struct rtp_x_hdr)) {
			DEBUGPC(DMUX, "received RTP frame too short for "
				"extension header\n");
			return -EINVAL;
		}
		rtpxh = (struct rtp_x_hdr *)payload;
		x_len = ntohs(rtpxh->length) * 4 + sizeof(struct rtp_x_hdr);
		payload += x_len;
		payload_len -= x_len;
		if (payload_len < 0) {
			DEBUGPC(DMUX, "received RTP frame too short, "
				"extension header exceeds frame length\n");
			return -EINVAL;
		}
	}
	if (rtph->padding) {
		if (payload_len < 0) {
			DEBUGPC(DMUX, "received RTP frame too short for "
				"padding length\n");
			return -EINVAL;
		}
		payload_len -= payload[payload_len - 1];
		if (payload_len < 0) {
			DEBUGPC(DMUX, "received RTP frame with padding "
				"greater than payload\n");
			return -EINVAL;
		}
	}

	switch (rtph->payload_type) {
	case RTP_PT_GSM_FULL:
		msg_type = GSM_TCHF_FRAME;
		if (payload_len != 33) {
			DEBUGPC(DMUX, "received RTP full rate frame with "
				"payload length != 32 (len = %d)\n",
				payload_len);
			return -EINVAL;
		}
		break;
	case RTP_PT_GSM_EFR:
		msg_type = GSM_TCHF_FRAME_EFR;
		break;
	default:
		DEBUGPC(DMUX, "received RTP frame with unknown payload "
			"type %d\n", rtph->payload_type);
		return -EINVAL;
	}

	new_msg = msgb_alloc(sizeof(struct gsm_data_frame) + payload_len,
				"GSM-DATA");
	if (!new_msg)
		return -ENOMEM;
	frame = (struct gsm_data_frame *)(new_msg->data);
	frame->msg_type = msg_type;
	frame->callref = callref;
	memcpy(frame->data, payload, payload_len);
	msgb_put(new_msg, sizeof(struct gsm_data_frame) + payload_len);

	*data = new_msg;
	return 0;
}