blob: f12d758826d0589ba5549a03e899964dbde77b6f [file] [log] [blame]
Harald Welteb8b85a12016-06-17 00:06:42 +02001#pragma once
2
3#include <stdint.h>
4#include <osmocom/core/linuxlist.h>
5#include <osmocom/core/fsm.h>
6#include <osmocom/core/logging.h>
7#include <osmocom/gsm/protocol/gsm_23_003.h>
8#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
9#include <osmocom/gsm/gsm23003.h>
Neels Hofmeyrcf309132017-12-14 03:57:31 +010010#include <osmocom/gsm/gsm0808.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020011#include <osmocom/msc/gsm_data.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020012// for GSM_NAME_LENGTH
Neels Hofmeyr90843962017-09-04 15:04:35 +020013#include <osmocom/msc/gsm_subscriber.h>
Harald Welteb8b85a12016-06-17 00:06:42 +020014
Maxa263bb22017-12-27 13:23:44 +010015#define LOGGSUPP(level, gsup, fmt, args...) \
16 LOGP(DVLR, level, "GSUP(%s) " fmt, (gsup)->imsi, ## args)
17
18#define LOGVSUBP(level, vsub, fmt, args...) \
19 LOGP(DVLR, level, "SUBSCR(%s) " fmt, vlr_subscr_name(vsub), ## args)
20
Harald Welte2483f1b2016-06-19 18:06:02 +020021struct log_target;
22
Stefan Sperlingdefc3c82018-05-15 14:48:04 +020023#define VLR_SUBSCRIBER_NO_EXPIRATION 0
24#define VLR_SUBSCRIBER_LU_EXPIRATION_INTERVAL 60 /* in seconds */
25
Harald Welteb8b85a12016-06-17 00:06:42 +020026/* from 3s to 10s */
27#define GSM_29002_TIMER_S 10
28/* from 15s to 30s */
29#define GSM_29002_TIMER_M 30
30/* from 1min to 10min */
31#define GSM_29002_TIMER_ML (10*60)
32/* from 28h to 38h */
33#define GSM_29002_TIMER_L (32*60*60)
34
Harald Welteb8b85a12016-06-17 00:06:42 +020035/* VLR subscriber authentication state */
36enum vlr_subscr_auth_state {
37 /* subscriber needs to be autenticated */
38 VLR_SUB_AS_NEEDS_AUTH,
39 /* waiting for AuthInfo from HLR/AUC */
40 VLR_SUB_AS_NEEDS_AUTH_WAIT_AI,
41 /* waiting for response from subscriber */
42 VLR_SUB_AS_WAIT_RESP,
43 /* successfully authenticated */
44 VLR_SUB_AS_AUTHENTICATED,
45 /* subscriber needs re-sync */
46 VLR_SUB_AS_NEEDS_RESYNC,
47 /* waiting for AuthInfo with ReSync */
48 VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC,
49 /* waiting for response from subscr, resync case */
50 VLR_SUB_AS_WAIT_RESP_RESYNC,
51 /* waiting for IMSI from subscriber */
52 VLR_SUB_AS_WAIT_ID_IMSI,
53 /* authentication has failed */
54 VLR_SUB_AS_AUTH_FAILED,
55};
56
57enum vlr_lu_event {
58 VLR_ULA_E_UPDATE_LA, /* Initial trigger (LU from MS) */
59 VLR_ULA_E_SEND_ID_ACK, /* Result of Send-ID from PVLR */
60 VLR_ULA_E_SEND_ID_NACK, /* Result of Send-ID from PVLR */
61 VLR_ULA_E_AUTH_RES, /* Result of auth procedure */
62 VLR_ULA_E_CIPH_RES, /* Result of Ciphering Mode Command */
63 VLR_ULA_E_ID_IMSI, /* IMSI recieved from MS */
64 VLR_ULA_E_ID_IMEI, /* IMEI received from MS */
65 VLR_ULA_E_ID_IMEISV, /* IMEISV received from MS */
66 VLR_ULA_E_HLR_LU_RES, /* HLR UpdateLocation result */
67 VLR_ULA_E_UPD_HLR_COMPL,/* UpdatE_HLR_VLR result */
68 VLR_ULA_E_LU_COMPL_SUCCESS,/* Location_Update_Completion_VLR result */
69 VLR_ULA_E_LU_COMPL_FAILURE,/* Location_Update_Completion_VLR result */
70 VLR_ULA_E_NEW_TMSI_ACK, /* TMSI Reallocation Complete */
71};
72
73enum vlr_ciph_result_cause {
74 VLR_CIPH_REJECT, /* ? */
75 VLR_CIPH_COMPL,
76};
77
78struct vlr_ciph_result {
79 enum vlr_ciph_result_cause cause;
Neels Hofmeyrfa10eda2018-03-13 01:22:01 +010080 char imeisv[GSM48_MI_SIZE];
Harald Welteb8b85a12016-06-17 00:06:42 +020081};
82
83enum vlr_subscr_security_context {
84 VLR_SEC_CTX_NONE,
85 VLR_SEC_CTX_GSM,
86 VLR_SEC_CTX_UMTS,
87};
88
89enum vlr_lu_type {
90 VLR_LU_TYPE_PERIODIC,
91 VLR_LU_TYPE_IMSI_ATTACH,
92 VLR_LU_TYPE_REGULAR,
93};
94
95#define OSMO_LBUF_DECL(name, xlen) \
96 struct { \
97 uint8_t buf[xlen]; \
98 size_t len; \
99 } name
100
101struct sgsn_mm_ctx;
102struct vlr_instance;
103
104/* The VLR subscriber is the part of the GSM subscriber state in VLR (CS) or
105 * SGSN (PS), particularly while interacting with the HLR via GSUP */
106struct vlr_subscr {
107 struct llist_head list;
108 struct vlr_instance *vlr;
109
110 /* TODO either populate from HLR or drop this completely? */
111 long long unsigned int id;
112
113 /* Data from HLR */ /* 3GPP TS 23.008 */
114 /* Always use vlr_subscr_set_imsi() to write to imsi[] */
115 char imsi[GSM23003_IMSI_MAX_DIGITS+1]; /* 2.1.1.1 */
116 char msisdn[GSM_EXTENSION_LENGTH+1]; /* 2.1.2 */
117 char name[GSM_NAME_LENGTH+1]; /* proprietary */
118 OSMO_LBUF_DECL(hlr, 16); /* 2.4.7 */
119 uint32_t periodic_lu_timer; /* 2.4.24 */
120 uint32_t age_indicator; /* 2.17.1 */
121
122 /* Authentication Data */
123 struct gsm_auth_tuple auth_tuples[5]; /* 2.3.1-2.3.4 */
124 struct gsm_auth_tuple *last_tuple;
125 enum vlr_subscr_security_context sec_ctx;
126
127 /* Data local to VLR is below */
128 uint32_t tmsi; /* 2.1.4 */
129 /* Newly allocated TMSI that was not yet acked by MS */
130 uint32_t tmsi_new;
131
132 /* some redundancy in information below? */
133 struct osmo_cell_global_id cgi; /* 2.4.16 */
134 uint16_t lac; /* 2.4.2 */
135
136 char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.2.3 */
137 char imei[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.1.9 */
138 bool imsi_detached_flag; /* 2.7.1 */
139 bool conf_by_radio_contact_ind; /* 2.7.4.1 */
140 bool sub_dataconf_by_hlr_ind; /* 2.7.4.2 */
141 bool loc_conf_in_hlr_ind; /* 2.7.4.3 */
142 bool dormant_ind; /* 2.7.8 */
143 bool cancel_loc_rx; /* 2.7.8A */
144 bool ms_not_reachable_flag; /* 2.10.2 (MNRF) */
145 bool la_allowed;
146
147 int use_count;
Harald Welteb8b85a12016-06-17 00:06:42 +0200148
149 struct osmo_fsm_inst *lu_fsm;
150 struct osmo_fsm_inst *auth_fsm;
151 struct osmo_fsm_inst *proc_arq_fsm;
152
153 bool lu_complete;
Stefan Sperlingdefc3c82018-05-15 14:48:04 +0200154 time_t expire_lu;
Harald Welteb8b85a12016-06-17 00:06:42 +0200155
156 void *msc_conn_ref;
157
158 /* PS (SGSN) specific parts */
159 struct {
160 struct llist_head pdp_list;
161 uint8_t rac;
162 uint8_t sac;
163 struct gprs_mm_ctx *mmctx;
164 } ps;
165 /* CS (NITB/CSCN) specific parts */
166 struct {
167 /* pending requests */
168 bool is_paging;
Neels Hofmeyr2ff5bcd2017-12-15 03:02:27 +0100169 struct osmo_timer_list paging_response_timer;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200170 /* list of struct subscr_request */
Harald Welteb8b85a12016-06-17 00:06:42 +0200171 struct llist_head requests;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200172 uint8_t lac;
173 enum ran_type attached_via_ran;
Harald Welteb8b85a12016-06-17 00:06:42 +0200174 } cs;
175};
176
Harald Welteb8b85a12016-06-17 00:06:42 +0200177enum vlr_ciph {
178 VLR_CIPH_NONE, /*< A5/0, no encryption */
179 VLR_CIPH_A5_1, /*< A5/1, encryption */
180 VLR_CIPH_A5_2, /*< A5/2, deprecated export-grade encryption */
181 VLR_CIPH_A5_3, /*< A5/3, 'new secure' encryption */
182};
183
Neels Hofmeyrcf309132017-12-14 03:57:31 +0100184static inline uint8_t vlr_ciph_to_gsm0808_alg_id(enum vlr_ciph ciph)
185{
186 switch (ciph) {
187 default:
188 case VLR_CIPH_NONE:
189 return GSM0808_ALG_ID_A5_0;
190 case VLR_CIPH_A5_1:
191 return GSM0808_ALG_ID_A5_1;
192 case VLR_CIPH_A5_2:
193 return GSM0808_ALG_ID_A5_2;
194 case VLR_CIPH_A5_3:
195 return GSM0808_ALG_ID_A5_3;
196 }
197}
198
Harald Welteb8b85a12016-06-17 00:06:42 +0200199struct vlr_ops {
200 /* encode + transmit an AUTH REQ towards the MS.
201 * \param[in] at auth tuple providing rand, key_seq and autn.
202 * \param[in] send_autn True to send AUTN, for r99 UMTS auth.
203 */
204 int (*tx_auth_req)(void *msc_conn_ref, struct gsm_auth_tuple *at,
205 bool send_autn);
206 /* encode + transmit an AUTH REJECT towards the MS */
207 int (*tx_auth_rej)(void *msc_conn_ref);
208
209 /* encode + transmit an IDENTITY REQUEST towards the MS */
210 int (*tx_id_req)(void *msc_conn_ref, uint8_t mi_type);
211
212 int (*tx_lu_acc)(void *msc_conn_ref, uint32_t send_tmsi);
Neels Hofmeyr15809592018-04-06 02:57:51 +0200213 int (*tx_lu_rej)(void *msc_conn_ref, enum gsm48_reject_value cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200214 int (*tx_cm_serv_acc)(void *msc_conn_ref);
Neels Hofmeyr15809592018-04-06 02:57:51 +0200215 int (*tx_cm_serv_rej)(void *msc_conn_ref, enum gsm48_reject_value cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200216
Harald Welte71c51df2017-12-23 18:51:48 +0100217 int (*set_ciph_mode)(void *msc_conn_ref, bool umts_aka, bool retrieve_imeisv);
Harald Welteb8b85a12016-06-17 00:06:42 +0200218
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200219 /* UTRAN: send Common Id (when auth+ciph are complete) */
220 int (*tx_common_id)(void *msc_conn_ref);
221
Stefan Sperling3a741282018-03-13 21:11:49 +0100222 int (*tx_mm_info)(void *msc_conn_ref);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200223
Harald Welteb8b85a12016-06-17 00:06:42 +0200224 /* notify MSC/SGSN that the subscriber data in VLR has been updated */
225 void (*subscr_update)(struct vlr_subscr *vsub);
226 /* notify MSC/SGSN that the given subscriber has been associated
227 * with this msc_conn_ref */
228 void (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub);
229};
230
231enum vlr_timer {
232 VLR_T_3250,
233 VLR_T_3260,
234 VLR_T_3270,
235 _NUM_VLR_TIMERS
236};
237
238/* An instance of the VLR codebase */
239struct vlr_instance {
240 struct llist_head subscribers;
241 struct llist_head operations;
242 struct gsup_client *gsup_client;
243 struct vlr_ops ops;
Stefan Sperlingdefc3c82018-05-15 14:48:04 +0200244 struct osmo_timer_list lu_expire_timer;
Harald Welteb8b85a12016-06-17 00:06:42 +0200245 struct {
Neels Hofmeyr54a706c2017-07-18 15:39:27 +0200246 bool retrieve_imeisv_early;
247 bool retrieve_imeisv_ciphered;
Harald Welteb8b85a12016-06-17 00:06:42 +0200248 bool assign_tmsi;
249 bool check_imei_rqd;
Neels Hofmeyr33f53412017-10-29 02:11:18 +0100250 int auth_tuple_max_reuse_count;
Harald Welteb8b85a12016-06-17 00:06:42 +0200251 bool auth_reuse_old_sets_on_error;
252 bool parq_retrieve_imsi;
253 bool is_ps;
254 uint32_t timer[_NUM_VLR_TIMERS];
255 } cfg;
256 /* A free-form pointer for use by the caller */
257 void *user_ctx;
258};
259
260extern const struct value_string vlr_ciph_names[];
261static inline const char *vlr_ciph_name(enum vlr_ciph val)
262{
263 return get_value_string(vlr_ciph_names, val);
264}
265
266/* Location Updating request */
267struct osmo_fsm_inst *
268vlr_loc_update(struct osmo_fsm_inst *parent,
269 uint32_t parent_event_success,
270 uint32_t parent_event_failure,
271 void *parent_event_data,
272 struct vlr_instance *vlr, void *msc_conn_ref,
273 enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
274 const struct osmo_location_area_id *old_lai,
275 const struct osmo_location_area_id *new_lai,
276 bool authentication_required,
Harald Welte71c51df2017-12-23 18:51:48 +0100277 bool ciphering_required,
Harald Welteb8b85a12016-06-17 00:06:42 +0200278 bool is_r99, bool is_utran,
279 bool assign_tmsi);
280
Neels Hofmeyr15809592018-04-06 02:57:51 +0200281void vlr_loc_update_cancel(struct osmo_fsm_inst *fi,
282 enum osmo_fsm_term_cause fsm_cause,
283 uint8_t gsm48_cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200284
285/* tell the VLR that the subscriber connection is gone */
286int vlr_subscr_disconnected(struct vlr_subscr *vsub);
Maxdcc193d2017-12-27 19:34:15 +0100287bool vlr_subscr_expire(struct vlr_subscr *vsub);
Harald Welteb8b85a12016-06-17 00:06:42 +0200288int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub, const uint8_t *mi, size_t mi_len);
289int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99, bool is_utran,
290 const uint8_t *res, uint8_t res_len);
291int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts);
Max770fbd22018-01-24 12:48:33 +0100292int vlr_subscr_tx_auth_fail_rep(const struct vlr_subscr *vsub) __attribute__((warn_unused_result));
Harald Welteb8b85a12016-06-17 00:06:42 +0200293void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, struct vlr_ciph_result *res);
294int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub);
295int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub);
Harald Welteb8b85a12016-06-17 00:06:42 +0200296
297struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops);
298int vlr_start(const char *gsup_unit_name, struct vlr_instance *vlr,
299 const char *gsup_server_addr_str, uint16_t gsup_server_port);
300
301/* internal use only */
302
Neels Hofmeyr1a5bcd52017-11-18 22:19:55 +0100303void sub_pres_vlr_fsm_start(struct osmo_fsm_inst **fsm,
304 struct osmo_fsm_inst *parent,
305 struct vlr_subscr *vsub,
306 uint32_t term_event);
Harald Welteb8b85a12016-06-17 00:06:42 +0200307struct osmo_fsm_inst *
308upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
309 struct vlr_subscr *vsub,
310 uint32_t parent_event);
311
312struct osmo_fsm_inst *
313lu_compl_vlr_proc_start(struct osmo_fsm_inst *parent,
314 struct vlr_subscr *vsub,
315 void *msc_conn_ref,
316 uint32_t parent_event_success,
317 uint32_t parent_event_failure);
318
319
320const char *vlr_subscr_name(struct vlr_subscr *vsub);
321const char *vlr_subscr_msisdn_or_name(struct vlr_subscr *vsub);
322
323#define vlr_subscr_find_by_imsi(vlr, imsi) \
324 _vlr_subscr_find_by_imsi(vlr, imsi, __BASE_FILE__, __LINE__)
325#define vlr_subscr_find_or_create_by_imsi(vlr, imsi, created) \
326 _vlr_subscr_find_or_create_by_imsi(vlr, imsi, created, \
327 __BASE_FILE__, __LINE__)
328
329#define vlr_subscr_find_by_tmsi(vlr, tmsi) \
330 _vlr_subscr_find_by_tmsi(vlr, tmsi, __BASE_FILE__, __LINE__)
331#define vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created) \
332 _vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, created, \
333 __BASE_FILE__, __LINE__)
334
335#define vlr_subscr_find_by_msisdn(vlr, msisdn) \
336 _vlr_subscr_find_by_msisdn(vlr, msisdn, __BASE_FILE__, __LINE__)
337
338struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr,
339 const char *imsi,
340 const char *file, int line);
341struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr,
342 const char *imsi,
343 bool *created,
344 const char *file,
345 int line);
346
347struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr,
348 uint32_t tmsi,
349 const char *file, int line);
350struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr,
351 uint32_t tmsi,
352 bool *created,
353 const char *file,
354 int line);
355
356struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr,
357 const char *msisdn,
358 const char *file, int line);
359
360#define vlr_subscr_get(sub) _vlr_subscr_get(sub, __BASE_FILE__, __LINE__)
361#define vlr_subscr_put(sub) _vlr_subscr_put(sub, __BASE_FILE__, __LINE__)
362struct vlr_subscr *_vlr_subscr_get(struct vlr_subscr *sub, const char *file, int line);
363struct vlr_subscr *_vlr_subscr_put(struct vlr_subscr *sub, const char *file, int line);
364
365struct vlr_subscr *vlr_subscr_alloc(struct vlr_instance *vlr);
366void vlr_subscr_free(struct vlr_subscr *vsub);
367int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub);
368
369void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi);
370void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei);
371void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv);
372void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn);
373
374bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi);
375bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi);
376bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn);
377bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei);
378
379uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer);
380
381int vlr_subscr_changed(struct vlr_subscr *vsub);
Max770fbd22018-01-24 12:48:33 +0100382int vlr_subscr_purge(struct vlr_subscr *vsub) __attribute__((warn_unused_result));
Neels Hofmeyr15809592018-04-06 02:57:51 +0200383void vlr_subscr_cancel_attach_fsm(struct vlr_subscr *vsub,
384 enum osmo_fsm_term_cause fsm_cause,
385 uint8_t gsm48_cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200386
Stefan Sperlingdefc3c82018-05-15 14:48:04 +0200387void vlr_subscr_enable_expire_lu(struct vlr_subscr *vsub);
Harald Welteb8b85a12016-06-17 00:06:42 +0200388
389/* Process Acccess Request FSM */
390
Harald Welteb8b85a12016-06-17 00:06:42 +0200391enum proc_arq_vlr_event {
392 PR_ARQ_E_START,
393 PR_ARQ_E_ID_IMSI,
394 PR_ARQ_E_AUTH_RES,
395 PR_ARQ_E_CIPH_RES,
396 PR_ARQ_E_UPD_LOC_RES,
397 PR_ARQ_E_TRACE_RES,
398 PR_ARQ_E_IMEI_RES,
399 PR_ARQ_E_PRES_RES,
400 PR_ARQ_E_TMSI_ACK,
401};
402
403enum vlr_parq_type {
404 VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */
405 VLR_PR_ARQ_T_CM_SERV_REQ,
406 VLR_PR_ARQ_T_PAGING_RESP,
407 /* FIXME: differentiate between services of 24.008 10.5.3.3 */
408};
409
410/* Process Access Request (CM SERV REQ / PAGING RESP) */
411void
412vlr_proc_acc_req(struct osmo_fsm_inst *parent,
413 uint32_t parent_event_success,
414 uint32_t parent_event_failure,
415 void *parent_event_data,
416 struct vlr_instance *vlr, void *msc_conn_ref,
417 enum vlr_parq_type type, const uint8_t *mi_lv,
418 const struct osmo_location_area_id *lai,
419 bool authentication_required,
Harald Welte71c51df2017-12-23 18:51:48 +0100420 bool ciphering_required,
Harald Welteb8b85a12016-06-17 00:06:42 +0200421 bool is_r99, bool is_utran);
422
Neels Hofmeyr15809592018-04-06 02:57:51 +0200423void vlr_parq_cancel(struct osmo_fsm_inst *fi,
424 enum osmo_fsm_term_cause fsm_cause,
425 enum gsm48_reject_value gsm48_cause);
Harald Welteb8b85a12016-06-17 00:06:42 +0200426
427void vlr_parq_fsm_init(void);
428
429int vlr_set_ciph_mode(struct vlr_instance *vlr,
430 struct osmo_fsm_inst *fi,
431 void *msc_conn_ref,
Harald Welte71c51df2017-12-23 18:51:48 +0100432 bool ciph_required,
Neels Hofmeyr2ef2da52017-12-18 01:23:42 +0100433 bool umts_aka,
Harald Welteb8b85a12016-06-17 00:06:42 +0200434 bool retrieve_imeisv);
435
Neels Hofmeyre3d72d72017-12-18 02:06:44 +0100436bool vlr_use_umts_aka(struct osmo_auth_vector *vec, bool is_r99);
437
Harald Welteb8b85a12016-06-17 00:06:42 +0200438void log_set_filter_vlr_subscr(struct log_target *target,
439 struct vlr_subscr *vlr_subscr);