diff options
author | Harald Welte <laforge@gnumonks.org> | 2009-08-17 09:41:48 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2009-08-17 09:41:48 +0200 |
commit | 712573b66a7957d91943d00cedd3229b8f9a5d9f (patch) | |
tree | 34af1df8729e1f37dc2d897ba923719d6858c434 /openbsc | |
parent | 9085cda9595d1e2e8d614fdf27e74898bde54e37 (diff) | |
parent | ee4410a4f312d927dc8b4901c71c52436c18ca4a (diff) |
Merge commit 'har/master'
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/db.h | 5 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_04_08.h | 2 | ||||
-rw-r--r-- | openbsc/src/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/src/bsc_hack.c | 14 | ||||
-rw-r--r-- | openbsc/src/db.c | 131 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08.c | 51 | ||||
-rw-r--r-- | openbsc/src/gsm_04_11.c | 8 | ||||
-rw-r--r-- | openbsc/src/rrlp.c | 73 |
8 files changed, 276 insertions, 10 deletions
diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index 67436dfb3..07135937b 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -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 */ diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 1ca1ccdb8..161364cbf 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.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); diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index cbfeeaa36..448de06c0 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -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 diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 5f845136c..9945aa9c9 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.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); diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 0704bca2b..45e950b6f 100644 --- a/openbsc/src/db.c +++ b/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; +} diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index e5ab49d76..46b447900 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -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 diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index 277a321a8..85fd6b690 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -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) { diff --git a/openbsc/src/rrlp.c b/openbsc/src/rrlp.c new file mode 100644 index 000000000..61bb20244 --- /dev/null +++ b/openbsc/src/rrlp.c @@ -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); +} |