Merge commit 'har/master'
This commit is contained in:
commit
712573b66a
|
@ -48,4 +48,9 @@ int db_sms_store(struct gsm_sms *sms);
|
|||
struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id);
|
||||
struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr);
|
||||
int db_sms_mark_sent(struct gsm_sms *sms);
|
||||
|
||||
/* APDU blob storage */
|
||||
int db_apdu_blob_store(struct gsm_subscriber *subscr,
|
||||
u_int8_t apdu_id_flags, u_int8_t len,
|
||||
u_int8_t *apdu);
|
||||
#endif /* _DB_H */
|
||||
|
|
|
@ -705,6 +705,8 @@ int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans);
|
|||
int generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi);
|
||||
|
||||
int gsm48_send_rr_release(struct gsm_lchan *lchan);
|
||||
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
|
||||
u_int8_t apdu_len, u_int8_t *apdu);
|
||||
|
||||
int bsc_upqueue(struct gsm_network *net);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_04_08.c gsm_data.c mncc.c \
|
|||
gsm_04_11.c telnet_interface.c subchan_demux.c \
|
||||
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
|
||||
input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c talloc_ctx.c \
|
||||
transaction.c rtp_proxy.c bsc_rll.c token_auth.c
|
||||
transaction.c rtp_proxy.c bsc_rll.c token_auth.c rrlp.c
|
||||
|
||||
libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
|
||||
|
||||
|
|
|
@ -930,6 +930,8 @@ static void patch_si_tables(struct gsm_bts *bts)
|
|||
(struct gsm48_system_information_type_3*)&si3;
|
||||
struct gsm48_system_information_type_4 *type_4 =
|
||||
(struct gsm48_system_information_type_4*)&si4;
|
||||
struct gsm48_system_information_type_5 *type_5 =
|
||||
(struct gsm48_system_information_type_5*)&si5;
|
||||
struct gsm48_system_information_type_6 *type_6 =
|
||||
(struct gsm48_system_information_type_6*)&si6;
|
||||
struct gsm48_loc_area_id lai;
|
||||
|
@ -969,6 +971,17 @@ static void patch_si_tables(struct gsm_bts *bts)
|
|||
type_3->rach_control.cell_bar = 0;
|
||||
type_4->rach_control.cell_bar = 0;
|
||||
}
|
||||
|
||||
/* FIXME: This is just for HAR */
|
||||
if (bts->c0->arfcn == 121) {
|
||||
/* this is setting pin 124 */
|
||||
type_2->bcch_frequency_list[0] = 0x08;
|
||||
type_5->bcch_frequency_list[0] = 0x08;
|
||||
} else if (bts->c0->arfcn == 124) {
|
||||
/* this is setting pin 121 */
|
||||
type_2->bcch_frequency_list[0] = 0x01;
|
||||
type_5->bcch_frequency_list[0] = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1219,6 +1232,7 @@ int main(int argc, char **argv)
|
|||
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
|
||||
talloc_ctx_init();
|
||||
on_dso_load_token();
|
||||
on_dso_load_rrlp();
|
||||
|
||||
/* parse options */
|
||||
handle_options(argc, argv);
|
||||
|
|
131
openbsc/src/db.c
131
openbsc/src/db.c
|
@ -24,6 +24,7 @@
|
|||
#include <openbsc/gsm_04_11.h>
|
||||
#include <openbsc/db.h>
|
||||
#include <openbsc/talloc.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
|
@ -88,6 +89,7 @@ static char *create_stmts[] = {
|
|||
"sent TIMESTAMP, "
|
||||
"sender_id INTEGER NOT NULL, "
|
||||
"receiver_id INTEGER NOT NULL, "
|
||||
"deliver_attempts INTEGER NOT NULL DEFAULT 0, "
|
||||
/* data directly copied/derived from SMS */
|
||||
"valid_until TIMESTAMP, "
|
||||
"reply_path_req INTEGER NOT NULL, "
|
||||
|
@ -108,6 +110,13 @@ static char *create_stmts[] = {
|
|||
"subscriber_id NUMERIC UNIQUE NOT NULL, "
|
||||
"last_bts NUMERIC NOT NULL "
|
||||
")",
|
||||
"CREATE TABLE IF NOT EXISTS ApduBlobs ("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"created TIMESTAMP NOT NULL, "
|
||||
"apdu_id_flags INTEGER NOT NULL, "
|
||||
"subscriber_id INTEGER NOT NULL, "
|
||||
"apdu BLOB "
|
||||
")",
|
||||
};
|
||||
|
||||
void db_error_func(dbi_conn conn, void* data) {
|
||||
|
@ -252,6 +261,53 @@ struct gsm_subscriber* db_create_subscriber(struct gsm_network *net, char *imsi)
|
|||
return subscr;
|
||||
}
|
||||
|
||||
static int get_equipment_by_subscr(struct gsm_subscriber *subscr)
|
||||
{
|
||||
dbi_result result;
|
||||
char *string;
|
||||
unsigned int cm1;
|
||||
const unsigned char *cm2, *cm3;
|
||||
struct gsm_equipment *equip = &subscr->equipment;
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT equipment.* FROM equipment,equipmentwatch "
|
||||
"WHERE equipmentwatch.equipment_id=equipment.id "
|
||||
"AND equipmentwatch.subscriber_id = %llu "
|
||||
"ORDER BY updated DESC", subscr->id);
|
||||
if (!result)
|
||||
return -EIO;
|
||||
|
||||
if (!dbi_result_next_row(result)) {
|
||||
dbi_result_free(result);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
equip->id = dbi_result_get_ulonglong(result, "id");
|
||||
|
||||
string = dbi_result_get_string(result, "imei");
|
||||
if (string)
|
||||
strncpy(equip->imei, string, sizeof(equip->imei));
|
||||
|
||||
cm1 = dbi_result_get_uint(result, "classmark1") & 0xff;
|
||||
equip->classmark1 = *((struct gsm48_classmark1 *) &cm1);
|
||||
|
||||
equip->classmark2_len = dbi_result_get_field_length(result, "classmark2");
|
||||
cm2 = dbi_result_get_binary(result, "classmark2");
|
||||
if (equip->classmark2_len > sizeof(equip->classmark2))
|
||||
equip->classmark2_len = sizeof(equip->classmark2);
|
||||
memcpy(equip->classmark2, cm2, equip->classmark2_len);
|
||||
|
||||
equip->classmark3_len = dbi_result_get_field_length(result, "classmark3");
|
||||
cm3 = dbi_result_get_binary(result, "classmark3");
|
||||
if (equip->classmark3_len > sizeof(equip->classmark3))
|
||||
equip->classmark3_len = sizeof(equip->classmark3);
|
||||
memcpy(equip->classmark3, cm3, equip->classmark3_len);
|
||||
|
||||
dbi_result_free(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define BASE_QUERY "SELECT * FROM Subscriber "
|
||||
struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
||||
enum gsm_subscriber_field field,
|
||||
const char *id)
|
||||
|
@ -265,7 +321,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
|||
case GSM_SUBSCRIBER_IMSI:
|
||||
dbi_conn_quote_string_copy(conn, id, "ed);
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM Subscriber "
|
||||
BASE_QUERY
|
||||
"WHERE imsi = %s ",
|
||||
quoted
|
||||
);
|
||||
|
@ -274,7 +330,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
|||
case GSM_SUBSCRIBER_TMSI:
|
||||
dbi_conn_quote_string_copy(conn, id, "ed);
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM Subscriber "
|
||||
BASE_QUERY
|
||||
"WHERE tmsi = %s ",
|
||||
quoted
|
||||
);
|
||||
|
@ -283,7 +339,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
|||
case GSM_SUBSCRIBER_EXTENSION:
|
||||
dbi_conn_quote_string_copy(conn, id, "ed);
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM Subscriber "
|
||||
BASE_QUERY
|
||||
"WHERE extension = %s ",
|
||||
quoted
|
||||
);
|
||||
|
@ -292,7 +348,7 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
|||
case GSM_SUBSCRIBER_ID:
|
||||
dbi_conn_quote_string_copy(conn, id, "ed);
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM Subscriber "
|
||||
BASE_QUERY
|
||||
"WHERE id = %s ", quoted);
|
||||
free(quoted);
|
||||
break;
|
||||
|
@ -336,6 +392,9 @@ struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
|
|||
subscr->id, subscr->imsi, subscr->name, subscr->tmsi, subscr->extension,
|
||||
subscr->lac, subscr->authorized);
|
||||
dbi_result_free(result);
|
||||
|
||||
get_equipment_by_subscr(subscr);
|
||||
|
||||
return subscr;
|
||||
}
|
||||
|
||||
|
@ -378,6 +437,16 @@ int db_sync_equipment(struct gsm_equipment *equip)
|
|||
dbi_result result;
|
||||
unsigned char *cm2, *cm3;
|
||||
|
||||
printf("DB: Sync Equipment IMEI=%s, classmark1=%02x",
|
||||
equip->imei, equip->classmark1);
|
||||
if (equip->classmark2_len)
|
||||
printf(", classmark2=%s",
|
||||
hexdump(equip->classmark2, equip->classmark2_len));
|
||||
if (equip->classmark3_len)
|
||||
printf(", classmark3=%s",
|
||||
hexdump(equip->classmark3, equip->classmark3_len));
|
||||
printf("\n");
|
||||
|
||||
dbi_conn_quote_binary_copy(conn, equip->classmark2,
|
||||
equip->classmark2_len, &cm2);
|
||||
dbi_conn_quote_binary_copy(conn, equip->classmark3,
|
||||
|
@ -688,8 +757,10 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id)
|
|||
struct gsm_sms *sms;
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM SMS "
|
||||
"WHERE id >= %llu AND sent is NULL ORDER BY id",
|
||||
"SELECT * FROM SMS,Subscriber "
|
||||
"WHERE sms.id >= %llu AND sms.sent is NULL "
|
||||
"AND subscriber.lac > 0 "
|
||||
"ORDER BY id",
|
||||
min_id);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
@ -713,8 +784,10 @@ struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr)
|
|||
struct gsm_sms *sms;
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"SELECT * FROM SMS "
|
||||
"WHERE receiver_id = %llu AND sent is NULL ORDER BY id",
|
||||
"SELECT * FROM SMS,Subscriber "
|
||||
"WHERE sms.receiver_id = %llu AND sms.sent is NULL "
|
||||
"AND subscriber.lac > 0 "
|
||||
"ORDER BY id",
|
||||
subscr->id);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
@ -748,3 +821,45 @@ int db_sms_mark_sent(struct gsm_sms *sms)
|
|||
dbi_result_free(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* increase the number of attempted deliveries */
|
||||
int db_sms_inc_deliver_attempts(struct gsm_sms *sms)
|
||||
{
|
||||
dbi_result result;
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"UPDATE SMS "
|
||||
"SET deliver_attempts = deliver_attempts + 1 "
|
||||
"WHERE id = %llu", sms->id);
|
||||
if (!result) {
|
||||
printf("DB: Failed to inc deliver attempts for SMS %llu.\n", sms->id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dbi_result_free(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int db_apdu_blob_store(struct gsm_subscriber *subscr,
|
||||
u_int8_t apdu_id_flags, u_int8_t len,
|
||||
u_int8_t *apdu)
|
||||
{
|
||||
dbi_result result;
|
||||
char *q_apdu;
|
||||
|
||||
dbi_conn_quote_binary_copy(conn, apdu, len, &q_apdu);
|
||||
|
||||
result = dbi_conn_queryf(conn,
|
||||
"INSERT INTO ApduBlobs "
|
||||
"(created,subscriber_id,apdu_id_flags,apdu) VALUES "
|
||||
"(datetime('now'),%llu,%u,%s)",
|
||||
subscr->id, apdu_id_flags, q_apdu);
|
||||
|
||||
free(q_apdu);
|
||||
|
||||
if (!result)
|
||||
return -EIO;
|
||||
|
||||
dbi_result_free(result);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1165,8 +1165,10 @@ static int mm_rx_id_resp(struct msgb *msg)
|
|||
case GSM_MI_TYPE_IMEI:
|
||||
case GSM_MI_TYPE_IMEISV:
|
||||
/* update subscribe <-> IMEI mapping */
|
||||
if (lchan->subscr)
|
||||
if (lchan->subscr) {
|
||||
db_subscriber_assoc_imei(lchan->subscr, mi_string);
|
||||
db_sync_equipment(&lchan->subscr->equipment);
|
||||
}
|
||||
if (lchan->loc_operation)
|
||||
lchan->loc_operation->waiting_for_imei = 0;
|
||||
break;
|
||||
|
@ -1289,6 +1291,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
|
|||
}
|
||||
|
||||
lchan->subscr = subscr;
|
||||
lchan->subscr->equipment.classmark1 = lu->classmark1;
|
||||
|
||||
/* check if we can let the subscriber into our network immediately
|
||||
* or if we need to wait for identity responses. */
|
||||
|
@ -1614,6 +1617,10 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
|
|||
GSM_SUBSCRIBER_UPDATE_DETACHED);
|
||||
DEBUGP(DMM, "Subscriber: %s\n",
|
||||
subscr->name ? subscr->name : subscr->imsi);
|
||||
|
||||
subscr->equipment.classmark1 = idi->classmark1;
|
||||
db_sync_equipment(&subscr->equipment);
|
||||
|
||||
subscr_put(subscr);
|
||||
} else
|
||||
DEBUGP(DMM, "Unknown Subscriber ?!?\n");
|
||||
|
@ -1825,6 +1832,24 @@ static int gsm48_rx_rr_meas_rep(struct msgb *msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gsm48_rx_rr_app_info(struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
u_int8_t apdu_id_flags;
|
||||
u_int8_t apdu_len;
|
||||
u_int8_t *apdu_data;
|
||||
|
||||
apdu_id_flags = gh->data[0];
|
||||
apdu_len = gh->data[1];
|
||||
apdu_data = gh->data+2;
|
||||
|
||||
DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s",
|
||||
apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len));
|
||||
|
||||
return db_apdu_blob_store(msg->lchan->subscr, apdu_id_flags, apdu_len, apdu_data);
|
||||
}
|
||||
|
||||
|
||||
/* Receive a GSM 04.08 Radio Resource (RR) message */
|
||||
static int gsm0408_rcv_rr(struct msgb *msg)
|
||||
{
|
||||
|
@ -1854,6 +1879,9 @@ static int gsm0408_rcv_rr(struct msgb *msg)
|
|||
case GSM48_MT_RR_MEAS_REP:
|
||||
rc = gsm48_rx_rr_meas_rep(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_APP_INFO:
|
||||
rc = gsm48_rx_rr_app_info(msg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
|
||||
gh->msg_type);
|
||||
|
@ -1888,6 +1916,27 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan)
|
|||
return rsl_deact_sacch(lchan);
|
||||
}
|
||||
|
||||
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
|
||||
u_int8_t apdu_len, u_int8_t *apdu)
|
||||
{
|
||||
struct msgb *msg = gsm48_msgb_alloc();
|
||||
struct gsm48_hdr *gh;
|
||||
|
||||
msg->lchan = lchan;
|
||||
|
||||
DEBUGP(DRR, "TX APPLICATION INFO id=0x%02x, len=%u\n",
|
||||
apdu_id, apdu_len);
|
||||
|
||||
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2 + apdu_len);
|
||||
gh->proto_discr = GSM48_PDISC_RR;
|
||||
gh->msg_type = GSM48_MT_RR_APP_INFO;
|
||||
gh->data[0] = apdu_id;
|
||||
gh->data[1] = apdu_len;
|
||||
memcpy(gh->data+2, apdu, apdu_len);
|
||||
|
||||
return gsm48_sendmsg(msg, NULL);
|
||||
}
|
||||
|
||||
/* Call Control */
|
||||
|
||||
/* The entire call control code is written in accordance with Figure 7.10c
|
||||
|
|
|
@ -295,6 +295,9 @@ static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
|
|||
}
|
||||
/* dispatch a signal to tell higher level about it */
|
||||
dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
|
||||
/* try delivering the SMS right now */
|
||||
//gsm411_send_sms_subscr(gsms->receiver, gsms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -675,14 +678,19 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
|
|||
|
||||
if (!trans->sms.is_mt) {
|
||||
DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
|
||||
#if 0
|
||||
return gsm411_send_rp_error(trans, rph->msg_ref,
|
||||
GSM411_RP_CAUSE_MSG_INCOMP_STATE);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!sms) {
|
||||
DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
|
||||
return -EINVAL;
|
||||
#if 0
|
||||
return gsm411_send_rp_error(trans, rph->msg_ref,
|
||||
GSM411_RP_CAUSE_PROTOCOL_ERR);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
|
||||
|
||||
/* (C) 2009 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 <sys/types.h>
|
||||
|
||||
#include <openbsc/gsm_04_08.h>
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
|
||||
/* RRLP MS based position request */
|
||||
static const u_int8_t ms_based_pos_req[] = { 0x40, 0x01, 0x78, 0xa8 };
|
||||
|
||||
static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct gsm_subscriber *subscr;
|
||||
struct gsm_lchan *lchan;
|
||||
|
||||
switch (signal) {
|
||||
case S_SUBSCR_ATTACHED:
|
||||
/* A subscriber has attached. */
|
||||
subscr = signal_data;
|
||||
lchan = lchan_for_subscr(subscr);
|
||||
if (!lchan)
|
||||
break;
|
||||
gsm48_send_rr_app_info(lchan, 0x00, sizeof(ms_based_pos_req),
|
||||
ms_based_pos_req);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int paging_sig_cb(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct paging_signal_data *psig_data = signal_data;
|
||||
|
||||
switch (signal) {
|
||||
case S_PAGING_COMPLETED:
|
||||
/* A subscriber has attached. */
|
||||
gsm48_send_rr_app_info(psig_data->lchan, 0x00,
|
||||
sizeof(ms_based_pos_req),
|
||||
ms_based_pos_req);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void on_dso_load_rrlp(void)
|
||||
{
|
||||
register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
|
||||
register_signal_handler(SS_PAGING, paging_sig_cb, NULL);
|
||||
}
|
Loading…
Reference in New Issue