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