diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-05-13 19:27:34 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-05-13 21:29:11 +0200 |
commit | 24c9fc170034c85519958bc61ba54c4e0e5cd149 (patch) | |
tree | 39a3287b4c8b4193c7ea80b9ea1e0171c6676fa1 /openbsc/src/gprs/gsm_04_08_gprs.c | |
parent | 4cc605ac24b647a85ca6760997cb178eacab021c (diff) |
[GPRS] Rename gsm_04_08_gprs.c to gprs_gmm.c
GMM refers to GPRS Mobility Management.
Diffstat (limited to 'openbsc/src/gprs/gsm_04_08_gprs.c')
-rw-r--r-- | openbsc/src/gprs/gsm_04_08_gprs.c | 762 |
1 files changed, 0 insertions, 762 deletions
diff --git a/openbsc/src/gprs/gsm_04_08_gprs.c b/openbsc/src/gprs/gsm_04_08_gprs.c deleted file mode 100644 index 4a42113f0..000000000 --- a/openbsc/src/gprs/gsm_04_08_gprs.c +++ /dev/null @@ -1,762 +0,0 @@ -/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface - * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ - -/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <errno.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <openbsc/db.h> -#include <osmocore/msgb.h> -#include <osmocore/tlv.h> -#include <osmocore/gsm_utils.h> -#include <osmocore/signal.h> -#include <osmocore/talloc.h> - -#include <openbsc/debug.h> -#include <openbsc/gsm_data.h> -#include <openbsc/gsm_subscriber.h> -#include <openbsc/gsm_04_08.h> -#include <openbsc/gsm_04_08_gprs.h> -#include <openbsc/paging.h> -#include <openbsc/transaction.h> -#include <openbsc/gprs_bssgp.h> -#include <openbsc/gprs_llc.h> -#include <openbsc/gprs_sgsn.h> - -/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */ -struct value_string gmm_cause_names[] = { - /* FIXME */ - { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" }, - { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" }, - { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL, - "Message type non-existant or not implemented" }, - { GMM_CAUSE_MSGT_INCOMP_P_STATE, - "Message type not compatible with protocol state" }, - { GMM_CAUSE_IE_NOTEXIST_NOTIMPL, - "Information element non-existent or not implemented" }, - { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" }, - { GMM_CAUSE_MSG_INCOMP_P_STATE, - "Message not compatible with protocol state " }, - { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" }, - { 0, NULL } -}; - -/* 10.5.6.6 SM Cause / Table 10.5.157 */ -struct value_string gsm_cause_names[] = { - { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" }, - { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" }, - { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" }, - { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" }, - { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" }, - { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" }, - { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" }, - { GSM_CAUSE_REQ_SERV_OPT_NOTSUB, - "Requested service option not subscribed" }, - { GSM_CAUSE_SERV_OPT_TEMP_OOO, - "Service option temporarily out of order" }, - { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" }, - { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" }, - { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" }, - { GSM_CAUSE_NET_FAIL, "Network Failure" }, - { GSM_CAUSE_REACT_RQD, "Reactivation required" }, - { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " }, - { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" }, - { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" }, - { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" }, - { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL, - "Message type non-existant or not implemented" }, - { GSM_CAUSE_MSGT_INCOMP_P_STATE, - "Message type not compatible with protocol state" }, - { GSM_CAUSE_IE_NOTEXIST_NOTIMPL, - "Information element non-existent or not implemented" }, - { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" }, - { GSM_CAUSE_MSG_INCOMP_P_STATE, - "Message not compatible with protocol state " }, - { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" }, - { 0, NULL } -}; - -static const char *att_name(uint8_t type) -{ - switch (type) { - case GPRS_ATT_T_ATTACH: - return "GPRS attach"; - case GPRS_ATT_T_ATT_WHILE_IMSI: - return "GPRS attach while IMSI attached"; - case GPRS_ATT_T_COMBINED: - return "Combined GPRS/IMSI attach"; - default: - return "unknown"; - } -} - -static const char *upd_name(uint8_t type) -{ - switch (type) { - case GPRS_UPD_T_RA: - return "RA updating"; - case GPRS_UPD_T_RA_LA: - return "combined RA/LA updating"; - case GPRS_UPD_T_RA_LA_IMSI_ATT: - return "combined RA/LA updating + IMSI attach"; - case GPRS_UPD_T_PERIODIC: - return "periodic updating"; - } - return "unknown"; -} - -/* Send a message through the underlying layer */ -static int gsm48_gmm_sendmsg(struct msgb *msg, int command) -{ - /* caller needs to provide TLLI, BVCI and NSEI */ - return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command); -} - -/* copy identifiers from old message to new message, this - * is required so lower layers can route it correctly */ -static void gmm_copy_id(struct msgb *msg, const struct msgb *old) -{ - msgb_tlli(msg) = msgb_tlli(old); - msgb_bvci(msg) = msgb_bvci(old); - msgb_nsei(msg) = msgb_nsei(old); -} - -static struct gsm48_qos default_qos = { - .delay_class = 4, /* best effort */ - .reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT, - .peak_tput = GSM48_QOS_PEAK_TPUT_32000bps, - .preced_class = GSM48_QOS_PC_NORMAL, - .mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT, - .traf_class = GSM48_QOS_TC_INTERACTIVE, - .deliv_order = GSM48_QOS_DO_UNORDERED, - .deliv_err_sdu = GSM48_QOS_ERRSDU_YES, - .max_sdu_size = GSM48_QOS_MAXSDU_1520, - .max_bitrate_up = GSM48_QOS_MBRATE_63k, - .max_bitrate_down = GSM48_QOS_MBRATE_63k, - .resid_ber = GSM48_QOS_RBER_5e_2, - .sdu_err_ratio = GSM48_QOS_SERR_1e_2, - .handling_prio = 3, - .xfer_delay = 0x10, /* 200ms */ - .guar_bitrate_up = GSM48_QOS_MBRATE_0k, - .guar_bitrate_down = GSM48_QOS_MBRATE_0k, - .sig_ind = 0, /* not optimised for signalling */ - .max_bitrate_down_ext = 0, /* use octet 9 */ - .guar_bitrate_down_ext = 0, /* use octet 13 */ -}; - -/* Chapter 9.4.2: Attach accept */ -static int gsm48_tx_gmm_att_ack(struct msgb *old_msg) -{ - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_hdr *gh; - struct gsm48_attach_ack *aa; - struct gprs_ra_id ra_id; - - DEBUGP(DMM, "<- GPRS ATTACH ACCEPT\n"); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_MM_GPRS; - gh->msg_type = GSM48_MT_GMM_ATTACH_ACK; - - aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa)); - aa->force_stby = 0; /* not indicated */ - aa->att_result = 1; /* GPRS only */ - aa->ra_upd_timer = GPRS_TMR_MINUTE | 10; - aa->radio_prio = 4; /* lowest */ - bssgp_parse_cell_id(&ra_id, msgb_bcid(old_msg)); - gsm48_construct_ra(aa->ra_id.digits, &ra_id); - - /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */ - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Chapter 9.4.5: Attach reject */ -static int gsm48_tx_gmm_att_rej(struct msgb *old_msg, uint8_t gmm_cause) -{ - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_hdr *gh; - - DEBUGP(DMM, "<- GPRS ATTACH REJECT\n"); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); - gh->proto_discr = GSM48_PDISC_MM_GPRS; - gh->msg_type = GSM48_MT_GMM_ATTACH_REJ; - gh->data[0] = gmm_cause; - - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Transmit Chapter 9.4.12 Identity Request */ -static int gsm48_tx_gmm_id_req(struct msgb *old_msg, uint8_t id_type) -{ - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_hdr *gh; - - DEBUGP(DMM, "-> GPRS IDENTITY REQUEST: mi_type=%02x\n", id_type); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); - gh->proto_discr = GSM48_PDISC_MM_GPRS; - gh->msg_type = GSM48_MT_GMM_ID_REQ; - /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */ - gh->data[0] = id_type & 0xf; - - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Check if we can already authorize a subscriber */ -static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx, struct msgb *msg) -{ - if (strlen(ctx->imei) && strlen(ctx->imsi)) { - ctx->mm_state = GMM_REGISTERED_NORMAL; - return gsm48_tx_gmm_att_ack(msg); - } - if (!strlen(ctx->imei)) - return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMEI); - - if (!strlen(ctx->imsi)) - return gsm48_tx_gmm_id_req(msg, GSM_MI_TYPE_IMSI); - - return 0; -} - -/* Parse Chapter 9.4.13 Identity Response */ -static int gsm48_rx_gmm_id_resp(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK; - char mi_string[GSM48_MI_SIZE]; - struct gprs_ra_id ra_id; - struct sgsn_mm_ctx *ctx; - - gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]); - DEBUGP(DMM, "GMM IDENTITY RESPONSE: mi_type=0x%02x MI(%s) ", - mi_type, mi_string); - - bssgp_parse_cell_id(&ra_id, msgb_bcid(msg)); - ctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id); - if (!ctx) { - DEBUGP(DMM, "from unknown TLLI 0x%08x?!?\n", msgb_tlli(msg)); - return -EINVAL; - } - - switch (mi_type) { - case GSM_MI_TYPE_IMSI: - /* we already have a mm context with current TLLI, but no - * P-TMSI / IMSI yet. What we now need to do is to fill - * this initial context with data from the HLR */ - strncpy(ctx->imsi, mi_string, sizeof(ctx->imei)); - break; - case GSM_MI_TYPE_IMEI: - strncpy(ctx->imei, mi_string, sizeof(ctx->imei)); - break; - case GSM_MI_TYPE_IMEISV: - break; - } - - DEBUGPC(DMM, "\n"); - /* Check if we can let the mobile station enter */ - return gsm48_gmm_authorize(ctx, msg); -} - -static void attach_rej_cb(void *data) -{ - struct sgsn_mm_ctx *ctx = data; - - /* FIXME: determine through which BTS/TRX to send this */ - //gsm48_tx_gmm_att_rej(ctx->tlli, GMM_CAUSE_MS_ID_NOT_DERIVED); - ctx->mm_state = GMM_DEREGISTERED; - /* FIXME: release the context */ -} - -static void schedule_reject(struct sgsn_mm_ctx *ctx) -{ - ctx->T = 3370; - ctx->timer.cb = attach_rej_cb; - ctx->timer.data = ctx; - bsc_schedule_timer(&ctx->timer, 6, 0); -} - -/* Section 9.4.1 Attach request */ -static int gsm48_rx_gmm_att_req(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - uint8_t *cur = gh->data, *msnc, *mi, *old_ra_info; - uint8_t msnc_len, att_type, mi_len, mi_type; - uint16_t drx_par; - uint32_t tmsi; - char mi_string[GSM48_MI_SIZE]; - struct gprs_ra_id ra_id; - uint16_t cid; - struct sgsn_mm_ctx *ctx; - - DEBUGP(DMM, "GMM ATTACH REQUEST "); - - /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either - * with a foreign TLLI (P-TMSI that was allocated to the MS before), - * or with random TLLI. */ - - cid = bssgp_parse_cell_id(&ra_id, msgb_bcid(msg)); - - /* MS network capability 10.5.5.12 */ - msnc_len = *cur++; - msnc = cur; - if (msnc_len > 2) - goto err_inval; - cur += msnc_len; - - /* aTTACH Type 10.5.5.2 */ - att_type = *cur++ & 0x0f; - - /* DRX parameter 10.5.5.6 */ - drx_par = *cur++; - drx_par |= *cur++ << 8; - - /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */ - mi_len = *cur++; - mi = cur; - if (mi_len > 8) - goto err_inval; - mi_type = *mi & GSM_MI_TYPE_MASK; - cur += mi_len; - - gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len); - - DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string, att_name(att_type)); - - /* Old routing area identification 10.5.5.15 */ - old_ra_info = cur; - cur += 6; - - /* MS Radio Access Capability 10.5.5.12a */ - - /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */ - - switch (mi_type) { - case GSM_MI_TYPE_IMSI: - /* Try to find MM context based on IMSI */ - ctx = sgsn_mm_ctx_by_imsi(mi_string); - if (!ctx) { -#if 0 - return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN); -#else - /* As a temorary hack, we simply assume that the IMSI exists */ - ctx = sgsn_mm_ctx_alloc(0, &ra_id); - if (!ctx) - return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_NET_FAIL); - strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi)); -#endif - } - /* FIXME: Start some timer */ - ctx->mm_state = GMM_COMMON_PROC_INIT; - ctx->tlli = msgb_tlli(msg); - break; - case GSM_MI_TYPE_TMSI: - tmsi = strtoul(mi_string, NULL, 10); - /* Try to find MM context based on P-TMSI */ - ctx = sgsn_mm_ctx_by_ptmsi(tmsi); - if (!ctx) { - ctx = sgsn_mm_ctx_alloc(msgb_tlli(msg), &ra_id); - /* FIXME: Start some timer */ - ctx->mm_state = GMM_COMMON_PROC_INIT; - ctx->tlli = msgb_tlli(msg); - } - break; - default: - return 0; - } - /* Update MM Context with currient RA and Cell ID */ - ctx->ra = ra_id; - ctx->cell_id = cid; - - /* FIXME: allocate a new P-TMSI (+ P-TMSI signature) */ - /* FIXME: update the TLLI with the new local TLLI based on the P-TMSI */ - - DEBUGPC(DMM, "\n"); - - return ctx ? gsm48_gmm_authorize(ctx, msg) : 0; - -err_inval: - DEBUGPC(DMM, "\n"); - return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_SEM_INCORR_MSG); -} - -/* Chapter 9.4.15: Routing area update accept */ -static int gsm48_tx_gmm_ra_upd_ack(struct msgb *old_msg) -{ - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_hdr *gh; - struct gsm48_ra_upd_ack *rua; - struct gprs_ra_id ra_id; - - DEBUGP(DMM, "<- ROUTING AREA UPDATE ACCEPT\n"); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_MM_GPRS; - gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK; - - rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua)); - rua->force_stby = 0; /* not indicated */ - rua->upd_result = 0; /* RA updated */ - rua->ra_upd_timer = GPRS_TMR_MINUTE | 10; - - bssgp_parse_cell_id(&ra_id, msgb_bcid(old_msg)); - gsm48_construct_ra(rua->ra_id.digits, &ra_id); - - /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */ - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Chapter 9.4.17: Routing area update reject */ -static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause) -{ - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_hdr *gh; - - DEBUGP(DMM, "<- ROUTING AREA UPDATE REJECT\n"); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2); - gh->proto_discr = GSM48_PDISC_MM_GPRS; - gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ; - gh->data[0] = cause; - gh->data[1] = 0; /* ? */ - - /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */ - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Chapter 9.4.14: Routing area update request */ -static int gsm48_rx_gmm_ra_upd_req(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - struct sgsn_mm_ctx *mmctx; - uint8_t *cur = gh->data; - struct gprs_ra_id old_ra_id; - uint8_t upd_type; - - /* Update Type 10.5.5.18 */ - upd_type = *cur++ & 0x0f; - - DEBUGP(DMM, "GMM RA UPDATE REQUEST type=\"%s\" ", upd_name(upd_type)); - - /* Old routing area identification 10.5.5.15 */ - gsm48_parse_ra(&old_ra_id, cur); - cur += 6; - - /* MS Radio Access Capability 10.5.5.12a */ - - /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status, - * DRX parameter, MS network capability */ - - switch (upd_type) { - case GPRS_UPD_T_RA_LA: - case GPRS_UPD_T_RA_LA_IMSI_ATT: - DEBUGPC(DMM, " unsupported in Mode III, is your SI13 corrupt?\n"); - return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC); - break; - case GPRS_UPD_T_RA: - case GPRS_UPD_T_PERIODIC: - break; - } - - /* Look-up the MM context based on old RA-ID and TLLI */ - mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &old_ra_id); - if (!mmctx || mmctx->mm_state == GMM_DEREGISTERED) { - /* The MS has to perform GPRS attach */ - DEBUGPC(DMM, " REJECT\n"); - return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_IMPL_DETACHED); - } - - /* Update the MM context with the new RA-ID */ - bssgp_parse_cell_id(&mmctx->ra, msgb_bcid(msg)); - /* Update the MM context with the new TLLI */ - mmctx->tlli = msgb_tlli(msg); - /* FIXME: Update the MM context with the MS radio acc capabilities */ - /* FIXME: Update the MM context with the MS network capabilities */ - - DEBUGPC(DMM, " ACCEPT\n"); - return gsm48_tx_gmm_ra_upd_ack(msg); -} - -static int gsm48_rx_gmm_status(struct msgb *msg) -{ - struct gsm48_hdr *gh = msgb_l3(msg); - - DEBUGP(DMM, "GPRS MM STATUS (cause: %s)\n", - get_value_string(gmm_cause_names, gh->data[0])); - - return 0; -} - -/* GPRS Mobility Management */ -static int gsm0408_rcv_gmm(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - int rc; - - switch (gh->msg_type) { - case GSM48_MT_GMM_RA_UPD_REQ: - rc = gsm48_rx_gmm_ra_upd_req(msg); - break; - case GSM48_MT_GMM_ATTACH_REQ: - rc = gsm48_rx_gmm_att_req(msg); - break; - case GSM48_MT_GMM_ID_RESP: - rc = gsm48_rx_gmm_id_resp(msg); - break; - case GSM48_MT_GMM_STATUS: - rc = gsm48_rx_gmm_status(msg); - break; - case GSM48_MT_GMM_RA_UPD_COMPL: - /* only in case SGSN offered new P-TMSI */ - case GSM48_MT_GMM_ATTACH_COMPL: - /* only in case SGSN offered new P-TMSI */ - case GSM48_MT_GMM_DETACH_REQ: - case GSM48_MT_GMM_PTMSI_REALL_COMPL: - case GSM48_MT_GMM_AUTH_CIPH_RESP: - DEBUGP(DMM, "Unimplemented GSM 04.08 GMM msg type 0x%02x\n", - gh->msg_type); - break; - default: - DEBUGP(DMM, "Unknown GSM 04.08 GMM msg type 0x%02x\n", - gh->msg_type); - break; - } - - return rc; -} - -static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr) -{ - uint8_t v[6]; - - v[0] = PDP_TYPE_ORG_IETF; - v[1] = PDP_TYPE_N_IETF_IPv4; - *(uint32_t *)(v+2) = htonl(ipaddr); - - msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v); -} - -static void msgb_put_pdp_addr_ppp(struct msgb *msg) -{ - uint8_t v[2]; - - v[0] = PDP_TYPE_ORG_ETSI; - v[1] = PDP_TYPE_N_ETSI_PPP; - - msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v); -} - -/* Section 9.5.2: Ativate PDP Context Accept */ -static int gsm48_tx_gsm_act_pdp_acc(struct msgb *old_msg, struct gsm48_act_pdp_ctx_req *req) -{ - struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg); - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_act_pdp_ctx_ack *act_ack; - struct gsm48_hdr *gh; - uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */ - - DEBUGP(DMM, "<- ACTIVATE PDP CONTEXT ACK\n"); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4); - gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK; - - /* Negotiated LLC SAPI */ - msgb_v_put(msg, req->req_llc_sapi); - /* copy QoS parameters from original request */ - msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos); - /* Radio priority 10.5.7.2 */ - msgb_v_put(msg, 4); - /* PDP address */ - msgb_put_pdp_addr_ipv4(msg, 0x01020304); - /* Optional: Protocol configuration options */ - /* Optional: Packet Flow Identifier */ - - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Section 9.5.9: Deactivate PDP Context Accept */ -static int gsm48_tx_gsm_deact_pdp_acc(struct msgb *old_msg) -{ - struct gsm48_hdr *old_gh = (struct gsm48_hdr *) msgb_gmmh(old_msg); - struct msgb *msg = gsm48_msgb_alloc(); - struct gsm48_hdr *gh; - uint8_t transaction_id = ((old_gh->proto_discr >> 4) ^ 0x8); /* flip */ - - DEBUGP(DMM, "<- DEACTIVATE PDP CONTEXT ACK\n"); - - gmm_copy_id(msg, old_msg); - - gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); - gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4); - gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK; - - return gsm48_gmm_sendmsg(msg, 0); -} - -/* Section 9.5.1: Activate PDP Context Request */ -static int gsm48_rx_gsm_act_pdp_req(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data; - uint8_t *pdp_addr_lv = act_req->data; - uint8_t req_qos_len, req_pdpa_len; - uint8_t *req_qos, *req_pdpa; - struct tlv_parsed tp; - - DEBUGP(DMM, "ACTIVATE PDP CONTEXT REQ: "); - req_qos_len = act_req->data[0]; - req_qos = act_req->data + 1; /* 10.5.6.5 */ - req_pdpa_len = act_req->data[1 + req_qos_len]; - req_pdpa = act_req->data + 1 + req_qos_len + 1; /* 10.5.6.4 */ - - switch (req_pdpa[0] & 0xf) { - case 0x0: - DEBUGPC(DMM, "ETSI "); - break; - case 0x1: - DEBUGPC(DMM, "IETF "); - break; - case 0xf: - DEBUGPC(DMM, "Empty "); - break; - } - - switch (req_pdpa[1]) { - case 0x21: - DEBUGPC(DMM, "IPv4 "); - if (req_pdpa_len >= 6) { - struct in_addr ia; - ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2))); - DEBUGPC(DMM, "%s ", inet_ntoa(ia)); - } - break; - case 0x57: - DEBUGPC(DMM, "IPv6 "); - if (req_pdpa_len >= 18) { - /* FIXME: print IPv6 address */ - } - break; - default: - DEBUGPC(DMM, "0x%02x ", req_pdpa[1]); - break; - } - - /* FIXME: parse TLV for AP name and protocol config options */ - if (TLVP_PRESENT(&tp, GSM48_IE_GSM_APN)) {} - if (TLVP_PRESENT(&tp, GSM48_IE_GSM_PROTO_CONF_OPT)) {} - - return gsm48_tx_gsm_act_pdp_acc(msg, act_req); -} - -/* Section 9.5.8: Deactivate PDP Context Request */ -static int gsm48_rx_gsm_deact_pdp_req(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - - DEBUGP(DMM, "DEACTIVATE PDP CONTEXT REQ (cause: %s)\n", - get_value_string(gsm_cause_names, gh->data[0])); - - return gsm48_tx_gsm_deact_pdp_acc(msg); -} - -static int gsm48_rx_gsm_status(struct msgb *msg) -{ - struct gsm48_hdr *gh = msgb_l3(msg); - - DEBUGP(DMM, "GPRS SM STATUS (cause: %s)\n", - get_value_string(gsm_cause_names, gh->data[0])); - - return 0; -} - -/* GPRS Session Management */ -static int gsm0408_rcv_gsm(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - int rc; - - switch (gh->msg_type) { - case GSM48_MT_GSM_ACT_PDP_REQ: - rc = gsm48_rx_gsm_act_pdp_req(msg); - break; - case GSM48_MT_GSM_DEACT_PDP_REQ: - rc = gsm48_rx_gsm_deact_pdp_req(msg); - case GSM48_MT_GSM_STATUS: - rc = gsm48_rx_gsm_status(msg); - break; - case GSM48_MT_GSM_REQ_PDP_ACT_REJ: - case GSM48_MT_GSM_ACT_AA_PDP_REQ: - case GSM48_MT_GSM_DEACT_AA_PDP_REQ: - DEBUGP(DMM, "Unimplemented GSM 04.08 GSM msg type 0x%02x\n", - gh->msg_type); - break; - default: - DEBUGP(DMM, "Unknown GSM 04.08 GSM msg type 0x%02x\n", - gh->msg_type); - break; - - } - - return rc; -} - -/* Main entry point for incoming 04.08 GPRS messages */ -int gsm0408_gprs_rcvmsg(struct msgb *msg) -{ - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); - uint8_t pdisc = gh->proto_discr & 0x0f; - int rc = -EINVAL; - - switch (pdisc) { - case GSM48_PDISC_MM_GPRS: - rc = gsm0408_rcv_gmm(msg); - break; - case GSM48_PDISC_SM_GPRS: - rc = gsm0408_rcv_gsm(msg); - break; - default: - DEBUGP(DMM, "Unknown GSM 04.08 discriminator 0x%02x\n", - pdisc); - break; - } - - return rc; -} |