#include #include #include #include #include #include #include #include #include static int handle_sup_upd_loc_req(struct gsm_sup_server *sup_server, struct osmo_gsup_message *sup_msg) { int rc = 0; struct reg_proxy *reg = sup_server->app; struct sip_client *sip_client = reg->sip_client; osip_t *osip = reg->osip; LOGGSUPP(LOGL_INFO, sup_msg, "Try to send sip_register 0x%02x\n", sup_msg->message_type); rc = tx_sip_register(sip_client, osip, sup_msg->imsi, sip_client->expires_time); LOGGSUPP(LOGL_INFO, sup_msg, "Sip_register was send 0x%02x\n", sup_msg->message_type); return rc; } static int handle_sup_purge_ms_req(struct gsm_sup_server *sup_server, struct osmo_gsup_message *sup_msg) { int rc = 0; struct reg_proxy *reg = sup_server->app; struct sip_client *sip_client = reg->sip_client; osip_t *osip = reg->osip; LOGGSUPP(LOGL_INFO, sup_msg, "Try to send sip_register (cancellation) 0x%02x\n", sup_msg->message_type); rc = tx_sip_register(sip_client, osip, sup_msg->imsi, 0); LOGGSUPP(LOGL_INFO, sup_msg, "Sip_register (cancellation) was send 0x%02x\n", sup_msg->message_type); return rc; } #if 0 static int handle_sup_ss(struct gsm_sup_server *sup_server, struct ss_request *ss, const char* extention) { int rc = 0; struct reg_proxy *reg = sup_server->app; struct sip_client *sip_client = reg->sip_client; osip_t *osip = reg->osip; LOGP(DGPRS, LOGL_INFO, "Try to send sip_register 0x%02x\n", ss->message_type); rc = tx_ss_handle(sip_client, osip, ss, extention); LOGP(DGPRS, LOGL_INFO, "Sip_register was send 0x%02x\n", ss->message_type); return rc; } enum { FMAP_MSISDN = 0x80 }; static int rx_uss_message_parse(struct ss_request *ss, const uint8_t* data, size_t len, char* extention, size_t extention_len) { const uint8_t* const_data = data; if (len < 1 + 2 + 3 + 3) return -1; /* skip OSMO_GSUP_MSGT_MAP */ ss->message_type = *(++const_data); ss->component_type = *(++const_data); const_data += 2; // if (*const_data != GSM0480_COMPIDTAG_INVOKE_ID) { return -1; } const_data += 2; ss->invoke_id = *const_data; const_data++; // if (*const_data != GSM0480_OPERATION_CODE) { return -1; } const_data += 2; ss->opcode = *const_data; const_data++; while (const_data - data < len) { uint8_t len; switch (*const_data) { case ASN1_OCTET_STRING_TAG: len = *(++const_data); strncpy((char*)ss->ussd_text, (const char*)++const_data, (len > MAX_LEN_USSD_STRING) ? MAX_LEN_USSD_STRING : len); const_data += len; break; case FMAP_MSISDN: len = *(++const_data); gsm48_decode_bcd_number(extention, extention_len, const_data, 0); const_data += len + 1; break; default: DEBUGP(DMM, "Unknown code: %d\n", *const_data); return -1; } } return 0; } static int subscr_uss_message(struct msgb *msg, struct ss_request *req, const char* extention) { size_t bcd_len = 0; uint8_t *gsup_indicator; gsup_indicator = msgb_put(msg, 4); /* First byte should always be OSMO_GSUP_MSGT_MAP */ gsup_indicator[0] = OSMO_GSUP_MSGT_MAP; gsup_indicator[1] = req->message_type; /* TODO ADD tid */ gsup_indicator[2] = req->component_type; /* invokeId */ msgb_tlv_put(msg, GSM0480_COMPIDTAG_INVOKE_ID, 1, &req->invoke_id); /* opCode */ msgb_tlv_put(msg, GSM0480_OPERATION_CODE, 1, &req->opcode); if (req->ussd_text_len > 0) { //msgb_tlv_put(msg, ASN1_OCTET_STRING_TAG, 1, &req->ussd_text_language); msgb_tlv_put(msg, ASN1_OCTET_STRING_TAG, req->ussd_text_len, req->ussd_text); } if (extention) { uint8_t bcd_buf[32]; bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0, extention); msgb_tlv_put(msg, FMAP_MSISDN, bcd_len - 1, &bcd_buf[1]); } /* fill actual length */ gsup_indicator[3] = 3 + 3 + (req->ussd_text_len + 2) + (bcd_len + 2); /* wrap with GSM0480_CTYPE_INVOKE */ // gsm0480_wrap_invoke(msg, req->opcode, invoke_id); // gsup_indicator = msgb_push(msgb, 1); // gsup_indicator[0] = OSMO_GSUP_MSGT_MAP; return 0; } static int rx_sup_uss_message(struct gsm_sup_server *sup_server, const uint8_t* data, size_t len) { char extention[32] = {0}; struct ss_request ss; memset(&ss, 0, sizeof(ss)); if (rx_uss_message_parse(&ss, data, len, extention, sizeof(extention))) { LOGP(DSUP, LOGL_ERROR, "Can't parse uss message\n"); return -1; } LOGP(DSUP, LOGL_ERROR, "Got mtype=0x%02x invoke_id=0x%02x opcode=0x%02x component_type=0x%02x text=%s\n", ss.message_type, ss.invoke_id, ss.opcode, ss.component_type, ss.ussd_text); handle_sup_ss(sup_server, &ss, extention); return 0; #if 0 if (strcmp((const char*)ss.ussd_text, "*#100#") == 0) { ss.ussd_text_len = snprintf(ss.ussd_text, sizeof(ss.ussd_text), "Your extention is %s", extention); /* Last message in the transaction */ ss.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; ss.component_type = GSM0480_CTYPE_RETURN_RESULT; } else if (strcmp((const char*)ss.ussd_text, "*#101#") == 0) { ss.ussd_text_len = snprintf(ss.ussd_text, sizeof(ss.ussd_text), "Select option:\n1) Option 1\n2) Option 2"); ss.message_type = GSM0480_MTYPE_FACILITY; ss.component_type = GSM0480_CTYPE_INVOKE; ss.opcode = GSM0480_OP_CODE_USS_REQUEST; } else { if (ss.component_type == GSM0480_CTYPE_RETURN_RESULT && ss.opcode == GSM0480_OP_CODE_USS_REQUEST) { // Menu selected char buffer[160]; strncpy(buffer, ss.ussd_text, sizeof(buffer)); ss.ussd_text_len = snprintf(ss.ussd_text, sizeof(ss.ussd_text), "You've selected \"%s\"", buffer); ss.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; ss.component_type = GSM0480_CTYPE_RETURN_RESULT; ss.opcode = GSM0480_OP_CODE_PROCESS_USS_REQ; } else { ss.ussd_text_len = 0; ss.message_type = GSM0480_MTYPE_RELEASE_COMPLETE; ss.component_type = GSM0480_CTYPE_REJECT; } } if (ss.ussd_text_len > sizeof(ss.ussd_text)) ss.ussd_text_len = sizeof(ss.ussd_text); struct msgb *msg = gsup_client_msgb_alloc(); subscr_uss_message(msg, &ss, (extention[0] == 0) ? NULL : extention); LOGP(DGPRS, LOGL_INFO, "Sending USS, will send: %s\n", msgb_hexdump(msg)); if (!sup_server) { msgb_free(msg); return -ENOTSUP; } return sup_server_send(sup_server, msg); #endif } #endif int rx_sup_message(struct gsm_sup_server *sup_server, struct msgb *msg) { uint8_t *data = msgb_l2(msg); size_t data_len = msgb_l2len(msg); int rc = 0; struct osmo_gsup_message sup_msg = {0}; //struct gsm_subscriber *subscr; #if 0 if (*data == OSMO_GSUP_MSGT_MAP) { LOGP(DSUP, LOGL_INFO, "Receive USS: %s\n", msgb_hexdump(msg)); return rx_sup_uss_message(sup_server, data, data_len); } #endif rc = osmo_gsup_decode(data, data_len, &sup_msg); if (rc < 0) { LOGP(DSUP, LOGL_ERROR, "decoding SUP message fails with error '%s' (%d)\n", get_value_string(gsm48_gmm_cause_names, -rc), -rc); return rc; } if (!sup_msg.imsi[0]) { LOGP(DSUP, LOGL_ERROR, "Missing IMSI in SUP message\n"); // if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type)) // subscr_tx_sup_error_reply(sup_client, NULL, &gsup_msg, // GMM_CAUSE_INV_MAND_INFO); return -GMM_CAUSE_INV_MAND_INFO; } // if (!gsup_msg.cause && OSMO_GSUP_IS_MSGT_ERROR(gsup_msg.message_type)) // gsup_msg.cause = GMM_CAUSE_NET_FAIL; // subscr = subscr_get_by_imsi(NULL, gsup_msg.imsi); // if (!subscr) { // return subscr_handle_unknown_imsi(sup_client, &gsup_msg); // } LOGGSUPP(LOGL_INFO, &sup_msg, "Received SUP message of type 0x%02x\n", sup_msg.message_type); switch (sup_msg.message_type) { case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST: rc = handle_sup_upd_loc_req(sup_server, &sup_msg); break; case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST: //FIXME!!!! //rc = subscr_handle_sup_auth_req(sup_server, &sup_msg); rc = handle_sup_upd_loc_req(sup_server, &sup_msg); break; case OSMO_GSUP_MSGT_LOCATION_CANCEL_ERROR: case OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT: case OSMO_GSUP_MSGT_PURGE_MS_REQUEST: rc = handle_sup_purge_ms_req(sup_server, &sup_msg); break; case OSMO_GSUP_MSGT_INSERT_DATA_ERROR: case OSMO_GSUP_MSGT_INSERT_DATA_RESULT: LOGGSUPP(LOGL_ERROR, &sup_msg, "Rx SUP message type %d not yet implemented\n", sup_msg.message_type); //tx_sup_error_reply(sup_server, &sup_msg, // GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL); rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL; break; default: LOGGSUPP(LOGL_ERROR, &sup_msg, "Rx SUP message type %d not valid\n", sup_msg.message_type); rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL; break; }; //subscr_put(subscr); return rc; } static int tx_sup_message(struct gsm_sup_server *sup_server, struct osmo_gsup_message *sup_msg) { struct msgb *msg = gsup_client_msgb_alloc(); printf("tx_sup_message \n"); osmo_gsup_encode(msg, sup_msg); printf("tx_sup_message encoded\n"); LOGGSUPP(LOGL_INFO, sup_msg, "Sending SUP, will send: %s\n", msgb_hexdump(msg)); if (!sup_server) { msgb_free(msg); return -ENOTSUP; } printf("tx_sup_message lets try to send\n"); return sup_server_send(sup_server, msg); } int handle_location_update_result(struct gsm_sup_server *sup_server, char *imsi, char *msisdn) { struct osmo_gsup_message gsup_msg = {0}; u_int8_t msisdn_enc[9]; gsup_msg.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT; printf("handle_location_update_result 1\n"); memcpy(gsup_msg.imsi, imsi, 17); printf("handle_location_update_result %d len = %d 2\n", gsup_msg.msisdn_enc, strlen(msisdn)); if (strcmp(imsi, msisdn) != 0) { gsm48_encode_bcd_number(msisdn_enc, 9, 0, msisdn); (&gsup_msg)->msisdn_enc = msisdn_enc + 1; gsup_msg.msisdn_enc_len = msisdn_enc[0]; printf("handle_location_update_result %d %d\n", gsup_msg.msisdn_enc_len, gsup_msg.msisdn_enc); } return tx_sup_message(sup_server, &gsup_msg); } int handle_purge_ms_result(struct gsm_sup_server *sup_server, char *imsi) { struct osmo_gsup_message gsup_msg = {0}; gsup_msg.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT; memcpy(gsup_msg.imsi, imsi, 17); return tx_sup_message(sup_server, &gsup_msg); } static int sup_read_cb(struct gsm_sup_server *sup_server, struct msgb *msg) { int rc; printf("Got message from nitb!\n"); rc = rx_sup_message(sup_server, msg); msgb_free(msg); if (rc < 0) return -1; return rc; } int sup_server_init(struct reg_proxy *reg) { const char *addr_str; addr_str = "127.0.0.1"; reg->sup_server = sup_server_create(addr_str, 8183, &sup_read_cb, reg); if (!reg->sup_server) return -1; return 1; }