This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.
Neels Hofmeyr nhofmeyr at sysmocom.deOn Fri, Apr 22, 2016 at 02:41:32PM +0200, Sergey Kostanbaev wrote:
> ---
> openbsc/include/openbsc/gsm_04_80.h | 15 +++--
> openbsc/src/libmsc/gsm_04_80.c | 128 ++++++++++++++++++++++++------------
> openbsc/src/libmsc/ussd.c | 79 ++++++++++++++++++----
> 3 files changed, 162 insertions(+), 60 deletions(-)
>
> diff --git a/openbsc/include/openbsc/gsm_04_80.h b/openbsc/include/openbsc/gsm_04_80.h
> index 0a60652..371bc17 100644
> --- a/openbsc/include/openbsc/gsm_04_80.h
> +++ b/openbsc/include/openbsc/gsm_04_80.h
> @@ -7,12 +7,17 @@
>
> struct gsm_subscriber_connection;
>
> -int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
> - const struct msgb *in_msg, const char* response_text,
> - const struct ussd_request *req);
> +int gsm0480_send_component(struct gsm_subscriber_connection *conn,
Why remove the '_ussd_' name component here while you keep it in the other
functions?
IMHO you should also describe function renames in the log message.
> + struct msgb *msg,
> + struct ss_header* reqhdr);
> +
> int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
> - const struct msgb *msg,
> - const struct ussd_request *request);
> + uint8_t invoke_id,
> + uint8_t transaction_id);
> +
> +struct msgb *gsm0480_compose_ussd_component(struct ss_request* req);
...and additions/out-factorings as well.
> +
> +
^ osmo* is usually sparse on whitespace ;)
>
> int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text);
> int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn);
> diff --git a/openbsc/src/libmsc/gsm_04_80.c b/openbsc/src/libmsc/gsm_04_80.c
> index f1d75f2..e6e4a92 100644
> --- a/openbsc/src/libmsc/gsm_04_80.c
> +++ b/openbsc/src/libmsc/gsm_04_80.c
> @@ -39,6 +39,22 @@
> #include <osmocom/core/msgb.h>
> #include <osmocom/gsm/tlv.h>
>
> +/* This function can handle ASN1 length up to 255 which is enough for USSD */
> +static inline unsigned char *msgb_wrap_with_ASN1_TL(struct msgb *msgb, uint8_t tag)
> +{
> + uint16_t origlen = msgb->len;
> + uint8_t *data = msgb_push(msgb, (origlen > 0x7f) ? 3 : 2);
> + data[0] = tag;
> + if (origlen > 0x7f) {
> + data[1] = 0x81;
> + data[2] = origlen;
> + } else {
> + data[1] = origlen;
> + }
> + return data;
> +}
Would be good to use constants instead of the two magic values, which
would also improve readability; otherwise I would like to see comments
describing the semantics to the uninformed reader.
> +
> +
^ Again, a single line of whitespace would be usual in osmo*.
...
This patch is rather large, especially for a one-liner commit log; would
it be possible to break this patch down into smaller changes that are
easier to review? That would be great!
Unfortunately I have to redirect my attention to other tasks now and
cannot look at the remaining changes...
Thanks!
~Neels
> static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
> {
> uint8_t *data = msgb_push(msgb, 2);
> @@ -59,83 +75,111 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
> return data;
> }
>
> +static inline unsigned char *msgb_wrap_with_L(struct msgb *msgb)
> +{
> + uint8_t *data = msgb_push(msgb, 1);
>
> -/* Send response to a mobile-originated ProcessUnstructuredSS-Request */
> -int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
> - const struct msgb *in_msg, const char *response_text,
> - const struct ussd_request *req)
> + data[0] = msgb->len - 1;
> + return data;
> +}
> +
> +/* Compose universial USSD packet invoke/return_result payload */
> +struct msgb *gsm0480_compose_ussd_component(struct ss_request* req)
> {
> struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD RSP");
> - struct gsm48_hdr *gh;
> uint8_t *ptr8;
> - int response_len;
>
> /* First put the payload text into the message */
> ptr8 = msgb_put(msg, 0);
> - gsm_7bit_encode_n_ussd(ptr8, msgb_tailroom(msg), response_text, &response_len);
> - msgb_put(msg, response_len);
> +
> + memcpy(ptr8, req->ussd_text, req->ussd_text_len);
> + msgb_put(msg, req->ussd_text_len);
>
> /* Then wrap it as an Octet String */
> - msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG);
> + msgb_wrap_with_ASN1_TL(msg, ASN1_OCTET_STRING_TAG);
>
> /* Pre-pend the DCS octet string */
> - msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F);
> + msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, req->ussd_text_language);
>
> /* Then wrap these as a Sequence */
> - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
> -
> - /* Pre-pend the operation code */
> - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE,
> - GSM0480_OP_CODE_PROCESS_USS_REQ);
> -
> - /* Wrap the operation code and IA5 string as a sequence */
> - msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG);
> + msgb_wrap_with_ASN1_TL(msg, GSM_0480_SEQUENCE_TAG);
> +
> + if (req->component_type == GSM0480_CTYPE_RETURN_RESULT) {
> + /* Pre-pend the operation code */
> + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode);
> +
> + /* Wrap the operation code and IA5 string as a sequence */
> + msgb_wrap_with_ASN1_TL(msg, GSM_0480_SEQUENCE_TAG);
> +
> + /* Pre-pend the invoke ID */
> + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
> + } else if (req->component_type == GSM0480_CTYPE_INVOKE) {
> + /* Pre-pend the operation code */
> + msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, req->opcode);
> +
> + /* Pre-pend the invoke ID */
> + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
> + } else {
> + abort();
> + }
> +
> + /* Wrap this up as an Invoke or a Return Result component */
> + msgb_wrap_with_ASN1_TL(msg, req->component_type);
> + return msg;
> +}
>
> - /* Pre-pend the invoke ID */
> - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
> +#ifndef NO_GSM0480_SEND_FUNC
>
> - /* Wrap this up as a Return Result component */
> - msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT);
> +int gsm0480_send_component(struct gsm_subscriber_connection *conn,
> + struct msgb *msg,
> + struct ss_header* reqhdr)
> +{
> + struct gsm48_hdr *gh;
>
> - /* Wrap the component in a Facility message */
> - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
> + if (reqhdr->message_type == GSM0480_MTYPE_REGISTER ||
> + reqhdr->message_type == GSM0480_MTYPE_RELEASE_COMPLETE) {
> + /* Wrap the component in a Facility message, it's not ASN1 */
> + msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
> + } else if (reqhdr->message_type == GSM0480_MTYPE_FACILITY) {
> + /* For GSM0480_MTYPE_FACILITY it's LV not TLV */
> + msgb_wrap_with_L(msg);
> + } else {
> + abort();
> + }
>
> /* And finally pre-pend the L3 header */
> gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
> - gh->proto_discr = GSM48_PDISC_NC_SS | req->transaction_id
> + gh->proto_discr = GSM48_PDISC_NC_SS | reqhdr->transaction_id
> | (1<<7); /* TI direction = 1 */
> - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
> + gh->msg_type = reqhdr->message_type;
> +
> + DEBUGP(DSS, "Sending SS to mobile: %s\n", msgb_hexdump(msg));
>
> return gsm0808_submit_dtap(conn, msg, 0, 0);
> }
>
> +
> int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
> - const struct msgb *in_msg,
> - const struct ussd_request *req)
> + uint8_t invoke_id,
> + uint8_t transaction_id)
> {
> struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 USSD REJ");
> - struct gsm48_hdr *gh;
> + struct ss_header ssh;
>
> /* First insert the problem code */
> msgb_push_TLV1(msg, GSM_0480_PROBLEM_CODE_TAG_GENERAL,
> GSM_0480_GEN_PROB_CODE_UNRECOGNISED);
>
> /* Before it insert the invoke ID */
> - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, req->invoke_id);
> + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
>
> /* Wrap this up as a Reject component */
> - msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT);
> -
> - /* Wrap the component in a Facility message */
> - msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
> + msgb_wrap_with_ASN1_TL(msg, GSM0480_CTYPE_REJECT);
>
> - /* 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 |= req->transaction_id | (1<<7); /* TI direction = 1 */
> - gh->msg_type = GSM0480_MTYPE_RELEASE_COMPLETE;
> -
> - return gsm0808_submit_dtap(conn, msg, 0, 0);
> + /* Prepare data for L3 header */
> + ssh.transaction_id = transaction_id;
> + ssh.message_type = GSM0480_MTYPE_RELEASE_COMPLETE;
> + return gsm0480_send_component(conn, msg, &ssh);
> }
>
> int gsm0480_send_ussdNotify(struct gsm_subscriber_connection *conn, int level, const char *text)
> @@ -173,3 +217,5 @@ int gsm0480_send_releaseComplete(struct gsm_subscriber_connection *conn)
>
> return gsm0808_submit_dtap(conn, msg, 0, 0);
> }
> +
> +#endif
> diff --git a/openbsc/src/libmsc/ussd.c b/openbsc/src/libmsc/ussd.c
> index 7f01eae..3cafe02 100644
> --- a/openbsc/src/libmsc/ussd.c
> +++ b/openbsc/src/libmsc/ussd.c
> @@ -33,41 +33,71 @@
> #include <openbsc/gsm_subscriber.h>
> #include <openbsc/debug.h>
> #include <openbsc/osmo_msc.h>
> +#include <openbsc/ussd.h>
> +#include <osmocom/gsm/gsm_utils.h>
> +#include <osmocom/gsm/gsm0480.h>
>
> /* Declarations of USSD strings to be recognised */
> const char USSD_TEXT_OWN_NUMBER[] = "*#100#";
>
> /* Forward declarations of network-specific handler functions */
> -static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req);
> +static int send_own_number(struct gsm_subscriber_connection *conn,
> + const struct ss_header *reqhdr,
> + const struct ss_request *req);
>
>
> /* Entrypoint - handler function common to all mobile-originated USSDs */
> int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
> {
> int rc;
> - struct ussd_request req;
> + struct ss_header reqhdr;
> + struct ss_request req;
> + char request_string[MAX_LEN_USSD_STRING + 1];
> struct gsm48_hdr *gh;
>
> memset(&req, 0, sizeof(req));
> + memset(&reqhdr, 0, sizeof(reqhdr));
> gh = msgb_l3(msg);
> - rc = gsm0480_decode_ussd_request(gh, msgb_l3len(msg), &req);
> + rc = gsm0480_decode_ss_request(gh, msgb_l3len(msg), &reqhdr);
> if (!rc) {
> - DEBUGP(DMM, "Unhandled SS\n");
> - rc = gsm0480_send_ussd_reject(conn, msg, &req);
> + DEBUGP(DSS, "Incorrect SS header\n");
> msc_release_connection(conn);
> return rc;
> }
>
> - /* Release-Complete */
> - if (req.text[0] == '\0')
> + rc = gsm0480_parse_ss_facility(gh->data + reqhdr.component_offset,
> + reqhdr.component_length,
> + &req);
> + if (!rc) {
> + DEBUGP(DSS, "Unhandled SS\n");
> + /* TODO req.invoke_id may not be set!!! */
> + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id);
> + msc_release_connection(conn);
> + return rc;
> + }
> +
> + if (reqhdr.message_type == GSM0480_MTYPE_RELEASE_COMPLETE)
> return 0;
>
> - if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)req.text)) {
> - DEBUGP(DMM, "USSD: Own number requested\n");
> - rc = send_own_number(conn, msg, &req);
> + if (reqhdr.message_type != GSM0480_MTYPE_REGISTER ||
> + req.component_type != GSM0480_CTYPE_INVOKE ||
> + req.opcode != GSM0480_OP_CODE_PROCESS_USS_REQ ||
> + req.ussd_text_language != 0x0f)
> + {
> + DEBUGP(DSS, "Unexpected SS\n");
> + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id);
> + msc_release_connection(conn);
> + return rc;
> + }
> +
> + gsm_7bit_decode_n_ussd(request_string, MAX_LEN_USSD_STRING, req.ussd_text, req.ussd_text_len);
> +
> + if (!strcmp(USSD_TEXT_OWN_NUMBER, (const char *)request_string)) {
> + DEBUGP(DSS, "USSD: Own number requested\n");
> + rc = send_own_number(conn, &reqhdr, &req);
> } else {
> - DEBUGP(DMM, "Unhandled USSD %s\n", req.text);
> - rc = gsm0480_send_ussd_reject(conn, msg, &req);
> + DEBUGP(DSS, "Unhandled USSD %s\n", request_string);
> + rc = gsm0480_send_ussd_reject(conn, req.invoke_id, reqhdr.transaction_id);
> }
>
> /* check if we can release it */
> @@ -76,12 +106,33 @@ int handle_rcv_ussd(struct gsm_subscriber_connection *conn, struct msgb *msg)
> }
>
> /* A network-specific handler function */
> -static int send_own_number(struct gsm_subscriber_connection *conn, const struct msgb *msg, const struct ussd_request *req)
> +static int send_own_number(struct gsm_subscriber_connection *conn,
> + const struct ss_header *reqhdr,
> + const struct ss_request *req)
> {
> + struct ss_request rss;
> + struct ss_header rssh;
> +
> char *own_number = conn->subscr->extension;
> char response_string[GSM_EXTENSION_LENGTH + 20];
> + int response_len;
>
> /* Need trailing CR as EOT character */
> snprintf(response_string, sizeof(response_string), "Your extension is %s\r", own_number);
> - return gsm0480_send_ussd_response(conn, msg, response_string, req);
> +
> + memset(&rss, 0, sizeof(rss));
> + gsm_7bit_encode_n_ussd(rss.ussd_text, MAX_LEN_USSD_STRING, response_string, &response_len);
> + rss.ussd_text_len = response_len;
> + rss.ussd_text_language = 0x0f;
> +
> + rss.component_type = GSM0480_CTYPE_RETURN_RESULT;
> + rss.invoke_id = req->invoke_id;
> + rss.opcode = GSM0480_OP_CODE_PROCESS_USS_REQ;
> +
> + rssh.message_type = GSM0480_MTYPE_RELEASE_COMPLETE;
> + rssh.transaction_id = reqhdr->transaction_id;
> +
> + return gsm0480_send_component(conn,
> + gsm0480_compose_ussd_component(&rss),
> + &rssh);
> }
> --
> 1.9.1
>
--
- Neels Hofmeyr <nhofmeyr at sysmocom.de> http://www.sysmocom.de/
=======================================================================
* sysmocom - systems for mobile communications GmbH
* Alt-Moabit 93
* 10559 Berlin, Germany
* Sitz / Registered office: Berlin, HRB 134158 B
* Geschäftsführer / Managing Directors: Holger Freyther, Harald Welte
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.osmocom.org/pipermail/openbsc/attachments/20160426/77b2cc8c/attachment.bin>