941c814ab04b37f3015a39f6da229855f6a01e98
[kamailio] / src / core / kemi.c
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 "mem/shm.h"
34 #include "parser/parse_uri.h"
35
36 #include "kemi.h"
37
38
39 /**
40  *
41  */
42 static run_act_ctx_t *_sr_kemi_act_ctx = NULL;
43
44 /**
45  *
46  */
47 void sr_kemi_act_ctx_set(run_act_ctx_t *ctx)
48 {
49         _sr_kemi_act_ctx = ctx;
50 }
51
52 /**
53  *
54  */
55 run_act_ctx_t* sr_kemi_act_ctx_get(void)
56 {
57         return _sr_kemi_act_ctx;
58 }
59
60 /**
61  *
62  */
63 static int sr_kemi_core_dbg(sip_msg_t *msg, str *txt)
64 {
65         if(txt!=NULL && txt->s!=NULL)
66                 LM_DBG("%.*s", txt->len, txt->s);
67         return 0;
68 }
69
70 /**
71  *
72  */
73 static int sr_kemi_core_err(sip_msg_t *msg, str *txt)
74 {
75         if(txt!=NULL && txt->s!=NULL)
76                 LM_ERR("%.*s", txt->len, txt->s);
77         return 0;
78 }
79
80 /**
81  *
82  */
83 static int sr_kemi_core_info(sip_msg_t *msg, str *txt)
84 {
85         if(txt!=NULL && txt->s!=NULL)
86                 LM_INFO("%.*s", txt->len, txt->s);
87         return 0;
88 }
89
90 /**
91  *
92  */
93 static int sr_kemi_core_log(sip_msg_t *msg, str *level, str *txt)
94 {
95         if(txt!=NULL && txt->s!=NULL) {
96                 if(level==NULL || level->s==NULL) {
97                         LM_ERR("%s", txt->s);
98                 } else {
99                         if(strcasecmp(level->s, "dbg")==0) {
100                                 LM_DBG("%s", txt->s);
101                         } else if(strcasecmp(level->s, "info")==0) {
102                                 LM_INFO("%s", txt->s);
103                         } else if(strcasecmp(level->s, "warn")==0) {
104                                 LM_WARN("%s", txt->s);
105                         } else if(strcasecmp(level->s, "crit")==0) {
106                                 LM_CRIT("%s", txt->s);
107                         } else {
108                                 LM_ERR("%s", txt->s);
109                         }
110                 }
111         }
112         return 0;
113 }
114
115 /**
116  *
117  */
118 int sr_kemi_core_drop(sip_msg_t *msg)
119 {
120         if(_sr_kemi_act_ctx==NULL)
121                 return 0;
122         LM_DBG("drop action executed inside embedded interpreter\n");
123         _sr_kemi_act_ctx->run_flags |= EXIT_R_F|DROP_R_F;
124         return 0;
125 }
126
127 /**
128  *
129  */
130 static int sr_kemi_core_is_myself(sip_msg_t *msg, str *uri)
131 {
132         struct sip_uri puri;
133         int ret;
134
135         if(uri==NULL || uri->s==NULL) {
136                 return SR_KEMI_FALSE;
137         }
138         if(uri->len>4 && (strncmp(uri->s, "sip:", 4)==0
139                                 || strncmp(uri->s, "sips:", 5)==0)) {
140                 if(parse_uri(uri->s, uri->len, &puri)!=0) {
141                         LM_ERR("failed to parse uri [%.*s]\n", uri->len, uri->s);
142                         return SR_KEMI_FALSE;
143                 }
144                 ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
145                                 (puri.transport_val.s)?puri.proto:0);
146         } else {
147                 ret = check_self(uri, 0, 0);
148         }
149         if(ret==1) {
150                 return SR_KEMI_TRUE;
151         }
152         return SR_KEMI_FALSE;
153 }
154
155 /**
156  *
157  */
158 static int sr_kemi_core_setflag(sip_msg_t *msg, int flag)
159 {
160         if(msg==NULL) {
161                 LM_WARN("invalid msg parameter\n");
162                 return SR_KEMI_FALSE;
163         }
164
165         if (!flag_in_range(flag)) {
166                 LM_ERR("invalid flag parameter %d\n", flag);
167                 return SR_KEMI_FALSE;
168         }
169
170         setflag(msg, flag);
171         return SR_KEMI_TRUE;
172 }
173
174 /**
175  *
176  */
177 static int sr_kemi_core_resetflag(sip_msg_t *msg, int flag)
178 {
179         if(msg==NULL) {
180                 LM_WARN("invalid msg parameter\n");
181                 return SR_KEMI_FALSE;
182         }
183
184         if (!flag_in_range(flag)) {
185                 LM_ERR("invalid flag parameter %d\n", flag);
186                 return SR_KEMI_FALSE;
187         }
188
189         resetflag(msg, flag);
190         return SR_KEMI_TRUE;
191 }
192
193 /**
194  *
195  */
196 static int sr_kemi_core_isflagset(sip_msg_t *msg, int flag)
197 {
198         int ret;
199
200         if(msg==NULL) {
201                 LM_WARN("invalid msg parameter\n");
202                 return SR_KEMI_FALSE;
203         }
204
205         if (!flag_in_range(flag)) {
206                 LM_ERR("invalid flag parameter %d\n", flag);
207                 return SR_KEMI_FALSE;
208         }
209
210         ret = isflagset(msg, flag);
211         if(ret>0)
212                 return SR_KEMI_TRUE;
213         return SR_KEMI_FALSE;
214 }
215
216 /**
217  *
218  */
219 static int sr_kemi_core_setbiflag(sip_msg_t *msg, int flag, int branch)
220 {
221         if(msg==NULL) {
222                 LM_WARN("invalid msg parameter\n");
223                 return SR_KEMI_FALSE;
224         }
225
226         if (!flag_in_range(flag)) {
227                 LM_ERR("invalid flag parameter %d\n", flag);
228                 return SR_KEMI_FALSE;
229         }
230
231         setbflag(branch, flag);
232         return SR_KEMI_TRUE;
233 }
234
235 /**
236  *
237  */
238 static int sr_kemi_core_resetbiflag(sip_msg_t *msg, int flag, int branch)
239 {
240         if(msg==NULL) {
241                 LM_WARN("invalid msg parameter\n");
242                 return SR_KEMI_FALSE;
243         }
244
245         if (!flag_in_range(flag)) {
246                 LM_ERR("invalid flag parameter %d\n", flag);
247                 return SR_KEMI_FALSE;
248         }
249
250         resetbflag(branch, flag);
251         return SR_KEMI_TRUE;
252 }
253
254 /**
255  *
256  */
257 static int sr_kemi_core_isbiflagset(sip_msg_t *msg, int flag, int branch)
258 {
259         int ret;
260
261         if(msg==NULL) {
262                 LM_WARN("invalid msg parameter\n");
263                 return SR_KEMI_FALSE;
264         }
265
266         if (!flag_in_range(flag)) {
267                 LM_ERR("invalid flag parameter %d\n", flag);
268                 return SR_KEMI_FALSE;
269         }
270
271         ret = isbflagset(branch, flag);
272         if(ret>0)
273                 return SR_KEMI_TRUE;
274         return SR_KEMI_FALSE;
275 }
276
277 /**
278  *
279  */
280 static int sr_kemi_core_setbflag(sip_msg_t *msg, int flag)
281 {
282         return sr_kemi_core_setbiflag(msg, flag, 0);
283 }
284
285 /**
286  *
287  */
288 static int sr_kemi_core_resetbflag(sip_msg_t *msg, int flag)
289 {
290         return sr_kemi_core_resetbiflag(msg, flag, 0);
291 }
292
293 /**
294  *
295  */
296 static int sr_kemi_core_isbflagset(sip_msg_t *msg, int flag)
297 {
298         return sr_kemi_core_isbiflagset(msg, flag, 0);
299 }
300
301 /**
302  *
303  */
304 static int sr_kemi_core_setsflag(sip_msg_t *msg, int flag)
305 {
306         if (!flag_in_range(flag)) {
307                 LM_ERR("invalid flag parameter %d\n", flag);
308                 return SR_KEMI_FALSE;
309         }
310
311         setsflag(flag);
312         return SR_KEMI_TRUE;
313 }
314
315 /**
316  *
317  */
318 static int sr_kemi_core_resetsflag(sip_msg_t *msg, int flag)
319 {
320         if (!flag_in_range(flag)) {
321                 LM_ERR("invalid flag parameter %d\n", flag);
322                 return SR_KEMI_FALSE;
323         }
324
325         resetsflag(flag);
326         return SR_KEMI_TRUE;
327 }
328
329 /**
330  *
331  */
332 static int sr_kemi_core_issflagset(sip_msg_t *msg, int flag)
333 {
334         int ret;
335
336         if (!flag_in_range(flag)) {
337                 LM_ERR("invalid flag parameter %d\n", flag);
338                 return SR_KEMI_FALSE;
339         }
340
341         ret = issflagset(flag);
342         if(ret>0)
343                 return SR_KEMI_TRUE;
344         return SR_KEMI_FALSE;
345 }
346
347 /**
348  *
349  */
350 static int sr_kemi_core_seturi(sip_msg_t *msg, str *uri)
351 {
352         if(uri==NULL || uri->s==NULL) {
353                 LM_ERR("invalid uri parameter\n");
354                 return SR_KEMI_FALSE;
355         }
356
357         if(msg==NULL) {
358                 LM_WARN("invalid msg parameter\n");
359                 return SR_KEMI_FALSE;
360         }
361
362         if(rewrite_uri(msg, uri)<0) {
363                 LM_ERR("updating r-uri failed\n");
364                 return SR_KEMI_FALSE;
365         }
366         return SR_KEMI_TRUE;
367 }
368
369 /**
370  *
371  */
372 static int sr_kemi_core_setuser(sip_msg_t *msg, str *user)
373 {
374         struct action  act;
375         struct run_act_ctx h;
376
377         if(user==NULL || user->s==NULL) {
378                 LM_ERR("invalid user parameter\n");
379                 return SR_KEMI_FALSE;
380         }
381
382         if(msg==NULL) {
383                 LM_WARN("invalid user parameter\n");
384                 return SR_KEMI_FALSE;
385         }
386
387         memset(&act, 0, sizeof(act));
388         act.val[0].type = STRING_ST;
389         act.val[0].u.string = user->s;
390         act.type = SET_USER_T;
391         init_run_actions_ctx(&h);
392         if (do_action(&h, &act, msg)<0) {
393                 LM_ERR("do action failed\n");
394                 return SR_KEMI_FALSE;
395         }
396         return SR_KEMI_TRUE;
397 }
398
399 /**
400  *
401  */
402 static int sr_kemi_core_sethost(sip_msg_t *msg, str *host)
403 {
404         struct action  act;
405         struct run_act_ctx h;
406
407         if(host==NULL || host->s==NULL) {
408                 LM_ERR("invalid host parameter\n");
409                 return SR_KEMI_FALSE;
410         }
411
412         if(msg==NULL) {
413                 LM_WARN("invalid msg parameter\n");
414                 return SR_KEMI_FALSE;
415         }
416
417         memset(&act, 0, sizeof(act));
418         act.val[0].type = STRING_ST;
419         act.val[0].u.string = host->s;
420         act.type = SET_HOST_T;
421         init_run_actions_ctx(&h);
422         if (do_action(&h, &act, msg)<0)
423         {
424                 LM_ERR("do action failed\n");
425                 return SR_KEMI_FALSE;
426         }
427         return SR_KEMI_TRUE;
428 }
429
430 /**
431  *
432  */
433 static int sr_kemi_core_setdsturi(sip_msg_t *msg, str *uri)
434 {
435         if(uri==NULL || uri->s==NULL) {
436                 LM_ERR("invalid uri parameter\n");
437                 return SR_KEMI_FALSE;
438         }
439
440         if(msg==NULL) {
441                 LM_WARN("invalid msg parameter\n");
442                 return SR_KEMI_FALSE;
443         }
444
445         if(set_dst_uri(msg, uri)<0) {
446                 LM_ERR("setting dst uri failed\n");
447                 return SR_KEMI_TRUE;
448         }
449         return SR_KEMI_TRUE;
450 }
451
452 /**
453  *
454  */
455 static int sr_kemi_core_resetdsturi(sip_msg_t *msg)
456 {
457         if(msg==NULL) {
458                 LM_WARN("invalid msg parameter\n");
459                 return SR_KEMI_FALSE;
460         }
461
462         reset_dst_uri(msg);
463         return SR_KEMI_TRUE;
464 }
465
466 /**
467  *
468  */
469 static int sr_kemi_core_isdsturiset(sip_msg_t *msg)
470 {
471         if(msg==NULL) {
472                 LM_WARN("invalid msg parameter\n");
473                 return SR_KEMI_FALSE;
474         }
475
476         if(msg->dst_uri.s!=NULL && msg->dst_uri.len>0) {
477                 return SR_KEMI_TRUE;
478         }
479         return SR_KEMI_FALSE;
480 }
481
482 /**
483  *
484  */
485 static int sr_kemi_core_force_rport(sip_msg_t *msg)
486 {
487         if(msg==NULL) {
488                 LM_WARN("invalid msg parameter\n");
489                 return SR_KEMI_FALSE;
490         }
491
492         msg->msg_flags|=FL_FORCE_RPORT;
493         return SR_KEMI_TRUE;
494 }
495
496 /**
497  *
498  */
499 static sr_kemi_t _sr_kemi_core[] = {
500         { str_init(""), str_init("dbg"),
501                 SR_KEMIP_NONE, sr_kemi_core_dbg,
502                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
503                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
504         },
505         { str_init(""), str_init("err"),
506                 SR_KEMIP_NONE, sr_kemi_core_err,
507                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
508                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
509         },
510         { str_init(""), str_init("info"),
511                 SR_KEMIP_NONE, sr_kemi_core_info,
512                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
513                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
514         },
515         { str_init(""), str_init("log"),
516                 SR_KEMIP_NONE, sr_kemi_core_log,
517                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
518                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
519         },
520         { str_init(""), str_init("drop"),
521                 SR_KEMIP_NONE, sr_kemi_core_drop,
522                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
523                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
524         },
525         { str_init(""), str_init("is_myself"),
526                 SR_KEMIP_BOOL, sr_kemi_core_is_myself,
527                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
528                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
529         },
530         { str_init(""), str_init("setflag"),
531                 SR_KEMIP_BOOL, sr_kemi_core_setflag,
532                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
533                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
534         },
535         { str_init(""), str_init("resetflag"),
536                 SR_KEMIP_BOOL, sr_kemi_core_resetflag,
537                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
538                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
539         },
540         { str_init(""), str_init("isflagset"),
541                 SR_KEMIP_BOOL, sr_kemi_core_isflagset,
542                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
543                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
544         },
545         { str_init(""), str_init("setbflag"),
546                 SR_KEMIP_BOOL, sr_kemi_core_setbflag,
547                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
548                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
549         },
550         { str_init(""), str_init("resetbflag"),
551                 SR_KEMIP_BOOL, sr_kemi_core_resetbflag,
552                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
553                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
554         },
555         { str_init(""), str_init("isbflagset"),
556                 SR_KEMIP_BOOL, sr_kemi_core_isbflagset,
557                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
558                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
559         },
560         { str_init(""), str_init("setbiflag"),
561                 SR_KEMIP_BOOL, sr_kemi_core_setbiflag,
562                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
563                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
564         },
565         { str_init(""), str_init("resetbiflag"),
566                 SR_KEMIP_BOOL, sr_kemi_core_resetbiflag,
567                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
568                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
569         },
570         { str_init(""), str_init("isbiflagset"),
571                 SR_KEMIP_BOOL, sr_kemi_core_isbiflagset,
572                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
573                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
574         },
575         { str_init(""), str_init("setsflag"),
576                 SR_KEMIP_BOOL, sr_kemi_core_setsflag,
577                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
578                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
579         },
580         { str_init(""), str_init("resetsflag"),
581                 SR_KEMIP_BOOL, sr_kemi_core_resetsflag,
582                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
583                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
584         },
585         { str_init(""), str_init("issflagset"),
586                 SR_KEMIP_BOOL, sr_kemi_core_issflagset,
587                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
588                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
589         },
590         { str_init(""), str_init("seturi"),
591                 SR_KEMIP_BOOL, sr_kemi_core_seturi,
592                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
593                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
594         },
595         { str_init(""), str_init("setuser"),
596                 SR_KEMIP_BOOL, sr_kemi_core_setuser,
597                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
598                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
599         },
600         { str_init(""), str_init("sethost"),
601                 SR_KEMIP_BOOL, sr_kemi_core_sethost,
602                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
603                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
604         },
605         { str_init(""), str_init("setdsturi"),
606                 SR_KEMIP_BOOL, sr_kemi_core_setdsturi,
607                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
608                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
609         },
610         { str_init(""), str_init("resetdsturi"),
611                 SR_KEMIP_BOOL, sr_kemi_core_resetdsturi,
612                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
613                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
614         },
615         { str_init(""), str_init("isdsturiset"),
616                 SR_KEMIP_BOOL, sr_kemi_core_isdsturiset,
617                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
618                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
619         },
620         { str_init(""), str_init("force_rport"),
621                 SR_KEMIP_BOOL, sr_kemi_core_force_rport,
622                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
623                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
624         },
625
626         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
627 };
628
629 /**
630  *
631  */
632 static int sr_kemi_hdr_append(sip_msg_t *msg, str *txt)
633 {
634         struct lump* anchor;
635         struct hdr_field *hf;
636         char *hdr;
637
638         if(txt==NULL || txt->s==NULL || msg==NULL)
639                 return -1;
640
641         LM_DBG("append hf: %.*s\n", txt->len, txt->s);
642         if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
643                 LM_ERR("error while parsing message\n");
644                 return -1;
645         }
646
647         hf = msg->last_header;
648         hdr = (char*)pkg_malloc(txt->len);
649         if(hdr==NULL) {
650                 LM_ERR("no pkg memory left\n");
651                 return -1;
652         }
653         memcpy(hdr, txt->s, txt->len);
654         anchor = anchor_lump(msg,
655                                 hf->name.s + hf->len - msg->buf, 0, 0);
656         if(insert_new_lump_before(anchor, hdr, txt->len, 0) == 0)
657         {
658                 LM_ERR("can't insert lump\n");
659                 pkg_free(hdr);
660                 return -1;
661         }
662         return 1;
663 }
664
665 /**
666  *
667  */
668 static int sr_kemi_hdr_remove(sip_msg_t *msg, str *txt)
669 {
670         struct lump* anchor;
671         struct hdr_field *hf;
672
673         if(txt==NULL || txt->s==NULL || msg==NULL)
674                 return -1;
675
676         LM_DBG("remove hf: %.*s\n", txt->len, txt->s);
677         if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
678                 LM_ERR("error while parsing message\n");
679                 return -1;
680         }
681
682         for (hf=msg->headers; hf; hf=hf->next) {
683                 if (hf->name.len==txt->len
684                                 && strncasecmp(hf->name.s, txt->s, txt->len)==0) {
685                         anchor=del_lump(msg,
686                                         hf->name.s - msg->buf, hf->len, 0);
687                         if (anchor==0) {
688                                 LM_ERR("cannot remove hdr %.*s\n", txt->len, txt->s);
689                                 return -1;
690                         }
691                 }
692         }
693         return 1;
694 }
695
696 /**
697  *
698  */
699 static int sr_kemi_hdr_insert(sip_msg_t *msg, str *txt)
700 {
701         struct lump* anchor;
702         struct hdr_field *hf;
703         char *hdr;
704
705         if(txt==NULL || txt->s==NULL || msg==NULL)
706                 return -1;
707
708         LM_DBG("insert hf: %.*s\n", txt->len, txt->s);
709         hf = msg->headers;
710         hdr = (char*)pkg_malloc(txt->len);
711         if(hdr==NULL) {
712                 LM_ERR("no pkg memory left\n");
713                 return -1;
714         }
715         memcpy(hdr, txt->s, txt->len);
716         anchor = anchor_lump(msg, hf->name.s + hf->len - msg->buf, 0, 0);
717         if(insert_new_lump_before(anchor, hdr, txt->len, 0) == 0) {
718                 LM_ERR("can't insert lump\n");
719                 pkg_free(hdr);
720                 return -1;
721         }
722         return 1;
723 }
724
725 /**
726  *
727  */
728 static int sr_kemi_hdr_append_to_reply(sip_msg_t *msg, str *txt)
729 {
730         if(txt==NULL || txt->s==NULL || msg==NULL)
731                 return -1;
732
733         LM_DBG("append to reply: %.*s\n", txt->len, txt->s);
734
735         if(add_lump_rpl(msg, txt->s, txt->len, LUMP_RPL_HDR)==0) {
736                 LM_ERR("unable to add reply lump\n");
737                 return -1;
738         }
739
740         return 1;
741 }
742
743 /**
744  *
745  */
746 static sr_kemi_t _sr_kemi_hdr[] = {
747         { str_init("hdr"), str_init("append"),
748                 SR_KEMIP_INT, sr_kemi_hdr_append,
749                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
750                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
751         },
752         { str_init("hdr"), str_init("insert"),
753                 SR_KEMIP_INT, sr_kemi_hdr_insert,
754                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
755                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
756         },
757         { str_init("hdr"), str_init("remove"),
758                 SR_KEMIP_INT, sr_kemi_hdr_remove,
759                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
760                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
761         },
762         { str_init("hdr"), str_init("append_to_reply"),
763                 SR_KEMIP_INT, sr_kemi_hdr_append_to_reply,
764                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
765                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
766         },
767
768         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
769 };
770
771 #define SR_KEMI_MODULES_MAX_SIZE        1024
772 static int _sr_kemi_modules_size = 0;
773 static sr_kemi_module_t _sr_kemi_modules[SR_KEMI_MODULES_MAX_SIZE];
774
775 /**
776  *
777  */
778 int sr_kemi_modules_add(sr_kemi_t *klist)
779 {
780         if(_sr_kemi_modules_size>=SR_KEMI_MODULES_MAX_SIZE) {
781                 LM_ERR("exceeded max number of modules\n");
782                 return -1;
783         }
784         if(_sr_kemi_modules_size==0) {
785                 LM_DBG("adding core module\n");
786                 _sr_kemi_modules[_sr_kemi_modules_size].mname = _sr_kemi_core[0].mname;
787                 _sr_kemi_modules[_sr_kemi_modules_size].kexp = _sr_kemi_core;
788                 _sr_kemi_modules_size++;
789                 LM_DBG("adding hdr module\n");
790                 _sr_kemi_modules[_sr_kemi_modules_size].mname = _sr_kemi_hdr[0].mname;
791                 _sr_kemi_modules[_sr_kemi_modules_size].kexp = _sr_kemi_hdr;
792                 _sr_kemi_modules_size++;
793         }
794         if((_sr_kemi_modules_size>1)
795                         && (_sr_kemi_modules[_sr_kemi_modules_size-1].mname.len
796                                         ==klist[0].mname.len)
797                         && (strncmp(_sr_kemi_modules[_sr_kemi_modules_size-1].mname.s,
798                                         klist[0].mname.s, klist[0].mname.len)==0)) {
799                 /* handle re-open of the module */
800                 LM_DBG("updating module: %.*s\n", klist[0].mname.len, klist[0].mname.s);
801                 _sr_kemi_modules[_sr_kemi_modules_size-1].kexp = klist;
802         } else {
803                 LM_DBG("adding module: %.*s\n", klist[0].mname.len, klist[0].mname.s);
804                 _sr_kemi_modules[_sr_kemi_modules_size].mname = klist[0].mname;
805                 _sr_kemi_modules[_sr_kemi_modules_size].kexp = klist;
806                 _sr_kemi_modules_size++;
807         }
808         return 0;
809 }
810
811 /**
812  *
813  */
814 int sr_kemi_modules_size_get(void)
815 {
816         return _sr_kemi_modules_size;
817 }
818
819 /**
820  *
821  */
822 sr_kemi_module_t* sr_kemi_modules_get(void)
823 {
824         return _sr_kemi_modules;
825 }
826
827 /**
828  *
829  */
830 sr_kemi_t* sr_kemi_lookup(str *mname, int midx, str *fname)
831 {
832         int i;
833         sr_kemi_t *ket;
834
835         if(mname==NULL || mname->len<=0) {
836                 for(i=0; _sr_kemi_core[i].fname.s!=NULL; i++) {
837                         ket = &_sr_kemi_core[i];
838                         if(ket->fname.len==fname->len
839                                         && strncasecmp(ket->fname.s, fname->s, fname->len)==0) {
840                                 return ket;
841                         }
842                 }
843         } else {
844                 if(midx>0 && midx<SR_KEMI_MODULES_MAX_SIZE) {
845                         for(i=0; _sr_kemi_modules[midx].kexp[i].fname.s!=NULL; i++) {
846                                 ket = &_sr_kemi_modules[midx].kexp[i];
847                                 if(ket->fname.len==fname->len
848                                                 && strncasecmp(ket->fname.s, fname->s, fname->len)==0) {
849                                         return ket;
850                                 }
851                         }
852                 }
853         }
854         return NULL;
855 }
856
857 /**
858  *
859  */
860
861 #define SR_KEMI_ENG_LIST_MAX_SIZE       8
862 static sr_kemi_eng_t _sr_kemi_eng_list[SR_KEMI_ENG_LIST_MAX_SIZE];
863 sr_kemi_eng_t *_sr_kemi_eng = NULL;
864 static int _sr_kemi_eng_list_size=0;
865
866 /**
867  *
868  */
869 int sr_kemi_eng_register(str *ename, sr_kemi_eng_route_f froute)
870 {
871         int i;
872
873         for(i=0; i<_sr_kemi_eng_list_size; i++) {
874                 if(_sr_kemi_eng_list[i].ename.len==ename->len
875                                 && strncasecmp(_sr_kemi_eng_list[i].ename.s, ename->s,
876                                         ename->len)==0) {
877                         /* found */
878                         return 1;
879                 }
880         }
881         if(_sr_kemi_eng_list_size>=SR_KEMI_ENG_LIST_MAX_SIZE) {
882                 LM_ERR("too many config routing engines registered\n");
883                 return -1;
884         }
885         if(ename->len>=SR_KEMI_BNAME_SIZE) {
886                 LM_ERR("config routing engine name too long\n");
887                 return -1;
888         }
889         strncpy(_sr_kemi_eng_list[_sr_kemi_eng_list_size].bname,
890                         ename->s, ename->len);
891         _sr_kemi_eng_list[_sr_kemi_eng_list_size].ename.s
892                         = _sr_kemi_eng_list[_sr_kemi_eng_list_size].bname;
893         _sr_kemi_eng_list[_sr_kemi_eng_list_size].ename.len = ename->len;
894         _sr_kemi_eng_list[_sr_kemi_eng_list_size].ename.s[ename->len] = 0;
895         _sr_kemi_eng_list[_sr_kemi_eng_list_size].froute = froute;
896         _sr_kemi_eng_list_size++;
897
898         LM_DBG("registered config routing enginge [%.*s]",
899                         ename->len, ename->s);
900
901         return 0;
902 }
903
904 /**
905  *
906  */
907 int sr_kemi_eng_set(str *ename, str *cpath)
908 {
909         int i;
910
911         /* skip native and default */
912         if(ename->len==6 && strncasecmp(ename->s, "native", 6)==0) {
913                 return 0;
914         }
915         if(ename->len==7 && strncasecmp(ename->s, "default", 7)==0) {
916                 return 0;
917         }
918
919         if(sr_kemi_cbname_list_init()<0) {
920                 return -1;
921         }
922
923         for(i=0; i<_sr_kemi_eng_list_size; i++) {
924                 if(_sr_kemi_eng_list[i].ename.len==ename->len
925                                 && strncasecmp(_sr_kemi_eng_list[i].ename.s, ename->s,
926                                         ename->len)==0) {
927                         /* found */
928                         _sr_kemi_eng = &_sr_kemi_eng_list[i];
929                         return 0;
930                 }
931         }
932         return -1;
933 }
934
935 /**
936  *
937  */
938 int sr_kemi_eng_setz(char *ename, char *cpath)
939 {
940         str sname;
941         str spath;
942
943         sname.s = ename;
944         sname.len = strlen(ename);
945
946         if(cpath!=0) {
947                 spath.s = cpath;
948                 spath.len = strlen(cpath);
949                 return sr_kemi_eng_set(&sname, &spath);
950         } else {
951                 return sr_kemi_eng_set(&sname, NULL);
952         }
953 }
954
955 /**
956  *
957  */
958 sr_kemi_eng_t* sr_kemi_eng_get(void)
959 {
960         return _sr_kemi_eng;
961 }
962
963 /**
964  *
965  */
966 #define KEMI_CBNAME_MAX_LEN     128
967 #define KEMI_CBNAME_LIST_SIZE   256
968
969 typedef struct sr_kemi_cbname {
970         str name;
971         char bname[KEMI_CBNAME_MAX_LEN];
972 } sr_kemi_cbname_t;
973
974 static gen_lock_t *_sr_kemi_cbname_lock = 0;
975 static sr_kemi_cbname_t *_sr_kemi_cbname_list = NULL;
976 static int *_sr_kemi_cbname_list_size = NULL;
977
978 /**
979  *
980  */
981 int sr_kemi_cbname_list_init(void)
982 {
983         if(_sr_kemi_cbname_list!=NULL) {
984                 return 0;
985         }
986         if ( (_sr_kemi_cbname_lock=lock_alloc())==0) {
987                 LM_CRIT("failed to alloc lock\n");
988                 return -1;
989         }
990         if (lock_init(_sr_kemi_cbname_lock)==0 ) {
991                 LM_CRIT("failed to init lock\n");
992                 lock_dealloc(_sr_kemi_cbname_lock);
993                 _sr_kemi_cbname_lock = NULL;
994                 return -1;
995         }
996         _sr_kemi_cbname_list_size = shm_malloc(sizeof(int));
997         if(_sr_kemi_cbname_list_size==NULL) {
998                 lock_destroy(_sr_kemi_cbname_lock);
999                 lock_dealloc(_sr_kemi_cbname_lock);
1000                 LM_ERR("no more shared memory\n");
1001                 return -1;
1002         }
1003         *_sr_kemi_cbname_list_size = 0;
1004         _sr_kemi_cbname_list
1005                         = shm_malloc(KEMI_CBNAME_LIST_SIZE*sizeof(sr_kemi_cbname_t));
1006         if(_sr_kemi_cbname_list==NULL) {
1007                 LM_ERR("no more shared memory\n");
1008                 shm_free(_sr_kemi_cbname_list_size);
1009                 _sr_kemi_cbname_list_size = NULL;
1010                 lock_destroy(_sr_kemi_cbname_lock);
1011                 lock_dealloc(_sr_kemi_cbname_lock);
1012                 _sr_kemi_cbname_lock = NULL;
1013                 return -1;
1014         }
1015         memset(_sr_kemi_cbname_list, 0,
1016                         KEMI_CBNAME_LIST_SIZE*sizeof(sr_kemi_cbname_t));
1017         return 0;
1018 }
1019
1020 /**
1021  *
1022  */
1023 int sr_kemi_cbname_lookup_name(str *name)
1024 {
1025         int n;
1026         int i;
1027
1028         if(_sr_kemi_cbname_list==NULL) {
1029                 return 0;
1030         }
1031         if(name->len >= KEMI_CBNAME_MAX_LEN) {
1032                 LM_ERR("callback name is too long [%.*s] (max: %d)\n",
1033                                 name->len, name->s, KEMI_CBNAME_MAX_LEN);
1034                 return 0;
1035         }
1036         n = *_sr_kemi_cbname_list_size;
1037
1038         for(i=0; i<n; i++) {
1039                 if(_sr_kemi_cbname_list[i].name.len==name->len
1040                                 && strncmp(_sr_kemi_cbname_list[i].name.s,
1041                                                 name->s, name->len)==0) {
1042                         return i+1;
1043                 }
1044         }
1045
1046         /* not found -- add it */
1047         lock_get(_sr_kemi_cbname_lock);
1048
1049         /* check if new callback were indexed meanwhile */
1050         for(; i<*_sr_kemi_cbname_list_size; i++) {
1051                 if(_sr_kemi_cbname_list[i].name.len==name->len
1052                                 && strncmp(_sr_kemi_cbname_list[i].name.s,
1053                                                 name->s, name->len)==0) {
1054                         lock_release(_sr_kemi_cbname_lock);
1055                         return i+1;
1056                 }
1057         }
1058         if(*_sr_kemi_cbname_list_size>=KEMI_CBNAME_LIST_SIZE) {
1059                 lock_release(_sr_kemi_cbname_lock);
1060                 LM_ERR("no more space to index callbacks\n");
1061                 return 0;
1062         }
1063         strncpy(_sr_kemi_cbname_list[i].bname, name->s, name->len);
1064         _sr_kemi_cbname_list[i].bname[name->len] = '\0';
1065         _sr_kemi_cbname_list[i].name.s = _sr_kemi_cbname_list[i].bname;
1066         _sr_kemi_cbname_list[i].name.len = name->len;
1067         i++;
1068         *_sr_kemi_cbname_list_size = i;
1069         lock_release(_sr_kemi_cbname_lock);
1070         return i;
1071 }
1072
1073 /**
1074  *
1075  */
1076 str* sr_kemi_cbname_lookup_idx(int idx)
1077 {
1078         int n;
1079
1080         if(_sr_kemi_cbname_list==NULL) {
1081                 return NULL;
1082         }
1083         n = *_sr_kemi_cbname_list_size;
1084         if(idx<1 || idx>n) {
1085                 LM_ERR("index %d is out of range\n", idx);
1086                 return NULL;
1087         }
1088         return &_sr_kemi_cbname_list[idx-1].name;
1089 }
1090
1091 /**
1092  *
1093  */
1094 typedef struct sr_kemi_param_map {
1095         int ptype;
1096         str pname;
1097 } sr_kemi_param_map_t;
1098
1099 /**
1100  *
1101  */
1102 static sr_kemi_param_map_t _sr_kemi_param_map[] = {
1103         { SR_KEMIP_NONE,   str_init("none") },
1104         { SR_KEMIP_INT,    str_init("int") },
1105         { SR_KEMIP_STR,    str_init("str") },
1106         { SR_KEMIP_BOOL,   str_init("bool") },
1107         { SR_KEMIP_INTSTR, str_init("int-str") },
1108         { 0, STR_NULL }
1109 };
1110
1111 /**
1112  *
1113  */
1114 str *sr_kemi_param_map_get_name(int ptype)
1115 {
1116         int i;
1117
1118         for(i=0; _sr_kemi_param_map[i].pname.s!=NULL; i++) {
1119                 if(_sr_kemi_param_map[i].ptype==ptype)
1120                         return &_sr_kemi_param_map[i].pname;
1121         }
1122         return NULL;
1123 }
1124
1125 /**
1126  *
1127  */
1128 str *sr_kemi_param_map_get_params(int *ptypes)
1129 {
1130         int i;
1131         int l;
1132 #define KEMI_PARAM_MAP_SIZE 72
1133         static char pbuf[KEMI_PARAM_MAP_SIZE];
1134         static str sret = STR_NULL;
1135         str *pn;
1136
1137         pbuf[0] = '\0';
1138         l = 0;
1139         for(i = 0; i < SR_KEMI_PARAMS_MAX; i++) {
1140                 if(ptypes[i] == SR_KEMIP_NONE)
1141                         break;
1142                 if(i > 0) {
1143                         l += 2;
1144                         if(l >= KEMI_PARAM_MAP_SIZE - 8) {
1145                                 strcat(pbuf, ", ...");
1146                                 goto done;
1147                         }
1148                         strcat(pbuf, ", ");
1149                 }
1150                 pn = sr_kemi_param_map_get_name(ptypes[i]);
1151                 if(pn == NULL)
1152                         return NULL;
1153                 l += pn->len;
1154                 if(l >= KEMI_PARAM_MAP_SIZE - 8) {
1155                         strcat(pbuf, ", ...");
1156                         goto done;
1157                 }
1158                 strcat(pbuf, pn->s);
1159         }
1160         if(pbuf[0]=='\0') {
1161                 pn = sr_kemi_param_map_get_name(SR_KEMIP_NONE);
1162                 if(pn == NULL)
1163                         return NULL;
1164                 if(pn->len<KEMI_PARAM_MAP_SIZE-1) strcat(pbuf, pn->s);
1165         }
1166 done:
1167         sret.s = pbuf;
1168         sret.len = strlen(sret.s);
1169         return &sret;
1170 }