blob: edad38c34b8c6c3bd111eae3b1ce79c0aebea82a [file] [log] [blame]
Holger Hans Peter Freytherb408d792010-11-05 11:21:18 +01001/* (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
2 * (C) 2009-2010 by On-Waves
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 */
20
21#include <openbsc/osmo_bsc.h>
Holger Hans Peter Freyther0a104d82010-11-05 18:41:04 +010022#include <openbsc/osmo_msc_data.h>
23#include <openbsc/gsm_04_80.h>
Holger Hans Peter Freytherbe984442010-11-15 13:34:03 +010024#include <openbsc/gsm_subscriber.h>
Holger Hans Peter Freyther5035bba2010-11-05 11:31:08 +010025#include <openbsc/debug.h>
Holger Hans Peter Freytherbe984442010-11-15 13:34:03 +010026#include <openbsc/paging.h>
27
28#include <stdlib.h>
Holger Hans Peter Freyther5035bba2010-11-05 11:31:08 +010029
30static void handle_lu_request(struct gsm_subscriber_connection *conn,
31 struct msgb *msg)
32{
33 struct gsm48_hdr *gh;
34 struct gsm48_loc_upd_req *lu;
35 struct gsm48_loc_area_id lai;
36 struct gsm_network *net;
37
38 if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
39 LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
40 return;
41 }
42
43 net = conn->bts->network;
44
45 gh = msgb_l3(msg);
46 lu = (struct gsm48_loc_upd_req *) gh->data;
47
48 gsm48_generate_lai(&lai, net->country_code, net->network_code,
49 conn->bts->location_area_code);
50
51 if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
52 LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
53 conn->sccp_con->new_subscriber = 1;
54 }
55}
Holger Hans Peter Freytherb408d792010-11-05 11:21:18 +010056
Holger Hans Peter Freytherbe984442010-11-15 13:34:03 +010057/* we will need to stop the paging request */
58static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
59{
60 uint8_t mi_type;
61 char mi_string[GSM48_MI_SIZE];
62 struct gsm48_hdr *gh;
63 struct gsm48_pag_resp *resp;
64 struct gsm_subscriber *subscr;
65
66 if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
67 LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
68 return -1;
69 }
70
71 gh = msgb_l3(msg);
72 resp = (struct gsm48_pag_resp *) &gh->data[0];
73
74 gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
75 mi_string, &mi_type);
76 DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
77 mi_type, mi_string);
78
79 switch (mi_type) {
80 case GSM_MI_TYPE_TMSI:
81 subscr = subscr_active_by_tmsi(conn->bts->network,
82 tmsi_from_string(mi_string));
83 break;
84 case GSM_MI_TYPE_IMSI:
85 subscr = subscr_active_by_imsi(conn->bts->network, mi_string);
86 break;
87 }
88
89 if (!subscr) {
90 LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
91 return -1;
92 }
93
Harald Weltefe3e0cb2010-12-15 15:33:08 +010094 paging_request_stop(conn->bts, subscr, conn, msg);
Holger Hans Peter Freytherbe984442010-11-15 13:34:03 +010095 subscr_put(subscr);
96 return 0;
97}
98
Holger Hans Peter Freytherb408d792010-11-05 11:21:18 +010099/**
100 * This is used to scan a message for extra functionality of the BSC. This
101 * includes scanning for location updating requests/acceptd and then send
102 * a welcome USSD message to the subscriber.
103 */
104int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
105{
Holger Hans Peter Freyther5035bba2010-11-05 11:31:08 +0100106 struct gsm48_hdr *gh = msgb_l3(msg);
107 uint8_t pdisc = gh->proto_discr & 0x0f;
108 uint8_t mtype = gh->msg_type & 0xbf;
109
110 if (pdisc == GSM48_PDISC_MM) {
111 if (mtype == GSM48_MT_MM_LOC_UPD_REQUEST)
112 handle_lu_request(conn, msg);
Holger Hans Peter Freytherbe984442010-11-15 13:34:03 +0100113 } else if (pdisc == GSM48_PDISC_RR) {
114 if (mtype == GSM48_MT_RR_PAG_RESP)
115 handle_page_resp(conn, msg);
Holger Hans Peter Freyther5035bba2010-11-05 11:31:08 +0100116 }
117
Holger Hans Peter Freytherb408d792010-11-05 11:21:18 +0100118 return 0;
119}
Holger Hans Peter Freythera6af88f2010-11-05 18:11:19 +0100120
Holger Hans Peter Freyther0a104d82010-11-05 18:41:04 +0100121static void send_welcome_ussd(struct gsm_subscriber_connection *conn)
122{
123 struct gsm_network *net;
124 net = conn->bts->network;
125
126 if (!net->msc_data->ussd_welcome_txt)
127 return;
128
129 gsm0480_send_ussdNotify(conn, 1, net->msc_data->ussd_welcome_txt);
130 gsm0480_send_releaseComplete(conn);
131}
132
Holger Hans Peter Freythera6af88f2010-11-05 18:11:19 +0100133/**
134 * Messages coming back from the MSC.
135 */
136int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
137{
Holger Hans Peter Freyther0a104d82010-11-05 18:41:04 +0100138 struct gsm_network *net;
139 struct gsm48_loc_area_id *lai;
140 struct gsm48_hdr *gh;
141 uint8_t mtype;
142
143 if (msgb_l3len(msg) < sizeof(*gh)) {
144 LOGP(DMSC, LOGL_ERROR, "GSM48 header does not fit.\n");
145 return -1;
146 }
147
148 gh = (struct gsm48_hdr *) msgb_l3(msg);
149 mtype = gh->msg_type & 0xbf;
150 net = conn->bts->network;
151
152 if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
Holger Hans Peter Freyther3e0525f2010-11-05 19:43:07 +0100153 if (net->msc_data->core_ncc != -1 ||
154 net->msc_data->core_mcc != -1) {
Holger Hans Peter Freyther0a104d82010-11-05 18:41:04 +0100155 if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
156 lai = (struct gsm48_loc_area_id *) &gh->data[0];
157 gsm48_generate_lai(lai, net->country_code,
158 net->network_code,
159 conn->bts->location_area_code);
160 }
161 }
162
163 if (conn->sccp_con->new_subscriber)
164 send_welcome_ussd(conn);
165 }
166
Holger Hans Peter Freythera6af88f2010-11-05 18:11:19 +0100167 return 0;
168}