From dc329a6cdb204d89c15599ca606e239dde368e7f Mon Sep 17 00:00:00 2001 From: Mike Haben Date: Thu, 22 Oct 2009 09:56:44 +0200 Subject: [USSD] eliminate static global variables This patch removes the need of static global variables and introduces a new, caller-allocated 'struct ussd_request' that needs to be passed to the various functions. --- openbsc/include/openbsc/gsm_04_80.h | 15 +++++-- openbsc/src/gsm_04_80.c | 90 +++++++++++++++++++------------------ openbsc/src/ussd.c | 19 ++++---- 3 files changed, 68 insertions(+), 56 deletions(-) diff --git a/openbsc/include/openbsc/gsm_04_80.h b/openbsc/include/openbsc/gsm_04_80.h index 11962d81d..9bdf2c200 100644 --- a/openbsc/include/openbsc/gsm_04_80.h +++ b/openbsc/include/openbsc/gsm_04_80.h @@ -125,8 +125,17 @@ #include -char* gsm0480_rcv_ussd(struct msgb *msg); -int gsm0480_send_ussd_response(struct msgb *msg, const char* response_text); -int gsm0480_send_ussd_reject(struct msgb *msg); +struct ussd_request { + char text[32]; + u_int8_t transaction_id; + u_int8_t invoke_id; +}; + +int gsm0480_decode_ussd_request(struct msgb *msg, + struct ussd_request *request); +int gsm0480_send_ussd_response(struct msgb *in_msg, const char* response_text, + const struct ussd_request *req); +int gsm0480_send_ussd_reject(struct msgb *msg, + const struct ussd_request *request); #endif diff --git a/openbsc/src/gsm_04_80.c b/openbsc/src/gsm_04_80.c index 052b0a77a..5d85c8221 100644 --- a/openbsc/src/gsm_04_80.c +++ b/openbsc/src/gsm_04_80.c @@ -37,16 +37,16 @@ #include #include -static char ussd_string_buff[32]; -static u_int8_t last_transaction_id; -static u_int8_t last_invoke_id; - /* Forward declarations */ -static int parse_ussd(u_int8_t *ussd); -static int parse_ussd_information_elements(u_int8_t *ussd_ie); -static int parse_facility_ie(u_int8_t *facility_ie, u_int8_t length); -static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length); -static int parse_process_uss_req(u_int8_t *uss_req_data, u_int8_t length); +static int parse_ussd(u_int8_t *ussd, struct ussd_request *req); +static int parse_ussd_info_elements(u_int8_t *ussd_ie, + struct ussd_request *req); +static int parse_facility_ie(u_int8_t *facility_ie, u_int8_t length, + struct ussd_request *req); +static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length, + struct ussd_request *req); +static int parse_process_uss_req(u_int8_t *uss_req_data, u_int8_t length, + struct ussd_request *req); static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, u_int8_t tag) { @@ -69,26 +69,24 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, u_int8_t tag, } -/* Receive a mobile-originated USSD message and return the decoded text */ -char *gsm0480_rcv_ussd(struct msgb *msg) +/* Decode a mobile-originated USSD-request message */ +int gsm0480_decode_ussd_request(struct msgb *msg, struct ussd_request *req) { int rc = 0; u_int8_t *parse_ptr = msgb_l3(msg); - memset(ussd_string_buff, 0, sizeof(ussd_string_buff)); - if ((*parse_ptr & 0x0F) == GSM48_PDISC_NC_SS) { - last_transaction_id = *parse_ptr & 0x70; - rc = parse_ussd(parse_ptr + 1); + req->transaction_id = *parse_ptr & 0x70; + rc = parse_ussd(parse_ptr+1, req); } if (!rc) DEBUGP(DMM, "Error occurred while parsing received USSD!\n"); - return ussd_string_buff; + return rc; } -static int parse_ussd(u_int8_t *ussd) +static int parse_ussd(u_int8_t *ussd, struct ussd_request *req) { int rc = 1; u_int8_t msg_type = ussd[0] & 0xBF; /* message-type - section 3.4 */ @@ -97,11 +95,11 @@ static int parse_ussd(u_int8_t *ussd) case GSM0480_MTYPE_RELEASE_COMPLETE: DEBUGP(DMM, "USS Release Complete\n"); /* could also parse out the optional Cause/Facility data */ - ussd_string_buff[0] = 0xFF; + req->text[0] = 0xFF; break; case GSM0480_MTYPE_REGISTER: case GSM0480_MTYPE_FACILITY: - rc &= parse_ussd_information_elements(ussd+1); + rc &= parse_ussd_info_elements(ussd+1, req); break; default: fprintf(stderr, "Unknown GSM 04.80 message-type field 0x%02x\n", @@ -113,7 +111,7 @@ static int parse_ussd(u_int8_t *ussd) return rc; } -static int parse_ussd_information_elements(u_int8_t *ussd_ie) +static int parse_ussd_info_elements(u_int8_t *ussd_ie, struct ussd_request *req) { int rc; /* Information Element Identifier - table 3.2 & GSM 04.08 section 10.5 */ @@ -124,7 +122,7 @@ static int parse_ussd_information_elements(u_int8_t *ussd_ie) case GSM48_IE_CAUSE: break; case GSM0480_IE_FACILITY: - rc = parse_facility_ie(ussd_ie+2, iei_length); + rc = parse_facility_ie(ussd_ie+2, iei_length, req); break; case GSM0480_IE_SS_VERSION: break; @@ -138,7 +136,8 @@ static int parse_ussd_information_elements(u_int8_t *ussd_ie) return rc; } -static int parse_facility_ie(u_int8_t *facility_ie, u_int8_t length) +static int parse_facility_ie(u_int8_t *facility_ie, u_int8_t length, + struct ussd_request *req) { int rc = 1; u_int8_t offset = 0; @@ -150,7 +149,9 @@ static int parse_facility_ie(u_int8_t *facility_ie, u_int8_t length) switch (component_type) { case GSM0480_CTYPE_INVOKE: - rc &= parse_ss_invoke(facility_ie+2, component_length); + rc &= parse_ss_invoke(facility_ie+2, + component_length, + req); break; case GSM0480_CTYPE_RETURN_RESULT: break; @@ -171,7 +172,8 @@ static int parse_facility_ie(u_int8_t *facility_ie, u_int8_t length) } /* Parse an Invoke component - see table 3.3 */ -static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length) +static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length, + struct ussd_request *req) { int rc = 1; u_int8_t offset; @@ -183,7 +185,7 @@ static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length) } offset = invoke_data[1] + 2; - last_invoke_id = invoke_data[2]; + req->invoke_id = invoke_data[2]; /* optional part */ if (invoke_data[offset] == GSM0480_COMPIDTAG_LINKED_ID) @@ -195,7 +197,8 @@ static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length) switch (operation_code) { case GSM0480_OP_CODE_PROCESS_USS_REQ: rc = parse_process_uss_req(invoke_data + offset + 3, - length - offset - 3); + length - offset - 3, + req); break; default: fprintf(stderr, "GSM 04.80 operation code 0x%02x " @@ -214,36 +217,33 @@ static int parse_ss_invoke(u_int8_t *invoke_data, u_int8_t length) } /* Parse the parameters of a Process UnstructuredSS Request */ -static int parse_process_uss_req(u_int8_t *uss_req_data, u_int8_t length) +static int parse_process_uss_req(u_int8_t *uss_req_data, u_int8_t length, + struct ussd_request *req) { - int rc = 1; + int rc = 0; int num_chars; u_int8_t dcs; - /* FIXME: most phones send USSD text as a 7-bit encoded octet string; - * the following code also handles the case of plain ASCII text - * (IA5String), but other encodings might be used */ - if (uss_req_data[0] == GSM_0480_SEQUENCE_TAG) { if (uss_req_data[2] == ASN1_OCTET_STRING_TAG) { dcs = uss_req_data[4]; if ((dcs == 0x0F) && (uss_req_data[5] == ASN1_OCTET_STRING_TAG)) { num_chars = (uss_req_data[6] * 8) / 7; - gsm_7bit_decode(ussd_string_buff, + gsm_7bit_decode(req->text, &(uss_req_data[7]), num_chars); + /* append null-terminator */ + req->text[num_chars+1] = 0; + rc = 1; } } - } else if (uss_req_data[0] == ASN1_IA5_STRING_TAG) { - num_chars = uss_req_data[1]; - memcpy(ussd_string_buff, &(uss_req_data[2]), num_chars); - } - + } return rc; } /* Send response to a mobile-originated ProcessUnstructuredSS-Request */ -int gsm0480_send_ussd_response(struct msgb *in_msg, const char* response_text) +int gsm0480_send_ussd_response(struct msgb *in_msg, const char* response_text, + const struct ussd_request *req) { struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh; @@ -278,7 +278,7 @@ int gsm0480_send_ussd_response(struct msgb *in_msg, const char* response_text) msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); /* Pre-pend the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, last_invoke_id); + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); /* Wrap this up as a Return Result component */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); @@ -288,13 +288,15 @@ int gsm0480_send_ussd_response(struct msgb *in_msg, const char* response_text) /* And finally pre-pend the L3 header */ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_NC_SS | last_transaction_id | (1<<7); /* TI direction = 1 */ + gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id + | (1<<7); /* TI direction = 1 */ gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; return gsm48_sendmsg(msg, NULL); } -int gsm0480_send_ussd_reject(struct msgb *in_msg) +int gsm0480_send_ussd_reject(struct msgb *in_msg, + const struct ussd_request *req) { struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh; @@ -307,7 +309,7 @@ int gsm0480_send_ussd_reject(struct msgb *in_msg) GSM_0480_GEN_PROB_CODE_UNRECOGNISED); /* Before it insert the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, last_invoke_id); + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id); /* Wrap this up as a Reject component */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT); @@ -318,7 +320,7 @@ int gsm0480_send_ussd_reject(struct msgb *in_msg) /* And finally pre-pend the L3 header */ gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); gh->proto_discr = GSM48_PDISC_NC_SS; - gh->proto_discr |= last_transaction_id | (1<<7); /* TI direction = 1 */ + gh->proto_discr |= req->transaction_id | (1<<7); /* TI direction = 1 */ gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE; return gsm48_sendmsg(msg, NULL); diff --git a/openbsc/src/ussd.c b/openbsc/src/ussd.c index 9dc2205f1..e414b1cea 100644 --- a/openbsc/src/ussd.c +++ b/openbsc/src/ussd.c @@ -38,33 +38,34 @@ const char USSD_TEXT_OWN_NUMBER[] = "*#100#"; /* Forward declarations of network-specific handler functions */ -static int send_own_number(struct msgb *msg); +static int send_own_number(const struct msgb *msg, const struct ussd_request *req); /* Entrypoint - handler function common to all mobile-originated USSDs */ int handle_rcv_ussd(struct msgb *msg) { - char *ussd_text_rcvd = gsm0480_rcv_ussd(msg); + struct ussd_request req; - if (ussd_text_rcvd[0] == 0xFF) /* Release-Complete */ + gsm0480_decode_ussd_request(msg, &req); + if (req.text[0] == 0xFF) /* Release-Complete */ return 0; - if (strstr(USSD_TEXT_OWN_NUMBER, ussd_text_rcvd) != NULL) { + if (strstr(USSD_TEXT_OWN_NUMBER, req.text) != NULL) { DEBUGP(DMM, "USSD: Own number requested\n"); - return send_own_number(msg); + return send_own_number(msg, &req); } else { - DEBUGP(DMM, "Unhandled USSD %s\n", ussd_text_rcvd); - return gsm0480_send_ussd_reject(msg); + DEBUGP(DMM, "Unhandled USSD %s\n", req.text); + return gsm0480_send_ussd_reject(msg, &req); } } /* A network-specific handler function */ -static int send_own_number(struct msgb *msg) +static int send_own_number(const struct msgb *msg, const struct ussd_request *req) { char *own_number = msg->lchan->subscr->extension; /* Need trailing CR as EOT character */ char response_string[] = "Your extension is xxxxx\r"; memcpy(response_string + 18, own_number, 5); - return gsm0480_send_ussd_response(msg, response_string); + return gsm0480_send_ussd_response(msg, response_string, req); } -- cgit v1.2.3