... | ... |
@@ -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; |
|
< |