aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/hlr/db.h
blob: 1f1bacb8a7981ec00b4e54cdb550ed65ce641987 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#pragma once

#include <stdbool.h>
#include <sqlite3.h>

#include <osmocom/gsupclient/gsup_peer_id.h>
#include <osmocom/gsm/gsup.h>

struct hlr;

enum stmt_idx {
	DB_STMT_SEL_BY_IMSI,
	DB_STMT_SEL_BY_MSISDN,
	DB_STMT_SEL_BY_ID,
	DB_STMT_SEL_BY_IMEI,
	DB_STMT_UPD_VLR_BY_ID,
	DB_STMT_UPD_SGSN_BY_ID,
	DB_STMT_UPD_IMEI_BY_IMSI,
	DB_STMT_AUC_BY_IMSI,
	DB_STMT_AUC_UPD_SQN,
	DB_STMT_UPD_PURGE_CS_BY_IMSI,
	DB_STMT_UPD_PURGE_PS_BY_IMSI,
	DB_STMT_UPD_NAM_PS_BY_IMSI,
	DB_STMT_UPD_NAM_CS_BY_IMSI,
	DB_STMT_SUBSCR_CREATE,
	DB_STMT_DEL_BY_ID,
	DB_STMT_SET_MSISDN_BY_IMSI,
	DB_STMT_DELETE_MSISDN_BY_IMSI,
	DB_STMT_AUC_2G_INSERT,
	DB_STMT_AUC_2G_DELETE,
	DB_STMT_AUC_3G_INSERT,
	DB_STMT_AUC_3G_DELETE,
	DB_STMT_SET_LAST_LU_SEEN,
	DB_STMT_SET_LAST_LU_SEEN_PS,
	DB_STMT_EXISTS_BY_IMSI,
	DB_STMT_EXISTS_BY_MSISDN,
	DB_STMT_IND_ADD,
	DB_STMT_IND_SELECT,
	DB_STMT_IND_DEL,
	_NUM_DB_STMT
};

struct db_context {
	char *fname;
	sqlite3 *db;
	sqlite3_stmt *stmt[_NUM_DB_STMT];
};

/* Optional feature to make SQLite3 using talloc */
#ifdef SQLITE_USE_TALLOC
int db_sqlite3_use_talloc(void *ctx);
#endif

void db_remove_reset(sqlite3_stmt *stmt);
bool db_bind_text(sqlite3_stmt *stmt, const char *param_name, const char *text);
bool db_bind_int(sqlite3_stmt *stmt, const char *param_name, int nr);
bool db_bind_int64(sqlite3_stmt *stmt, const char *param_name, int64_t nr);
bool db_bind_null(sqlite3_stmt *stmt, const char *param_name);
void db_close(struct db_context *dbc);
struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_logging, bool allow_upgrades);

#include <osmocom/crypt/auth.h>

/* obtain the authentication data for a given imsi */
int db_get_auth_data(struct db_context *dbc, const char *imsi,
		     struct osmo_sub_auth_data *aud2g,
		     struct osmo_sub_auth_data *aud3g,
		     int64_t *subscr_id);

int db_update_sqn(struct db_context *dbc, int64_t id,
		      uint64_t new_sqn);

int db_get_auc(struct db_context *dbc, const char *imsi,
	       unsigned int auc_3g_ind, struct osmo_auth_vector *vec,
	       unsigned int num_vec, const uint8_t *rand_auts,
	       const uint8_t *auts, bool separation_bit);

#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>

/* TODO: Get this from somewhere? */
#define GT_MAX_DIGITS	15

struct hlr_subscriber {
	struct llist_head list;

	int64_t		id;
	char		imsi[GSM23003_IMSI_MAX_DIGITS+1];
	char		msisdn[GSM23003_MSISDN_MAX_DIGITS+1];
	/* imeisv? */
	char		imei[GSM23003_IMEI_NUM_DIGITS+1];
	char		vlr_number[32];
	char		sgsn_number[32];
	char		sgsn_address[GT_MAX_DIGITS+1];
	/* ggsn number + address */
	/* gmlc number */
	/* smsc number */
	uint32_t	periodic_lu_timer;
	uint32_t	periodic_rau_tau_timer;
	bool		nam_cs;
	bool		nam_ps;
	uint32_t	lmsi;
	bool		ms_purged_cs;
	bool		ms_purged_ps;
	time_t		last_lu_seen;
	time_t		last_lu_seen_ps;
	/* talloc'd IPA unit name */
	struct osmo_ipa_name	vlr_via_proxy;
	struct osmo_ipa_name	sgsn_via_proxy;
};

/* A format string for use with strptime(3). This format string is
 * used to parse the last_lu_seen column stored in the HLR database.
 * See https://sqlite.org/lang_datefunc.html, function datetime(). */
#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"

/* Like struct osmo_sub_auth_data, but the keys are in hexdump representation.
 * This is useful because SQLite requires them in hexdump format, and callers
 * like the VTY and CTRL interface also have them available as hexdump to begin
 * with. In the binary format, a VTY command would first need to hexparse,
 * after which the db function would again hexdump, copying to separate
 * buffers. The roundtrip can be saved by providing char* to begin with. */
struct sub_auth_data_str {
	enum osmo_sub_auth_type type;
	enum osmo_auth_algo algo;
	union {
		struct {
			const char *opc;
			const char *k;
			uint64_t sqn;
			int opc_is_op;
			unsigned int ind_bitlen;
		} umts;
		struct {
			const char *ki;
		} gsm;
	} u;
};

#define DB_SUBSCR_FLAG_NAM_CS	(1 << 1)
#define DB_SUBSCR_FLAG_NAM_PS	(1 << 2)

int db_subscr_create(struct db_context *dbc, const char *imsi, uint8_t flags);
int db_subscr_delete_by_id(struct db_context *dbc, int64_t subscr_id);

int db_subscr_update_msisdn_by_imsi(struct db_context *dbc, const char *imsi,
				    const char *msisdn);
int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
			       const struct sub_auth_data_str *aud);
int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, const char *imei);

int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi);
int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn);

int db_subscr_get_by_imsi(struct db_context *dbc, const char *imsi,
			  struct hlr_subscriber *subscr);
int db_subscr_get_by_msisdn(struct db_context *dbc, const char *msisdn,
			    struct hlr_subscriber *subscr);
int db_subscr_get_by_id(struct db_context *dbc, int64_t id,
			struct hlr_subscriber *subscr);
int db_subscr_get_by_imei(struct db_context *dbc, const char *imei, struct hlr_subscriber *subscr);
int db_subscr_nam(struct db_context *dbc, const char *imsi, bool nam_val, bool is_ps);
int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
		 const struct osmo_ipa_name *vlr_name, bool is_ps,
		 const struct osmo_ipa_name *via_proxy);

int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
		    bool purge_val, bool is_ps);

int db_ind(struct db_context *dbc, const struct osmo_gsup_peer_id *vlr, unsigned int *ind);
int db_ind_del(struct db_context *dbc, const struct osmo_gsup_peer_id *vlr);

/*! Call sqlite3_column_text() and copy result to a char[].
 * \param[out] buf  A char[] used as sizeof() arg(!) and osmo_strlcpy() target.
 * \param[in] stmt  An sqlite3_stmt*.
 * \param[in] idx   Index in stmt's returned columns.
 */
#define copy_sqlite3_text_to_buf(buf, stmt, idx) \
	do { \
		const char *_txt = (const char *) sqlite3_column_text(stmt, idx); \
		osmo_strlcpy(buf, _txt, sizeof(buf)); \
	} while (0)

/*! Call sqlite3_column_text() and copy result to a struct osmo_ipa_name.
 * \param[out] ipa_name  A struct osmo_ipa_name* to write to.
 * \param[in] stmt  An sqlite3_stmt*.
 * \param[in] idx  Index in stmt's returned columns.
 */
#define copy_sqlite3_text_to_ipa_name(ipa_name, stmt, idx) \
	do { \
		const char *_txt = (const char *) sqlite3_column_text(stmt, idx); \
		osmo_ipa_name_set_str(ipa_name, _txt); \
	} while (0)