Browse code

initial commit

Wolfgang Kampichler authored on 24/01/2021 16:22:45
Showing 10 changed files
... ...
@@ -673,6 +673,18 @@ int http_client_request(
673 673
 			query_params.http_proxy_port = default_http_proxy_port;
674 674
 		}
675 675
 	}
676
+	if(default_tls_clientcert.s != NULL && default_tls_clientcert.len > 0) {
677
+		query_params.clientcert = default_tls_clientcert.s;
678
+	}
679
+	if(default_tls_clientkey.s != NULL && default_tls_clientkey.len > 0) {
680
+		query_params.clientkey = default_tls_clientkey.s;
681
+	}
682
+	if(default_tls_cacert != NULL) {
683
+		query_params.cacert = default_tls_cacert;
684
+	}
685
+	if(default_cipher_suite_list.s != NULL && default_cipher_suite_list.len) {
686
+		query_params.ciphersuites = default_cipher_suite_list.s;
687
+	}
676 688
 
677 689
 	res = curL_request_url(_m, _met, _url, _dst, &query_params);
678 690
 
... ...
@@ -44,6 +44,8 @@
44 44
 
45 45
 #include "pidf.h"
46 46
 #include "utilities.h"
47
+#include "response.h"
48
+#include "naptr.h"
47 49
 
48 50
 #define LOST_SUCCESS 200
49 51
 #define LOST_CLIENT_ERROR 400
... ...
@@ -52,6 +54,10 @@
52 54
 #define HELD_DEFAULT_TYPE "geodetic locationURI"
53 55
 #define HELD_DEFAULT_TYPE_LEN (sizeof(HELD_DEFAULT_TYPE) - 1)
54 56
 
57
+#define NAPTR_LOST_SERVICE_HTTP "LoST:http"
58
+#define NAPTR_LOST_SERVICE_HTTPS "LoST:https"
59
+#define NAPTR_LIS_SERVICE_HELD "LIS:HELD"
60
+
55 61
 extern httpc_api_t httpapi;
56 62
 
57 63
 extern int lost_geoloc_type;
... ...
@@ -138,6 +144,7 @@ char *lost_held_type(char *type, int *exact, int *lgth)
138 144
 
139 145
 err:
140 146
 	LM_ERR("no more private memory\n");
147
+	/* clean up */
141 148
 	if(ret != NULL) {
142 149
 		pkg_free(ret);
143 150
 	}
... ...
@@ -166,32 +173,56 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
166 173
 	xmlNodePtr root = NULL;
167 174
 	xmlNodePtr cur_node = NULL;
168 175
 
169
-	str did = {NULL, 0};
170
-	str que = {NULL, 0};
171
-	str con = {NULL, 0};
172
-	str geo = {NULL, 0};
173
-	str err = {NULL, 0};
174
-	str res = {NULL, 0};
175
-	str idhdr = {NULL, 0};
176
-	str pidfuri = {NULL, 0};
177
-	str rtype = {HELD_DEFAULT_TYPE, HELD_DEFAULT_TYPE_LEN};
178
-
179
-	int curlres = 0;
176
+	str geo = STR_NULL; /* return value geolocation uri */
177
+	str res = STR_NULL; /* return value pidf */
178
+	str err = STR_NULL; /* return value error */
179
+
180
+	str url = STR_NULL;
181
+	str did = STR_NULL;
182
+	str que = STR_NULL;
183
+	str con = STR_NULL;
184
+	str host = STR_NULL;
185
+	str name = STR_NULL;
186
+	str idhdr = STR_NULL;
187
+	str pidfuri = STR_NULL;
188
+
189
+	static str rtype = STR_STATIC_INIT(HELD_DEFAULT_TYPE);
190
+	static str sheld = STR_STATIC_INIT(NAPTR_LIS_SERVICE_HELD);
191
+
192
+	char ustr[MAX_URI_SIZE];
193
+	char istr[NI_MAXHOST];
194
+	char *ipstr = NULL;
195
+	char *lisurl = NULL;
196
+
197
+	int len = 0;
198
+	int curl = 0;
199
+	int flag = 0;
200
+	int naptr = 0;
180 201
 	int presence = 0;
181 202
 
182
-	if(_con == NULL || _pidf == NULL || _url == NULL || _err == NULL) {
203
+	if(_pidf == NULL || _url == NULL || _err == NULL) {
183 204
 		LM_ERR("invalid parameter\n");
184 205
 		goto err;
185 206
 	}
207
+
186 208
 	/* module parameter */
187 209
 	if(held_loc_type.len > 0) {
188 210
 		rtype.s = held_loc_type.s;
189 211
 		rtype.len = held_loc_type.len;
190 212
 	}
191 213
 	/* connection from parameter */
192
-	if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {
193
-		LM_ERR("cannot get connection string\n");
194
-		goto err;
214
+	if(_con) {
215
+		if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {
216
+			LM_ERR("cannot get connection string\n");
217
+			goto err;
218
+		}
219
+		/* check if connection exists */
220
+		if(con.s != NULL && con.len > 0) {
221
+			if(httpapi.http_connection_exists(&con) == 0) {
222
+				LM_ERR("connection: [%s] does not exist\n", con.s);
223
+				goto err;
224
+			}
225
+		}
195 226
 	}
196 227
 	/* id from parameter */
197 228
 	if(_id) {
... ...
@@ -225,30 +256,15 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
225 256
 		did.len = idhdr.len;
226 257
 	}
227 258
 	LM_INFO("### HELD id [%.*s]\n", did.len, did.s);
228
-
229
-	/* check if connection exists */
230
-	if(httpapi.http_connection_exists(&con) == 0) {
231
-		LM_ERR("connection: [%s] does not exist\n", con.s);
232
-		lost_free_string(&idhdr);
233
-		goto err;
234
-	}
235
-
236 259
 	/* assemble locationRequest */
237 260
 	held = lost_new_held(did, rtype, held_resp_time, held_exact_type);
238
-
239 261
 	if(held == NULL) {
240 262
 		LM_ERR("held object allocation failed\n");
241
-		lost_free_string(&idhdr);
263
+		lost_free_string(&idhdr); /* clean up */
242 264
 		goto err;
243 265
 	}
244 266
 	que.s = lost_held_location_request(held, &que.len);
245
-
246
-	/* free memory */
247
-	did.s = NULL;
248
-	did.len = 0;
249
-	lost_free_held(held);
250
-	lost_free_string(&idhdr);
251
-
267
+	lost_free_held(held); /* clean up */
252 268
 	if(que.len == 0) {
253 269
 		LM_ERR("held request document error\n");
254 270
 		que.s = NULL;
... ...
@@ -258,17 +274,89 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
258 274
 	LM_DBG("held location request: [%s]\n", que.s);
259 275
 
260 276
 	/* send locationRequest to location server - HTTP POST */
261
-	curlres = httpapi.http_connect(_m, &con, NULL, &res, mtheld, &que);
277
+	if(con.s != NULL && con.len > 0) {
278
+
279
+		LM_DBG("using connection [%.*s]\n", con.len, con.s);
280
+
281
+		/* send via connection */
282
+		curl = httpapi.http_connect(_m, &con, NULL, &res, mtheld, &que);
283
+	} else {
284
+		/* we have no connection ... do a NAPTR lookup */
285
+		if(lost_parse_host(did.s, &host, &flag) > 0) {
286
+
287
+			LM_DBG("no conn. trying NATPR lookup [%.*s]\n", host.len, host.s);
288
+
289
+			/* remove '[' and ']' from string (IPv6) */ 
290
+			if(flag == AF_INET6) {
291
+  				host.s++;
292
+  				host.len = host.len - 2;
293
+			}
294
+			/* is it a name or ip ... check nameinfo (reverse lookup) */
295
+			len = 0;
296
+			ipstr = lost_copy_string(host, &len);
297
+			if(len > 0) {
298
+				name.s = &(istr[0]);
299
+				name.len = NI_MAXHOST;
300
+				if(lost_get_nameinfo(ipstr, &name, flag) > 0) {
301
+
302
+					LM_DBG("ip [%s] to name [%.*s]\n", ipstr, name.len, name.s);
303
+
304
+					/* change ip string to name */ 
305
+					host.s = name.s;
306
+					host.len = name.len;
307
+				} else {
308
+
309
+					/* keep string */
310
+					LM_DBG("no nameinfo for [%s]\n", ipstr);
311
+				
312
+				}
313
+				pkg_free(ipstr); /* clean up */
314
+			}
315
+			url.s = &(ustr[0]);
316
+			url.len = MAX_URI_SIZE;
317
+			if((naptr = lost_naptr_lookup(host, &sheld, &url)) == 0) {
318
+				LM_ERR("NAPTR failed on [%.*s]\n", host.len, host.s);
319
+				lost_free_string(&que); /* clean up */
320
+				lost_free_string(&idhdr);
321
+				goto err;
322
+			}
323
+		} else {
324
+			LM_ERR("failed to get location service for [%.*s]\n", did.len, did.s);
325
+			lost_free_string(&que); /* clean up */
326
+			lost_free_string(&idhdr);
327
+			goto err;
328
+		}
329
+
330
+		LM_DBG("NATPR lookup returned [%.*s]\n", url.len, url.s);
331
+
332
+		/* curl doesn't like str */
333
+		len = 0;
334
+		lisurl = lost_copy_string(url, &len);
335
+		/* send to service */
336
+		if(len > 0) {
337
+			curl = httpapi.http_client_query(_m, lisurl, &res, que.s, mtheld);
338
+			pkg_free(lisurl); /*clean up */
339
+		} else {
340
+			goto err;	
341
+		}
342
+	}
262 343
 	/* only HTTP 2xx responses are accepted */
263
-	if(curlres >= 300 || curlres < 100) {
264
-		LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curlres);
344
+	if(curl >= 300 || curl < 100) {
345
+		if(con.s != NULL && con.len > 0) {
346
+			LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curl);
347
+		} else {
348
+			LM_ERR("[%.*s] failed with error: %d\n", url.len, url.s, curl);
349
+		}
265 350
 		lost_free_string(&res);
266 351
 		goto err;
267 352
 	}
268 353
 
269
-	LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curlres);
354
+	LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curl);
270 355
 
271
-	/* free memory */
356
+	did.s = NULL;
357
+	did.len = 0;
358
+	/* clean up */
359
+	lost_free_string(&idhdr);
272 360
 	lost_free_string(&que);
273 361
 	/* read and parse the returned xml */
274 362
 	doc = xmlReadMemory(res.s, res.len, 0, NULL,
... ...
@@ -288,7 +376,7 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
288 376
 		LM_ERR("empty xml document\n");
289 377
 		goto err;
290 378
 	}
291
-	/* check the root element ... shall be locationResponse, or errors */
379
+	/* check the root element ... shall be locationResponse, or error */
292 380
 	if(xmlStrcmp(root->name, (const xmlChar *)"locationResponse") == 0) {
293 381
 
294 382
 		LM_DBG("HELD location response [%.*s]\n", res.len, res.s);
... ...
@@ -310,8 +398,7 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
310 398
 						geo.s = lost_trim_content(geo.s, &geo.len);
311 399
 					}
312 400
 				}
313
-				if(xmlStrcmp(cur_node->name, (const xmlChar *)"presence")
314
-						== 0) {
401
+				if(xmlStrcmp(cur_node->name, (const xmlChar *)"presence") == 0) {
315 402
 
316 403
 					LM_DBG("*** node '%s' found\n", cur_node->name);
317 404
 
... ...
@@ -320,29 +407,22 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
320 407
 				}
321 408
 			}
322 409
 		}
323
-
324 410
 		/* if we do not have a presence node but a location URI */
325 411
 		/* dereference pidf.lo at location server via HTTP GET */
326
-		if((presence == 0) && (geo.len > 0)) {
327
-
412
+		if((presence == 0) && (geo.s != NULL && geo.len > 0)) {
328 413
 			LM_INFO("presence node not found in HELD response, trying URI "
329 414
 					"...\n");
330
-
331
-			curlres =
332
-					httpapi.http_client_query(_m, geo.s, &pidfuri, NULL, NULL);
415
+			curl = httpapi.http_client_query(_m, geo.s, &pidfuri, NULL, NULL);
333 416
 			/* only HTTP 2xx responses are accepted */
334
-			if(curlres >= 300 || curlres < 100) {
335
-				LM_ERR("dereferencing location failed: %d\n", curlres);
336
-				/* free memory */
417
+			if(curl >= 300 || curl < 100) {
418
+				LM_ERR("dereferencing location failed: %d\n", curl);
419
+				/* clean up */
337 420
 				lost_free_string(&pidfuri);
338 421
 				goto err;
339 422
 			}
340
-
341 423
 			if(pidfuri.len == 0) {
342
-
343 424
 				LM_WARN("HELD location request failed [%.*s]\n", geo.len,
344 425
 						geo.s);
345
-
346 426
 			} else {
347 427
 
348 428
 				LM_DBG("HELD location response [%.*s]\n", pidfuri.len,
... ...
@@ -352,14 +432,15 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
352 432
 				res.len = pidfuri.len;
353 433
 			}
354 434
 		}
435
+		/* error received */
355 436
 	} else if(xmlStrcmp(root->name, (const xmlChar *)"error") == 0) {
356 437
 
357 438
 		LM_DBG("HELD error response [%.*s]\n", res.len, res.s);
358 439
 
359
-		/* get the error patterm */
440
+		/* get the error property */
360 441
 		err.s = lost_get_property(root, (char *)"code", &err.len);
361 442
 		if(err.len == 0) {
362
-			LM_ERR("error - code property not found: [%.*s]\n", res.len, res.s);
443
+			LM_ERR("error - property not found: [%.*s]\n", res.len, res.s);
363 444
 			goto err;
364 445
 		}
365 446
 		LM_WARN("locationRequest error response: [%.*s]\n", err.len, err.s);
... ...
@@ -367,8 +448,9 @@ int lost_held_function(struct sip_msg *_m, char *_con, char *_pidf, char *_url,
367 448
 		LM_ERR("root element is not valid: [%.*s]\n", res.len, res.s);
368 449
 		goto err;
369 450
 	}
451
+
452
+	/* clean up */
370 453
 	xmlFreeDoc(doc);
371
-	doc = NULL;
372 454
 
373 455
 	/* set writeable pvars */
374 456
 	pvpidf.rs = res;
... ...
@@ -422,63 +504,85 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
422 504
 
423 505
 	p_loc_t loc = NULL;
424 506
 	p_geolist_t geolist = NULL;
425
-	int geotype;
426
-
427
-	str url = {NULL, 0};
428
-	str uri = {NULL, 0};
429
-	str urn = {NULL, 0};
430
-	str err = {NULL, 0};
431
-	str req = {NULL, 0};
432
-	str con = {NULL, 0};
433
-	str ret = {NULL, 0};
434
-	str name = {NULL, 0};
435
-	str pidf = {NULL, 0};
436
-	str geohdr = {NULL, 0};
437
-	str pidfhdr = {NULL, 0};
507
+	p_fsr_t fsrdata = NULL;
508
+
509
+	str name = STR_NULL; /* return value displayName */
510
+	str uri = STR_NULL;	 /* return value uri */
511
+	str err = STR_NULL;	 /* return value error */
512
+
513
+	str tmp = STR_NULL;
514
+	str url = STR_NULL;
515
+	str urn = STR_NULL;
516
+	str req = STR_NULL;
517
+	str con = STR_NULL;
518
+	str ret = STR_NULL;
519
+	str pidf = STR_NULL;
520
+	str geohdr = STR_NULL;
521
+	str oldurl = STR_NULL;
522
+	str losturl = STR_NULL;
523
+
524
+	static str shttp = STR_STATIC_INIT(NAPTR_LOST_SERVICE_HTTP);
525
+	static str shttps = STR_STATIC_INIT(NAPTR_LOST_SERVICE_HTTPS);
438 526
 
439 527
 	struct msg_start *fl;
528
+
529
+	char ustr[MAX_URI_SIZE];
440 530
 	char *search = NULL;
441 531
 	char *geoval = NULL;
442
-	int curlres = 0;
443
-	int geoitems = 0;
444 532
 
445
-	xmlDocPtr doc = NULL;
446
-	xmlNodePtr root = NULL;
533
+	int geotype = 0;
534
+	int redirect = 0;
535
+	int curl = 0;
536
+	int naptr = 0;
537
+	int geoitems = 0;
447 538
 
448 539
 	if(_con == NULL || _uri == NULL || _name == NULL || _err == NULL) {
449 540
 		LM_ERR("invalid parameter\n");
450 541
 		goto err;
451 542
 	}
452
-	if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {
453
-		LM_ERR("cannot get connection string\n");
454
-		goto err;
543
+	/* connection from parameter */
544
+	if(_con) {
545
+		if(fixup_get_svalue(_m, (gparam_p)_con, &con) != 0) {
546
+			LM_ERR("cannot get connection string\n");
547
+			goto err;
548
+		}
549
+		/* check if connection exists */
550
+		if(con.s != NULL && con.len > 0) {
551
+			if(httpapi.http_connection_exists(&con) == 0) {
552
+				LM_WARN("connection: [%.*s] does not exist\n", con.len, con.s);
553
+				/* check if NAPTR lookup works with connection parameter */
554
+				losturl.s = &(ustr[0]);
555
+				losturl.len = MAX_URI_SIZE;
556
+				if((naptr = lost_naptr_lookup(con, &shttps, &losturl)) == 0) {
557
+					naptr = lost_naptr_lookup(con, &shttp, &losturl);
558
+				}
559
+				if(naptr == 0) {
560
+					LM_ERR("NAPTR failed on [%.*s]\n", con.len, con.s);
561
+					goto err;
562
+				}
563
+			}
564
+		}
455 565
 	}
456 566
 	/* urn from parameter */
457 567
 	if(_urn) {
458 568
 		if(fixup_get_svalue(_m, (gparam_p)_urn, &urn) != 0) {
459
-			LM_ERR("cannot get service urn\n");
569
+			LM_ERR("cannot get service urn parameter\n");
460 570
 			goto err;
461 571
 		}
462 572
 	}
463 573
 	/* urn from request line */
464 574
 	if(urn.len == 0) {
465
-		LM_WARN("no sevice urn parameter, trying request line ...\n");
575
+
576
+		LM_DBG("no service urn parameter, trying request line ...\n");
577
+
466 578
 		fl = &(_m->first_line);
467 579
 		urn.len = fl->u.request.uri.len;
468 580
 		urn.s = fl->u.request.uri.s;
469 581
 	}
470 582
 	/* check urn scheme */
471
-	if(urn.len > 3) {
472
-		search = urn.s;
473
-		if(((*(search + 0) == 'u') || (*(search + 0) == 'U'))
474
-				&& ((*(search + 1) == 'r') || (*(search + 1) == 'R'))
475
-				&& ((*(search + 2) == 'n') || (*(search + 2) == 'N'))
476
-				&& (*(search + 3) == ':')) {
477
-			LM_INFO("### LOST urn\t[%.*s]\n", urn.len, urn.s);
478
-		} else {
479
-			LM_ERR("service urn not found\n");
480
-			goto err;
481
-		}
583
+	search = urn.s;
584
+	if(is_urn(search) > 0) {
585
+		LM_INFO("### LOST urn\t[%.*s]\n", urn.len, urn.s);
482 586
 	} else {
483 587
 		LM_ERR("service urn not found\n");
484 588
 		goto err;
... ...
@@ -486,44 +590,35 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
486 590
 	/* pidf from parameter */
487 591
 	if(_pidf) {
488 592
 		if(fixup_get_svalue(_m, (gparam_p)_pidf, &pidf) != 0) {
489
-			LM_WARN("cannot get pidf-lo parameter\n");
593
+			LM_ERR("cannot get pidf parameter\n");
490 594
 		} else {
491 595
 
492
-			LM_DBG("parsing pidf-lo from paramenter\n");
596
+			LM_DBG("parsing pidf parameter ...\n");
493 597
 
494
-			if(pidf.len > 0) {
598
+			if(pidf.s != NULL && pidf.len > 0) {
495 599
 
496
-				LM_DBG("pidf-lo: [%.*s]\n", pidf.len, pidf.s);
600
+				LM_DBG("pidf: [%.*s]\n", pidf.len, pidf.s);
497 601
 
498
-				/* parse the pidf-lo */
602
+				/* parse the pidf and get loc object */
499 603
 				loc = lost_parse_pidf(pidf, urn);
500
-				/* free memory */
501
-				pidf.s = NULL;
502
-				pidf.len = 0;
503
-			} else {
504
-				LM_WARN("no valid pidf parameter ...\n");
505 604
 			}
506 605
 		}
507 606
 	}
508
-
509
-	/* no pidf-lo so far ... check geolocation header */
607
+	/* neither valifd pidf parameter nor loc ... check geolocation header */
510 608
 	if(loc == NULL) {
511 609
 
512 610
 		LM_DBG("looking for geolocation header ...\n");
513 611
 
514
-		geohdr.s = lost_get_geolocation_header(_m, &geohdr.len);
515
-		if(geohdr.len == 0) {
612
+		if(lost_get_geolocation_header(_m, &geohdr) == 0) {
516 613
 			LM_ERR("geolocation header not found\n");
517
-			goto err;
518 614
 		}
519 615
 
520
-		LM_DBG("geolocation header found\n");
616
+		LM_DBG("parsing geolocation header ...\n");
521 617
 
522 618
 		/* parse Geolocation header */
523 619
 		geolist = lost_new_geoheader_list(geohdr, &geoitems);
524 620
 		if(geoitems == 0) {
525 621
 			LM_ERR("invalid geolocation header\n");
526
-			lost_free_string(&geohdr);
527 622
 			goto err;
528 623
 		}
529 624
 
... ...
@@ -535,7 +630,6 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
535 630
 
536 631
 			lost_reverse_geoheader_list(&geolist);
537 632
 		}
538
-
539 633
 		switch(lost_geoloc_type) {
540 634
 			case ANY: /* type: 0 */
541 635
 				geoval = lost_get_geoheader_value(geolist, ANY, &geotype);
... ...
@@ -580,36 +674,26 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
580 674
 
581 675
 				break;
582 676
 		}
583
-
584 677
 		if(geoval == NULL) {
585 678
 			LM_ERR("invalid geolocation header\n");
586
-			/* free memory */
587
-			lost_delete_geoheader_list(geolist);
588
-			lost_free_string(&geohdr);
589 679
 			goto err;
590 680
 		}
591
-
592 681
 		LM_INFO("### LOST loc\t[%s]\n", geoval);
593
-
682
+		/* clean up */
683
+		pidf.s = NULL;
684
+		pidf.len = 0;
594 685
 		/* use location by value */
595 686
 		if(geotype == CID) {
596
-
597 687
 			/* get body part - filter=>content-indirection */
598 688
 			pidf.s = get_body_part_by_filter(_m, 0, 0, geoval, NULL, &pidf.len);
599
-			if(pidf.len > 0) {
689
+			if(pidf.s != NULL && pidf.len > 0) {
600 690
 
601 691
 				LM_DBG("LbV pidf-lo: [%.*s]\n", pidf.len, pidf.s);
602 692
 
603
-				/* parse the pidf-lo */
604
-				loc = lost_parse_pidf(pidf, urn);
605
-				/* free memory */
606
-				pidf.s = NULL;
607
-				pidf.len = 0;
608 693
 			} else {
609 694
 				LM_WARN("no multipart body found\n");
610 695
 			}
611 696
 		}
612
-
613 697
 		/* use location by reference */
614 698
 		if((geotype == HTTPS) || (geotype == HTTP)) {
615 699
 			url.s = geoval;
... ...
@@ -617,60 +701,44 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
617 701
 			/* ! dereference pidf.lo at location server - HTTP GET */
618 702
 			/* ! requires hack in http_client module */
619 703
 			/* ! functions.c => http_client_query => query_params.oneline = 0; */
620
-			curlres =
621
-					httpapi.http_client_query(_m, url.s, &pidfhdr, NULL, NULL);
622
-			/* free memory */
704
+			curl = httpapi.http_client_query(_m, url.s, &ret, NULL, NULL);
623 705
 			url.s = NULL;
624 706
 			url.len = 0;
625 707
 			/* only HTTP 2xx responses are accepted */
626
-			if(curlres >= 300 || curlres < 100) {
627
-				LM_ERR("http GET failed with error: %d\n", curlres);
628
-				/* free memory */
629
-				lost_delete_geoheader_list(geolist);
630
-				lost_free_string(&pidfhdr);
631
-				lost_free_string(&geohdr);
708
+			if(curl >= 300 || curl < 100) {
709
+				LM_ERR("http GET failed with error: %d\n", curl);
710
+				/* clean up */
711
+				lost_free_string(&ret);
632 712
 				goto err;
633 713
 			}
634
-
635
-			pidf.s = pidfhdr.s;
636
-			pidf.len = pidfhdr.len;
637
-
638
-			if(pidf.len > 0) {
714
+			pidf.s = ret.s;
715
+			pidf.len = ret.len;
716
+			if(pidf.s != NULL && pidf.len > 0) {
639 717
 
640 718
 				LM_DBG("LbR pidf-lo: [%.*s]\n", pidf.len, pidf.s);
641 719
 
642
-				/* parse the pidf-lo */
643
-				loc = lost_parse_pidf(pidf, urn);
644
-				/* free memory */
645
-				pidf.s = NULL;
646
-				pidf.len = 0;
647 720
 			} else {
648 721
 				LM_WARN("dereferencing location failed\n");
649 722
 			}
650 723
 		}
651
-		/* free memory */
724
+		/* clean up */
652 725
 		lost_delete_geoheader_list(geolist);
653
-		lost_free_string(&geohdr);
654
-		lost_free_string(&pidfhdr);
726
+		lost_free_string(&ret);
655 727
 	}
656
-
657
-	if(loc == NULL) {
728
+	if(pidf.s == NULL && pidf.len == 0) {
658 729
 		LM_ERR("location object not found\n");
659 730
 		goto err;
660 731
 	}
661
-
662
-	/* check if connection exits */
663
-	if(httpapi.http_connection_exists(&con) == 0) {
664
-		LM_ERR("connection: [%.*s] does not exist\n", con.len, con.s);
732
+	/* parse the pidf and get loc object */
733
+	loc = lost_parse_pidf(pidf, urn);
734
+	if(loc == NULL) {
735
+		LM_ERR("parsing pidf failed\n");
665 736
 		goto err;
666 737
 	}
667 738
 	/* assemble findService request */
668 739
 	req.s = lost_find_service_request(loc, &req.len);
669
-	/* free memory */
670
-	lost_free_loc(loc);
671
-	loc = NULL;
672
-
673
-	if(req.len == 0) {
740
+	lost_free_loc(loc); /* clean up */
741
+	if(req.s == NULL && req.len == 0) {
674 742
 		LM_ERR("lost request failed\n");
675 743
 		goto err;
676 744
 	}
... ...
@@ -678,18 +746,19 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
678 746
 	LM_DBG("findService request: [%.*s]\n", req.len, req.s);
679 747
 
680 748
 	/* send findService request to mapping server - HTTP POST */
681
-	curlres = httpapi.http_connect(_m, &con, NULL, &ret, mtlost, &req);
749
+	if(naptr) {
750
+		curl = httpapi.http_client_query(_m, url.s, &ret, req.s, mtlost);
751
+	} else {
752
+		curl = httpapi.http_connect(_m, &con, NULL, &ret, mtlost, &req);
753
+	}
682 754
 	/* only HTTP 2xx responses are accepted */
683
-	if(curlres >= 300 || curlres < 100) {
684
-		LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curlres);
755
+	if(curl >= 300 || curl < 100) {
756
+		LM_ERR("[%.*s] failed with error: %d\n", con.len, con.s, curl);
685 757
 		lost_free_string(&ret);
686 758
 		goto err;
687 759
 	}
688 760
 
689
-	LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curlres);
690
-
691
-	/* free memory */
692
-	lost_free_string(&req);
761
+	LM_DBG("[%.*s] returned: %d\n", con.len, con.s, curl);
693 762
 
694 763
 	if(ret.len == 0) {
695 764
 		LM_ERR("findService request failed\n");
... ...
@@ -698,70 +767,117 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
698 767
 
699 768
 	LM_DBG("findService response: [%.*s]\n", ret.len, ret.s);
700 769
 
701
-	/* read and parse the returned xml */
702
-	doc = xmlReadMemory(ret.s, ret.len, 0, 0,
703
-			XML_PARSE_NOBLANKS | XML_PARSE_NONET | XML_PARSE_NOCDATA);
704
-
705
-	if(doc == NULL) {
706
-		LM_ERR("invalid xml document: [%.*s]\n", ret.len, ret.s);
707
-		doc = xmlRecoverMemory(ret.s, ret.len);
708
-		if(doc == NULL) {
709
-			LM_ERR("xml document recovery failed on: [%.*s]\n", ret.len, ret.s);
710
-			goto err;
711
-		}
712
-
713
-		LM_DBG("xml document recovered\n");
714
-	}
715
-	root = xmlDocGetRootElement(doc);
716
-	if(root == NULL) {
717
-		LM_ERR("empty xml document: [%.*s]\n", ret.len, ret.s);
718
-		/* free memory */
719
-		lost_free_string(&ret);
720
-		goto err;
721
-	}
722
-	/* check the root element, shall be findServiceResponse, or errors */
723
-	if((!xmlStrcmp(root->name, (const xmlChar *)"findServiceResponse"))) {
724
-		/* get the uri element */
725
-		uri.s = lost_get_content(root, uri_element, &uri.len);
726
-		if(uri.len == 0) {
727
-			LM_ERR("uri element not found: [%.*s]\n", ret.len, ret.s);
728
-			/* free memory */
729
-			lost_free_string(&ret);
730
-			goto err;
731
-		}
732
-		LM_INFO("### LOST uri\t[%.*s]\n", uri.len, uri.s);
733
-		/* get the displayName element */
734
-		name.s = lost_get_content(root, name_element, &name.len);
735
-		if(name.len == 0) {
736
-			LM_ERR("displayName element not found: [%.*s]\n", ret.len, ret.s);
737
-			/* free memory */
738
-			lost_free_string(&ret);
739
-			goto err;
740
-		}
741
-		LM_INFO("### LOST din\t[%.*s]\n", name.len, name.s);
742
-	} else if((!xmlStrcmp(root->name, (const xmlChar *)"errors"))) {
743
-
744
-		LM_DBG("findService error response received\n");
745
-
746
-		/* get the error patterm */
747
-		err.s = lost_get_childname(root, errors_element, &err.len);
748
-		LM_DBG("findService error response: [%.*s]\n", err.len, err.s);
749
-		if(err.len == 0) {
750
-			LM_ERR("error pattern element not found: [%.*s]\n", ret.len, ret.s);
751
-			/* free memory */
752
-			lost_free_string(&ret);
753
-			goto err;
770
+	/* at least parse one request */
771
+	redirect = 1;
772
+	while(redirect) {
773
+		fsrdata = lost_parse_findServiceResponse(ret);
774
+		lost_print_findServiceResponse(fsrdata);
775
+		switch(fsrdata->category) {
776
+			case RESPONSE:
777
+				if(fsrdata->uri != NULL) {
778
+					/* get the first uri element */
779
+					if((tmp.s = fsrdata->uri->value) != NULL) {
780
+						tmp.len = strlen(fsrdata->uri->value);
781
+						uri.s = lost_copy_string(tmp, &uri.len);
782
+					}
783
+				} else {
784
+					LM_ERR("uri not found: [%.*s]\n", ret.len, ret.s);
785
+					goto err;
786
+				}
787
+				if(fsrdata->mapping != NULL) {
788
+					/* get the displayName element */
789
+					if((tmp.s = fsrdata->mapping->name->text) != NULL) {
790
+						tmp.len = strlen(fsrdata->mapping->name->text);
791
+						name.s = lost_copy_string(tmp, &name.len);
792
+					}
793
+				} else {
794
+					LM_ERR("name not found: [%.*s]\n", ret.len, ret.s);
795
+					goto err;
796
+				}
797
+				/* we are done */
798
+				redirect = 0;
799
+				break;
800
+			case ERROR:
801
+				/* get the errors element */
802
+				if(fsrdata->errors != NULL) {
803
+					if((tmp.s = fsrdata->errors->issue->type) != NULL) {
804
+						tmp.len = strlen(fsrdata->errors->issue->type);
805
+						err.s = lost_copy_string(tmp, &err.len);
806
+					}
807
+					/* clean up */
808
+					tmp.s = NULL;
809
+					tmp.len = 0;
810
+				} else {
811
+					LM_ERR("errors not found: [%.*s]\n", ret.len, ret.s);
812
+					goto err;
813
+				}
814
+				/* we are done */
815
+				redirect = 0;
816
+				break;
817
+			case REDIRECT:
818
+				/* get the target element */
819
+				if(fsrdata->redirect != NULL) {
820
+					if((tmp.s = fsrdata->redirect->target) != NULL) {
821
+						tmp.len = strlen(fsrdata->redirect->target);
822
+						url.s = &(ustr[0]);
823
+						url.len = MAX_URI_SIZE;
824
+						if((naptr = lost_naptr_lookup(tmp, &shttps, &url))
825
+								== 0) {
826
+							naptr = lost_naptr_lookup(tmp, &shttp, &url);
827
+						}
828
+						if(naptr == 0) {
829
+							LM_ERR("NAPTR failed on [%.*s]\n", tmp.len, tmp.s);
830
+							goto err;
831
+						}
832
+						/* clean up */
833
+						tmp.s = NULL;
834
+						tmp.len = 0;
835
+						/* check loop */
836
+						if(oldurl.s != NULL && oldurl.len > 0) {
837
+							if(str_strcasecmp(&url, &oldurl) == 0) {
838
+								LM_ERR("loop detected: "
839
+									   "[%.*s]<-->[%.*s]\n",
840
+										oldurl.len, oldurl.s, url.len, url.s);
841
+								goto err;
842
+							}
843
+						}
844
+						/* remember the redirect target */
845
+						oldurl.s = lost_copy_string(url, &oldurl.len);
846
+						/* clean up */
847
+						lost_free_findServiceResponse(fsrdata);
848
+						lost_free_string(&ret);
849
+						/* send request */
850
+						curl = httpapi.http_client_query(
851
+								_m, url.s, &ret, req.s, mtlost);
852
+						url.s = NULL;
853
+						url.len = 0;
854
+						/* only HTTP 2xx responses are accepted */
855
+						if(curl >= 300 || curl < 100) {
856
+							LM_ERR("http GET failed with error: %d\n", curl);
857
+							goto err;
858
+						}
859
+						/* once more ... we got a redirect */
860
+						redirect = 1;
861
+					}
862
+				} else {
863
+					LM_ERR("redirect element not found: [%.*s]\n", ret.len,
864
+							ret.s);
865
+					goto err;
866
+				}
867
+				break;
868
+			case OTHER:
869
+			default:
870
+				LM_ERR("pidf is not valid: [%.*s]\n", ret.len, ret.s);
871
+				goto err;
872
+				break;
754 873
 		}
755
-		LM_WARN("findService error response: [%.*s]\n", err.len, err.s);
756
-	} else {
757
-		LM_ERR("root element is not valid: [%.*s]\n", ret.len, ret.s);
758
-		/* free memory */
759
-		lost_free_string(&ret);
760
-		goto err;
761 874
 	}
762 875
 
763
-	/* free memory */
876
+	/* clean up */
877
+	lost_free_findServiceResponse(fsrdata);
764 878
 	lost_free_string(&ret);
879
+	lost_free_string(&req);
880
+	lost_free_string(&oldurl);
765 881
 
766 882
 	/* set writable pvars */
767 883
 	pvname.rs = name;
... ...
@@ -791,14 +907,25 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name,
791 907
 	return (err.len > 0) ? LOST_SERVER_ERROR : LOST_SUCCESS;
792 908
 
793 909
 err:
794
-	/* free memory */
795
-	if(doc != NULL) {
796
-		xmlFreeDoc(doc);
797
-		doc = NULL;
910
+	/* clean up */
911
+	if(fsrdata != NULL) {
912
+		lost_free_findServiceResponse(fsrdata);
913
+	}
914
+	if(geolist != NULL) {
915
+		lost_delete_geoheader_list(geolist);
916
+	}
917
+	if(oldurl.s != NULL) {
918
+		lost_free_string(&oldurl);
798 919
 	}
799 920
 	if(loc != NULL) {
800 921
 		lost_free_loc(loc);
801 922
 	}
923
+	if(ret.s != NULL && ret.len > 0) {
924
+		lost_free_string(&ret);
925
+	}
926
+	if(req.s != NULL && req.len > 0) {
927
+		lost_free_string(&req);
928
+	}
802 929
 
803 930
 	return LOST_CLIENT_ERROR;
804 931
 }
... ...
@@ -155,7 +155,10 @@ static int child_init(int rank)
155 155
 
156 156
 static void destroy(void)
157 157
 {
158
-	pkg_free(held_loc_type.s);
158
+	if(held_loc_type.s != NULL && held_loc_type.len > 0) {
159
+		pkg_free(held_loc_type.s);
160
+		held_loc_type.len = 0;
161
+	}
159 162
 	/* do nothing */
160 163
 }
161 164
 
162 165
new file mode 100644
... ...
@@ -0,0 +1,254 @@
1
+/*
2
+ * lost module naptr functions
3
+ * thankfully taken over from the enum module
4
+ *
5
+ * Copyright (C) 2021 Wolfgang Kampichler
6
+ * DEC112, FREQUENTIS AG
7
+ *
8
+ * This file is part of Kamailio, a free SIP server.
9
+ *
10
+ * Kamailio is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * Kamailio is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License
21
+ * along with this program; if not, write to the Free Software
22
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
+ *
24
+ */
25
+
26
+/*!
27
+ * \file
28
+ * \brief Kamailio lost :: naptr
29
+ * \ingroup lost
30
+ * Module: \ref lost
31
+ */
32
+
33
+#include "../../core/resolve.h"
34
+#include "../../core/strutils.h"
35
+#include "../../core/qvalue.h"
36
+
37
+/* Checks if NAPTR record has flag u and its services field
38
+ * LoST:https or LOST:http
39
+ * LIS:HELD
40
+ */
41
+static inline int service_match(struct naptr_rdata *naptr, str *service)
42
+{
43
+	if(service->len == 0) {
44
+		return 0;
45
+	}
46
+
47
+	/* LoST:https or LOST:http or LIS:HELD */
48
+	if(naptr->flags_len == 1) {
49
+		return (((naptr->flags[0] == 'u') || (naptr->flags[0] == 'U'))
50
+				&& (naptr->services_len == service->len)
51
+				&& (strncasecmp(naptr->services, service->s, service->len) == 0));
52
+	}
53
+
54
+	/* LIS:HELD domain */
55
+	if(naptr->flags_len == 0) {
56
+		return ((naptr->services_len == service->len)
57
+				&& (strncasecmp(naptr->services, service->s, service->len) == 0));
58
+	}
59
+
60
+	/* no matching service found */
61
+	return 0;
62
+}
63
+
64
+/* Parse NAPTR regexp field of the form !pattern!replacement! and return its
65
+ * components in pattern and replacement parameters.  Regexp field starts at
66
+ * address first and is len characters long.
67
+ */
68
+static inline int parse_naptr_regexp(
69
+		char *first, int len, str *pattern, str *replacement)
70
+{
71
+	char *second, *third;
72
+
73
+	if(len > 0) {
74
+		if(*first == '!') {
75
+			second = (char *)memchr((void *)(first + 1), '!', len - 1);
76
+			if(second) {
77
+				len = len - (second - first + 1);
78
+				if(len > 0) {
79
+					third = memchr(second + 1, '!', len);
80
+					if(third) {
81
+						pattern->len = second - first - 1;
82
+						pattern->s = first + 1;
83
+						replacement->len = third - second - 1;
84
+						replacement->s = second + 1;
85
+						return 1;
86
+					} else {
87
+						LM_ERR("Third ! missing from regexp\n");
88
+						return -1;
89
+					}
90
+				} else {
91
+					LM_ERR("Third ! missing from regexp\n");
92
+					return -2;
93
+				}
94
+			} else {
95
+				LM_ERR("Second ! missing from regexp\n");
96
+				return -3;
97
+			}
98
+		} else {
99
+			LM_ERR("First ! missing from regexp\n");
100
+			return -4;
101
+		}
102
+	} else {
103
+		LM_ERR("Regexp missing\n");
104
+		return -5;
105
+	}
106
+}
107
+
108
+/*
109
+ * Tests if one result record is "greater" that the other.  Non-NAPTR records
110
+ * greater that NAPTR record.  An invalid NAPTR record is greater than a 
111
+ * valid one.  Valid NAPTR records are compared based on their
112
+ * (order,preference).
113
+ */
114
+static inline int naptr_greater(struct rdata *a, struct rdata *b)
115
+{
116
+	struct naptr_rdata *na, *nb;
117
+
118
+	if(a->type != T_NAPTR)
119
+		return 1;
120
+	if(b->type != T_NAPTR)
121
+		return 0;
122
+
123
+	na = (struct naptr_rdata *)a->rdata;
124
+	if(na == 0)
125
+		return 1;
126
+
127
+	nb = (struct naptr_rdata *)b->rdata;
128
+	if(nb == 0)
129
+		return 0;
130
+
131
+	return (((na->order) << 16) + na->pref) > (((nb->order) << 16) + nb->pref);
132
+}
133
+
134
+/*
135
+ * Bubble sorts result record list according to naptr (order,preference).
136
+ */
137
+static inline void naptr_sort(struct rdata **head)
138
+{
139
+	struct rdata *p, *q, *r, *s, *temp, *start;
140
+
141
+	/* r precedes p and s points to the node up to which comparisons
142
+         are to be made */
143
+
144
+	s = NULL;
145
+	start = *head;
146
+	while(s != start->next) {
147
+		r = p = start;
148
+		q = p->next;
149
+		while(p != s) {
150
+			if(naptr_greater(p, q)) {
151
+				if(p == start) {
152
+					temp = q->next;
153
+					q->next = p;
154
+					p->next = temp;
155
+					start = q;
156
+					r = q;
157
+				} else {
158
+					temp = q->next;
159
+					q->next = p;
160
+					p->next = temp;
161
+					r->next = q;
162
+					r = q;
163
+				}
164
+			} else {
165
+				r = p;
166
+				p = p->next;
167
+			}
168
+			q = p->next;
169
+			if(q == s)
170
+				s = p;
171
+		}
172
+	}
173
+	*head = start;
174
+}
175
+
176
+/*
177
+ * NAPTR lookup on hostname & service, returns result as string
178
+ */
179
+int lost_naptr_lookup(str hostname, str *service, str *result)
180
+{
181
+	struct rdata *head;
182
+	struct rdata *l;
183
+	struct naptr_rdata *naptr;
184
+
185
+	str pattern, replacement;
186
+
187
+	head = get_record(hostname.s, T_NAPTR, RES_ONLY_TYPE);
188
+
189
+	if(head == 0) {
190
+		LM_DBG("no NAPTR record found for [%.*s]\n", hostname.len, hostname.s);
191
+		return 0;
192
+	}
193
+
194
+	naptr_sort(&head);
195
+
196
+	/* we have the naptr records, loop and find an srv record with */
197
+	/* same ip address as source ip address, if we do then true is returned */
198
+
199
+	for(l = head; l; l = l->next) {
200
+
201
+		if(l->type != T_NAPTR)
202
+			continue; /*should never happen*/
203
+		naptr = (struct naptr_rdata *)l->rdata;
204
+
205
+		if(naptr == 0) {
206
+			LM_ERR("no rdata in DNS response\n");
207
+			free_rdata_list(head);
208
+			return 0;
209
+		}
210
+
211
+		LM_DBG("NAPTR query on %.*s: order %u, pref %u, flen %u, flags "
212
+			   "'%.*s', slen %u, services '%.*s', rlen %u, "
213
+			   "regexp '%.*s'\n",
214
+				hostname.len, hostname.s, naptr->order, naptr->pref,
215
+				naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags),
216
+				naptr->services_len, (int)(naptr->services_len),
217
+				ZSW(naptr->services), naptr->regexp_len,
218
+				(int)(naptr->regexp_len), ZSW(naptr->regexp));
219
+
220
+		if(service_match(naptr, service) == 0) {
221
+			continue;
222
+		}
223
+
224
+		if(parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len, &pattern,
225
+				   &replacement)
226
+				< 0) {
227
+			free_rdata_list(head); /*clean up*/
228
+			LM_ERR("parsing of NAPTR regexp failed\n");
229
+			return 0;
230
+		}
231
+		/* Avoid making copies of pattern and replacement */
232
+		pattern.s[pattern.len] = (char)0;
233
+		replacement.s[replacement.len] = (char)0;
234
+		/* replace hostname */
235
+		if(reg_replace(pattern.s, replacement.s, &(hostname.s[0]), result)
236
+				< 0) {
237
+			pattern.s[pattern.len] = '!';
238
+			replacement.s[replacement.len] = '!';
239
+			LM_ERR("regexp replace failed\n");
240
+			free_rdata_list(head); /*clean up*/
241
+			return 0;
242
+		} else {
243
+
244
+			LM_DBG("resulted in replacement: '%.*s'\n", result->len,
245
+					ZSW(result->s));
246
+
247
+			free_rdata_list(head); /*clean up*/
248
+			return 1;
249
+		}
250
+	}
251
+
252
+	/* must not have found the record */
253
+	return 0;
254
+}
0 255
\ No newline at end of file
1 256
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+/*
2
+ * lost module naptr functions
3
+ *
4
+ * Copyright (C) 2021 Wolfgang Kampichler
5
+ * DEC112, FREQUENTIS AG
6
+ *
7
+ * This file is part of Kamailio, a free SIP server.
8
+ *
9
+ * Kamailio is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * Kamailio is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
+ *
23
+ */
24
+
25
+/*!
26
+ * \file
27
+ * \brief Kamailio lost :: naptr
28
+ * \ingroup lost
29
+ * Module: \ref lost
30
+ */
31
+
32
+#ifndef LOST_NAPTR_H
33
+#define LOST_NAPTR_H
34
+
35
+/* NAPTR lookup and host string replacement */
36
+int lost_naptr_lookup(str, str *, str *);
37
+
38
+#endif
0 39
\ No newline at end of file
... ...
@@ -123,7 +123,10 @@ char *xmlNodeGetNodeContentByName(
123 123
 xmlNodePtr xmlDocGetNodeByName(xmlDocPtr doc, const char *name, const char *ns)
124 124
 {
125 125
 	xmlNodePtr cur = doc->children;
126
-	return xmlNodeGetNodeByName(cur, name, ns);
126
+	if(cur)
127
+		return xmlNodeGetNodeByName(cur, name, ns);
128
+	else
129
+		return NULL;
127 130
 }
128 131
 
129 132
 char *xmlDocGetNodeContentByName(
<
130 133
new file mode 100644
... ...
@@ -0,0 +1,946 @@
1
+/*
2
+ * lost module LoST response parsing functions
3
+ *
4
+ * Copyright (C) 2021 Wolfgang Kampichler
5
+ * DEC112, FREQUENTIS AG
6
+ *
7
+ * This file is part of Kamailio, a free SIP server.
8
+ *
9
+ * Kamailio is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * Kamailio is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
+ *
23
+ */
24
+
25
+/*!
26
+ * \file
27
+ * \brief Kamailio lost :: response
28
+ * \ingroup lost
29
+ * Module: \ref lost
30
+ */
31
+
32
+#include <stdio.h>
33
+#include <string.h>
34
+#include <stdlib.h>
35
+#include <ctype.h>
36
+#include <time.h>
37
+
38
+#include "../../core/parser/msg_parser.h"
39
+#include "../../core/parser/parse_content.h"
40
+#include "../../core/parser/parse_uri.h"
41
+#include "../../core/parser/parse_from.h"
42
+#include "../../core/parser/parse_ppi_pai.h"
43
+#include "../../core/dprint.h"
44
+#include "../../core/mem/mem.h"
45
+#include "../../core/mem/shm_mem.h"
46
+#include "../../core/rand/kam_rand.h"
47
+
48
+#include <libxml/parser.h>
49
+#include <libxml/xmlmemory.h>
50
+#include <libxml/xpath.h>
51
+#include <libxml/xpathInternals.h>
52
+
53
+#include "pidf.h"
54
+#include "utilities.h"
55
+#include "response.h"
56
+
57
+/* return 1 if true else 0 */
58
+int is_http_laquot(char *search)
59
+{
60
+	if(search == NULL) {
61
+		return 0;
62
+	}
63
+	if(strlen(search) < strlen("<http:")) {
64
+		return 0;
65
+	}
66
+	if((*(search + 0) == '<')
67
+			&& ((*(search + 1) == 'h') || (*(search + 1) == 'H'))
68
+			&& ((*(search + 2) == 't') || (*(search + 2) == 'T'))
69
+			&& ((*(search + 3) == 't') || (*(search + 3) == 'T'))
70
+			&& ((*(search + 4) == 'p') || (*(search + 4) == 'P'))
71
+			&& ((*(search + 5) == ':'))) {
72
+		return 1;
73
+	}
74
+	return 0;
75
+}
76
+
77
+/* return 1 if true else 0 */
78
+int is_https_laquot(char *search)
79
+{
80
+	if(search == NULL) {
81
+		return 0;
82
+	}
83
+	if(strlen(search) < strlen("<https:")) {
84
+		return 0;
85
+	}
86
+	if((*(search + 0) == '<')
87
+			&& ((*(search + 1) == 'h') || (*(search + 1) == 'H'))
88
+			&& ((*(search + 2) == 't') || (*(search + 2) == 'T'))
89
+			&& ((*(search + 3) == 't') || (*(search + 3) == 'T'))
90
+			&& ((*(search + 4) == 'p') || (*(search + 4) == 'P'))
91
+			&& ((*(search + 5) == 's') || (*(search + 5) == 'S'))
92
+			&& ((*(search + 6) == ':'))) {
93
+		return 1;
94
+	}
95
+	return 0;
96
+}
97
+
98
+/* return 1 if true else 0 */
99
+int is_http(char *search)
100
+{
101
+	if(search == NULL) {
102
+		return 0;
103
+	}
104
+	if(strlen(search) < strlen("http:")) {
105
+		return 0;
106
+	}
107
+	if(((*(search + 0) == 'h') || (*(search + 0) == 'H'))
108
+			&& ((*(search + 1) == 't') || (*(search + 1) == 'T'))
109
+			&& ((*(search + 2) == 't') || (*(search + 2) == 'T'))
110
+			&& ((*(search + 3) == 'p') || (*(search + 3) == 'P'))
111
+			&& ((*(search + 4) == ':'))) {
112
+		return 1;
113
+	}
114
+	return 0;
115
+}
116
+
117
+/* return 1 if true else 0 */
118
+int is_https(char *search)
119
+{
120
+	if(search == NULL) {
121
+		return 0;
122
+	}
123
+	if(strlen(search) < strlen("https:")) {
124
+		return 0;
125
+	}
126
+	if(((*(search + 0) == 'h') || (*(search + 0) == 'H'))
127
+			&& ((*(search + 1) == 't') || (*(search + 1) == 'T'))
128
+			&& ((*(search + 2) == 't') || (*(search + 2) == 'T'))
129
+			&& ((*(search + 3) == 'p') || (*(search + 3) == 'P'))
130
+			&& ((*(search + 4) == 's') || (*(search + 4) == 'S'))
131
+			&& ((*(search + 5) == ':'))) {
132
+		return 1;
133
+	}
134
+	return 0;
135
+}
136
+
137
+/* return 1 if true else 0 */
138
+int is_cid_laquot(char *search)
139
+{
140
+	if(search == NULL) {
141
+		return 0;
142
+	}
143
+	if(strlen(search) < strlen("<cid:")) {
144
+		return 0;
145
+	}
146
+	if((*(search + 0) == '<')
147
+			&& ((*(search + 1) == 'c') || (*(search + 1) == 'C'))
148
+			&& ((*(search + 2) == 'i') || (*(search + 2) == 'I'))
149
+			&& ((*(search + 3) == 'd') || (*(search + 3) == 'D'))
150
+			&& (*(search + 4) == ':')) {
151
+		return 1;
152
+	}
153
+	return 0;
154
+}
155
+
156
+/* return 1 if true else 0 */
157
+int is_cid(char *search)
158
+{
159
+	if(search == NULL) {
160
+		return 0;
161
+	}
162
+	if(strlen(search) < strlen("cid:")) {
163
+		return 0;
164
+	}
165
+	if(((*(search + 0) == 'c') || (*(search + 0) == 'C'))
166
+			&& ((*(search + 1) == 'i') || (*(search + 1) == 'I'))
167
+			&& ((*(search + 2) == 'd') || (*(search + 2) == 'D'))
168
+			&& (*(search + 3) == ':')) {
169
+		return 1;
170
+	}
171
+	return 0;
172
+}
173
+
174
+/* return 1 if true else 0 */
175
+int is_urn(char *search)
176
+{
177
+	if(search == NULL) {
178
+		return 0;
179
+	}
180
+	if(strlen(search) < strlen("urn:")) {
181
+		return 0;
182
+	}
183
+	if(((*(search + 0) == 'u') || (*(search + 0) == 'U'))
184
+			&& ((*(search + 1) == 'r') || (*(search + 1) == 'R'))
185
+			&& ((*(search + 2) == 'n') || (*(search + 2) == 'N'))
186
+			&& (*(search + 3) == ':')) {
187
+		return 1;
188
+	}
189
+	return 0;
190
+}
191
+
192
+/*
193
+ * lost_new_response(void)
194
+ * creates a new response object in private memory and returns a pointer
195
+ */
196
+p_fsr_t lost_new_response(void)
197
+{
198
+	p_fsr_t res;
199
+
200
+	res = (p_fsr_t)pkg_malloc(sizeof(s_fsr_t));
201
+	if(res == NULL) {
202
+		return NULL;
203
+	}
204
+	res->category = OTHER;
205
+	res->mapping = NULL;
206
+	res->path = NULL;
207
+	res->warnings = NULL;
208
+	res->errors = NULL;
209
+	res->redirect = NULL;
210
+	res->uri = NULL;
211
+
212
+	LM_DBG("### reponse data initialized\n");
213
+
214
+	return res;
215
+}
216
+
217
+/*
218
+ * lost_new_response_type(void)
219
+ * creates a new response type object in private memory and returns a pointer
220
+ */
221
+p_type_t lost_new_response_type(void)
222
+{
223
+	p_type_t res;
224
+
225
+	res = (p_type_t)pkg_malloc(sizeof(s_type_t));
226
+	if(res == NULL) {
227
+		LM_ERR("no more private memory\n");
228
+		return NULL;
229
+	}
230
+	res->type = NULL;
231
+	res->target = NULL;
232
+	res->source = NULL;
233