/* SMC TC1* is expired */
static void cp_timer_expired(void *data)
{
	struct gsm411_smc_inst *inst = data;
	struct msgb *nmsg;

	if (inst->cp_retx == inst->cp_max_retr) {

		LOGP(DLSMS, LOGL_INFO,
			SMC_LOG_STR "TC1* timeout, no more retries.\n",
			inst->id);
		/* 5.3.2.1: enter idle state */
		new_cp_state(inst, GSM411_CPS_IDLE);
		/* indicate error */
		nmsg = gsm411_msgb_alloc();
		inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, nmsg);
		msgb_free(nmsg);
		/* free pending stored msg */
		if (inst->cp_msg) {
			msgb_free(inst->cp_msg);
			inst->cp_msg = NULL;
		}
		/* release MM connection */
		nmsg = gsm411_msgb_alloc();
		inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
		return;
	}

	LOGP(DLSMS, LOGL_INFO,
		SMC_LOG_STR "TC1* timeout, retrying...\n", inst->id);
	inst->cp_retx++;
	gsm411_mmsms_est_cnf(inst, NULL);
}
/* message from lower layer
 * WARNING: We must not free msg, since it will be performed by the
 * lower layer. */
int gsm411_smc_recv(struct gsm411_smc_inst *inst, int msg_type,
	struct msgb *msg, int cp_msg_type)
{
	int i, rc;

	/* find function for current state and message */
	for (i = 0; i < SMCDATASLLEN; i++) {
		/* state must match, MM message must match
		 * CP msg must match only in case of MMSMS_DATA_IND
		 */
		if ((msg_type == smcdatastatelist[i].type)
		  && (SBIT(inst->cp_state) & smcdatastatelist[i].states)
		  && (msg_type != GSM411_MMSMS_DATA_IND
		   || cp_msg_type == smcdatastatelist[i].cp_type))
				break;
	}
	if (i == SMCDATASLLEN) {
		LOGP(DLSMS, LOGL_NOTICE,
			SMC_LOG_STR "message 0x%x/%u unhandled at this "
			"state %s.\n", inst->id, msg_type, cp_msg_type,
			smc_state_names[inst->cp_state]);
		if (msg_type == GSM411_MMSMS_EST_IND
		 || msg_type == GSM411_MMSMS_DATA_IND) {
			struct msgb *nmsg;

			LOGP(DLSMS, LOGL_NOTICE,
				SMC_LOG_STR "RX Unimplemented CP "
				"msg_type: 0x%02x\n", inst->id, msg_type);
			/* 5.3.4 enter idle */
			new_cp_state(inst, GSM411_CPS_IDLE);
			/* indicate error */
			gsm411_tx_cp_error(inst,
				GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
			/* send error indication to upper layer */
			nmsg = gsm411_msgb_alloc();
			inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, nmsg);
			msgb_free(nmsg);
			/* release MM connection */
			nmsg = gsm411_msgb_alloc();
			return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg,
						0);
		}
		return 0;
	}

	LOGP(DLSMS, LOGL_INFO,
		SMC_LOG_STR "message %s received in state %s\n", inst->id,
		smcdatastatelist[i].name, smc_state_names[inst->cp_state]);

	rc = smcdatastatelist[i].rout(inst, msg);

	return rc;
}
/* release SMC connection */
static int gsm411_mnsms_rel_req(struct gsm411_smc_inst *inst, struct msgb *msg)
{
	struct msgb *nmsg;

	msgb_free(msg);

	/* discard silently */
	if (inst->cp_state == GSM411_CPS_IDLE)
		return 0;

	/* store release, until established or released */
	if (inst->cp_state != GSM411_CPS_MM_ESTABLISHED) {
		LOGP(DLSMS, LOGL_NOTICE, "Cannot release yet.\n");
		inst->cp_rel = 1;
		return 0;
	}

	/* free stored msg */
	if (inst->cp_msg) {
		msgb_free(inst->cp_msg);
		inst->cp_msg = NULL;
	}

	new_cp_state(inst, GSM411_CPS_IDLE);
	/* release MM connection */
	nmsg = gsm411_msgb_alloc();
	return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
}
static int gsm411_mmsms_cp_ack(struct gsm411_smc_inst *inst, struct msgb *msg)
{
	/* free stored msg */
	if (inst->cp_msg) {
		msgb_free(inst->cp_msg);
		inst->cp_msg = NULL;
	}

	LOGP(DLSMS, LOGL_INFO, "Received CP-ACK\n");
	/* 5.3.2.1 enter MM Connection established */
	new_cp_state(inst, GSM411_CPS_MM_ESTABLISHED);
	/* 5.3.2.1: Reset Timer TC1* */
	osmo_timer_del(&inst->cp_timer);

	/* pending release? */
	if (inst->cp_rel) {
		struct msgb *nmsg;

		LOGP(DLSMS, LOGL_INFO, "We have pending release.\n");
		new_cp_state(inst, GSM411_CPS_IDLE);
		/* release MM connection */
		nmsg = gsm411_msgb_alloc();
		return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
	}

	return 0;
}
static int gsm411_send_report(struct gsm411_smr_inst *inst)
{
	struct msgb *msg = gsm411_msgb_alloc();

	LOGP(DLSMS, LOGL_DEBUG,
		SMR_LOG_STR "Sending empty SM_RL_REPORT_IND\n", inst->id);

	return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
}
static int gsm411_send_release(struct gsm411_smr_inst *inst)
{
	struct msgb *msg = gsm411_msgb_alloc();

	LOGP(DLSMS, LOGL_DEBUG,
		SMR_LOG_STR "TX: MNSMS-REL-REQ\n", inst->id);

	return inst->mn_send(inst, GSM411_MNSMS_REL_REQ, msg);
}
static int gsm411_send_abort(struct gsm411_smr_inst *inst)
{
	struct msgb *msg = gsm411_msgb_alloc();

	LOGP(DLSMS, LOGL_DEBUG,
		SMR_LOG_STR "TX: MNSMS-ABORT-REQ\n", inst->id);

	msgb_tv_put(msg, 1, 111); //FIXME: better idea ? */

	return inst->mn_send(inst, GSM411_MNSMS_ABORT_REQ, msg);
}
static int gsm411_tx_cp_error(struct gsm411_smc_inst *inst, uint8_t cause)
{
	struct msgb *nmsg = gsm411_msgb_alloc();
	uint8_t *causep;

	LOGP(DLSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
		get_value_string(gsm411_cp_cause_strs, cause));

	causep = msgb_put(nmsg, 1);
	*causep = cause;

	return inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, nmsg,
		GSM411_MT_CP_ERROR);
}
static int gsm411_send_rp_error(struct gsm411_smr_inst *inst,
				uint8_t msg_ref, uint8_t cause)
{
	struct msgb *msg = gsm411_msgb_alloc();

	msgb_tv_put(msg, 1, cause);

	LOGP(DLSMS, LOGL_NOTICE,
		SMR_LOG_STR "TX: SMS RP ERROR, cause %d (%s)\n", inst->id,
		cause, get_value_string(gsm411_rp_cause_strs, cause));

	return gsm411_rp_sendmsg(inst, msg,
		(inst->network) ? GSM411_MT_RP_ERROR_MT : GSM411_MT_RP_ERROR_MO,
		msg_ref, GSM411_MNSMS_DATA_REQ);
}
/* etablish SMC connection */
static int gsm411_mnsms_est_req(struct gsm411_smc_inst *inst, struct msgb *msg)
{
	struct msgb *nmsg;

	if (inst->cp_msg) {
		LOGP(DLSMS, LOGL_FATAL, "EST REQ, but we already have an "
			"cp_msg. This should never happen, please fix!\n");
		msgb_free(inst->cp_msg);
	}

	inst->cp_msg = msg;
	new_cp_state(inst, GSM411_CPS_MM_CONN_PENDING);
	/* clear stored release flag */
	inst->cp_rel = 0;
	/* send MMSMS_EST_REQ */
	nmsg = gsm411_msgb_alloc();
	return inst->mm_send(inst, GSM411_MMSMS_EST_REQ, nmsg, 0);
}
/* abort SMC connection */
static int gsm411_mnsms_abort_req(struct gsm411_smc_inst *inst,
	struct msgb *msg)
{
	struct msgb *nmsg;

	/* free stored msg */
	if (inst->cp_msg) {
		msgb_free(inst->cp_msg);
		inst->cp_msg = NULL;
	}

	/* 5.3.4 go idle */
	new_cp_state(inst, GSM411_CPS_IDLE);
	/* send MMSMS_DATA_REQ with CP-ERROR */
	inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, msg, GSM411_MT_CP_ERROR);
	/* release MM connection */
	nmsg = gsm411_msgb_alloc();
	return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
}
static int gsm411_mmsms_cp_error(struct gsm411_smc_inst *inst, struct msgb *msg)
{
	struct msgb *nmsg;

	/* free stored msg */
	if (inst->cp_msg) {
		msgb_free(inst->cp_msg);
		inst->cp_msg = NULL;
	}

	LOGP(DLSMS, LOGL_INFO, "Received CP-ERROR\n");
	/* 5.3.4 enter idle */
	new_cp_state(inst, GSM411_CPS_IDLE);
	/* indicate error */
	inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, msg);
	/* release MM connection */
	nmsg = gsm411_msgb_alloc();
	return inst->mm_send(inst, GSM411_MMSMS_REL_REQ, nmsg, 0);
}
static int gsm411_mmsms_rel_ind(struct gsm411_smc_inst *inst, struct msgb *msg)
{
	struct msgb *nmsg;

	/* free stored msg */
	if (inst->cp_msg) {
		msgb_free(inst->cp_msg);
		inst->cp_msg = NULL;
	}

	LOGP(DLSMS, LOGL_INFO, "MM layer is released\n");
	/* 5.3.4 enter idle */
	new_cp_state(inst, GSM411_CPS_IDLE);
	/* indicate error */
	nmsg = gsm411_msgb_alloc();
	inst->mn_recv(inst, GSM411_MNSMS_ERROR_IND, nmsg);
	msgb_free(nmsg);

	return 0;
}
static int gsm411_mmsms_cp_data(struct gsm411_smc_inst *inst, struct msgb *msg)
{
	struct msgb *nmsg;
	int mt = GSM411_MNSMS_DATA_IND;

	LOGP(DLSMS, LOGL_INFO, "Received CP-DATA\n");
	/* 5.3.1 enter MM Connection established (if idle) */
	if (inst->cp_state == GSM411_CPS_IDLE) {
		new_cp_state(inst, GSM411_CPS_MM_ESTABLISHED);
		mt = GSM411_MNSMS_EST_IND;
		/* clear stored release flag */
		inst->cp_rel = 0;
	}
	/* send MMSMS_DATA_REQ (CP ACK) */
	nmsg = gsm411_msgb_alloc();
	inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, nmsg, GSM411_MT_CP_ACK);
	/* indicate data */
	inst->mn_recv(inst, mt, msg);

	return 0;
}
static int gsm411_mmsms_send_msg(struct gsm411_smc_inst *inst)
{
	struct msgb *nmsg;

	LOGP(DLSMS, LOGL_INFO, "Send CP data\n");
	/* reset retry counter */
	if (inst->cp_state != GSM411_CPS_WAIT_CP_ACK)
		inst->cp_retx = 0;
	/* 5.2.3.1.2: enter MO-wait for CP-ACK */
	/* 5.2.3.2.3: enter MT-wait for CP-ACK */
	new_cp_state(inst, GSM411_CPS_WAIT_CP_ACK);
	inst->cp_timer.data = inst;
	inst->cp_timer.cb = cp_timer_expired;
	/* 5.3.2.1: Set Timer TC1A */
	osmo_timer_schedule(&inst->cp_timer, inst->cp_tc1, 0);
	/* clone cp_msg */
	nmsg = gsm411_msgb_alloc();
	memcpy(msgb_put(nmsg, inst->cp_msg->len), inst->cp_msg->data,
		inst->cp_msg->len);
	/* send MMSMS_DATA_REQ with CP-DATA */
	return inst->mm_send(inst, GSM411_MMSMS_DATA_REQ, nmsg,
				GSM411_MT_CP_DATA);
}
Exemple #16
0
int ga_csr_uplink_dtap_sms(int sock, char *dest, char *text, uint8_t tpdu_mr, uint8_t rpdu_mr){
	struct uma_msg_s *uma_msg;
	u_int8_t *titi, *tata;
	int j, i, len;
	struct gsm48_hdr *ngh;
	struct gsm411_rp_hdr *rph;
	struct msgb *nmsg;
	struct gsm_sms *sms = malloc(sizeof(struct gsm_sms));
	uint8_t *data;
	uint8_t oa[12];
	uint8_t oa_len;
	uint8_t *rp_ud_len;

	if(strlen(dest) >= sizeof(sms->dest_addr)){
		fprintf(stderr, "Broken destination number\n");
		return -2;
	}

	memset(sms, 0, sizeof(struct gsm_sms));

	sms->validity_period = 0xff;
	sms->status_rep_req = 0;
	sms->ud_hdr_ind = 0;
	sms->protocol_id = 0;
	sms->data_coding_scheme = 0;
	sms->reject_duplicates = 0;
	sms->msg_ref = tpdu_mr;
	sms->user_data_len =  gsm_7bit_encode(sms->user_data, text);
	/* workaround that libosmocore is currently returning the number of
	   encoded octets and not septets
	*/
	sms->user_data_len = (sms->user_data_len*8)/7;
	strncpy(sms->dest_addr, dest, sizeof(sms->dest_addr) - 1);

	nmsg = gsm411_msgb_alloc();
	if (!nmsg){
		return -1;
	}
	rph = (struct gsm411_rp_hdr *)msgb_push(nmsg, sizeof(*rph));
	rph->msg_type = GSM411_MT_RP_DATA_MO;
	rph->msg_ref = rpdu_mr;

	data = (u_int8_t *)msgb_put(nmsg, 1);
	data[0] = 0;

	/* hardcode smsc address for now */
	data = (u_int8_t *)msgb_put(nmsg, 8);
	data[0] = 0x07;
	data[1] = 0x91;
	data[2] = 0x33;
	data[3] = 0x06;
	data[4] = 0x09;
	data[5] = 0x10;
	data[6] = 0x93;
	data[7] = 0xf0;

	ngh = (struct gsm48_hdr *) msgb_push(nmsg, sizeof(*ngh));

	ngh->proto_discr = GSM48_PDISC_SMS;
	ngh->msg_type = GSM411_MT_CP_DATA;

	data = msgb_put(nmsg, 1);
	rp_ud_len = data;

	*rp_ud_len = gsm340_tpdu_encode(nmsg, sms);
	/* substract rpdu length, type and ref from total length */
	rph->len = nmsg->len - 3;

	uma_msg = uma_create_msg(GA_CSR_UPLINK_DIRECT_TRANSFER, 0, GA_CSR);
	uma_msg->tlv[uma_msg->ntlv++] = create_IEI_L3_Message(nmsg->data, nmsg->len);
	j = uma_create_buffer(&titi, uma_msg);

	printf("Sending GA-CSR UPLINK DIRECT TRANSFER CP-DATA RP-DATA...");
	write(sock, titi, j);
	printf("passed to proxy\n");
	// there seems to be a memory corruption in libosmocore/libuma, hence not freeing even though i should :/
	//uma_delete_msg(uma_msg);
	//msgb_free(nmsg);

	return 0;
}