blob: 94105bdeeb6f662dcac4b38f5b0f040c03d1562f [file] [log] [blame]
Jan Luebbefaaa49c2008-12-27 01:07:07 +00001/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
2 * All Rights Reserved
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 */
19
20#include <openbsc/db.h>
Jan Luebbe7398eb92008-12-27 00:45:41 +000021
22#include <stdio.h>
Jan Luebbe5c15c852008-12-27 15:59:25 +000023#include <stdlib.h>
24#include <string.h>
Jan Luebbe7398eb92008-12-27 00:45:41 +000025#include <dbi/dbi.h>
26
27dbi_conn conn;
28
29void db__error_func(dbi_conn conn, void* data) {
Jan Luebbe5c15c852008-12-27 15:59:25 +000030 const char* msg;
31 dbi_conn_error(conn, &msg);
32 printf("DBI: %s\n", msg);
Jan Luebbe7398eb92008-12-27 00:45:41 +000033}
34
35int db_init() {
Jan Luebbe5c15c852008-12-27 15:59:25 +000036 dbi_initialize(NULL);
37 conn = dbi_conn_new("sqlite3");
38 if (conn==NULL) {
39 printf("DB: Failed to create connection.\n");
40 return 1;
41 }
Jan Luebbe7398eb92008-12-27 00:45:41 +000042
Jan Luebbe5c15c852008-12-27 15:59:25 +000043 dbi_conn_error_handler( conn, db__error_func, NULL );
Jan Luebbe7398eb92008-12-27 00:45:41 +000044
Jan Luebbe5c15c852008-12-27 15:59:25 +000045 /* MySQL
46 dbi_conn_set_option(conn, "host", "localhost");
47 dbi_conn_set_option(conn, "username", "your_name");
48 dbi_conn_set_option(conn, "password", "your_password");
49 dbi_conn_set_option(conn, "dbname", "your_dbname");
50 dbi_conn_set_option(conn, "encoding", "UTF-8");
51 */
Jan Luebbe7398eb92008-12-27 00:45:41 +000052
Jan Luebbe5c15c852008-12-27 15:59:25 +000053 /* SqLite 3 */
54 dbi_conn_set_option(conn, "sqlite3_dbdir", "/tmp");
55 dbi_conn_set_option(conn, "dbname", "hlr.sqlite3");
Jan Luebbe7398eb92008-12-27 00:45:41 +000056
Jan Luebbe5c15c852008-12-27 15:59:25 +000057 if (dbi_conn_connect(conn) < 0) {
58 return 1;
59 }
60
61 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +000062}
63
64int db_prepare() {
Jan Luebbe5c15c852008-12-27 15:59:25 +000065 dbi_result result;
66 result = dbi_conn_query(conn,
67 "CREATE TABLE IF NOT EXISTS Subscriber ("
68 "id INTEGER PRIMARY KEY AUTOINCREMENT, "
69 "imsi NUMERIC UNIQUE NOT NULL, "
70 "tmsi NUMERIC UNIQUE, "
71 "extension TEXT UNIQUE, "
Jan Luebbe6e2e5452008-12-27 16:47:55 +000072 "lac INTEGER NOT NULL DEFAULT 0, "
73 "authorized INTEGER NOT NULL DEFAULT 0"
Jan Luebbe5c15c852008-12-27 15:59:25 +000074 ")"
75 );
76 if (result==NULL) {
77 printf("DB: Failed to create Subscriber table.\n");
78 return 1;
79 }
80 dbi_result_free(result);
81 result = dbi_conn_query(conn,
82 "CREATE TABLE IF NOT EXISTS Equipment ("
83 "id INTEGER PRIMARY KEY AUTOINCREMENT, "
84 "imei NUMERIC UNIQUE NOT NULL"
85 ")"
86 );
87 if (result==NULL) {
88 printf("DB: Failed to create Equipment table.\n");
89 return 1;
90 }
91 dbi_result_free(result);
92 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +000093}
94
95int db_fini() {
Jan Luebbe5c15c852008-12-27 15:59:25 +000096 dbi_conn_close(conn);
97 dbi_shutdown();
98 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +000099}
100
Jan Luebbe5c15c852008-12-27 15:59:25 +0000101int db_insert_imei(u_int64_t imei) {
102 dbi_result result;
103 result = dbi_conn_queryf(conn,
104 "INSERT OR IGNORE INTO Equipment "
105 "(imei) "
106 "VALUES "
107 "(%llu) ",
108 imei
109 );
110 if (result==NULL) {
111 printf("DB: Failed to create Equipment by IMEI.\n");
112 return 1;
113 }
114 dbi_result_free(result);
115 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +0000116}
117
Jan Luebbe5c15c852008-12-27 15:59:25 +0000118struct gsm_subscriber* db_create_subscriber(char imsi[GSM_IMSI_LENGTH]) {
119 dbi_result result;
120 struct gsm_subscriber* subscriber;
121 subscriber = malloc(sizeof(*subscriber));
122 if (!subscriber)
123 return NULL;
124 memset(subscriber, 0, sizeof(*subscriber));
125 strncpy(subscriber->imsi, imsi, GSM_IMSI_LENGTH-1);
126 if (!db_get_subscriber(GSM_SUBSCRIBER_IMSI, subscriber)) {
127 return subscriber;
128 }
129 result = dbi_conn_queryf(conn,
130 "INSERT OR IGNORE INTO Subscriber "
131 "(imsi) "
132 "VALUES "
133 "(%s) ",
134 imsi
135 );
136 if (result==NULL) {
137 printf("DB: Failed to create Subscriber by IMSI.\n");
138 }
139 dbi_result_free(result);
140 printf("DB: New Subscriber: IMSI %s\n", subscriber->imsi);
141 return subscriber;
Jan Luebbe7398eb92008-12-27 00:45:41 +0000142}
143
Jan Luebbe5c15c852008-12-27 15:59:25 +0000144int db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber* subscriber) {
145 dbi_result result;
146 switch (field) {
147 case GSM_SUBSCRIBER_IMSI:
148 result = dbi_conn_queryf(conn,
149 "SELECT * FROM Subscriber "
150 "WHERE imsi = %s ",
151 subscriber->imsi
152 );
153 break;
154 case GSM_SUBSCRIBER_TMSI:
155 result = dbi_conn_queryf(conn,
156 "SELECT * FROM Subscriber "
157 "WHERE tmsi = %s ",
158 subscriber->tmsi
159 );
160 break;
161 default:
162 printf("DB: Unknown query selector for Subscriber.\n");
163 return 1;
164 }
165 if (result==NULL) {
166 printf("DB: Failed to query Subscriber.\n");
167 return 1;
168 }
169 if (!dbi_result_next_row(result)) {
170 printf("DB: Failed to find the Subscriber.\n");
171 dbi_result_free(result);
172 return 1;
173 }
174 strncpy(subscriber->imsi, dbi_result_get_string(result, "imsi"), GSM_IMSI_LENGTH);
175 strncpy(subscriber->tmsi, dbi_result_get_string(result, "tmsi"), GSM_TMSI_LENGTH);
176 // FIXME handle extension
177 subscriber->lac = dbi_result_get_uint(result, "lac");
Jan Luebbe6e2e5452008-12-27 16:47:55 +0000178 subscriber->authorized = dbi_result_get_uint(result, "authorized");
179 printf("DB: Found Subscriber: IMSI %s, TMSI %s, LAC %hu, AUTH %u\n",
180 subscriber->imsi, subscriber->tmsi, subscriber->lac, subscriber->authorized);
Jan Luebbe5c15c852008-12-27 15:59:25 +0000181 dbi_result_free(result);
182 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +0000183}
184
Jan Luebbe5c15c852008-12-27 15:59:25 +0000185int db_set_subscriber(struct gsm_subscriber* subscriber) {
186 dbi_result result;
187 result = dbi_conn_queryf(conn,
188 "UPDATE Subscriber "
Jan Luebbe6e2e5452008-12-27 16:47:55 +0000189 "SET tmsi = %s, lac = %i, authorized = %i "
Jan Luebbe5c15c852008-12-27 15:59:25 +0000190 "WHERE imsi = %s ",
Jan Luebbe6e2e5452008-12-27 16:47:55 +0000191 subscriber->tmsi, subscriber->lac, subscriber->authorized, subscriber->imsi
Jan Luebbe5c15c852008-12-27 15:59:25 +0000192 );
193 if (result==NULL) {
194 printf("DB: Failed to update Subscriber (by IMSI).\n");
195 return 1;
196 }
197 dbi_result_free(result);
198 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +0000199}
200
Jan Luebbe5c15c852008-12-27 15:59:25 +0000201int db_subscriber_alloc_tmsi(struct gsm_subscriber* subscriber) {
202 int error;
203 dbi_result result=NULL;
204 char* tmsi_quoted;
205 for (;;) {
206 sprintf(subscriber->tmsi, "%i", rand() % 1000000); // FIXME how many nibbles do we want for the tmsi?
207 result = dbi_conn_queryf(conn,
208 "SELECT * FROM Subscriber "
209 "WHERE tmsi = %s ",
210 subscriber->tmsi
211 );
212 if (result==NULL) {
213 printf("DB: Failed to query Subscriber.\n");
214 return 1;
215 }
Jan Luebbe5c15c852008-12-27 15:59:25 +0000216 if (dbi_result_get_numrows(result)){
217 dbi_result_free(result);
218 continue;
219 }
220 if (!dbi_result_next_row(result)) {
Jan Luebbe5c15c852008-12-27 15:59:25 +0000221 dbi_result_free(result);
222 printf("DB: Allocated TMSI %s for IMSI %s.\n", subscriber->tmsi, subscriber->imsi);
223 return db_set_subscriber(subscriber);
224 }
225 dbi_result_free(result);
226 }
227 return 0;
Jan Luebbe7398eb92008-12-27 00:45:41 +0000228}
229