1 /*
2  * usrloc_db.c
3  *
4  *  Created on: Nov 11, 2013
5  *      Author: carlos
6  *
7  * Copyright (C) 2019 Aleksandar Yosifov
8  */
9 
10 #include "../../lib/srdb1/db.h"
11 #include "usrloc.h"
12 #include "usrloc_db.h"
13 
14 str id_col	        	= str_init(ID_COL);
15 str domain_col			= str_init(DOMAIN_COL);
16 str aor_col		    	= str_init(AOR_COL);
17 str host_col			= str_init(HOST_COL);
18 str port_col			= str_init(PORT_COL);
19 str protocol_col 		= str_init(PROTOCOL_COL);
20 str received_col    	= str_init(RECEIVED_COL);
21 str received_port_col	= str_init(RECEIVED_PORT_COL);
22 str received_proto_col	= str_init(RECEIVED_PROTO_COL);
23 str path_col			= str_init(PATH_COL);
24 str rinstance_col       = str_init(RINSTANCE_COL);
25 str rx_session_id_col	= str_init(RX_SESSION_ID_COL);
26 str reg_state_col		= str_init(REG_STATE_COL);
27 str expires_col			= str_init(EXPIRES_COL);
28 str service_routes_col	= str_init(SERVICE_ROUTES_COL);
29 str socket_col			= str_init(SOCKET_COL);
30 str public_ids_col		= str_init(PUBLIC_IDS_COL);
31 str security_type_col 	= str_init(SECURITY_TYPE_COL);
32 str mode_col			= str_init(MODE_COL);
33 str ck_col				= str_init(CK_COL);
34 str ik_col 				= str_init(IK_COL);
35 str ealg_col			= str_init(EALG_COL);
36 str ialg_col 			= str_init(IALG_COL);
37 str port_pc_col			= str_init(PORTPC_COL);
38 str port_ps_col 		= str_init(PORTPS_COL);
39 str port_uc_col			= str_init(PORTUC_COL);
40 str port_us_col 		= str_init(PORTUS_COL);
41 str spi_pc_col 			= str_init(SPIPC_COL);
42 str spi_ps_col 			= str_init(SPIPS_COL);
43 str spi_uc_col 			= str_init(SPIUC_COL);
44 str spi_us_col 			= str_init(SPIUS_COL);
45 str t_security_type_col	= str_init(T_SECURITY_TYPE_COL);
46 str t_protocol_col 		= str_init(T_PROTOCOL_COL);
47 str t_mode_col			= str_init(T_MODE_COL);
48 str t_ck_col			= str_init(T_CK_COL);
49 str t_ik_col 			= str_init(T_IK_COL);
50 str t_ealg_col			= str_init(T_EALG_COL);
51 str t_ialg_col 			= str_init(T_IALG_COL);
52 str t_port_pc_col		= str_init(T_PORTPC_COL);
53 str t_port_ps_col 		= str_init(T_PORTPS_COL);
54 str t_port_uc_col		= str_init(T_PORTUC_COL);
55 str t_port_us_col 		= str_init(T_PORTUS_COL);
56 str t_spi_pc_col 		= str_init(T_SPIPC_COL);
57 str t_spi_ps_col 		= str_init(T_SPIPS_COL);
58 str t_spi_uc_col 		= str_init(T_SPIUC_COL);
59 str t_spi_us_col 		= str_init(T_SPIUS_COL);
60 
61 t_reusable_buffer service_route_buffer = {0,0,0};
62 t_reusable_buffer impu_buffer = {0,0,0};
63 
connect_db(const str * db_url)64 int connect_db(const str *db_url)
65 {
66 	if (ul_dbh) {	/* we've obviously already connected... */
67 		LM_WARN("DB connection already open... continuing\n");
68 		return 0;
69 	}
70 
71 	if ((ul_dbh = ul_dbf.init(db_url)) == 0)
72 		return -1;
73 
74 	LM_DBG("Successfully connected to DB and returned DB handle ptr %p\n", ul_dbh);
75 	return 0;
76 }
77 
init_db(const str * db_url,int db_update_period,int fetch_num_rows)78 int init_db(const str *db_url, int db_update_period, int fetch_num_rows)
79 {
80 	/* Find a database module */
81 	if (db_bind_mod(db_url, &ul_dbf) < 0){
82 		LM_ERR("Unable to bind to a database driver\n");
83 		return -1;
84 	}
85 
86 	if (connect_db(db_url)!=0){
87 		LM_ERR("unable to connect to the database\n");
88 		return -1;
89 	}
90 
91 	if (!DB_CAPABILITY(ul_dbf, DB_CAP_ALL)) {
92 		LM_ERR("database module does not implement all functions needed by the module\n");
93 		return -1;
94 	}
95 
96 	ul_dbf.close(ul_dbh);
97 	ul_dbh = 0;
98 
99 	return 0;
100 }
101 
destroy_db()102 void destroy_db()
103 {
104 	/* close the DB connection */
105 	if (ul_dbh) {
106 		ul_dbf.close(ul_dbh);
107 		ul_dbh = 0;
108 	}
109 }
110 
use_location_pcscf_table(str * domain)111 int use_location_pcscf_table(str* domain)
112 {
113 	if(!ul_dbh){
114 		LM_ERR("invalid database handle\n");
115 		return -1;
116 	}
117 
118 	if (ul_dbf.use_table(ul_dbh, domain) < 0) {
119 		LM_ERR("Error in use_table\n");
120 		return -1;
121 	}
122 
123 	return 0;
124 }
125 
db_update_pcontact(pcontact_t * _c)126 int db_update_pcontact(pcontact_t* _c)
127 {
128 	str impus, service_routes;
129 
130 	db_val_t match_values[2];
131 	db_key_t match_keys[2] = { &aor_col, &received_port_col };
132     db_op_t op[2];
133 	db_key_t update_keys[8] = { &expires_col, &reg_state_col,
134 								&service_routes_col, &received_col,
135 								&received_port_col, &received_proto_col,
136 								&rx_session_id_col, &public_ids_col };
137 	db_val_t values[8];
138 
139 	LM_DBG("updating pcontact: aor[%.*s], received port %u\n", _c->aor.len, _c->aor.s, _c->received_port);
140 
141 	VAL_TYPE(match_values) = DB1_STR;
142 	VAL_NULL(match_values) = 0;
143 	VAL_STR(match_values) = _c->aor;
144 
145 	VAL_TYPE(match_values + 1)	= DB1_INT;
146 	VAL_NULL(match_values + 1)	= 0;
147 	VAL_INT(match_values + 1)	= _c->received_port;
148 
149 	op[0]=OP_EQ;
150 	op[1]=OP_EQ;
151 
152 	if (use_location_pcscf_table(_c->domain) < 0) {
153 		LM_ERR("Error trying to use table %.*s\n", _c->domain->len, _c->domain->s);
154 		return -1;
155 	}
156 
157 	VAL_TYPE(values) 	= DB1_DATETIME;
158 	VAL_TIME(values)	= _c->expires;
159 	VAL_NULL(values) 	= 0;
160 
161 	VAL_TYPE(values + 1)= DB1_INT;
162 	VAL_NULL(values + 1)= 0;
163 	VAL_INT(values + 1)	= _c->reg_state;
164 
165 	str empty_str = str_init("");
166 	if (_c->service_routes) {
167 		service_routes.len = service_routes_as_string(_c, &service_route_buffer);
168 		service_routes.s = service_route_buffer.buf;
169 	}
170 	SET_STR_VALUE(values + 2, (_c->service_routes)?service_routes:empty_str);
171 	VAL_TYPE(values + 2) = DB1_STR;
172 	VAL_NULL(values + 2) = 0;
173 
174 	SET_STR_VALUE(values + 3, _c->received_host);
175 	VAL_TYPE(values + 3) = DB1_STR;
176 	VAL_NULL(values + 3) = 0;
177 
178 	VAL_TYPE(values + 4)= DB1_INT;
179 	VAL_NULL(values + 4)= 0;
180 	VAL_INT(values + 4)	= _c->received_port;
181 
182 	VAL_TYPE(values + 5)= DB1_INT;
183 	VAL_NULL(values + 5)= 0;
184 	VAL_INT(values + 5)	= _c->received_proto;
185 
186 	VAL_TYPE(values + 6) = DB1_STR;
187 	SET_PROPER_NULL_FLAG(_c->rx_session_id, values, 6);
188 	LM_DBG("Trying to set rx session id: %.*s\n", _c->rx_session_id.len, _c->rx_session_id.s);
189 	SET_STR_VALUE(values + 6, _c->rx_session_id);
190 
191 	/* add the public identities */
192 	impus.len = impus_as_string(_c, &impu_buffer);
193 	impus.s = impu_buffer.buf;
194 	VAL_TYPE(values + 7) = DB1_STR;
195 	SET_PROPER_NULL_FLAG(impus, values, 7);
196 	SET_STR_VALUE(values + 7, impus);
197 
198 	if((ul_dbf.update(ul_dbh, match_keys, op, match_values, update_keys,values, 2, 8)) !=0){
199 		LM_ERR("could not update database info\n");
200 	    return -1;
201 	}
202 
203 	if (ul_dbf.affected_rows && ul_dbf.affected_rows(ul_dbh) == 0) {
204 		LM_DBG("no existing rows for an update... doing insert\n");
205 		if (db_insert_pcontact(_c) != 0) {
206 			LM_ERR("Failed to insert a pcontact on update\n");
207 		}
208 	}
209 
210 	return 0;
211 }
212 
db_delete_pcontact(pcontact_t * _c)213 int db_delete_pcontact(pcontact_t* _c)
214 {
215 	LM_DBG("Trying to delete contact: aor[%.*s], received port %u\n", _c->aor.len, _c->aor.s, _c->received_port);
216 	db_val_t values[2];
217 	db_key_t match_keys[2] = { &aor_col, &received_port_col };
218 
219 	VAL_TYPE(values) = DB1_STR;
220 	VAL_NULL(values) = 0;
221 	SET_STR_VALUE(values, _c->aor);
222 
223 	VAL_TYPE(values + 1) = DB1_INT;
224 	VAL_NULL(values + 1) = 0;
225 	VAL_INT(values + 1)	 = _c->received_port;
226 
227 	if (use_location_pcscf_table(_c->domain) < 0) {
228 		LM_ERR("Error trying to use table %.*s\n", _c->domain->len, _c->domain->s);
229 		return -1;
230 	}
231 
232 	if(ul_dbf.delete(ul_dbh, match_keys, 0, values, 2) < 0) {
233     	LM_ERR("Failed to delete database information: aor[%.*s], received port %u, rx_session_id=[%.*s]\n",
234     													_c->aor.len, _c->aor.s,
235 														_c->received_port,
236 														_c->rx_session_id.len, _c->rx_session_id.s);
237 		return -1;
238 	}
239 
240 	return 0;
241 }
242 
db_insert_pcontact(struct pcontact * _c)243 int db_insert_pcontact(struct pcontact* _c)
244 {
245 	str empty_str = str_init("");
246 	str impus, service_routes;
247 
248 	db_key_t keys[16] = {
249 				&domain_col,
250 				&aor_col,
251 				&received_col,
252 				&received_port_col,	&received_proto_col,
253 				&path_col,		&rinstance_col,
254                                 &rx_session_id_col,	&reg_state_col,
255 				&expires_col,		&service_routes_col,
256 				&socket_col,		&public_ids_col, &host_col, &port_col, &protocol_col
257 	};
258 	db_val_t values[16];
259 
260 	VAL_TYPE(GET_FIELD_IDX(values, LP_DOMAIN_IDX)) = DB1_STR;
261 	VAL_TYPE(GET_FIELD_IDX(values, LP_AOR_IDX)) = DB1_STR;
262 	VAL_TYPE(GET_FIELD_IDX(values, LP_RECEIVED_IDX)) = DB1_STR;
263 	VAL_TYPE(GET_FIELD_IDX(values, LP_RECEIVED_PORT_IDX)) = DB1_INT;
264 	VAL_TYPE(GET_FIELD_IDX(values, LP_RECEIVED_PROTO_IDX)) = DB1_INT;
265 	VAL_TYPE(GET_FIELD_IDX(values, LP_PATH_IDX)) = DB1_STR;
266 	VAL_TYPE(GET_FIELD_IDX(values, LP_RINSTANCE_IDX)) = DB1_STR;
267 	VAL_TYPE(GET_FIELD_IDX(values, LP_RX_SESSION_ID_IDX)) = DB1_STR;
268 	VAL_TYPE(GET_FIELD_IDX(values, LP_REG_STATE_IDX)) = DB1_INT;
269 	VAL_TYPE(GET_FIELD_IDX(values, LP_EXPIRES_IDX)) = DB1_DATETIME;
270 	VAL_TYPE(GET_FIELD_IDX(values, LP_SERVICE_ROUTES_IDX)) = DB1_STR;
271 	VAL_TYPE(GET_FIELD_IDX(values, LP_SOCKET_IDX)) = DB1_STR;
272 	VAL_TYPE(GET_FIELD_IDX(values, LP_PUBLIC_IPS_IDX)) = DB1_STR;
273 	VAL_TYPE(GET_FIELD_IDX(values, LP_HOST_IDX)) = DB1_STR;
274 	VAL_TYPE(GET_FIELD_IDX(values, LP_PORT_IDX)) = DB1_INT;
275 	VAL_TYPE(GET_FIELD_IDX(values, LP_PROTOCOL_IDX)) = DB1_INT;
276 
277 
278 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_DOMAIN_IDX), (*_c->domain));
279 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_AOR_IDX), _c->aor);	//TODO: need to clean AOR
280 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_RECEIVED_IDX), _c->received_host);
281 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_HOST_IDX), _c->via_host);
282 
283 	SET_PROPER_NULL_FLAG((*_c->domain), values, LP_DOMAIN_IDX);
284 	SET_PROPER_NULL_FLAG(_c->aor, values, LP_AOR_IDX);
285 	SET_PROPER_NULL_FLAG(_c->received_host, values, LP_RECEIVED_IDX);
286 	SET_PROPER_NULL_FLAG(_c->via_host, values, LP_HOST_IDX);
287 
288 	VAL_INT(GET_FIELD_IDX(values, LP_RECEIVED_PORT_IDX)) = _c->received_port;
289 	VAL_INT(GET_FIELD_IDX(values, LP_RECEIVED_PROTO_IDX)) = _c->received_proto;
290 	VAL_NULL(GET_FIELD_IDX(values, LP_RECEIVED_PORT_IDX)) = 0;
291 	VAL_NULL(GET_FIELD_IDX(values, LP_RECEIVED_PROTO_IDX)) = 0;
292 	VAL_INT(GET_FIELD_IDX(values, LP_PORT_IDX)) = _c->via_port;
293 	VAL_INT(GET_FIELD_IDX(values, LP_PROTOCOL_IDX)) = _c->via_proto;
294 	VAL_NULL(GET_FIELD_IDX(values, LP_PORT_IDX)) = 0;
295 	VAL_NULL(GET_FIELD_IDX(values, LP_PROTOCOL_IDX)) = 0;
296 
297 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_PATH_IDX), _c->path);
298 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_RINSTANCE_IDX), _c->rinstance);
299 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_RX_SESSION_ID_IDX), _c->rx_session_id);
300 	SET_PROPER_NULL_FLAG(_c->path, values, LP_PATH_IDX);
301 	SET_PROPER_NULL_FLAG(_c->rinstance, values, LP_RINSTANCE_IDX);
302 	SET_PROPER_NULL_FLAG(_c->rx_session_id, values, LP_RX_SESSION_ID_IDX);
303 
304 	VAL_DOUBLE(GET_FIELD_IDX(values, LP_REG_STATE_IDX)) = _c->reg_state;
305 	VAL_TIME(GET_FIELD_IDX(values, LP_EXPIRES_IDX)) = _c->expires;
306 	VAL_NULL(GET_FIELD_IDX(values, LP_REG_STATE_IDX)) = 0;
307 	VAL_NULL(GET_FIELD_IDX(values, LP_EXPIRES_IDX)) = 0;
308 
309 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_SERVICE_ROUTES_IDX), _c->service_routes?(*_c->service_routes):empty_str);
310 	VAL_NULL(GET_FIELD_IDX(values, LP_SERVICE_ROUTES_IDX)) = 1;
311 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_SOCKET_IDX), _c->sock?_c->sock->sock_str:empty_str);
312 	VAL_NULL(GET_FIELD_IDX(values, LP_SOCKET_IDX)) = 1;
313 
314 	if (_c->service_routes) {
315 		SET_PROPER_NULL_FLAG((*_c->service_routes), values, LP_SERVICE_ROUTES_IDX);
316 	}
317 	else {
318 		VAL_NULL(GET_FIELD_IDX(values, LP_SERVICE_ROUTES_IDX)) = 1;
319 	}
320 
321 	if (_c->sock) {
322 		SET_PROPER_NULL_FLAG(_c->sock->sock_str, values, LP_SOCKET_IDX);
323 	} else {
324 		VAL_NULL(GET_FIELD_IDX(values, LP_SOCKET_IDX)) = 1;
325 	}
326 
327 	/* add the public identities */
328 	impus.len = impus_as_string(_c, &impu_buffer);
329 	impus.s = impu_buffer.buf;
330 	SET_PROPER_NULL_FLAG(impus, values, LP_PUBLIC_IPS_IDX);
331 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_PUBLIC_IPS_IDX), impus);
332 
333 	/* add service routes */
334 	service_routes.len = service_routes_as_string(_c, &service_route_buffer);
335 	service_routes.s = service_route_buffer.buf;
336 	SET_PROPER_NULL_FLAG(service_routes, values, LP_SERVICE_ROUTES_IDX);
337 	SET_STR_VALUE(GET_FIELD_IDX(values, LP_SERVICE_ROUTES_IDX), service_routes);
338 
339 	if (use_location_pcscf_table(_c->domain) < 0) {
340 		LM_ERR("Error trying to use table %.*s\n", _c->domain->len, _c->domain->s);
341 		return -1;
342 	}
343 
344 	if (ul_dbf.insert(ul_dbh, keys, values, 15) < 0) {
345 		LM_ERR("inserting contact in db failed\n");
346 		return -1;
347 	}
348 
349 	return 0;
350 }
351 
db_update_pcontact_security_temp(struct pcontact * _c,security_type _t,security_t * _s)352 int db_update_pcontact_security_temp(struct pcontact* _c, security_type _t, security_t* _s) {
353 	db_val_t match_values[2];
354 	db_key_t match_keys[2] = { &aor_col, &received_port_col };
355 	db_op_t op[2];
356 
357 	db_key_t update_keys[15] = { &t_security_type_col, &t_protocol_col,
358 			&t_mode_col, &t_ck_col, &t_ik_col, &t_ealg_col, &t_ialg_col, &t_port_pc_col, &t_port_ps_col, &t_port_uc_col,
359 			&t_port_us_col, &t_spi_pc_col, &t_spi_ps_col, &t_spi_uc_col, &t_spi_us_col };
360 	db_val_t values[15];
361 
362 	LM_CRIT("updating temp security for pcontact: aor[%.*s], received port %u\n", _c->aor.len, _c->aor.s, _c->received_port);
363 
364 	VAL_TYPE(match_values) = DB1_STR;
365 	VAL_NULL(match_values) = 0;
366 	VAL_STR(match_values) = _c->aor;
367 
368 	VAL_TYPE(match_values + 1)	= DB1_INT;
369 	VAL_NULL(match_values + 1)	= 0;
370 	VAL_INT(match_values + 1)	= _c->received_port;
371 
372 	op[0]=OP_EQ;
373 	op[1]=OP_EQ;
374 
375 	if (use_location_pcscf_table(_c->domain) < 0) {
376 		LM_ERR("Error trying to use table %.*s\n", _c->domain->len, _c->domain->s);
377 		return -1;
378 	}
379 
380 	VAL_TYPE(values) = DB1_INT;
381 	VAL_TIME(values) = _s?_s->type:0;
382 	VAL_NULL(values) = 0;
383 
384 	switch (_t) {
385 	case SECURITY_IPSEC: {
386 		ipsec_t* ipsec = _s?_s->data.ipsec:0;
387 		str s_empty = {0,0};
388 		int i = 1;
389 		VAL_TYPE(values + i) = DB1_STR;
390 		VAL_NULL(values + i) = ipsec?0:1;
391 		VAL_STR(values + i) = ipsec?ipsec->prot:s_empty;
392 
393 		VAL_TYPE(values + ++i) = DB1_STR;
394 		VAL_NULL(values + i) = ipsec?0:1;
395 		VAL_STR(values + i) = ipsec?ipsec->mod:s_empty;
396 
397 		VAL_TYPE(values + ++i) = DB1_STR;
398 		VAL_NULL(values + i) = ipsec?0:1;
399 		VAL_STR(values + i) = ipsec?ipsec->ck:s_empty;
400 
401 		VAL_TYPE(values + ++i) = DB1_STR;
402 		VAL_NULL(values + i) = ipsec?0:1;
403 		VAL_STR(values + i) = ipsec?ipsec->ik:s_empty;
404 
405 		VAL_TYPE(values + ++i) = DB1_STR;
406 		VAL_NULL(values + i) = ipsec?0:1;
407 		VAL_STR(values + i) = ipsec?ipsec->ealg:s_empty;
408 
409 		VAL_TYPE(values + ++i) = DB1_STR;
410 		VAL_NULL(values + i) = ipsec?0:1;
411 		VAL_STR(values + i) = ipsec?ipsec->alg:s_empty;
412 
413 		VAL_TYPE(values + ++i) = DB1_INT;
414 		VAL_NULL(values + i) = ipsec?0:1;
415 		VAL_INT(values + i) = ipsec?ipsec->port_pc:0;
416 
417 		VAL_TYPE(values + ++i) = DB1_INT;
418 		VAL_NULL(values + i) = ipsec?0:1;
419 		VAL_INT(values + i) = ipsec?ipsec->port_ps:0;
420 
421 		VAL_TYPE(values + ++i) = DB1_INT;
422 		VAL_NULL(values + i) = ipsec?0:1;
423 		VAL_INT(values + i) = ipsec?ipsec->port_uc:0;
424 
425 		VAL_TYPE(values + ++i) = DB1_INT;
426 		VAL_NULL(values + i) = ipsec?0:1;
427 		VAL_INT(values + i) = ipsec?ipsec->port_us:0;
428 
429 		VAL_TYPE(values + ++i) = DB1_BIGINT;
430 		VAL_NULL(values + i) = ipsec?0:1;
431 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_pc:0;
432 
433 		VAL_TYPE(values + ++i) = DB1_BIGINT;
434 		VAL_NULL(values + i) = ipsec?0:1;
435 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_ps:0;
436 
437 		VAL_TYPE(values + ++i) = DB1_BIGINT;
438 		VAL_NULL(values + i) = ipsec?0:1;
439 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_uc:0;
440 
441 		VAL_TYPE(values + ++i) = DB1_BIGINT;
442 		VAL_NULL(values + i) = ipsec?0:1;
443 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_us:0;
444 
445 		if ((ul_dbf.update(ul_dbh, match_keys, op, match_values, update_keys, values, 2, 15)) != 0) {
446 			LM_ERR("could not update database info\n");
447 			return -1;
448 		}
449 
450 		if (ul_dbf.affected_rows && ul_dbf.affected_rows(ul_dbh) == 0) {
451 			LM_CRIT("no existing rows for an update... doing insert\n");
452 			if (db_insert_pcontact(_c) != 0) {
453 				LM_ERR("Failed to insert a pcontact on update\n");
454 			}
455 		}
456 		break;
457 	}
458 	default:
459 		LM_WARN("not yet implemented or unknown security type\n");
460 		return -1;
461 	}
462 
463 	return 0;
464 }
465 
db_update_pcontact_security(struct pcontact * _c,security_type _t,security_t * _s)466 int db_update_pcontact_security(struct pcontact* _c, security_type _t, security_t* _s) {
467 	db_val_t match_values[2];
468 	db_key_t match_keys[2] = { &aor_col, &received_port_col };
469 	db_op_t op[2];
470 
471 	db_key_t update_keys[15] = { &security_type_col, &protocol_col,
472 			&mode_col, &ck_col, &ik_col, &ealg_col, &ialg_col, &port_pc_col, &port_ps_col, &port_uc_col,
473 			&port_us_col, &spi_pc_col, &spi_ps_col, &spi_uc_col, &spi_us_col };
474 	db_val_t values[15];
475 
476 	LM_DBG("updating security for pcontact: aor[%.*s], received port %u\n", _c->aor.len, _c->aor.s, _c->received_port);
477 
478 	VAL_TYPE(match_values) = DB1_STR;
479 	VAL_NULL(match_values) = 0;
480 	VAL_STR(match_values) = _c->aor;
481 
482 	VAL_TYPE(match_values + 1)	= DB1_INT;
483 	VAL_NULL(match_values + 1)	= 0;
484 	VAL_INT(match_values + 1)	= _c->received_port;
485 
486 	op[0]=OP_EQ;
487 	op[1]=OP_EQ;
488 
489 	if (use_location_pcscf_table(_c->domain) < 0) {
490 		LM_ERR("Error trying to use table %.*s\n", _c->domain->len, _c->domain->s);
491 		return -1;
492 	}
493 
494 	VAL_TYPE(values) = DB1_INT;
495 	VAL_TIME(values) = _s?_s->type:0;
496 	VAL_NULL(values) = 0;
497 
498 	switch (_t) {
499 	case SECURITY_IPSEC: {
500 		ipsec_t* ipsec = _s?_s->data.ipsec:0;
501 		int i = 1;
502 		str s_empty = {0,0};
503 		VAL_TYPE(values + i) = DB1_STR;
504 		VAL_NULL(values + i) = ipsec?0:1;
505 		VAL_STR(values + i) = ipsec?ipsec->prot:s_empty;
506 
507 		VAL_TYPE(values + ++i) = DB1_STR;
508 		VAL_NULL(values + i) = ipsec?0:1;
509 		VAL_STR(values + i) = ipsec?ipsec->mod:s_empty;
510 
511 		VAL_TYPE(values + ++i) = DB1_STR;
512 		VAL_NULL(values + i) = ipsec?0:1;
513 		VAL_STR(values + i) = ipsec?ipsec->ck:s_empty;
514 
515 		VAL_TYPE(values + ++i) = DB1_STR;
516 		VAL_NULL(values + i) = ipsec?0:1;
517 		VAL_STR(values + i) = ipsec?ipsec->ik:s_empty;
518 
519 		VAL_TYPE(values + ++i) = DB1_STR;
520 		VAL_NULL(values + i) = ipsec?0:1;
521 		VAL_STR(values + i) = ipsec?ipsec->ealg:s_empty;
522 
523 		VAL_TYPE(values + ++i) = DB1_STR;
524 		VAL_NULL(values + i) = ipsec?0:1;
525 		VAL_STR(values + i) = ipsec?ipsec->alg:s_empty;
526 
527 		VAL_TYPE(values + ++i) = DB1_INT;
528 		VAL_NULL(values + i) = ipsec?0:1;
529 		VAL_INT(values + i) = ipsec?ipsec->port_pc:0;
530 
531 		VAL_TYPE(values + ++i) = DB1_INT;
532 		VAL_NULL(values + i) = ipsec?0:1;
533 		VAL_INT(values + i) = ipsec?ipsec->port_ps:0;
534 
535 		VAL_TYPE(values + ++i) = DB1_INT;
536 		VAL_NULL(values + i) = ipsec?0:1;
537 		VAL_INT(values + i) = ipsec?ipsec->port_uc:0;
538 
539 		VAL_TYPE(values + ++i) = DB1_INT;
540 		VAL_NULL(values + i) = ipsec?0:1;
541 		VAL_INT(values + i) = ipsec?ipsec->port_us:0;
542 
543 		VAL_TYPE(values + ++i) = DB1_BIGINT;
544 		VAL_NULL(values + i) = ipsec?0:1;
545 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_pc:0;
546 
547 		VAL_TYPE(values + ++i) = DB1_BIGINT;
548 		VAL_NULL(values + i) = ipsec?0:1;
549 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_ps:0;
550 
551 		VAL_TYPE(values + ++i) = DB1_BIGINT;
552 		VAL_NULL(values + i) = ipsec?0:1;
553 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_uc:0;
554 
555 		VAL_TYPE(values + ++i) = DB1_BIGINT;
556 		VAL_NULL(values + i) = ipsec?0:1;
557 		VAL_BIGINT(values + i) = ipsec?ipsec->spi_us:0;
558 
559 		if ((ul_dbf.update(ul_dbh, match_keys, op, match_values, update_keys, values, 2, 15)) != 0) {
560 			LM_ERR("could not update database info\n");
561 			return -1;
562 		}
563 
564 		if (ul_dbf.affected_rows && ul_dbf.affected_rows(ul_dbh) == 0) {
565 			LM_DBG("no existing rows for an update... doing insert\n");
566 			if (db_insert_pcontact(_c) != 0) {
567 				LM_ERR("Failed to insert a pcontact on update\n");
568 			}
569 		}
570 		break;
571 	}
572 	default:
573 		LM_WARN("not yet implemented or unknown security type\n");
574 		return -1;
575 	}
576 
577 	return 0;
578 }
579 
580 /* take a contact structure and a pointer to some memory and returns a list of public identities in the format
581  * <impu1><impu2>....<impu(n)>
582  * make sure p already has memory allocated
583  * returns the length of the string (list)
584  * the string list itself will be available in p
585  */
impus_as_string(struct pcontact * _c,t_reusable_buffer * buffer)586 int impus_as_string(struct pcontact* _c, t_reusable_buffer* buffer) {
587 	ppublic_t* impu;
588 	int len = 0;
589 	char *p;
590 
591 	impu = _c->head;
592 	while (impu) {
593 		len += 2 + impu->public_identity.len;
594 		impu = impu->next;
595 	}
596 
597 	if (!buffer->buf || buffer->buf_len == 0 || len > buffer->buf_len) {
598 		if (buffer->buf) {
599 			pkg_free(buffer->buf);
600 		}
601 		buffer->buf = (char*) pkg_malloc(len);
602 		if (!buffer->buf) {
603 			LM_CRIT("unable to allocate pkg memory\n");
604 			return 0;
605 		}
606 		buffer->buf_len = len;
607 	}
608 
609 	impu = _c->head;
610 	p = buffer->buf;
611 	while (impu) {
612 		*p++ = '<';
613 		memcpy(p, impu->public_identity.s, impu->public_identity.len);
614 		p += impu->public_identity.len;
615 		*p++ = '>';
616 		impu = impu->next;
617 	}
618 
619 	return len;
620 }
621 
622 /* take a contact structure and a pointer to some memory and returns a list of public identities in the format
623  * <impu1><impu2>....<impu(n)>
624  * make sure p already has memory allocated
625  * returns the length of the string (list)
626  * the string list itself will be available in p
627  */
service_routes_as_string(struct pcontact * _c,t_reusable_buffer * buffer)628 int service_routes_as_string(struct pcontact* _c, t_reusable_buffer *buffer) {
629 	int i;
630 	int len = 0;
631 	char *p;
632 	for (i=0; i<_c->num_service_routes; i++) {
633 		len += 2 + _c->service_routes[i].len;
634 	}
635 
636 	if (!buffer->buf || buffer->buf_len==0 || len > buffer->buf_len) {
637 		if (buffer->buf) {
638 			pkg_free(buffer->buf);
639 		}
640 		buffer->buf = (char*)pkg_malloc(len);
641 		if (!buffer->buf) {
642 			LM_CRIT("unable to allocate pkg memory\n");
643 			return 0;
644 		}
645 		buffer->buf_len = len;
646 	}
647 
648 	p = buffer->buf;
649 	for (i=0; i<_c->num_service_routes; i++) {
650 		*p = '<';
651 		p++;
652 		memcpy(p, _c->service_routes[i].s, _c->service_routes[i].len);
653 		p+=_c->service_routes[i].len;
654 		*p = '>';
655 		p++;
656 	}
657 
658 	return len;
659 }
660 
free_service_route_buf(void)661 void free_service_route_buf(void)
662 {
663 	if (service_route_buffer.buf) {
664 		pkg_free(service_route_buffer.buf);
665 		service_route_buffer.data_len = 0;
666 		service_route_buffer.buf_len = 0;
667 		service_route_buffer.buf = 0;
668 	}
669 }
670 
free_impu_buf(void)671 void free_impu_buf(void) {
672 	if (impu_buffer.buf) {
673 		pkg_free(impu_buffer.buf);
674 		impu_buffer.data_len = 0;
675 		impu_buffer.buf_len = 0;
676 		impu_buffer.buf = 0;
677 	}
678 }
679 
680