1 /**
2  * Copyright (C) 2016 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 
26 #include "dprint.h"
27 #include "forward.h"
28 #include "locking.h"
29 #include "dset.h"
30 #include "action.h"
31 #include "data_lump.h"
32 #include "data_lump_rpl.h"
33 #include "strutils.h"
34 #include "select_buf.h"
35 #include "pvar.h"
36 #include "mem/shm.h"
37 #include "parser/parse_uri.h"
38 #include "parser/parse_from.h"
39 #include "parser/parse_hname2.h"
40 #include "parser/parse_methods.h"
41 
42 #include "kemi.h"
43 
44 
45 #define SR_KEMI_HNAME_SIZE 128
46 
47 /* names for kemi callback functions */
48 str kemi_onsend_route_callback = str_init("ksr_onsend_route");
49 str kemi_reply_route_callback = str_init("ksr_reply_route");
50 str kemi_event_route_callback = str_init("");
51 
52 /**
53  *
54  */
55 static sr_kemi_xval_t _sr_kemi_xval = {0};
56 
57 /**
58  *
59  */
60 static run_act_ctx_t *_sr_kemi_act_ctx = NULL;
61 
62 /**
63  *
64  */
sr_kemi_act_ctx_set(run_act_ctx_t * ctx)65 void sr_kemi_act_ctx_set(run_act_ctx_t *ctx)
66 {
67 	_sr_kemi_act_ctx = ctx;
68 }
69 
70 /**
71  *
72  */
sr_kemi_act_ctx_get(void)73 run_act_ctx_t* sr_kemi_act_ctx_get(void)
74 {
75 	return _sr_kemi_act_ctx;
76 }
77 
78 /**
79  *
80  */
sr_kemi_core_dbg(sip_msg_t * msg,str * txt)81 static int sr_kemi_core_dbg(sip_msg_t *msg, str *txt)
82 {
83 	if(txt!=NULL && txt->s!=NULL)
84 		LM_DBG("%.*s", txt->len, txt->s);
85 	return 0;
86 }
87 
88 /**
89  *
90  */
sr_kemi_core_err(sip_msg_t * msg,str * txt)91 static int sr_kemi_core_err(sip_msg_t *msg, str *txt)
92 {
93 	if(txt!=NULL && txt->s!=NULL)
94 		LM_ERR("%.*s", txt->len, txt->s);
95 	return 0;
96 }
97 
98 /**
99  *
100  */
sr_kemi_core_info(sip_msg_t * msg,str * txt)101 static int sr_kemi_core_info(sip_msg_t *msg, str *txt)
102 {
103 	if(txt!=NULL && txt->s!=NULL)
104 		LM_INFO("%.*s", txt->len, txt->s);
105 	return 0;
106 }
107 
108 /**
109  *
110  */
sr_kemi_core_warn(sip_msg_t * msg,str * txt)111 static int sr_kemi_core_warn(sip_msg_t *msg, str *txt)
112 {
113 	if(txt!=NULL && txt->s!=NULL)
114 		LM_WARN("%.*s", txt->len, txt->s);
115 	return 0;
116 }
117 
118 /**
119  *
120  */
sr_kemi_core_notice(sip_msg_t * msg,str * txt)121 static int sr_kemi_core_notice(sip_msg_t *msg, str *txt)
122 {
123 	if(txt!=NULL && txt->s!=NULL)
124 		LM_NOTICE("%.*s", txt->len, txt->s);
125 	return 0;
126 }
127 
128 /**
129  *
130  */
sr_kemi_core_crit(sip_msg_t * msg,str * txt)131 static int sr_kemi_core_crit(sip_msg_t *msg, str *txt)
132 {
133 	if(txt!=NULL && txt->s!=NULL)
134 		LM_CRIT("%.*s", txt->len, txt->s);
135 	return 0;
136 }
137 
138 /**
139  *
140  */
sr_kemi_core_log(sip_msg_t * msg,str * level,str * txt)141 static int sr_kemi_core_log(sip_msg_t *msg, str *level, str *txt)
142 {
143 	if(txt!=NULL && txt->s!=NULL) {
144 		if(level==NULL || level->s==NULL) {
145 			LM_ERR("%s", txt->s);
146 		} else {
147 			if(strcasecmp(level->s, "dbg")==0) {
148 				LM_DBG("%s", txt->s);
149 			} else if(strcasecmp(level->s, "info")==0) {
150 				LM_INFO("%s", txt->s);
151 			} else if(strcasecmp(level->s, "notice")==0) {
152 				LM_NOTICE("%s", txt->s);
153 			} else if(strcasecmp(level->s, "warn")==0) {
154 				LM_WARN("%s", txt->s);
155 			} else if(strcasecmp(level->s, "err")==0) {
156 				LM_ERR("%s", txt->s);
157 			} else if(strcasecmp(level->s, "crit")==0) {
158 				LM_CRIT("%s", txt->s);
159 			} else {
160 				LM_ERR("%s", txt->s);
161 			}
162 		}
163 	}
164 	return 0;
165 }
166 
167 /**
168  *
169  */
sr_kemi_core_set_drop(sip_msg_t * msg)170 int sr_kemi_core_set_drop(sip_msg_t *msg)
171 {
172 	if(_sr_kemi_act_ctx==NULL)
173 		return 0;
174 	LM_DBG("set drop action executed inside embedded interpreter\n");
175 	_sr_kemi_act_ctx->run_flags |= EXIT_R_F|DROP_R_F;
176 	return 0;
177 }
178 
179 /**
180  *
181  */
sr_kemi_core_is_myself(sip_msg_t * msg,str * uri)182 static int sr_kemi_core_is_myself(sip_msg_t *msg, str *uri)
183 {
184 	struct sip_uri puri;
185 	int ret;
186 
187 	if(uri==NULL || uri->s==NULL) {
188 		return SR_KEMI_FALSE;
189 	}
190 	if(uri->len>4 && (strncmp(uri->s, "sip:", 4)==0
191 				|| strncmp(uri->s, "sips:", 5)==0)) {
192 		if(parse_uri(uri->s, uri->len, &puri)!=0) {
193 			LM_ERR("failed to parse uri [%.*s]\n", uri->len, uri->s);
194 			return SR_KEMI_FALSE;
195 		}
196 		ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
197 				(puri.transport_val.s)?puri.proto:0);
198 	} else {
199 		ret = check_self(uri, 0, 0);
200 	}
201 	if(ret==1) {
202 		return SR_KEMI_TRUE;
203 	}
204 	return SR_KEMI_FALSE;
205 }
206 
207 /**
208  *
209  */
sr_kemi_core_is_myself_ruri(sip_msg_t * msg)210 static int sr_kemi_core_is_myself_ruri(sip_msg_t *msg)
211 {
212 	if(msg==NULL) {
213 		LM_WARN("invalid msg parameter\n");
214 		return SR_KEMI_FALSE;
215 	}
216 
217 	if(msg->first_line.type == SIP_REPLY)	/* REPLY doesn't have a ruri */
218 		return SR_KEMI_FALSE;
219 
220 	if (msg->new_uri.s!=NULL)
221 		return sr_kemi_core_is_myself(msg, &msg->new_uri);
222 	return sr_kemi_core_is_myself(msg, &msg->first_line.u.request.uri);
223 }
224 
225 /**
226  *
227  */
sr_kemi_core_is_myself_duri(sip_msg_t * msg)228 static int sr_kemi_core_is_myself_duri(sip_msg_t *msg)
229 {
230 	if(msg==NULL) {
231 		LM_WARN("invalid msg parameter\n");
232 		return SR_KEMI_FALSE;
233 	}
234 
235 	if (msg->dst_uri.s!=NULL)
236 		return sr_kemi_core_is_myself(msg, &msg->dst_uri);
237 
238 	return SR_KEMI_FALSE;
239 }
240 
241 /**
242  *
243  */
sr_kemi_core_is_myself_nhuri(sip_msg_t * msg)244 static int sr_kemi_core_is_myself_nhuri(sip_msg_t *msg)
245 {
246 	if(msg==NULL) {
247 		LM_WARN("invalid msg parameter\n");
248 		return SR_KEMI_FALSE;
249 	}
250 
251 	if (msg->dst_uri.s!=NULL)
252 		return sr_kemi_core_is_myself(msg, &msg->dst_uri);
253 
254 	return sr_kemi_core_is_myself_ruri(msg);
255 }
256 
257 /**
258  *
259  */
sr_kemi_core_is_myself_furi(sip_msg_t * msg)260 static int sr_kemi_core_is_myself_furi(sip_msg_t *msg)
261 {
262 	to_body_t *xfrom;
263 
264 	if(msg==NULL) {
265 		LM_WARN("invalid msg parameter\n");
266 		return SR_KEMI_FALSE;
267 	}
268 
269 	if(parse_from_header(msg)<0) {
270 		LM_ERR("cannot parse From header\n");
271 		return SR_KEMI_FALSE;
272 	}
273 
274 	if(msg->from==NULL || get_from(msg)==NULL) {
275 		LM_DBG("no From header\n");
276 		return SR_KEMI_FALSE;
277 	}
278 
279 	xfrom = get_from(msg);
280 
281 	return sr_kemi_core_is_myself(msg, &xfrom->uri);
282 }
283 
284 /**
285  *
286  */
sr_kemi_core_is_myself_turi(sip_msg_t * msg)287 static int sr_kemi_core_is_myself_turi(sip_msg_t *msg)
288 {
289 	to_body_t *xto;
290 
291 	if(msg==NULL) {
292 		LM_WARN("invalid msg parameter\n");
293 		return SR_KEMI_FALSE;
294 	}
295 
296 	if(parse_to_header(msg)<0) {
297 		LM_ERR("cannot parse To header\n");
298 		return SR_KEMI_FALSE;
299 	}
300 
301 	if(msg->to==NULL || get_to(msg)==NULL) {
302 		LM_DBG("no To header\n");
303 		return SR_KEMI_FALSE;
304 	}
305 
306 	xto = get_to(msg);
307 
308 	return sr_kemi_core_is_myself(msg, &xto->uri);
309 }
310 
311 /**
312  *
313  */
sr_kemi_core_is_myself_suri(sip_msg_t * msg)314 static int sr_kemi_core_is_myself_suri(sip_msg_t *msg)
315 {
316 	str suri;
317 
318 	if(get_src_uri(msg, 0, &suri)<0) {
319 		LM_ERR("cannot src address uri\n");
320 		return SR_KEMI_FALSE;
321 	}
322 
323 	return sr_kemi_core_is_myself(msg, &suri);
324 }
325 
326 /**
327  *
328  */
sr_kemi_core_is_myself_srcip(sip_msg_t * msg)329 static int sr_kemi_core_is_myself_srcip(sip_msg_t *msg)
330 {
331 	str srcip;
332 	int ret;
333 
334 	srcip.s = ip_addr2a(&msg->rcv.src_ip);
335 	srcip.len = strlen(srcip.s);
336 
337 	ret = check_self(&srcip, 0, 0);
338 	if(ret==1) {
339 		return SR_KEMI_TRUE;
340 	}
341 	return SR_KEMI_FALSE;
342 }
343 
344 /**
345  *
346  */
sr_kemi_core_setflag(sip_msg_t * msg,int flag)347 static int sr_kemi_core_setflag(sip_msg_t *msg, int flag)
348 {
349 	if(msg==NULL) {
350 		LM_WARN("invalid msg parameter\n");
351 		return SR_KEMI_FALSE;
352 	}
353 
354 	if (!flag_in_range(flag)) {
355 		LM_ERR("invalid flag parameter %d\n", flag);
356 		return SR_KEMI_FALSE;
357 	}
358 
359 	setflag(msg, flag);
360 	return SR_KEMI_TRUE;
361 }
362 
363 /**
364  *
365  */
sr_kemi_core_resetflag(sip_msg_t * msg,int flag)366 static int sr_kemi_core_resetflag(sip_msg_t *msg, int flag)
367 {
368 	if(msg==NULL) {
369 		LM_WARN("invalid msg parameter\n");
370 		return SR_KEMI_FALSE;
371 	}
372 
373 	if (!flag_in_range(flag)) {
374 		LM_ERR("invalid flag parameter %d\n", flag);
375 		return SR_KEMI_FALSE;
376 	}
377 
378 	resetflag(msg, flag);
379 	return SR_KEMI_TRUE;
380 }
381 
382 /**
383  *
384  */
sr_kemi_core_isflagset(sip_msg_t * msg,int flag)385 static int sr_kemi_core_isflagset(sip_msg_t *msg, int flag)
386 {
387 	int ret;
388 
389 	if(msg==NULL) {
390 		LM_WARN("invalid msg parameter\n");
391 		return SR_KEMI_FALSE;
392 	}
393 
394 	if (!flag_in_range(flag)) {
395 		LM_ERR("invalid flag parameter %d\n", flag);
396 		return SR_KEMI_FALSE;
397 	}
398 
399 	ret = isflagset(msg, flag);
400 	if(ret>0)
401 		return SR_KEMI_TRUE;
402 	return SR_KEMI_FALSE;
403 }
404 
405 /**
406  *
407  */
sr_kemi_core_setbiflag(sip_msg_t * msg,int flag,int branch)408 static int sr_kemi_core_setbiflag(sip_msg_t *msg, int flag, int branch)
409 {
410 	if(msg==NULL) {
411 		LM_WARN("invalid msg parameter\n");
412 		return SR_KEMI_FALSE;
413 	}
414 
415 	if (!flag_in_range(flag)) {
416 		LM_ERR("invalid flag parameter %d\n", flag);
417 		return SR_KEMI_FALSE;
418 	}
419 
420 	setbflag(branch, flag);
421 	return SR_KEMI_TRUE;
422 }
423 
424 /**
425  *
426  */
sr_kemi_core_resetbiflag(sip_msg_t * msg,int flag,int branch)427 static int sr_kemi_core_resetbiflag(sip_msg_t *msg, int flag, int branch)
428 {
429 	if(msg==NULL) {
430 		LM_WARN("invalid msg parameter\n");
431 		return SR_KEMI_FALSE;
432 	}
433 
434 	if (!flag_in_range(flag)) {
435 		LM_ERR("invalid flag parameter %d\n", flag);
436 		return SR_KEMI_FALSE;
437 	}
438 
439 	resetbflag(branch, flag);
440 	return SR_KEMI_TRUE;
441 }
442 
443 /**
444  *
445  */
sr_kemi_core_isbiflagset(sip_msg_t * msg,int flag,int branch)446 static int sr_kemi_core_isbiflagset(sip_msg_t *msg, int flag, int branch)
447 {
448 	int ret;
449 
450 	if(msg==NULL) {
451 		LM_WARN("invalid msg parameter\n");
452 		return SR_KEMI_FALSE;
453 	}
454 
455 	if (!flag_in_range(flag)) {
456 		LM_ERR("invalid flag parameter %d\n", flag);
457 		return SR_KEMI_FALSE;
458 	}
459 
460 	ret = isbflagset(branch, flag);
461 	if(ret>0)
462 		return SR_KEMI_TRUE;
463 	return SR_KEMI_FALSE;
464 }
465 
466 /**
467  *
468  */
sr_kemi_core_setbflag(sip_msg_t * msg,int flag)469 static int sr_kemi_core_setbflag(sip_msg_t *msg, int flag)
470 {
471 	return sr_kemi_core_setbiflag(msg, flag, 0);
472 }
473 
474 /**
475  *
476  */
sr_kemi_core_resetbflag(sip_msg_t * msg,int flag)477 static int sr_kemi_core_resetbflag(sip_msg_t *msg, int flag)
478 {
479 	return sr_kemi_core_resetbiflag(msg, flag, 0);
480 }
481 
482 /**
483  *
484  */
sr_kemi_core_isbflagset(sip_msg_t * msg,int flag)485 static int sr_kemi_core_isbflagset(sip_msg_t *msg, int flag)
486 {
487 	return sr_kemi_core_isbiflagset(msg, flag, 0);
488 }
489 
490 /**
491  *
492  */
sr_kemi_core_setsflag(sip_msg_t * msg,int flag)493 static int sr_kemi_core_setsflag(sip_msg_t *msg, int flag)
494 {
495 	if (!flag_in_range(flag)) {
496 		LM_ERR("invalid flag parameter %d\n", flag);
497 		return SR_KEMI_FALSE;
498 	}
499 
500 	setsflag(flag);
501 	return SR_KEMI_TRUE;
502 }
503 
504 /**
505  *
506  */
sr_kemi_core_resetsflag(sip_msg_t * msg,int flag)507 static int sr_kemi_core_resetsflag(sip_msg_t *msg, int flag)
508 {
509 	if (!flag_in_range(flag)) {
510 		LM_ERR("invalid flag parameter %d\n", flag);
511 		return SR_KEMI_FALSE;
512 	}
513 
514 	resetsflag(flag);
515 	return SR_KEMI_TRUE;
516 }
517 
518 /**
519  *
520  */
sr_kemi_core_issflagset(sip_msg_t * msg,int flag)521 static int sr_kemi_core_issflagset(sip_msg_t *msg, int flag)
522 {
523 	int ret;
524 
525 	if (!flag_in_range(flag)) {
526 		LM_ERR("invalid flag parameter %d\n", flag);
527 		return SR_KEMI_FALSE;
528 	}
529 
530 	ret = issflagset(flag);
531 	if(ret>0)
532 		return SR_KEMI_TRUE;
533 	return SR_KEMI_FALSE;
534 }
535 
536 /**
537  *
538  */
sr_kemi_core_seturi(sip_msg_t * msg,str * uri)539 static int sr_kemi_core_seturi(sip_msg_t *msg, str *uri)
540 {
541 	if(uri==NULL || uri->s==NULL) {
542 		LM_ERR("invalid uri parameter\n");
543 		return SR_KEMI_FALSE;
544 	}
545 
546 	if(msg==NULL) {
547 		LM_WARN("invalid msg parameter\n");
548 		return SR_KEMI_FALSE;
549 	}
550 
551 	if(rewrite_uri(msg, uri)<0) {
552 		LM_ERR("updating r-uri failed\n");
553 		return SR_KEMI_FALSE;
554 	}
555 	return SR_KEMI_TRUE;
556 }
557 
558 /**
559  *
560  */
sr_kemi_core_setuser(sip_msg_t * msg,str * user)561 static int sr_kemi_core_setuser(sip_msg_t *msg, str *user)
562 {
563 	struct action  act;
564 	struct run_act_ctx h;
565 
566 	if(user==NULL || user->s==NULL) {
567 		LM_ERR("invalid user parameter\n");
568 		return SR_KEMI_FALSE;
569 	}
570 
571 	if(msg==NULL) {
572 		LM_WARN("invalid user parameter\n");
573 		return SR_KEMI_FALSE;
574 	}
575 
576 	memset(&act, 0, sizeof(act));
577 	act.val[0].type = STRING_ST;
578 	act.val[0].u.string = user->s;
579 	act.type = SET_USER_T;
580 	init_run_actions_ctx(&h);
581 	if (do_action(&h, &act, msg)<0) {
582 		LM_ERR("do action failed\n");
583 		return SR_KEMI_FALSE;
584 	}
585 	return SR_KEMI_TRUE;
586 }
587 
588 /**
589  *
590  */
sr_kemi_core_sethost(sip_msg_t * msg,str * host)591 static int sr_kemi_core_sethost(sip_msg_t *msg, str *host)
592 {
593 	struct action  act;
594 	struct run_act_ctx h;
595 
596 	if(host==NULL || host->s==NULL) {
597 		LM_ERR("invalid host parameter\n");
598 		return SR_KEMI_FALSE;
599 	}
600 
601 	if(msg==NULL) {
602 		LM_WARN("invalid msg parameter\n");
603 		return SR_KEMI_FALSE;
604 	}
605 
606 	memset(&act, 0, sizeof(act));
607 	act.val[0].type = STRING_ST;
608 	act.val[0].u.string = host->s;
609 	act.type = SET_HOST_T;
610 	init_run_actions_ctx(&h);
611 	if (do_action(&h, &act, msg)<0)
612 	{
613 		LM_ERR("do action failed\n");
614 		return SR_KEMI_FALSE;
615 	}
616 	return SR_KEMI_TRUE;
617 }
618 
619 /**
620  *
621  */
sr_kemi_core_setdsturi(sip_msg_t * msg,str * uri)622 static int sr_kemi_core_setdsturi(sip_msg_t *msg, str *uri)
623 {
624 	if(uri==NULL || uri->s==NULL) {
625 		LM_ERR("invalid uri parameter\n");
626 		return SR_KEMI_FALSE;
627 	}
628 
629 	if(msg==NULL) {
630 		LM_WARN("invalid msg parameter\n");
631 		return SR_KEMI_FALSE;
632 	}
633 
634 	if(set_dst_uri(msg, uri)<0) {
635 		LM_ERR("setting dst uri failed\n");
636 		return SR_KEMI_TRUE;
637 	}
638 	return SR_KEMI_TRUE;
639 }
640 
641 /**
642  *
643  */
sr_kemi_core_resetdsturi(sip_msg_t * msg)644 static int sr_kemi_core_resetdsturi(sip_msg_t *msg)
645 {
646 	if(msg==NULL) {
647 		LM_WARN("invalid msg parameter\n");
648 		return SR_KEMI_FALSE;
649 	}
650 
651 	reset_dst_uri(msg);
652 	return SR_KEMI_TRUE;
653 }
654 
655 /**
656  *
657  */
sr_kemi_core_isdsturiset(sip_msg_t * msg)658 static int sr_kemi_core_isdsturiset(sip_msg_t *msg)
659 {
660 	if(msg==NULL) {
661 		LM_WARN("invalid msg parameter\n");
662 		return SR_KEMI_FALSE;
663 	}
664 
665 	if(msg->dst_uri.s!=NULL && msg->dst_uri.len>0) {
666 		return SR_KEMI_TRUE;
667 	}
668 	return SR_KEMI_FALSE;
669 }
670 
671 /**
672  *
673  */
sr_kemi_core_force_rport(sip_msg_t * msg)674 static int sr_kemi_core_force_rport(sip_msg_t *msg)
675 {
676 	if(msg==NULL) {
677 		LM_WARN("invalid msg parameter\n");
678 		return SR_KEMI_FALSE;
679 	}
680 
681 	msg->msg_flags|=FL_FORCE_RPORT;
682 	return SR_KEMI_TRUE;
683 }
684 
685 /**
686  *
687  */
sr_kemi_core_add_local_rport(sip_msg_t * msg)688 static int sr_kemi_core_add_local_rport(sip_msg_t *msg)
689 {
690 	if(msg==NULL) {
691 		LM_WARN("invalid msg parameter\n");
692 		return SR_KEMI_FALSE;
693 	}
694 
695 	msg->msg_flags|=FL_ADD_LOCAL_RPORT;
696 	return SR_KEMI_TRUE;
697 }
698 
699 /**
700  *
701  */
sr_kemi_core_match_method_id(str * rmethod,str * vmethod,int mid)702 static int sr_kemi_core_match_method_id(str *rmethod, str *vmethod, int mid)
703 {
704 	char mbuf[SR_KEMI_HNAME_SIZE];
705 	int i;
706 	unsigned int method;
707 	str s;
708 
709 	if(memchr(vmethod->s, '|', vmethod->len)==NULL) {
710 		if(rmethod->len!=vmethod->len) {
711 			return SR_KEMI_FALSE;
712 		}
713 		if(strncasecmp(rmethod->s, vmethod->s, vmethod->len)!=0) {
714 			return SR_KEMI_FALSE;
715 		}
716 		return SR_KEMI_TRUE;
717 	}
718 	if(vmethod->len>=SR_KEMI_HNAME_SIZE-1) {
719 		LM_ERR("methods parameter is too long\n");
720 		return SR_KEMI_FALSE;
721 	}
722 	memcpy(mbuf, vmethod->s, vmethod->len);
723 	mbuf[vmethod->len] = '\0';
724 	for(i=0; i<vmethod->len; i++) {
725 		if(mbuf[i]=='|') {
726 			mbuf[i] = ',';
727 		}
728 	}
729 	s.s = mbuf;
730 	s.len = vmethod->len;
731 	if(parse_methods(&s, &method)!=0) {
732 		LM_ERR("failed to parse methods string [%.*s]\n", s.len, s.s);
733 		return SR_KEMI_FALSE;
734 	}
735 	if((method==METHOD_UNDEF) || (method&METHOD_OTHER)) {
736 		LM_ERR("unknown method in list [%.*s] - use only standard SIP methods\n",
737 				s.len, s.s);
738 		return SR_KEMI_FALSE;
739 	}
740 	if((int)method & mid) {
741 		return SR_KEMI_TRUE;
742 	}
743 	return SR_KEMI_FALSE;
744 }
745 
746 /**
747  *
748  */
sr_kemi_core_is_method(sip_msg_t * msg,str * vmethod)749 static int sr_kemi_core_is_method(sip_msg_t *msg, str *vmethod)
750 {
751 	if(msg==NULL || vmethod==NULL || vmethod->s==NULL || vmethod->len<=0) {
752 		LM_WARN("invalid parameters\n");
753 		return SR_KEMI_FALSE;
754 	}
755 
756 	if(msg->first_line.type==SIP_REQUEST) {
757 		if(msg->first_line.u.request.method_value==METHOD_OTHER) {
758 			if(msg->first_line.u.request.method.len!=vmethod->len) {
759 				return SR_KEMI_FALSE;
760 			}
761 			if(strncasecmp(msg->first_line.u.request.method.s, vmethod->s,
762 						vmethod->len)!=0) {
763 				return SR_KEMI_FALSE;
764 			}
765 			return SR_KEMI_TRUE;
766 		}
767 		return sr_kemi_core_match_method_id(&msg->first_line.u.request.method,
768 				vmethod, msg->first_line.u.request.method_value);
769 	}
770 
771 	if(parse_headers(msg, HDR_CSEQ_F, 0)!=0 || msg->cseq==NULL) {
772 		LM_ERR("cannot parse cseq header\n");
773 		return SR_KEMI_FALSE;
774 	}
775 	if(get_cseq(msg)->method_id==METHOD_OTHER) {
776 		if(get_cseq(msg)->method.len!=vmethod->len) {
777 			return SR_KEMI_FALSE;
778 		}
779 		if(strncasecmp(get_cseq(msg)->method.s, vmethod->s,
780 					vmethod->len)!=0) {
781 			return SR_KEMI_FALSE;
782 		}
783 		return SR_KEMI_TRUE;
784 	}
785 	return sr_kemi_core_match_method_id(&get_cseq(msg)->method, vmethod,
786 			get_cseq(msg)->method_id);
787 }
788 
789 /**
790  *
791  */
sr_kemi_core_is_method_in(sip_msg_t * msg,str * vmethod)792 static int sr_kemi_core_is_method_in(sip_msg_t *msg, str *vmethod)
793 {
794 	int imethod;
795 	int i;
796 
797 	if(msg==NULL || vmethod==NULL || vmethod->s==NULL || vmethod->len<=0) {
798 		LM_WARN("invalid parameters\n");
799 		return SR_KEMI_FALSE;
800 	}
801 
802 	if(msg->first_line.type==SIP_REQUEST) {
803 		imethod = msg->first_line.u.request.method_value;
804 	} else {
805 		if(parse_headers(msg, HDR_CSEQ_F, 0)!=0 || msg->cseq==NULL) {
806 			LM_ERR("cannot parse cseq header\n");
807 			return SR_KEMI_FALSE;
808 		}
809 		imethod = get_cseq(msg)->method_id;
810 	}
811 
812 	if(imethod==METHOD_OTHER) {
813 		return SR_KEMI_FALSE;
814 	}
815 
816 	for(i=0; i<vmethod->len; i++) {
817 		switch(vmethod->s[i]) {
818 			case 'I':
819 			case 'i':
820 				if(imethod==METHOD_INVITE) {
821 					return SR_KEMI_TRUE;
822 				}
823 			break;
824 			case 'A':
825 			case 'a':
826 				if(imethod==METHOD_ACK) {
827 					return SR_KEMI_TRUE;
828 				}
829 			break;
830 			case 'B':
831 			case 'b':
832 				if(imethod==METHOD_BYE) {
833 					return SR_KEMI_TRUE;
834 				}
835 			break;
836 			case 'C':
837 			case 'c':
838 				if(imethod==METHOD_CANCEL) {
839 					return SR_KEMI_TRUE;
840 				}
841 			break;
842 			case 'M':
843 			case 'm':
844 				if(imethod==METHOD_MESSAGE) {
845 					return SR_KEMI_TRUE;
846 				}
847 			break;
848 			case 'R':
849 			case 'r':
850 				if(imethod==METHOD_REGISTER) {
851 					return SR_KEMI_TRUE;
852 				}
853 			break;
854 			case 'E':
855 			case 'e':
856 				if(imethod==METHOD_PRACK) {
857 					return SR_KEMI_TRUE;
858 				}
859 			break;
860 			case 'P':
861 			case 'p':
862 				if(imethod==METHOD_PUBLISH) {
863 					return SR_KEMI_TRUE;
864 				}
865 			break;
866 			case 'S':
867 			case 's':
868 				if(imethod==METHOD_SUBSCRIBE) {
869 					return SR_KEMI_TRUE;
870 				}
871 			break;
872 			case 'N':
873 			case 'n':
874 				if(imethod==METHOD_NOTIFY) {
875 					return SR_KEMI_TRUE;
876 				}
877 			break;
878 			case 'O':
879 			case 'o':
880 				if(imethod==METHOD_OPTIONS) {
881 					return SR_KEMI_TRUE;
882 				}
883 			break;
884 			case 'F':
885 			case 'f':
886 				if(imethod==METHOD_REFER) {
887 					return SR_KEMI_TRUE;
888 				}
889 			break;
890 			case 'G':
891 			case 'g':
892 				if(imethod==METHOD_GET) {
893 					return SR_KEMI_TRUE;
894 				}
895 			break;
896 			case 'U':
897 			case 'u':
898 				if(imethod==METHOD_UPDATE) {
899 					return SR_KEMI_TRUE;
900 				}
901 			break;
902 			case 'K':
903 			case 'k':
904 				if(imethod==METHOD_KDMQ) {
905 					return SR_KEMI_TRUE;
906 				}
907 			break;
908 			case 'D':
909 			case 'd':
910 				if(imethod==METHOD_DELETE) {
911 					return SR_KEMI_TRUE;
912 				}
913 			break;
914 			case 'T':
915 			case 't':
916 				if(imethod==METHOD_POST) {
917 					return SR_KEMI_TRUE;
918 				}
919 			break;
920 			case 'V':
921 			case 'v':
922 				if(imethod==METHOD_PUT) {
923 					return SR_KEMI_TRUE;
924 				}
925 			break;
926 			default:
927 				LM_WARN("unsupported method flag: %c\n", vmethod->s[i]);
928 		}
929 	}
930 	return SR_KEMI_FALSE;
931 }
932 
933 /**
934  *
935  */
sr_kemi_core_is_method_type(sip_msg_t * msg,int mtype)936 static int sr_kemi_core_is_method_type(sip_msg_t *msg, int mtype)
937 {
938 	int imethod;
939 
940 	if(msg==NULL) {
941 		LM_WARN("invalid parameters\n");
942 		return SR_KEMI_FALSE;
943 	}
944 
945 	if(msg->first_line.type==SIP_REQUEST) {
946 		imethod = msg->first_line.u.request.method_value;
947 	} else {
948 		if(parse_headers(msg, HDR_CSEQ_F, 0)!=0 || msg->cseq==NULL) {
949 			LM_ERR("cannot parse cseq header\n");
950 			return SR_KEMI_FALSE;
951 		}
952 		imethod = get_cseq(msg)->method_id;
953 	}
954 
955 	if(imethod==mtype) {
956 		return SR_KEMI_TRUE;
957 	}
958 
959 	return SR_KEMI_FALSE;
960 }
961 
962 /**
963  *
964  */
sr_kemi_core_is_method_invite(sip_msg_t * msg)965 static int sr_kemi_core_is_method_invite(sip_msg_t *msg)
966 {
967 	return sr_kemi_core_is_method_type(msg, METHOD_INVITE);
968 }
969 
970 /**
971  *
972  */
sr_kemi_core_is_method_ack(sip_msg_t * msg)973 static int sr_kemi_core_is_method_ack(sip_msg_t *msg)
974 {
975 	return sr_kemi_core_is_method_type(msg, METHOD_ACK);
976 }
977 
978 /**
979  *
980  */
sr_kemi_core_is_method_bye(sip_msg_t * msg)981 static int sr_kemi_core_is_method_bye(sip_msg_t *msg)
982 {
983 	return sr_kemi_core_is_method_type(msg, METHOD_BYE);
984 }
985 
986 /**
987  *
988  */
sr_kemi_core_is_method_cancel(sip_msg_t * msg)989 static int sr_kemi_core_is_method_cancel(sip_msg_t *msg)
990 {
991 	return sr_kemi_core_is_method_type(msg, METHOD_CANCEL);
992 }
993 
994 /**
995  *
996  */
sr_kemi_core_is_method_register(sip_msg_t * msg)997 static int sr_kemi_core_is_method_register(sip_msg_t *msg)
998 {
999 	return sr_kemi_core_is_method_type(msg, METHOD_REGISTER);
1000 }
1001 
1002 /**
1003  *
1004  */
sr_kemi_core_is_method_options(sip_msg_t * msg)1005 static int sr_kemi_core_is_method_options(sip_msg_t *msg)
1006 {
1007 	return sr_kemi_core_is_method_type(msg, METHOD_OPTIONS);
1008 }
1009 
1010 /**
1011  *
1012  */
sr_kemi_core_is_method_update(sip_msg_t * msg)1013 static int sr_kemi_core_is_method_update(sip_msg_t *msg)
1014 {
1015 	return sr_kemi_core_is_method_type(msg, METHOD_UPDATE);
1016 }
1017 
1018 /**
1019  *
1020  */
sr_kemi_core_is_method_subscribe(sip_msg_t * msg)1021 static int sr_kemi_core_is_method_subscribe(sip_msg_t *msg)
1022 {
1023 	return sr_kemi_core_is_method_type(msg, METHOD_SUBSCRIBE);
1024 }
1025 
1026 /**
1027  *
1028  */
sr_kemi_core_is_method_publish(sip_msg_t * msg)1029 static int sr_kemi_core_is_method_publish(sip_msg_t *msg)
1030 {
1031 	return sr_kemi_core_is_method_type(msg, METHOD_PUBLISH);
1032 }
1033 
1034 /**
1035  *
1036  */
sr_kemi_core_is_method_notify(sip_msg_t * msg)1037 static int sr_kemi_core_is_method_notify(sip_msg_t *msg)
1038 {
1039 	return sr_kemi_core_is_method_type(msg, METHOD_NOTIFY);
1040 }
1041 
1042 /**
1043  *
1044  */
sr_kemi_core_is_method_refer(sip_msg_t * msg)1045 static int sr_kemi_core_is_method_refer(sip_msg_t *msg)
1046 {
1047 	return sr_kemi_core_is_method_type(msg, METHOD_REFER);
1048 }
1049 
1050 /**
1051  *
1052  */
sr_kemi_core_is_method_info(sip_msg_t * msg)1053 static int sr_kemi_core_is_method_info(sip_msg_t *msg)
1054 {
1055 	return sr_kemi_core_is_method_type(msg, METHOD_INFO);
1056 }
1057 
1058 /**
1059  *
1060  */
sr_kemi_core_is_method_prack(sip_msg_t * msg)1061 static int sr_kemi_core_is_method_prack(sip_msg_t *msg)
1062 {
1063 	return sr_kemi_core_is_method_type(msg, METHOD_PRACK);
1064 }
1065 
1066 
1067 /**
1068  *
1069  */
sr_kemi_core_is_method_message(sip_msg_t * msg)1070 static int sr_kemi_core_is_method_message(sip_msg_t *msg)
1071 {
1072 	return sr_kemi_core_is_method_type(msg, METHOD_MESSAGE);
1073 }
1074 
1075 
1076 /**
1077  *
1078  */
sr_kemi_core_is_method_kdmq(sip_msg_t * msg)1079 static int sr_kemi_core_is_method_kdmq(sip_msg_t *msg)
1080 {
1081 	return sr_kemi_core_is_method_type(msg, METHOD_KDMQ);
1082 }
1083 
1084 
1085 /**
1086  *
1087  */
sr_kemi_core_is_method_get(sip_msg_t * msg)1088 static int sr_kemi_core_is_method_get(sip_msg_t *msg)
1089 {
1090 	return sr_kemi_core_is_method_type(msg, METHOD_GET);
1091 }
1092 
1093 /**
1094  *
1095  */
sr_kemi_core_is_method_post(sip_msg_t * msg)1096 static int sr_kemi_core_is_method_post(sip_msg_t *msg)
1097 {
1098 	return sr_kemi_core_is_method_type(msg, METHOD_POST);
1099 }
1100 
1101 /**
1102  *
1103  */
sr_kemi_core_is_method_put(sip_msg_t * msg)1104 static int sr_kemi_core_is_method_put(sip_msg_t *msg)
1105 {
1106 	return sr_kemi_core_is_method_type(msg, METHOD_PUT);
1107 }
1108 
1109 /**
1110  *
1111  */
sr_kemi_core_is_method_delete(sip_msg_t * msg)1112 static int sr_kemi_core_is_method_delete(sip_msg_t *msg)
1113 {
1114 	return sr_kemi_core_is_method_type(msg, METHOD_DELETE);
1115 }
1116 
1117 /**
1118  *
1119  */
sr_kemi_core_is_proto_udp(sip_msg_t * msg)1120 static int sr_kemi_core_is_proto_udp(sip_msg_t *msg)
1121 {
1122 	return (msg->rcv.proto == PROTO_UDP)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1123 }
1124 
1125 /**
1126  *
1127  */
sr_kemi_core_is_proto_tcp(sip_msg_t * msg)1128 static int sr_kemi_core_is_proto_tcp(sip_msg_t *msg)
1129 {
1130 	return (msg->rcv.proto == PROTO_TCP)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1131 }
1132 
1133 /**
1134  *
1135  */
sr_kemi_core_is_proto_tls(sip_msg_t * msg)1136 static int sr_kemi_core_is_proto_tls(sip_msg_t *msg)
1137 {
1138 	return (msg->rcv.proto == PROTO_TLS)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1139 }
1140 
1141 /**
1142  *
1143  */
sr_kemi_core_is_proto_ws(sip_msg_t * msg)1144 static int sr_kemi_core_is_proto_ws(sip_msg_t *msg)
1145 {
1146 	return (msg->rcv.proto == PROTO_WS)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1147 }
1148 
1149 /**
1150  *
1151  */
sr_kemi_core_is_proto_wss(sip_msg_t * msg)1152 static int sr_kemi_core_is_proto_wss(sip_msg_t *msg)
1153 {
1154 	return (msg->rcv.proto == PROTO_WSS)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1155 }
1156 
1157 /**
1158  *
1159  */
sr_kemi_core_is_proto_sctp(sip_msg_t * msg)1160 static int sr_kemi_core_is_proto_sctp(sip_msg_t *msg)
1161 {
1162 	return (msg->rcv.proto == PROTO_SCTP)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1163 }
1164 
1165 /**
1166  *
1167  */
sr_kemi_core_is_proto(sip_msg_t * msg,str * sproto)1168 static int sr_kemi_core_is_proto(sip_msg_t *msg, str *sproto)
1169 {
1170 	int i;
1171 	if (msg==NULL || sproto==NULL || sproto->s==NULL || sproto->len<=0) {
1172 		return SR_KEMI_FALSE;
1173 	}
1174 	for(i=0; i<sproto->len; i++) {
1175 		switch(sproto->s[i]) {
1176 			case 'e':
1177 			case 'E':
1178 				if (msg->rcv.proto == PROTO_TLS) {
1179 					return SR_KEMI_TRUE;
1180 				}
1181 			break;
1182 			case 's':
1183 			case 'S':
1184 				if (msg->rcv.proto == PROTO_SCTP) {
1185 					return SR_KEMI_TRUE;
1186 				}
1187 			break;
1188 			case 't':
1189 			case 'T':
1190 				if (msg->rcv.proto == PROTO_TCP) {
1191 					return SR_KEMI_TRUE;
1192 				}
1193 			break;
1194 			case 'u':
1195 			case 'U':
1196 				if (msg->rcv.proto == PROTO_UDP) {
1197 					return SR_KEMI_TRUE;
1198 				}
1199 			break;
1200 			case 'v':
1201 			case 'V':
1202 				if (msg->rcv.proto == PROTO_WS) {
1203 					return SR_KEMI_TRUE;
1204 				}
1205 			break;
1206 
1207 			case 'w':
1208 			case 'W':
1209 				if (msg->rcv.proto == PROTO_WSS) {
1210 					return SR_KEMI_TRUE;
1211 				}
1212 			break;
1213 		}
1214 	}
1215 	return SR_KEMI_FALSE;
1216 }
1217 
1218 /**
1219  *
1220  */
sr_kemi_core_is_af_ipv4(sip_msg_t * msg)1221 static int sr_kemi_core_is_af_ipv4(sip_msg_t *msg)
1222 {
1223 	if(msg==NULL || msg->rcv.bind_address==NULL) {
1224 		return SR_KEMI_FALSE;
1225 	}
1226 	return (msg->rcv.bind_address->address.af==AF_INET)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1227 }
1228 
1229 /**
1230  *
1231  */
sr_kemi_core_is_af_ipv6(sip_msg_t * msg)1232 static int sr_kemi_core_is_af_ipv6(sip_msg_t *msg)
1233 {
1234 	if(msg==NULL || msg->rcv.bind_address==NULL) {
1235 		return SR_KEMI_FALSE;
1236 	}
1237 	return (msg->rcv.bind_address->address.af==AF_INET6)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1238 }
1239 
1240 /**
1241  *
1242  */
sr_kemi_core_is_src_port(sip_msg_t * msg,int vport)1243 static int sr_kemi_core_is_src_port(sip_msg_t *msg, int vport)
1244 {
1245 	return (vport == (int)msg->rcv.src_port)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1246 }
1247 
1248 /**
1249  *
1250  */
sr_kemi_core_is_dst_port(sip_msg_t * msg,int vport)1251 static int sr_kemi_core_is_dst_port(sip_msg_t *msg, int vport)
1252 {
1253 	if(msg==NULL || msg->rcv.bind_address==NULL) {
1254 		return SR_KEMI_FALSE;
1255 	}
1256 	return (vport == (int)msg->rcv.bind_address->port_no)?SR_KEMI_TRUE:SR_KEMI_FALSE;
1257 }
1258 
1259 /**
1260  *
1261  */
sr_kemi_core_forward_uri(sip_msg_t * msg,str * vuri)1262 static int sr_kemi_core_forward_uri(sip_msg_t *msg, str *vuri)
1263 {
1264 	int ret;
1265 	dest_info_t dst;
1266 	sip_uri_t *u;
1267 	sip_uri_t next_hop;
1268 
1269 	if(msg==NULL) {
1270 		LM_WARN("invalid msg parameter\n");
1271 		return -1;
1272 	}
1273 
1274 	init_dest_info(&dst);
1275 
1276 	if(vuri==NULL || vuri->s==NULL || vuri->len<=0) {
1277 		if (msg->dst_uri.len) {
1278 			ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop);
1279 			u = &next_hop;
1280 		} else {
1281 			ret = parse_sip_msg_uri(msg);
1282 			u = &msg->parsed_uri;
1283 		}
1284 	} else {
1285 		ret = parse_uri(vuri->s, vuri->len, &next_hop);
1286 		u = &next_hop;
1287 	}
1288 
1289 	if (ret<0) {
1290 		LM_ERR("forward - bad_uri dropping packet\n");
1291 		return -1;
1292 	}
1293 
1294 	dst.proto=u->proto;
1295 	ret=forward_request(msg, &u->host, u->port_no, &dst);
1296 	if (ret>=0) {
1297 		return 1;
1298 	}
1299 
1300 	return -1;
1301 }
1302 
1303 /**
1304  *
1305  */
sr_kemi_core_forward(sip_msg_t * msg)1306 static int sr_kemi_core_forward(sip_msg_t *msg)
1307 {
1308 	return sr_kemi_core_forward_uri(msg, NULL);
1309 }
1310 
1311 /**
1312  *
1313  */
sr_kemi_core_set_forward_close(sip_msg_t * msg)1314 static int sr_kemi_core_set_forward_close(sip_msg_t *msg)
1315 {
1316 	if(msg==NULL) {
1317 		LM_WARN("invalid msg parameter\n");
1318 		return SR_KEMI_FALSE;
1319 	}
1320 
1321 	msg->fwd_send_flags.f |= SND_F_CON_CLOSE;
1322 	return SR_KEMI_TRUE;
1323 }
1324 
1325 /**
1326  *
1327  */
sr_kemi_core_set_forward_no_connect(sip_msg_t * msg)1328 static int sr_kemi_core_set_forward_no_connect(sip_msg_t *msg)
1329 {
1330 	if(msg==NULL) {
1331 		LM_WARN("invalid msg parameter\n");
1332 		return SR_KEMI_FALSE;
1333 	}
1334 
1335 	msg->fwd_send_flags.f |= SND_F_FORCE_CON_REUSE;
1336 	return SR_KEMI_TRUE;
1337 }
1338 
1339 /**
1340  *
1341  */
sr_kemi_core_set_reply_close(sip_msg_t * msg)1342 static int sr_kemi_core_set_reply_close(sip_msg_t *msg)
1343 {
1344 	if(msg==NULL) {
1345 		LM_WARN("invalid msg parameter\n");
1346 		return SR_KEMI_FALSE;
1347 	}
1348 
1349 	msg->rpl_send_flags.f |= SND_F_CON_CLOSE;
1350 	return SR_KEMI_TRUE;
1351 }
1352 
1353 /**
1354  *
1355  */
sr_kemi_core_set_reply_no_connect(sip_msg_t * msg)1356 static int sr_kemi_core_set_reply_no_connect(sip_msg_t *msg)
1357 {
1358 	if(msg==NULL) {
1359 		LM_WARN("invalid msg parameter\n");
1360 		return SR_KEMI_FALSE;
1361 	}
1362 
1363 	msg->rpl_send_flags.f |= SND_F_FORCE_CON_REUSE;
1364 	return SR_KEMI_TRUE;
1365 }
1366 
1367 /**
1368  *
1369  */
sr_kemi_core_set_advertised_address(sip_msg_t * msg,str * addr)1370 static int sr_kemi_core_set_advertised_address(sip_msg_t *msg, str *addr)
1371 {
1372 #define SR_ADV_ADDR_SIZE 128
1373 	static char _sr_adv_addr_buf[SR_ADV_ADDR_SIZE];
1374 
1375 	if(addr==NULL || addr->s==NULL) {
1376 		LM_ERR("invalid addr parameter\n");
1377 		return SR_KEMI_FALSE;
1378 	}
1379 
1380 	if(addr->len>=SR_ADV_ADDR_SIZE) {
1381 		LM_ERR("addr parameter is too large\n");
1382 		return SR_KEMI_FALSE;
1383 	}
1384 
1385 	if(msg==NULL) {
1386 		LM_WARN("invalid msg parameter\n");
1387 		return SR_KEMI_FALSE;
1388 	}
1389 
1390 	memcpy(_sr_adv_addr_buf, addr->s, addr->len);
1391 	_sr_adv_addr_buf[addr->len] = '\0';
1392 	msg->set_global_address.s = _sr_adv_addr_buf;
1393 	msg->set_global_address.len = addr->len;
1394 
1395 	return SR_KEMI_TRUE;
1396 }
1397 
1398 /**
1399  *
1400  */
sr_kemi_core_set_advertised_port(sip_msg_t * msg,str * port)1401 static int sr_kemi_core_set_advertised_port(sip_msg_t *msg, str *port)
1402 {
1403 #define SR_ADV_PORT_SIZE 8
1404 	static char _sr_adv_port_buf[SR_ADV_PORT_SIZE];
1405 
1406 	if(port==NULL || port->s==NULL) {
1407 		LM_ERR("invalid port parameter\n");
1408 		return SR_KEMI_FALSE;
1409 	}
1410 
1411 	if(port->len>=SR_ADV_PORT_SIZE) {
1412 		LM_ERR("port parameter is too large\n");
1413 		return SR_KEMI_FALSE;
1414 	}
1415 
1416 	if(msg==NULL) {
1417 		LM_WARN("invalid msg parameter\n");
1418 		return SR_KEMI_FALSE;
1419 	}
1420 
1421 	memcpy(_sr_adv_port_buf, port->s, port->len);
1422 	_sr_adv_port_buf[port->len] = '\0';
1423 	msg->set_global_port.s = _sr_adv_port_buf;
1424 	msg->set_global_port.len = port->len;
1425 
1426 	return SR_KEMI_TRUE;
1427 }
1428 
1429 /**
1430  *
1431  */
sr_kemi_core_add_tcp_alias(sip_msg_t * msg,int port)1432 static int sr_kemi_core_add_tcp_alias(sip_msg_t *msg, int port)
1433 {
1434 	if(msg==NULL) {
1435 		LM_WARN("invalid msg parameter\n");
1436 		return SR_KEMI_FALSE;
1437 	}
1438 
1439 #ifdef USE_TCP
1440 	if ( msg->rcv.proto==PROTO_TCP
1441 #ifdef USE_TLS
1442 				|| msg->rcv.proto==PROTO_TLS
1443 #endif
1444 			) {
1445 		if (tcpconn_add_alias(msg->rcv.proto_reserved1, port,
1446 							msg->rcv.proto)!=0){
1447 			LM_ERR("adding tcp alias failed\n");
1448 			return SR_KEMI_FALSE;
1449 		}
1450 	}
1451 #endif
1452 
1453 	return SR_KEMI_TRUE;
1454 }
1455 
1456 /**
1457  *
1458  */
sr_kemi_core_add_tcp_alias_via(sip_msg_t * msg)1459 static int sr_kemi_core_add_tcp_alias_via(sip_msg_t *msg)
1460 {
1461 	if(msg==NULL) {
1462 		LM_WARN("invalid msg parameter\n");
1463 		return SR_KEMI_FALSE;
1464 	}
1465 
1466 #ifdef USE_TCP
1467 	if ( msg->rcv.proto==PROTO_TCP
1468 #ifdef USE_TLS
1469 				|| msg->rcv.proto==PROTO_TLS
1470 #endif
1471 			) {
1472 		if (tcpconn_add_alias(msg->rcv.proto_reserved1, msg->via1->port,
1473 							msg->rcv.proto)!=0){
1474 			LM_ERR("adding tcp alias failed\n");
1475 			return SR_KEMI_FALSE;
1476 		}
1477 	}
1478 #endif
1479 	return SR_KEMI_TRUE;
1480 }
1481 
1482 
1483 /**
1484  *
1485  */
sr_kemi_core_get_debug(sip_msg_t * msg)1486 static int sr_kemi_core_get_debug(sip_msg_t *msg)
1487 {
1488 	return get_cfg_debug_level();
1489 }
1490 
1491 /**
1492  *
1493  */
sr_kemi_core_route(sip_msg_t * msg,str * route)1494 static int sr_kemi_core_route(sip_msg_t *msg, str *route)
1495 {
1496 	run_act_ctx_t tctx;
1497 	run_act_ctx_t *pctx = NULL;
1498 	int rtid = -1;
1499 	int ret = 0;
1500 
1501 	if(route == NULL || route->s == NULL) {
1502 		return -1;
1503 	}
1504 
1505 	rtid = route_lookup(&main_rt, route->s);
1506 	if (rtid < 0) {
1507 		return -1;
1508 	}
1509 
1510 	if(_sr_kemi_act_ctx != NULL) {
1511 		pctx = _sr_kemi_act_ctx;
1512 	} else {
1513 		init_run_actions_ctx(&tctx);
1514 		pctx = &tctx;
1515 	}
1516 
1517 	ret=run_actions(pctx, main_rt.rlist[rtid], msg);
1518 
1519 	if (pctx->run_flags & EXIT_R_F) {
1520 		return 0;
1521 	}
1522 
1523 	return ret;
1524 }
1525 
1526 /**
1527  *
1528  */
1529 static sr_kemi_t _sr_kemi_core[] = {
1530 	{ str_init(""), str_init("dbg"),
1531 		SR_KEMIP_NONE, sr_kemi_core_dbg,
1532 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1533 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1534 	},
1535 	{ str_init(""), str_init("err"),
1536 		SR_KEMIP_NONE, sr_kemi_core_err,
1537 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1538 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1539 	},
1540 	{ str_init(""), str_init("info"),
1541 		SR_KEMIP_NONE, sr_kemi_core_info,
1542 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1543 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1544 	},
1545 	{ str_init(""), str_init("warn"),
1546 		SR_KEMIP_NONE, sr_kemi_core_warn,
1547 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1548 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1549 	},
1550 	{ str_init(""), str_init("notice"),
1551 		SR_KEMIP_NONE, sr_kemi_core_notice,
1552 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1553 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1554 	},
1555 	{ str_init(""), str_init("crit"),
1556 		SR_KEMIP_NONE, sr_kemi_core_crit,
1557 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1558 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1559 	},
1560 	{ str_init(""), str_init("log"),
1561 		SR_KEMIP_NONE, sr_kemi_core_log,
1562 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
1563 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1564 	},
1565 	{ str_init(""), str_init("set_drop"),
1566 		SR_KEMIP_NONE, sr_kemi_core_set_drop,
1567 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1568 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1569 	},
1570 	{ str_init(""), str_init("is_myself"),
1571 		SR_KEMIP_BOOL, sr_kemi_core_is_myself,
1572 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1573 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1574 	},
1575 	{ str_init(""), str_init("is_myself_ruri"),
1576 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_ruri,
1577 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1578 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1579 	},
1580 	{ str_init(""), str_init("is_myself_duri"),
1581 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_duri,
1582 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1583 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1584 	},
1585 	{ str_init(""), str_init("is_myself_nhuri"),
1586 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_nhuri,
1587 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1588 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1589 	},
1590 	{ str_init(""), str_init("is_myself_furi"),
1591 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_furi,
1592 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1593 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1594 	},
1595 	{ str_init(""), str_init("is_myself_turi"),
1596 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_turi,
1597 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1598 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1599 	},
1600 	{ str_init(""), str_init("is_myself_suri"),
1601 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_suri,
1602 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1603 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1604 	},
1605 	{ str_init(""), str_init("is_myself_srcip"),
1606 		SR_KEMIP_BOOL, sr_kemi_core_is_myself_srcip,
1607 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1608 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1609 	},
1610 	{ str_init(""), str_init("setflag"),
1611 		SR_KEMIP_BOOL, sr_kemi_core_setflag,
1612 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1613 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1614 	},
1615 	{ str_init(""), str_init("resetflag"),
1616 		SR_KEMIP_BOOL, sr_kemi_core_resetflag,
1617 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1618 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1619 	},
1620 	{ str_init(""), str_init("isflagset"),
1621 		SR_KEMIP_BOOL, sr_kemi_core_isflagset,
1622 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1623 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1624 	},
1625 	{ str_init(""), str_init("setbflag"),
1626 		SR_KEMIP_BOOL, sr_kemi_core_setbflag,
1627 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1628 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1629 	},
1630 	{ str_init(""), str_init("resetbflag"),
1631 		SR_KEMIP_BOOL, sr_kemi_core_resetbflag,
1632 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1633 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1634 	},
1635 	{ str_init(""), str_init("isbflagset"),
1636 		SR_KEMIP_BOOL, sr_kemi_core_isbflagset,
1637 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1638 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1639 	},
1640 	{ str_init(""), str_init("setbiflag"),
1641 		SR_KEMIP_BOOL, sr_kemi_core_setbiflag,
1642 		{ SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_NONE,
1643 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1644 	},
1645 	{ str_init(""), str_init("resetbiflag"),
1646 		SR_KEMIP_BOOL, sr_kemi_core_resetbiflag,
1647 		{ SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_NONE,
1648 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1649 	},
1650 	{ str_init(""), str_init("isbiflagset"),
1651 		SR_KEMIP_BOOL, sr_kemi_core_isbiflagset,
1652 		{ SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_NONE,
1653 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1654 	},
1655 	{ str_init(""), str_init("setsflag"),
1656 		SR_KEMIP_BOOL, sr_kemi_core_setsflag,
1657 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1658 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1659 	},
1660 	{ str_init(""), str_init("resetsflag"),
1661 		SR_KEMIP_BOOL, sr_kemi_core_resetsflag,
1662 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1663 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1664 	},
1665 	{ str_init(""), str_init("issflagset"),
1666 		SR_KEMIP_BOOL, sr_kemi_core_issflagset,
1667 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1668 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1669 	},
1670 	{ str_init(""), str_init("seturi"),
1671 		SR_KEMIP_BOOL, sr_kemi_core_seturi,
1672 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1673 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1674 	},
1675 	{ str_init(""), str_init("setuser"),
1676 		SR_KEMIP_BOOL, sr_kemi_core_setuser,
1677 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1678 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1679 	},
1680 	{ str_init(""), str_init("sethost"),
1681 		SR_KEMIP_BOOL, sr_kemi_core_sethost,
1682 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1683 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1684 	},
1685 	{ str_init(""), str_init("setdsturi"),
1686 		SR_KEMIP_BOOL, sr_kemi_core_setdsturi,
1687 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1688 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1689 	},
1690 	{ str_init(""), str_init("resetdsturi"),
1691 		SR_KEMIP_BOOL, sr_kemi_core_resetdsturi,
1692 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1693 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1694 	},
1695 	{ str_init(""), str_init("isdsturiset"),
1696 		SR_KEMIP_BOOL, sr_kemi_core_isdsturiset,
1697 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1698 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1699 	},
1700 	{ str_init(""), str_init("force_rport"),
1701 		SR_KEMIP_BOOL, sr_kemi_core_force_rport,
1702 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1703 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1704 	},
1705 	{ str_init(""), str_init("add_local_rport"),
1706 		SR_KEMIP_BOOL, sr_kemi_core_add_local_rport,
1707 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1708 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1709 	},
1710 	{ str_init(""), str_init("is_method"),
1711 		SR_KEMIP_BOOL, sr_kemi_core_is_method,
1712 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1713 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1714 	},
1715 	{ str_init(""), str_init("is_method_in"),
1716 		SR_KEMIP_BOOL, sr_kemi_core_is_method_in,
1717 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1718 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1719 	},
1720 	{ str_init(""), str_init("forward"),
1721 		SR_KEMIP_INT, sr_kemi_core_forward,
1722 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1723 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1724 	},
1725 	{ str_init(""), str_init("forward_uri"),
1726 		SR_KEMIP_INT, sr_kemi_core_forward_uri,
1727 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1728 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1729 	},
1730 	{ str_init(""), str_init("set_forward_close"),
1731 		SR_KEMIP_BOOL, sr_kemi_core_set_forward_close,
1732 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1733 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1734 	},
1735 	{ str_init(""), str_init("set_forward_no_connect"),
1736 		SR_KEMIP_BOOL, sr_kemi_core_set_forward_no_connect,
1737 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1738 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1739 	},
1740 	{ str_init(""), str_init("set_reply_close"),
1741 		SR_KEMIP_BOOL, sr_kemi_core_set_reply_close,
1742 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1743 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1744 	},
1745 	{ str_init(""), str_init("set_reply_no_connect"),
1746 		SR_KEMIP_BOOL, sr_kemi_core_set_reply_no_connect,
1747 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1748 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1749 	},
1750 	{ str_init(""), str_init("set_advertised_address"),
1751 		SR_KEMIP_INT, sr_kemi_core_set_advertised_address,
1752 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1753 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1754 	},
1755 	{ str_init(""), str_init("set_advertised_port"),
1756 		SR_KEMIP_INT, sr_kemi_core_set_advertised_port,
1757 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1758 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1759 	},
1760 	{ str_init(""), str_init("add_tcp_alias"),
1761 		SR_KEMIP_INT, sr_kemi_core_add_tcp_alias,
1762 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1763 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1764 	},
1765 	{ str_init(""), str_init("add_tcp_alias_via"),
1766 		SR_KEMIP_INT, sr_kemi_core_add_tcp_alias_via,
1767 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1768 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1769 	},
1770 	{ str_init(""), str_init("is_INVITE"),
1771 		SR_KEMIP_BOOL, sr_kemi_core_is_method_invite,
1772 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1773 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1774 	},
1775 	{ str_init(""), str_init("is_ACK"),
1776 		SR_KEMIP_BOOL, sr_kemi_core_is_method_ack,
1777 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1778 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1779 	},
1780 	{ str_init(""), str_init("is_BYE"),
1781 		SR_KEMIP_BOOL, sr_kemi_core_is_method_bye,
1782 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1783 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1784 	},
1785 	{ str_init(""), str_init("is_CANCEL"),
1786 		SR_KEMIP_BOOL, sr_kemi_core_is_method_cancel,
1787 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1788 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1789 	},
1790 	{ str_init(""), str_init("is_REGISTER"),
1791 		SR_KEMIP_BOOL, sr_kemi_core_is_method_register,
1792 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1793 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1794 	},
1795 	{ str_init(""), str_init("is_OPTIONS"),
1796 		SR_KEMIP_BOOL, sr_kemi_core_is_method_options,
1797 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1798 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1799 	},
1800 	{ str_init(""), str_init("is_SUBSCRIBE"),
1801 		SR_KEMIP_BOOL, sr_kemi_core_is_method_subscribe,
1802 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1803 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1804 	},
1805 	{ str_init(""), str_init("is_PUBLISH"),
1806 		SR_KEMIP_BOOL, sr_kemi_core_is_method_publish,
1807 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1808 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1809 	},
1810 	{ str_init(""), str_init("is_NOTIFY"),
1811 		SR_KEMIP_BOOL, sr_kemi_core_is_method_notify,
1812 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1813 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1814 	},
1815 	{ str_init(""), str_init("is_REFER"),
1816 		SR_KEMIP_BOOL, sr_kemi_core_is_method_refer,
1817 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1818 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1819 	},
1820 	{ str_init(""), str_init("is_INFO"),
1821 		SR_KEMIP_BOOL, sr_kemi_core_is_method_info,
1822 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1823 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1824 	},
1825 	{ str_init(""), str_init("is_UPDATE"),
1826 		SR_KEMIP_BOOL, sr_kemi_core_is_method_update,
1827 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1828 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1829 	},
1830 	{ str_init(""), str_init("is_PRACK"),
1831 		SR_KEMIP_BOOL, sr_kemi_core_is_method_prack,
1832 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1833 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1834 	},
1835 	{ str_init(""), str_init("is_MESSAGE"),
1836 		SR_KEMIP_BOOL, sr_kemi_core_is_method_message,
1837 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1838 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1839 	},
1840 	{ str_init(""), str_init("is_KDMQ"),
1841 		SR_KEMIP_BOOL, sr_kemi_core_is_method_kdmq,
1842 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1843 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1844 	},
1845 	{ str_init(""), str_init("is_GET"),
1846 		SR_KEMIP_BOOL, sr_kemi_core_is_method_get,
1847 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1848 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1849 	},
1850 	{ str_init(""), str_init("is_POST"),
1851 		SR_KEMIP_BOOL, sr_kemi_core_is_method_post,
1852 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1853 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1854 	},
1855 	{ str_init(""), str_init("is_PUT"),
1856 		SR_KEMIP_BOOL, sr_kemi_core_is_method_put,
1857 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1858 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1859 	},
1860 	{ str_init(""), str_init("is_DELETE"),
1861 		SR_KEMIP_BOOL, sr_kemi_core_is_method_delete,
1862 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1863 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1864 	},
1865 	{ str_init(""), str_init("is_UDP"),
1866 		SR_KEMIP_BOOL, sr_kemi_core_is_proto_udp,
1867 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1868 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1869 	},
1870 	{ str_init(""), str_init("is_TCP"),
1871 		SR_KEMIP_BOOL, sr_kemi_core_is_proto_tcp,
1872 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1873 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1874 	},
1875 	{ str_init(""), str_init("is_TLS"),
1876 		SR_KEMIP_BOOL, sr_kemi_core_is_proto_tls,
1877 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1878 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1879 	},
1880 	{ str_init(""), str_init("is_WS"),
1881 		SR_KEMIP_BOOL, sr_kemi_core_is_proto_ws,
1882 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1883 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1884 	},
1885 	{ str_init(""), str_init("is_WSS"),
1886 		SR_KEMIP_BOOL, sr_kemi_core_is_proto_wss,
1887 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1888 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1889 	},
1890 	{ str_init(""), str_init("is_SCTP"),
1891 		SR_KEMIP_BOOL, sr_kemi_core_is_proto_sctp,
1892 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1893 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1894 	},
1895 	{ str_init(""), str_init("is_proto"),
1896 		SR_KEMIP_BOOL, sr_kemi_core_is_proto,
1897 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1898 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1899 	},
1900 	{ str_init(""), str_init("is_IPv4"),
1901 		SR_KEMIP_BOOL, sr_kemi_core_is_af_ipv4,
1902 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1903 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1904 	},
1905 	{ str_init(""), str_init("is_IPv6"),
1906 		SR_KEMIP_BOOL, sr_kemi_core_is_af_ipv6,
1907 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1908 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1909 	},
1910 	{ str_init(""), str_init("is_src_port"),
1911 		SR_KEMIP_BOOL, sr_kemi_core_is_src_port,
1912 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1913 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1914 	},
1915 	{ str_init(""), str_init("is_dst_port"),
1916 		SR_KEMIP_BOOL, sr_kemi_core_is_dst_port,
1917 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
1918 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1919 	},
1920 	{ str_init(""), str_init("get_debug"),
1921 		SR_KEMIP_INT, sr_kemi_core_get_debug,
1922 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
1923 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1924 	},
1925 	{ str_init(""), str_init("route"),
1926 		SR_KEMIP_INT, sr_kemi_core_route,
1927 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
1928 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
1929 	},
1930 
1931 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
1932 };
1933 
1934 /**
1935  *
1936  */
sr_kemi_hdr_append(sip_msg_t * msg,str * txt)1937 static int sr_kemi_hdr_append(sip_msg_t *msg, str *txt)
1938 {
1939 	struct lump* anchor;
1940 	char *hdr;
1941 
1942 	if(txt==NULL || txt->s==NULL || msg==NULL)
1943 		return -1;
1944 
1945 	LM_DBG("append hf: %.*s\n", txt->len, txt->s);
1946 	if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
1947 		LM_ERR("error while parsing message\n");
1948 		return -1;
1949 	}
1950 
1951 	hdr = (char*)pkg_malloc(txt->len);
1952 	if(hdr==NULL) {
1953 		PKG_MEM_ERROR;
1954 		return -1;
1955 	}
1956 	memcpy(hdr, txt->s, txt->len);
1957 	/* anchor after last header */
1958 	anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
1959 	if((anchor==NULL)
1960 			|| (insert_new_lump_before(anchor, hdr, txt->len, 0) == 0)) {
1961 		LM_ERR("can't insert lump\n");
1962 		pkg_free(hdr);
1963 		return -1;
1964 	}
1965 	return 1;
1966 }
1967 
1968 /**
1969  *
1970  */
sr_kemi_hdr_append_after(sip_msg_t * msg,str * txt,str * hname)1971 static int sr_kemi_hdr_append_after(sip_msg_t *msg, str *txt, str *hname)
1972 {
1973 	struct lump* anchor;
1974 	hdr_field_t *hf;
1975 	hdr_field_t hfm;
1976 	char *hdr;
1977 	char hbuf[SR_KEMI_HNAME_SIZE];
1978 
1979 	if(txt==NULL || txt->s==NULL || hname==NULL || hname->s==NULL || msg==NULL)
1980 		return -1;
1981 
1982 	if(hname->len>SR_KEMI_HNAME_SIZE-4) {
1983 		LM_ERR("header name too long: %d\n", hname->len);
1984 		return -1;
1985 	}
1986 	memcpy(hbuf, hname->s, hname->len);
1987 	hbuf[hname->len] = ':';
1988 	hbuf[hname->len+1] = '\0';
1989 
1990 	if (parse_hname2_short(hbuf, hbuf+hname->len+1, &hfm)==0) {
1991 		LM_ERR("error parsing header name [%.*s]\n", hname->len, hname->s);
1992 		return -1;
1993 	}
1994 
1995 	if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
1996 		LM_ERR("error while parsing message\n");
1997 		return -1;
1998 	}
1999 	for (hf=msg->headers; hf; hf=hf->next) {
2000 		if (hfm.type!=HDR_OTHER_T && hfm.type!=HDR_ERROR_T) {
2001 			if (hfm.type!=hf->type)
2002 				continue;
2003 		} else {
2004 			if (hf->name.len!=hfm.name.len)
2005 				continue;
2006 			if (cmp_hdrname_str(&hf->name, &hfm.name)!=0)
2007 				continue;
2008 		}
2009 		break;
2010 	}
2011 
2012 	hdr = (char*)pkg_malloc(txt->len);
2013 	if(hdr==NULL) {
2014 		PKG_MEM_ERROR;
2015 		return -1;
2016 	}
2017 	memcpy(hdr, txt->s, txt->len);
2018 
2019 	if(hf==0) { /* after last header */
2020 		anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0);
2021 	} else { /* after hf */
2022 		anchor = anchor_lump(msg, hf->name.s + hf->len - msg->buf, 0, 0);
2023 	}
2024 
2025 	if((anchor==NULL)
2026 			|| (insert_new_lump_before(anchor, hdr, txt->len, 0) == 0)) {
2027 		LM_ERR("can't insert lump\n");
2028 		pkg_free(hdr);
2029 		return -1;
2030 	}
2031 	LM_DBG("appended after [%.*s] the hf: [%.*s]\n", hname->len, hname->s,
2032 			txt->len, txt->s);
2033 
2034 	return 1;
2035 }
2036 
2037 /**
2038  *
2039  */
sr_kemi_hdr_remove(sip_msg_t * msg,str * hname)2040 int sr_kemi_hdr_remove(sip_msg_t *msg, str *hname)
2041 {
2042 	struct lump* anchor;
2043 	hdr_field_t *hf;
2044 	hdr_field_t hfm;
2045 	char hbuf[SR_KEMI_HNAME_SIZE];
2046 
2047 	if(hname==NULL || hname->s==NULL || msg==NULL)
2048 		return -1;
2049 
2050 	if(hname->len>SR_KEMI_HNAME_SIZE-4) {
2051 		LM_ERR("header name too long: %d\n", hname->len);
2052 		return -1;
2053 	}
2054 	memcpy(hbuf, hname->s, hname->len);
2055 	hbuf[hname->len] = ':';
2056 	hbuf[hname->len+1] = '\0';
2057 
2058 	if (parse_hname2_short(hbuf, hbuf+hname->len+1, &hfm)==0) {
2059 		LM_ERR("error parsing header name [%.*s]\n", hname->len, hname->s);
2060 		return -1;
2061 	}
2062 
2063 	if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
2064 		LM_ERR("error while parsing message\n");
2065 		return -1;
2066 	}
2067 
2068 	LM_DBG("remove hf: %.*s\n", hname->len, hname->s);
2069 	for (hf=msg->headers; hf; hf=hf->next) {
2070 		if (hfm.type!=HDR_OTHER_T && hfm.type!=HDR_ERROR_T) {
2071 			if (hfm.type!=hf->type)
2072 				continue;
2073 		} else {
2074 			if (hf->name.len!=hname->len)
2075 				continue;
2076 			if(strncasecmp(hf->name.s, hname->s, hname->len)!=0)
2077 				continue;
2078 		}
2079 		anchor=del_lump(msg, hf->name.s - msg->buf, hf->len, 0);
2080 		if (anchor==0) {
2081 			LM_ERR("cannot remove hdr %.*s\n", hname->len, hname->s);
2082 			return -1;
2083 		}
2084 	}
2085 	return 1;
2086 }
2087 
2088 /**
2089  *
2090  */
sr_kemi_hdr_is_present(sip_msg_t * msg,str * hname)2091 static int sr_kemi_hdr_is_present(sip_msg_t *msg, str *hname)
2092 {
2093 	hdr_field_t *hf;
2094 	hdr_field_t hfm;
2095 	char hbuf[SR_KEMI_HNAME_SIZE];
2096 
2097 	if(hname==NULL || hname->s==NULL || msg==NULL)
2098 		return -1;
2099 
2100 	if(hname->len>SR_KEMI_HNAME_SIZE-4) {
2101 		LM_ERR("header name too long: %d\n", hname->len);
2102 		return -1;
2103 	}
2104 	memcpy(hbuf, hname->s, hname->len);
2105 	hbuf[hname->len] = ':';
2106 	hbuf[hname->len+1] = '\0';
2107 
2108 	if (parse_hname2_short(hbuf, hbuf+hname->len+1, &hfm)==0) {
2109 		LM_ERR("error parsing header name [%.*s]\n", hname->len, hname->s);
2110 		return -1;
2111 	}
2112 
2113 	if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
2114 		LM_ERR("error while parsing message\n");
2115 		return -1;
2116 	}
2117 
2118 	LM_DBG("searching hf: %.*s\n", hname->len, hname->s);
2119 	for (hf=msg->headers; hf; hf=hf->next) {
2120 		if (hfm.type!=HDR_OTHER_T && hfm.type!=HDR_ERROR_T) {
2121 			if (hfm.type!=hf->type)
2122 				continue;
2123 		} else {
2124 			if (hf->name.len!=hname->len)
2125 				continue;
2126 			if(strncasecmp(hf->name.s, hname->s, hname->len)!=0)
2127 				continue;
2128 		}
2129 		return 1;
2130 	}
2131 	return -1;
2132 }
2133 
2134 /**
2135  *
2136  */
sr_kemi_hdr_insert(sip_msg_t * msg,str * txt)2137 static int sr_kemi_hdr_insert(sip_msg_t *msg, str *txt)
2138 {
2139 	struct lump* anchor;
2140 	char *hdr;
2141 
2142 	if(txt==NULL || txt->s==NULL || msg==NULL)
2143 		return -1;
2144 
2145 	LM_DBG("insert hf: %.*s\n", txt->len, txt->s);
2146 	hdr = (char*)pkg_malloc(txt->len);
2147 	if(hdr==NULL) {
2148 		PKG_MEM_ERROR;
2149 		return -1;
2150 	}
2151 	memcpy(hdr, txt->s, txt->len);
2152 	/* anchor before first header */
2153 	anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0, 0);
2154 	if((anchor==NULL)
2155 			|| (insert_new_lump_before(anchor, hdr, txt->len, 0) == 0)) {
2156 		LM_ERR("can't insert lump\n");
2157 		pkg_free(hdr);
2158 		return -1;
2159 	}
2160 	return 1;
2161 }
2162 
2163 /**
2164  *
2165  */
sr_kemi_hdr_insert_before(sip_msg_t * msg,str * txt,str * hname)2166 static int sr_kemi_hdr_insert_before(sip_msg_t *msg, str *txt, str *hname)
2167 {
2168 	struct lump* anchor;
2169 	hdr_field_t *hf;
2170 	hdr_field_t hfm;
2171 	char *hdr;
2172 	char hbuf[SR_KEMI_HNAME_SIZE];
2173 
2174 	if(txt==NULL || txt->s==NULL || hname==NULL || hname->s==NULL || msg==NULL)
2175 		return -1;
2176 
2177 	if(hname->len>SR_KEMI_HNAME_SIZE-4) {
2178 		LM_ERR("header name too long: %d\n", hname->len);
2179 		return -1;
2180 	}
2181 	memcpy(hbuf, hname->s, hname->len);
2182 	hbuf[hname->len] = ':';
2183 	hbuf[hname->len+1] = '\0';
2184 
2185 	if (parse_hname2_short(hbuf, hbuf+hname->len+1, &hfm)==0) {
2186 		LM_ERR("error parsing header name [%.*s]\n", hname->len, hname->s);
2187 		return -1;
2188 	}
2189 
2190 	if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
2191 		LM_ERR("error while parsing message\n");
2192 		return -1;
2193 	}
2194 	for (hf=msg->headers; hf; hf=hf->next) {
2195 		if (hfm.type!=HDR_OTHER_T && hfm.type!=HDR_ERROR_T) {
2196 			if (hfm.type!=hf->type)
2197 				continue;
2198 		} else {
2199 			if (hf->name.len!=hfm.name.len)
2200 				continue;
2201 			if (cmp_hdrname_str(&hf->name, &hfm.name)!=0)
2202 				continue;
2203 		}
2204 		break;
2205 	}
2206 
2207 	hdr = (char*)pkg_malloc(txt->len);
2208 	if(hdr==NULL) {
2209 		PKG_MEM_ERROR;
2210 		return -1;
2211 	}
2212 	memcpy(hdr, txt->s, txt->len);
2213 	if(hf==0) { /* before first header */
2214 		anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0, 0);
2215 	} else { /* before hf */
2216 		anchor = anchor_lump(msg, hf->name.s - msg->buf, 0, 0);
2217 	}
2218 	if((anchor==NULL)
2219 			|| (insert_new_lump_before(anchor, hdr, txt->len, 0) == 0)) {
2220 		LM_ERR("can't insert lump\n");
2221 		pkg_free(hdr);
2222 		return -1;
2223 	}
2224 	LM_DBG("inserted before [%.*s] the hf: %.*s\n", hname->len, hname->s,
2225 			txt->len, txt->s);
2226 
2227 	return 1;
2228 }
2229 
2230 /**
2231  *
2232  */
sr_kemi_hdr_rmappend(sip_msg_t * msg,str * hrm,str * hadd)2233 static int sr_kemi_hdr_rmappend(sip_msg_t *msg, str *hrm, str *hadd)
2234 {
2235 	int ret;
2236 
2237 	ret = sr_kemi_hdr_remove(msg, hrm);
2238 	if(ret<0) {
2239 		return ret;
2240 	}
2241 	return sr_kemi_hdr_append(msg, hadd);
2242 }
2243 
2244 /**
2245  *
2246  */
sr_kemi_hdr_rminsert(sip_msg_t * msg,str * hrm,str * hadd)2247 static int sr_kemi_hdr_rminsert(sip_msg_t *msg, str *hrm, str *hadd)
2248 {
2249 	int ret;
2250 
2251 	ret = sr_kemi_hdr_remove(msg, hrm);
2252 	if(ret<0) {
2253 		return ret;
2254 	}
2255 	return sr_kemi_hdr_insert(msg, hadd);
2256 }
2257 
2258 
2259 /**
2260  *
2261  */
sr_kemi_hdr_append_to_reply(sip_msg_t * msg,str * txt)2262 static int sr_kemi_hdr_append_to_reply(sip_msg_t *msg, str *txt)
2263 {
2264 	if(txt==NULL || txt->s==NULL || msg==NULL)
2265 		return -1;
2266 
2267 	LM_DBG("append to reply: %.*s\n", txt->len, txt->s);
2268 
2269 	if(add_lump_rpl(msg, txt->s, txt->len, LUMP_RPL_HDR)==0) {
2270 		LM_ERR("unable to add reply lump\n");
2271 		return -1;
2272 	}
2273 
2274 	return 1;
2275 }
2276 
2277 /**
2278  *
2279  */
sr_kemi_hdr_get_mode(sip_msg_t * msg,str * hname,int idx,int rmode)2280 static sr_kemi_xval_t* sr_kemi_hdr_get_mode(sip_msg_t *msg, str *hname, int idx,
2281 		int rmode)
2282 {
2283 	char hbuf[256];
2284 	str s;
2285 	hdr_field_t shdr;
2286 	hdr_field_t *ihdr;
2287 #define SR_KEMI_VHDR_SIZE 256
2288 	hdr_field_t *vhdr[SR_KEMI_VHDR_SIZE];
2289 	int n;
2290 	int hmatch;
2291 
2292 	memset(&_sr_kemi_xval, 0, sizeof(sr_kemi_xval_t));
2293 
2294 	if(msg==NULL) {
2295 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2296 		return &_sr_kemi_xval;
2297 	}
2298 	/* we need to be sure we have parsed all headers */
2299 	if(parse_headers(msg, HDR_EOH_F, 0)<0) {
2300 		LM_ERR("error parsing headers\n");
2301 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2302 		return &_sr_kemi_xval;
2303 	}
2304 	if(hname->len>=252) {
2305 		LM_ERR("header name too long\n");
2306 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2307 		return &_sr_kemi_xval;
2308 	}
2309 
2310 	memcpy(hbuf, hname->s, hname->len);
2311 	hbuf[hname->len] = ':';
2312 	hbuf[hname->len+1] = '\0';
2313 	s.s = hbuf;
2314 	s.len = hname->len + 1;
2315 
2316 	if (parse_hname2_short(s.s, s.s + s.len, &shdr)==0) {
2317 		LM_ERR("error parsing header name [%.*s]\n", s.len, s.s);
2318 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2319 		return &_sr_kemi_xval;
2320 	}
2321 	n = 0;
2322 	for (ihdr=msg->headers; ihdr; ihdr=ihdr->next) {
2323 		hmatch = 0;
2324 		if (shdr.type!=HDR_OTHER_T && shdr.type!=HDR_ERROR_T) {
2325 			/* find by type */
2326 			if (shdr.type==ihdr->type) {
2327 				hmatch = 1;
2328 			}
2329 		} else {
2330 			/* find by name */
2331 			if (cmp_hdrname_str(&ihdr->name, hname)==0) {
2332 				hmatch = 1;
2333 			}
2334 		}
2335 		if (hmatch == 1) {
2336 			if(idx==n) {
2337 				break;
2338 			} else {
2339 				if(idx<0) {
2340 					vhdr[n] = ihdr;
2341 				}
2342 				n++;
2343 				if(n==SR_KEMI_VHDR_SIZE) {
2344 					LM_DBG("too many headers with name: %.*s\n",
2345 							hname->len, hname->s);
2346 					sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2347 					return &_sr_kemi_xval;
2348 				}
2349 			}
2350 		}
2351 	}
2352 	if(idx>=0) {
2353 		if(ihdr==NULL) {
2354 			sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2355 			return &_sr_kemi_xval;
2356 		}
2357 	} else {
2358 		if(n + idx < 0) {
2359 			sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2360 			return &_sr_kemi_xval;
2361 		}
2362 		ihdr = vhdr[n + idx];
2363 	}
2364 
2365 	_sr_kemi_xval.vtype = SR_KEMIP_STR;
2366 	_sr_kemi_xval.v.s = ihdr->body;
2367 	return &_sr_kemi_xval;
2368 }
2369 
2370 /**
2371  *
2372  */
sr_kemi_hdr_get(sip_msg_t * msg,str * hname)2373 static sr_kemi_xval_t* sr_kemi_hdr_get(sip_msg_t *msg, str *hname)
2374 {
2375 	return sr_kemi_hdr_get_mode(msg, hname, 0, SR_KEMI_XVAL_NULL_NONE);
2376 }
2377 
2378 /**
2379  *
2380  */
sr_kemi_hdr_gete(sip_msg_t * msg,str * hname)2381 static sr_kemi_xval_t* sr_kemi_hdr_gete(sip_msg_t *msg, str *hname)
2382 {
2383 	return sr_kemi_hdr_get_mode(msg, hname, 0, SR_KEMI_XVAL_NULL_EMPTY);
2384 }
2385 
2386 /**
2387  *
2388  */
sr_kemi_hdr_getw(sip_msg_t * msg,str * hname)2389 static sr_kemi_xval_t* sr_kemi_hdr_getw(sip_msg_t *msg, str *hname)
2390 {
2391 	return sr_kemi_hdr_get_mode(msg, hname, 0, SR_KEMI_XVAL_NULL_PRINT);
2392 }
2393 
2394 /**
2395  *
2396  */
sr_kemi_hdr_get_idx(sip_msg_t * msg,str * hname,int idx)2397 static sr_kemi_xval_t* sr_kemi_hdr_get_idx(sip_msg_t *msg, str *hname, int idx)
2398 {
2399 	return sr_kemi_hdr_get_mode(msg, hname, idx, SR_KEMI_XVAL_NULL_NONE);
2400 }
2401 
2402 /**
2403  *
2404  */
sr_kemi_hdr_gete_idx(sip_msg_t * msg,str * hname,int idx)2405 static sr_kemi_xval_t* sr_kemi_hdr_gete_idx(sip_msg_t *msg, str *hname, int idx)
2406 {
2407 	return sr_kemi_hdr_get_mode(msg, hname, idx, SR_KEMI_XVAL_NULL_EMPTY);
2408 }
2409 
2410 /**
2411  *
2412  */
sr_kemi_hdr_getw_idx(sip_msg_t * msg,str * hname,int idx)2413 static sr_kemi_xval_t* sr_kemi_hdr_getw_idx(sip_msg_t *msg, str *hname, int idx)
2414 {
2415 	return sr_kemi_hdr_get_mode(msg, hname, idx, SR_KEMI_XVAL_NULL_PRINT);
2416 }
2417 
2418 /**
2419  *
2420  */
2421 static sr_kemi_t _sr_kemi_hdr[] = {
2422 	{ str_init("hdr"), str_init("append"),
2423 		SR_KEMIP_INT, sr_kemi_hdr_append,
2424 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2425 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2426 	},
2427 	{ str_init("hdr"), str_init("append_after"),
2428 		SR_KEMIP_INT, sr_kemi_hdr_append_after,
2429 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2430 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2431 	},
2432 	{ str_init("hdr"), str_init("insert"),
2433 		SR_KEMIP_INT, sr_kemi_hdr_insert,
2434 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2435 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2436 	},
2437 	{ str_init("hdr"), str_init("insert_before"),
2438 		SR_KEMIP_INT, sr_kemi_hdr_insert_before,
2439 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2440 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2441 	},
2442 	{ str_init("hdr"), str_init("remove"),
2443 		SR_KEMIP_INT, sr_kemi_hdr_remove,
2444 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2445 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2446 	},
2447 	{ str_init("hdr"), str_init("rmappend"),
2448 		SR_KEMIP_INT, sr_kemi_hdr_rmappend,
2449 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2450 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2451 	},
2452 	{ str_init("hdr"), str_init("rminsert"),
2453 		SR_KEMIP_INT, sr_kemi_hdr_rminsert,
2454 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2455 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2456 	},
2457 	{ str_init("hdr"), str_init("is_present"),
2458 		SR_KEMIP_INT, sr_kemi_hdr_is_present,
2459 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2460 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2461 	},
2462 	{ str_init("hdr"), str_init("append_to_reply"),
2463 		SR_KEMIP_INT, sr_kemi_hdr_append_to_reply,
2464 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2465 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2466 	},
2467 	{ str_init("hdr"), str_init("get"),
2468 		SR_KEMIP_XVAL, sr_kemi_hdr_get,
2469 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2470 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2471 	},
2472 	{ str_init("hdr"), str_init("gete"),
2473 		SR_KEMIP_XVAL, sr_kemi_hdr_gete,
2474 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2475 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2476 	},
2477 	{ str_init("hdr"), str_init("getw"),
2478 		SR_KEMIP_XVAL, sr_kemi_hdr_getw,
2479 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2480 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2481 	},
2482 	{ str_init("hdr"), str_init("get_idx"),
2483 		SR_KEMIP_XVAL, sr_kemi_hdr_get_idx,
2484 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
2485 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2486 	},
2487 	{ str_init("hdr"), str_init("gete_idx"),
2488 		SR_KEMIP_XVAL, sr_kemi_hdr_gete_idx,
2489 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
2490 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2491 	},
2492 	{ str_init("hdr"), str_init("getw_idx"),
2493 		SR_KEMIP_XVAL, sr_kemi_hdr_getw_idx,
2494 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
2495 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2496 	},
2497 
2498 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
2499 };
2500 
2501 
2502 /**
2503  *
2504  */
sr_kemi_xval_null(sr_kemi_xval_t * xval,int rmode)2505 void sr_kemi_xval_null(sr_kemi_xval_t *xval, int rmode)
2506 {
2507 	switch(rmode) {
2508 		case SR_KEMI_XVAL_NULL_PRINT:
2509 			xval->vtype = SR_KEMIP_STR;
2510 			xval->v.s = *pv_get_null_str();
2511 			return;
2512 		case SR_KEMI_XVAL_NULL_EMPTY:
2513 			xval->vtype = SR_KEMIP_STR;
2514 			xval->v.s = *pv_get_empty_str();
2515 			return;
2516 		case SR_KEMI_XVAL_NULL_ZERO:
2517 			xval->vtype = SR_KEMIP_INT;
2518 			xval->v.n = 0;
2519 			return;
2520 		default:
2521 			xval->vtype = SR_KEMIP_NULL;
2522 			xval->v.s.s = NULL;
2523 			xval->v.s.len = 0;
2524 			return;
2525 	}
2526 }
2527 
2528 /**
2529  *
2530  */
sr_kemi_dict_item_free(sr_kemi_dict_item_t * item)2531 void sr_kemi_dict_item_free(sr_kemi_dict_item_t *item)
2532 {
2533 	sr_kemi_dict_item_t *v;
2534 
2535 	while(item) {
2536 		if (item->vtype == SR_KEMIP_ARRAY || item->vtype == SR_KEMIP_DICT) {
2537 			sr_kemi_dict_item_free(item->v.dict);
2538 		}
2539 		v = item;
2540 		item = item->next;
2541 		pkg_free(v);
2542 	}
2543 }
2544 
2545 /**
2546  *
2547  */
sr_kemi_xval_free(sr_kemi_xval_t * xval)2548 void sr_kemi_xval_free(sr_kemi_xval_t *xval)
2549 {
2550 	if(xval && (xval->vtype == SR_KEMIP_ARRAY || xval->vtype == SR_KEMIP_DICT))
2551 	{
2552 		sr_kemi_dict_item_free(xval->v.dict);
2553 	}
2554 }
2555 
2556 /**
2557  *
2558  */
sr_kemi_pv_get_mode(sip_msg_t * msg,str * pvn,int rmode)2559 static sr_kemi_xval_t* sr_kemi_pv_get_mode(sip_msg_t *msg, str *pvn, int rmode)
2560 {
2561 	pv_spec_t *pvs;
2562 	pv_value_t val;
2563 	int pl;
2564 
2565 	memset(&_sr_kemi_xval, 0, sizeof(sr_kemi_xval_t));
2566 
2567 	LM_DBG("pv get: %.*s\n", pvn->len, pvn->s);
2568 	pl = pv_locate_name(pvn);
2569 	if(pl != pvn->len) {
2570 		LM_ERR("invalid pv [%.*s] (%d/%d)\n", pvn->len, pvn->s, pl, pvn->len);
2571 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2572 		return &_sr_kemi_xval;
2573 	}
2574 	pvs = pv_cache_get(pvn);
2575 	if(pvs==NULL) {
2576 		LM_ERR("cannot get pv spec for [%.*s]\n", pvn->len, pvn->s);
2577 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2578 		return &_sr_kemi_xval;
2579 	}
2580 
2581 	memset(&val, 0, sizeof(pv_value_t));
2582 	if(pv_get_spec_value(msg, pvs, &val) != 0) {
2583 		LM_ERR("unable to get pv value for [%.*s]\n", pvn->len, pvn->s);
2584 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2585 		return &_sr_kemi_xval;
2586 	}
2587 	if(val.flags&PV_VAL_NULL) {
2588 		sr_kemi_xval_null(&_sr_kemi_xval, rmode);
2589 		return &_sr_kemi_xval;
2590 	}
2591 	if(val.flags&PV_TYPE_INT) {
2592 		_sr_kemi_xval.vtype = SR_KEMIP_INT;
2593 		_sr_kemi_xval.v.n = val.ri;
2594 		return &_sr_kemi_xval;
2595 	}
2596 	_sr_kemi_xval.vtype = SR_KEMIP_STR;
2597 	_sr_kemi_xval.v.s = val.rs;
2598 	return &_sr_kemi_xval;
2599 }
2600 
2601 /**
2602  *
2603  */
sr_kemi_pv_get(sip_msg_t * msg,str * pvn)2604 static sr_kemi_xval_t* sr_kemi_pv_get(sip_msg_t *msg, str *pvn)
2605 {
2606 	return sr_kemi_pv_get_mode(msg, pvn, SR_KEMI_XVAL_NULL_NONE);
2607 }
2608 
2609 /**
2610  *
2611  */
sr_kemi_pv_getw(sip_msg_t * msg,str * pvn)2612 static sr_kemi_xval_t* sr_kemi_pv_getw(sip_msg_t *msg, str *pvn)
2613 {
2614 	return sr_kemi_pv_get_mode(msg, pvn, SR_KEMI_XVAL_NULL_PRINT);
2615 }
2616 
2617 /**
2618  *
2619  */
sr_kemi_pv_gete(sip_msg_t * msg,str * pvn)2620 static sr_kemi_xval_t* sr_kemi_pv_gete(sip_msg_t *msg, str *pvn)
2621 {
2622 	return sr_kemi_pv_get_mode(msg, pvn, SR_KEMI_XVAL_NULL_EMPTY);
2623 }
2624 
2625 /**
2626  *
2627  */
sr_kemi_pv_push_valx(sr_kemi_xval_t * xval,int rmode,int vi,str * vs)2628 static void sr_kemi_pv_push_valx (sr_kemi_xval_t *xval, int rmode, int vi, str *vs)
2629 {
2630 	if(rmode==1) {
2631 		xval->vtype = SR_KEMIP_INT;
2632 		xval->v.n = vi;
2633 	} else {
2634 		xval->vtype = SR_KEMIP_STR;
2635 		xval->v.s = *vs;
2636 	}
2637 }
2638 
2639 /**
2640  *
2641  */
sr_kemi_pv_get_valx(sip_msg_t * msg,str * pvn,str * xsval,int xival,int rmode)2642 static sr_kemi_xval_t* sr_kemi_pv_get_valx (sip_msg_t *msg, str *pvn, str *xsval,
2643 		int xival, int rmode)
2644 {
2645 	pv_spec_t *pvs;
2646 	pv_value_t val;
2647 	int pl;
2648 
2649 	memset(&_sr_kemi_xval, 0, sizeof(sr_kemi_xval_t));
2650 
2651 	LM_DBG("pv get: %.*s\n", pvn->len, pvn->s);
2652 	pl = pv_locate_name(pvn);
2653 	if(pl != pvn->len) {
2654 		LM_ERR("invalid pv [%.*s] (%d/%d)\n", pvn->len, pvn->s, pl, pvn->len);
2655 		sr_kemi_pv_push_valx(&_sr_kemi_xval, rmode, xival, xsval);
2656 		return &_sr_kemi_xval;
2657 	}
2658 	pvs = pv_cache_get(pvn);
2659 	if(pvs==NULL) {
2660 		LM_ERR("cannot get pv spec for [%.*s]\n", pvn->len, pvn->s);
2661 		sr_kemi_pv_push_valx(&_sr_kemi_xval, rmode, xival, xsval);
2662 		return &_sr_kemi_xval;
2663 	}
2664 
2665 	memset(&val, 0, sizeof(pv_value_t));
2666 	if(pv_get_spec_value(msg, pvs, &val) != 0) {
2667 		LM_ERR("unable to get pv value for [%.*s]\n", pvn->len, pvn->s);
2668 		sr_kemi_pv_push_valx(&_sr_kemi_xval, rmode, xival, xsval);
2669 		return &_sr_kemi_xval;
2670 	}
2671 	if(val.flags&PV_VAL_NULL) {
2672 		sr_kemi_pv_push_valx(&_sr_kemi_xval, rmode, xival, xsval);
2673 		return &_sr_kemi_xval;
2674 	}
2675 	if(val.flags&PV_TYPE_INT) {
2676 		_sr_kemi_xval.vtype = SR_KEMIP_INT;
2677 		_sr_kemi_xval.v.n = val.ri;
2678 		return &_sr_kemi_xval;
2679 	}
2680 	_sr_kemi_xval.vtype = SR_KEMIP_STR;
2681 	_sr_kemi_xval.v.s = val.rs;
2682 	return &_sr_kemi_xval;
2683 }
2684 
2685 /**
2686  *
2687  */
sr_kemi_pv_getvs(sip_msg_t * msg,str * pvn,str * xsval)2688 static sr_kemi_xval_t* sr_kemi_pv_getvs (sip_msg_t *msg, str *pvn, str *xsval)
2689 {
2690 	return sr_kemi_pv_get_valx (msg, pvn, xsval, 0, 0);
2691 }
2692 
2693 /**
2694  *
2695  */
sr_kemi_pv_getvn(sip_msg_t * msg,str * pvn,int xival)2696 static sr_kemi_xval_t* sr_kemi_pv_getvn (sip_msg_t *msg, str *pvn, int xival)
2697 {
2698 	return sr_kemi_pv_get_valx (msg, pvn, NULL, xival, 1);
2699 }
2700 
2701 /**
2702  *
2703  */
sr_kemi_pv_seti(sip_msg_t * msg,str * pvn,int ival)2704 static int sr_kemi_pv_seti (sip_msg_t *msg, str *pvn, int ival)
2705 {
2706 	pv_spec_t *pvs;
2707 	pv_value_t val;
2708 	int pl;
2709 
2710 	LM_DBG("pv get: %.*s\n", pvn->len, pvn->s);
2711 	pl = pv_locate_name(pvn);
2712 	if(pl != pvn->len) {
2713 		LM_ERR("invalid pv [%.*s] (%d/%d)\n", pvn->len, pvn->s, pl, pvn->len);
2714 		return SR_KEMI_FALSE;
2715 	}
2716 	pvs = pv_cache_get(pvn);
2717 	if(pvs==NULL) {
2718 		LM_ERR("cannot get pv spec for [%.*s]\n", pvn->len, pvn->s);
2719 		return SR_KEMI_FALSE;
2720 	}
2721 
2722 	memset(&val, 0, sizeof(pv_value_t));
2723 	val.ri = ival;
2724 	val.flags |= PV_TYPE_INT|PV_VAL_INT;
2725 
2726 	if(pv_set_spec_value(msg, pvs, 0, &val)<0) {
2727 		LM_ERR("unable to set pv [%.*s]\n", pvn->len, pvn->s);
2728 		return SR_KEMI_FALSE;
2729 	}
2730 
2731 	return SR_KEMI_TRUE;
2732 }
2733 
2734 /**
2735  *
2736  */
sr_kemi_pv_sets(sip_msg_t * msg,str * pvn,str * sval)2737 static int sr_kemi_pv_sets (sip_msg_t *msg, str *pvn, str *sval)
2738 {
2739 	pv_spec_t *pvs;
2740 	pv_value_t val;
2741 	int pl;
2742 
2743 	LM_DBG("pv set: %.*s\n", pvn->len, pvn->s);
2744 	pl = pv_locate_name(pvn);
2745 	if(pl != pvn->len) {
2746 		LM_ERR("invalid pv [%.*s] (%d/%d)\n", pvn->len, pvn->s, pl, pvn->len);
2747 		return SR_KEMI_FALSE;
2748 	}
2749 	pvs = pv_cache_get(pvn);
2750 	if(pvs==NULL) {
2751 		LM_ERR("cannot get pv spec for [%.*s]\n", pvn->len, pvn->s);
2752 		return SR_KEMI_FALSE;
2753 	}
2754 
2755 	memset(&val, 0, sizeof(pv_value_t));
2756 	val.rs = *sval;
2757 	val.flags |= PV_VAL_STR;
2758 
2759 	if(pv_set_spec_value(msg, pvs, 0, &val)<0) {
2760 		LM_ERR("unable to set pv [%.*s]\n", pvn->len, pvn->s);
2761 		return SR_KEMI_FALSE;
2762 	}
2763 
2764 	return SR_KEMI_TRUE;
2765 }
2766 
2767 /**
2768  *
2769  */
sr_kemi_pv_unset(sip_msg_t * msg,str * pvn)2770 static int sr_kemi_pv_unset (sip_msg_t *msg, str *pvn)
2771 {
2772 	pv_spec_t *pvs;
2773 	pv_value_t val;
2774 	int pl;
2775 
2776 	LM_DBG("pv unset: %.*s\n", pvn->len, pvn->s);
2777 	pl = pv_locate_name(pvn);
2778 	if(pl != pvn->len) {
2779 		LM_ERR("invalid pv [%.*s] (%d/%d)\n", pvn->len, pvn->s, pl, pvn->len);
2780 		return SR_KEMI_FALSE;
2781 	}
2782 	pvs = pv_cache_get(pvn);
2783 	if(pvs==NULL) {
2784 		LM_ERR("cannot get pv spec for [%.*s]\n", pvn->len, pvn->s);
2785 		return SR_KEMI_FALSE;
2786 	}
2787 	memset(&val, 0, sizeof(pv_value_t));
2788 	val.flags |= PV_VAL_NULL;
2789 	if(pv_set_spec_value(msg, pvs, 0, &val)<0) {
2790 		LM_ERR("unable to unset pv [%.*s]\n", pvn->len, pvn->s);
2791 		return SR_KEMI_FALSE;
2792 	}
2793 
2794 	return SR_KEMI_TRUE;
2795 }
2796 
2797 /**
2798  *
2799  */
sr_kemi_pv_is_null(sip_msg_t * msg,str * pvn)2800 static int sr_kemi_pv_is_null (sip_msg_t *msg, str *pvn)
2801 {
2802 	pv_spec_t *pvs;
2803 	pv_value_t val;
2804 	int pl;
2805 
2806 	LM_DBG("pv is null test: %.*s\n", pvn->len, pvn->s);
2807 	pl = pv_locate_name(pvn);
2808 	if(pl != pvn->len) {
2809 		LM_ERR("invalid pv [%.*s] (%d/%d)\n", pvn->len, pvn->s, pl, pvn->len);
2810 		return SR_KEMI_TRUE;
2811 	}
2812 	pvs = pv_cache_get(pvn);
2813 	if(pvs==NULL) {
2814 		LM_ERR("cannot get pv spec for [%.*s]\n", pvn->len, pvn->s);
2815 		return SR_KEMI_TRUE;
2816 	}
2817 
2818 	memset(&val, 0, sizeof(pv_value_t));
2819 	if(pv_get_spec_value(msg, pvs, &val) != 0) {
2820 		LM_NOTICE("unable to get pv value for [%.*s]\n", pvn->len, pvn->s);
2821 		return SR_KEMI_TRUE;
2822 	}
2823 	if(val.flags&PV_VAL_NULL) {
2824 		return SR_KEMI_TRUE;
2825 	} else {
2826 		return SR_KEMI_FALSE;
2827 	}
2828 }
2829 
2830 /**
2831  *
2832  */
2833 static sr_kemi_t _sr_kemi_pv[] = {
2834 	{ str_init("pv"), str_init("get"),
2835 		SR_KEMIP_XVAL, sr_kemi_pv_get,
2836 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2837 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2838 	},
2839 	{ str_init("pv"), str_init("getw"),
2840 		SR_KEMIP_XVAL, sr_kemi_pv_getw,
2841 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2842 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2843 	},
2844 	{ str_init("pv"), str_init("gete"),
2845 		SR_KEMIP_XVAL, sr_kemi_pv_gete,
2846 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2847 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2848 	},
2849 	{ str_init("pv"), str_init("getvn"),
2850 		SR_KEMIP_XVAL, sr_kemi_pv_getvn,
2851 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
2852 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2853 	},
2854 	{ str_init("pv"), str_init("getvs"),
2855 		SR_KEMIP_XVAL, sr_kemi_pv_getvs,
2856 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2857 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2858 	},
2859 	{ str_init("pv"), str_init("seti"),
2860 		SR_KEMIP_BOOL, sr_kemi_pv_seti,
2861 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
2862 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2863 	},
2864 	{ str_init("pv"), str_init("sets"),
2865 		SR_KEMIP_BOOL, sr_kemi_pv_sets,
2866 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
2867 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2868 	},
2869 	{ str_init("pv"), str_init("unset"),
2870 		SR_KEMIP_BOOL, sr_kemi_pv_unset,
2871 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2872 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2873 	},
2874 	{ str_init("pv"), str_init("is_null"),
2875 		SR_KEMIP_BOOL, sr_kemi_pv_is_null,
2876 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2877 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2878 	},
2879 
2880 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
2881 };
2882 
2883 /**
2884  *
2885  */
sr_kemi_exports_get_pv(void)2886 sr_kemi_t* sr_kemi_exports_get_pv(void)
2887 {
2888 	return _sr_kemi_pv;
2889 }
2890 
2891 #define SR_KEMI_MODULES_MAX_SIZE	1024
2892 static int _sr_kemi_modules_size = 0;
2893 static sr_kemi_module_t _sr_kemi_modules[SR_KEMI_MODULES_MAX_SIZE];
2894 
2895 /**
2896  *
2897  */
sr_kemi_modules_add(sr_kemi_t * klist)2898 int sr_kemi_modules_add(sr_kemi_t *klist)
2899 {
2900 	if(_sr_kemi_modules_size>=SR_KEMI_MODULES_MAX_SIZE) {
2901 		LM_ERR("exceeded max number of modules\n");
2902 		return -1;
2903 	}
2904 	if(_sr_kemi_modules_size==0) {
2905 		LM_DBG("adding core module\n");
2906 		_sr_kemi_modules[_sr_kemi_modules_size].mname = _sr_kemi_core[0].mname;
2907 		_sr_kemi_modules[_sr_kemi_modules_size].kexp = _sr_kemi_core;
2908 		_sr_kemi_modules_size++;
2909 		LM_DBG("adding pv module\n");
2910 		_sr_kemi_modules[_sr_kemi_modules_size].mname = _sr_kemi_pv[0].mname;
2911 		_sr_kemi_modules[_sr_kemi_modules_size].kexp = _sr_kemi_pv;
2912 		_sr_kemi_modules_size++;
2913 		LM_DBG("adding hdr module\n");
2914 		_sr_kemi_modules[_sr_kemi_modules_size].mname = _sr_kemi_hdr[0].mname;
2915 		_sr_kemi_modules[_sr_kemi_modules_size].kexp = _sr_kemi_hdr;
2916 		_sr_kemi_modules_size++;
2917 	}
2918 	if((_sr_kemi_modules_size>1)
2919 			&& (_sr_kemi_modules[_sr_kemi_modules_size-1].mname.len
2920 					==klist[0].mname.len)
2921 			&& (strncmp(_sr_kemi_modules[_sr_kemi_modules_size-1].mname.s,
2922 					klist[0].mname.s, klist[0].mname.len)==0)) {
2923 		/* handle re-open of the module */
2924 		LM_DBG("updating module: %.*s\n", klist[0].mname.len, klist[0].mname.s);
2925 		_sr_kemi_modules[_sr_kemi_modules_size-1].kexp = klist;
2926 	} else {
2927 		LM_DBG("adding module: %.*s\n", klist[0].mname.len, klist[0].mname.s);
2928 		_sr_kemi_modules[_sr_kemi_modules_size].mname = klist[0].mname;
2929 		_sr_kemi_modules[_sr_kemi_modules_size].kexp = klist;
2930 		_sr_kemi_modules_size++;
2931 	}
2932 	return 0;
2933 }
2934 
2935 /**
2936  *
2937  */
sr_kemi_modules_size_get(void)2938 int sr_kemi_modules_size_get(void)
2939 {
2940 	return _sr_kemi_modules_size;
2941 }
2942 
2943 /**
2944  *
2945  */
sr_kemi_modules_get(void)2946 sr_kemi_module_t* sr_kemi_modules_get(void)
2947 {
2948 	return _sr_kemi_modules;
2949 }
2950 
2951 /**
2952  *
2953  */
sr_kemi_lookup(str * mname,int midx,str * fname)2954 sr_kemi_t* sr_kemi_lookup(str *mname, int midx, str *fname)
2955 {
2956 	int i;
2957 	sr_kemi_t *ket;
2958 
2959 	if(mname==NULL || mname->len<=0) {
2960 		for(i=0; _sr_kemi_core[i].fname.s!=NULL; i++) {
2961 			ket = &_sr_kemi_core[i];
2962 			if(ket->fname.len==fname->len
2963 					&& strncasecmp(ket->fname.s, fname->s, fname->len)==0) {
2964 				return ket;
2965 			}
2966 		}
2967 	} else {
2968 		if(midx>0 && midx<SR_KEMI_MODULES_MAX_SIZE) {
2969 			for(i=0; _sr_kemi_modules[midx].kexp[i].fname.s!=NULL; i++) {
2970 				ket = &_sr_kemi_modules[midx].kexp[i];
2971 				if(ket->fname.len==fname->len
2972 						&& strncasecmp(ket->fname.s, fname->s, fname->len)==0) {
2973 					return ket;
2974 				}
2975 			}
2976 		}
2977 	}
2978 	return NULL;
2979 }
2980 
2981 /**
2982  *
2983  */
2984 
2985 #define SR_KEMI_ENG_LIST_MAX_SIZE	8
2986 static sr_kemi_eng_t _sr_kemi_eng_list[SR_KEMI_ENG_LIST_MAX_SIZE];
2987 sr_kemi_eng_t *_sr_kemi_eng = NULL;
2988 static int _sr_kemi_eng_list_size=0;
2989 
2990 /**
2991  *
2992  */
sr_kemi_eng_register(str * ename,sr_kemi_eng_route_f froute)2993 int sr_kemi_eng_register(str *ename, sr_kemi_eng_route_f froute)
2994 {
2995 	int i;
2996 
2997 	for(i=0; i<_sr_kemi_eng_list_size; i++) {
2998 		if(_sr_kemi_eng_list[i].ename.len==ename->len
2999 				&& strncasecmp(_sr_kemi_eng_list[i].ename.s, ename->s,
3000 					ename->len)==0) {
3001 			/* found */
3002 			return 1;
3003 		}
3004 	}
3005 	if(_sr_kemi_eng_list_size>=SR_KEMI_ENG_LIST_MAX_SIZE) {
3006 		LM_ERR("too many config routing engines registered\n");
3007 		return -1;
3008 	}
3009 	if(ename->len>=SR_KEMI_BNAME_SIZE) {
3010 		LM_ERR("config routing engine name too long\n");
3011 		return -1;
3012 	}
3013 	strncpy(_sr_kemi_eng_list[_sr_kemi_eng_list_size].bname,
3014 			ename->s, ename->len);
3015 	_sr_kemi_eng_list[_sr_kemi_eng_list_size].ename.s
3016 			= _sr_kemi_eng_list[_sr_kemi_eng_list_size].bname;
3017 	_sr_kemi_eng_list[_sr_kemi_eng_list_size].ename.len = ename->len;
3018 	_sr_kemi_eng_list[_sr_kemi_eng_list_size].ename.s[ename->len] = 0;
3019 	_sr_kemi_eng_list[_sr_kemi_eng_list_size].froute = froute;
3020 	_sr_kemi_eng_list_size++;
3021 
3022 	LM_DBG("registered config routing enginge [%.*s]\n",
3023 			ename->len, ename->s);
3024 
3025 	return 0;
3026 }
3027 
3028 /**
3029  *
3030  */
sr_kemi_eng_set(str * ename,str * cpath)3031 int sr_kemi_eng_set(str *ename, str *cpath)
3032 {
3033 	int i;
3034 
3035 	/* skip native and default */
3036 	if(ename->len==6 && strncasecmp(ename->s, "native", 6)==0) {
3037 		return 0;
3038 	}
3039 	if(ename->len==7 && strncasecmp(ename->s, "default", 7)==0) {
3040 		return 0;
3041 	}
3042 
3043 	if(sr_kemi_cbname_list_init()<0) {
3044 		return -1;
3045 	}
3046 
3047 	for(i=0; i<_sr_kemi_eng_list_size; i++) {
3048 		if(_sr_kemi_eng_list[i].ename.len==ename->len
3049 				&& strncasecmp(_sr_kemi_eng_list[i].ename.s, ename->s,
3050 					ename->len)==0) {
3051 			/* found */
3052 			_sr_kemi_eng = &_sr_kemi_eng_list[i];
3053 			return 0;
3054 		}
3055 	}
3056 	return -1;
3057 }
3058 
3059 /**
3060  *
3061  */
sr_kemi_eng_setz(char * ename,char * cpath)3062 int sr_kemi_eng_setz(char *ename, char *cpath)
3063 {
3064 	str sname;
3065 	str spath;
3066 
3067 	sname.s = ename;
3068 	sname.len = strlen(ename);
3069 
3070 	if(cpath!=0) {
3071 		spath.s = cpath;
3072 		spath.len = strlen(cpath);
3073 		return sr_kemi_eng_set(&sname, &spath);
3074 	} else {
3075 		return sr_kemi_eng_set(&sname, NULL);
3076 	}
3077 }
3078 
3079 /**
3080  *
3081  */
sr_kemi_eng_get(void)3082 sr_kemi_eng_t* sr_kemi_eng_get(void)
3083 {
3084 	return _sr_kemi_eng;
3085 }
3086 
3087 /**
3088  *
3089  */
3090 #define KEMI_CBNAME_MAX_LEN	128
3091 #define KEMI_CBNAME_LIST_SIZE	256
3092 
3093 typedef struct sr_kemi_cbname {
3094 	str name;
3095 	char bname[KEMI_CBNAME_MAX_LEN];
3096 } sr_kemi_cbname_t;
3097 
3098 static gen_lock_t *_sr_kemi_cbname_lock = 0;
3099 static sr_kemi_cbname_t *_sr_kemi_cbname_list = NULL;
3100 static int *_sr_kemi_cbname_list_size = NULL;
3101 
3102 /**
3103  *
3104  */
sr_kemi_cbname_list_init(void)3105 int sr_kemi_cbname_list_init(void)
3106 {
3107 	if(_sr_kemi_cbname_list!=NULL) {
3108 		return 0;
3109 	}
3110 	if ( (_sr_kemi_cbname_lock=lock_alloc())==0) {
3111 		LM_CRIT("failed to alloc lock\n");
3112 		return -1;
3113 	}
3114 	if (lock_init(_sr_kemi_cbname_lock)==0 ) {
3115 		LM_CRIT("failed to init lock\n");
3116 		lock_dealloc(_sr_kemi_cbname_lock);
3117 		_sr_kemi_cbname_lock = NULL;
3118 		return -1;
3119 	}
3120 	_sr_kemi_cbname_list_size = shm_malloc(sizeof(int));
3121 	if(_sr_kemi_cbname_list_size==NULL) {
3122 		lock_destroy(_sr_kemi_cbname_lock);
3123 		lock_dealloc(_sr_kemi_cbname_lock);
3124 		SHM_MEM_ERROR;
3125 		return -1;
3126 	}
3127 	*_sr_kemi_cbname_list_size = 0;
3128 	_sr_kemi_cbname_list
3129 			= shm_malloc(KEMI_CBNAME_LIST_SIZE*sizeof(sr_kemi_cbname_t));
3130 	if(_sr_kemi_cbname_list==NULL) {
3131 		SHM_MEM_ERROR;
3132 		shm_free(_sr_kemi_cbname_list_size);
3133 		_sr_kemi_cbname_list_size = NULL;
3134 		lock_destroy(_sr_kemi_cbname_lock);
3135 		lock_dealloc(_sr_kemi_cbname_lock);
3136 		_sr_kemi_cbname_lock = NULL;
3137 		return -1;
3138 	}
3139 	memset(_sr_kemi_cbname_list, 0,
3140 			KEMI_CBNAME_LIST_SIZE*sizeof(sr_kemi_cbname_t));
3141 	return 0;
3142 }
3143 
3144 /**
3145  *
3146  */
sr_kemi_cbname_lookup_name(str * name)3147 int sr_kemi_cbname_lookup_name(str *name)
3148 {
3149 	int n;
3150 	int i;
3151 
3152 	if(_sr_kemi_cbname_list==NULL) {
3153 		return 0;
3154 	}
3155 	if(name->len >= KEMI_CBNAME_MAX_LEN) {
3156 		LM_ERR("callback name is too long [%.*s] (max: %d)\n",
3157 				name->len, name->s, KEMI_CBNAME_MAX_LEN);
3158 		return 0;
3159 	}
3160 	n = *_sr_kemi_cbname_list_size;
3161 
3162 	for(i=0; i<n; i++) {
3163 		if(_sr_kemi_cbname_list[i].name.len==name->len
3164 				&& strncmp(_sr_kemi_cbname_list[i].name.s,
3165 						name->s, name->len)==0) {
3166 			return i+1;
3167 		}
3168 	}
3169 
3170 	/* not found -- add it */
3171 	lock_get(_sr_kemi_cbname_lock);
3172 
3173 	/* check if new callback were indexed meanwhile */
3174 	for(; i<*_sr_kemi_cbname_list_size; i++) {
3175 		if(_sr_kemi_cbname_list[i].name.len==name->len
3176 				&& strncmp(_sr_kemi_cbname_list[i].name.s,
3177 						name->s, name->len)==0) {
3178 			lock_release(_sr_kemi_cbname_lock);
3179 			return i+1;
3180 		}
3181 	}
3182 	if(*_sr_kemi_cbname_list_size>=KEMI_CBNAME_LIST_SIZE) {
3183 		lock_release(_sr_kemi_cbname_lock);
3184 		LM_ERR("no more space to index callbacks\n");
3185 		return 0;
3186 	}
3187 	strncpy(_sr_kemi_cbname_list[i].bname, name->s, name->len);
3188 	_sr_kemi_cbname_list[i].bname[name->len] = '\0';
3189 	_sr_kemi_cbname_list[i].name.s = _sr_kemi_cbname_list[i].bname;
3190 	_sr_kemi_cbname_list[i].name.len = name->len;
3191 	i++;
3192 	*_sr_kemi_cbname_list_size = i;
3193 	lock_release(_sr_kemi_cbname_lock);
3194 	return i;
3195 }
3196 
3197 /**
3198  *
3199  */
sr_kemi_cbname_lookup_idx(int idx)3200 str* sr_kemi_cbname_lookup_idx(int idx)
3201 {
3202 	int n;
3203 
3204 	if(_sr_kemi_cbname_list==NULL) {
3205 		return NULL;
3206 	}
3207 	n = *_sr_kemi_cbname_list_size;
3208 	if(idx<1 || idx>n) {
3209 		LM_ERR("index %d is out of range\n", idx);
3210 		return NULL;
3211 	}
3212 	return &_sr_kemi_cbname_list[idx-1].name;
3213 }
3214 
3215 /**
3216  *
3217  */
3218 typedef struct sr_kemi_param_map {
3219 	int ptype;
3220 	str pname;
3221 } sr_kemi_param_map_t;
3222 
3223 /**
3224  *
3225  */
3226 static sr_kemi_param_map_t _sr_kemi_param_map[] = {
3227 	{ SR_KEMIP_NONE,   str_init("none") },
3228 	{ SR_KEMIP_INT,    str_init("int") },
3229 	{ SR_KEMIP_STR,    str_init("str") },
3230 	{ SR_KEMIP_BOOL,   str_init("bool") },
3231 	{ SR_KEMIP_XVAL,   str_init("xval") },
3232 	{ 0, STR_NULL }
3233 };
3234 
3235 /**
3236  *
3237  */
sr_kemi_param_map_get_name(int ptype)3238 str *sr_kemi_param_map_get_name(int ptype)
3239 {
3240 	int i;
3241 
3242 	for(i=0; _sr_kemi_param_map[i].pname.s!=NULL; i++) {
3243 		if(_sr_kemi_param_map[i].ptype==ptype)
3244 			return &_sr_kemi_param_map[i].pname;
3245 	}
3246 	return NULL;
3247 }
3248 
3249 /**
3250  *
3251  */
sr_kemi_param_map_get_params(int * ptypes)3252 str *sr_kemi_param_map_get_params(int *ptypes)
3253 {
3254 	int i;
3255 	int l;
3256 #define KEMI_PARAM_MAP_SIZE 72
3257 	static char pbuf[KEMI_PARAM_MAP_SIZE];
3258 	static str sret = STR_NULL;
3259 	str *pn;
3260 
3261 	pbuf[0] = '\0';
3262 	l = 0;
3263 	for(i = 0; i < SR_KEMI_PARAMS_MAX; i++) {
3264 		if(ptypes[i] == SR_KEMIP_NONE)
3265 			break;
3266 		if(i > 0) {
3267 			l += 2;
3268 			if(l >= KEMI_PARAM_MAP_SIZE - 8) {
3269 				strcat(pbuf, ", ...");
3270 				goto done;
3271 			}
3272 			strcat(pbuf, ", ");
3273 		}
3274 		pn = sr_kemi_param_map_get_name(ptypes[i]);
3275 		if(pn == NULL)
3276 			return NULL;
3277 		l += pn->len;
3278 		if(l >= KEMI_PARAM_MAP_SIZE - 8) {
3279 			strcat(pbuf, ", ...");
3280 			goto done;
3281 		}
3282 		strcat(pbuf, pn->s);
3283 	}
3284 	if(pbuf[0]=='\0') {
3285 		pn = sr_kemi_param_map_get_name(SR_KEMIP_NONE);
3286 		if(pn == NULL)
3287 			return NULL;
3288 		if(pn->len<KEMI_PARAM_MAP_SIZE-1) strncat(pbuf, pn->s, pn->len);
3289 	}
3290 done:
3291 	sret.s = pbuf;
3292 	sret.len = strlen(sret.s);
3293 	return &sret;
3294 }
3295 
3296 /**
3297  *
3298  */
sr_kemi_route(sr_kemi_eng_t * keng,sip_msg_t * msg,int rtype,str * ename,str * edata)3299 int sr_kemi_route(sr_kemi_eng_t *keng, sip_msg_t *msg, int rtype,
3300 		str *ename, str *edata)
3301 {
3302 	flag_t sfbk;
3303 	int ret;
3304 
3305 	sfbk = getsflags();
3306 	setsflagsval(0);
3307 	reset_static_buffer();
3308 	ret = keng->froute(msg, rtype, ename, edata);
3309 	setsflagsval(sfbk);
3310 	return ret;
3311 }
3312 
3313 /**
3314  *
3315  */
sr_kemi_ctx_route(sr_kemi_eng_t * keng,run_act_ctx_t * ctx,sip_msg_t * msg,int rtype,str * ename,str * edata)3316 int sr_kemi_ctx_route(sr_kemi_eng_t *keng, run_act_ctx_t *ctx, sip_msg_t *msg,
3317 		int rtype, str *ename, str *edata)
3318 {
3319 	run_act_ctx_t *bctx;
3320 	int ret;
3321 
3322 	bctx = sr_kemi_act_ctx_get();
3323 	sr_kemi_act_ctx_set(ctx);
3324 	ret = sr_kemi_route(keng, msg, rtype, ename, edata);
3325 	sr_kemi_act_ctx_set(bctx);
3326 	return ret;
3327 }
3328