corex: added set_send_socket() and set_recv_socket()
[sip-router] / src / modules / corex / corex_mod.c
1 /**
2  * Copyright (C) 2011 Daniel-Constantin Mierla (asipto.com)
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "../../core/sr_module.h"
26 #include "../../core/dprint.h"
27 #include "../../core/ut.h"
28 #include "../../core/lvalue.h"
29 #include "../../core/pvar.h"
30 #include "../../core/kemi.h"
31
32 #include "corex_lib.h"
33 #include "corex_rpc.h"
34 #include "corex_var.h"
35 #include "corex_nio.h"
36
37 MODULE_VERSION
38
39 static int nio_intercept = 0;
40 static int w_append_branch(sip_msg_t *msg, char *su, char *sq);
41 static int w_send(sip_msg_t *msg, char *su, char *sq);
42 static int w_send_tcp(sip_msg_t *msg, char *su, char *sq);
43 static int w_send_data(sip_msg_t *msg, char *suri, char *sdata);
44 static int w_msg_iflag_set(sip_msg_t *msg, char *pflag, char *p2);
45 static int w_msg_iflag_reset(sip_msg_t *msg, char *pflag, char *p2);
46 static int w_msg_iflag_is_set(sip_msg_t *msg, char *pflag, char *p2);
47 static int w_file_read(sip_msg_t *msg, char *fn, char *vn);
48 static int w_file_write(sip_msg_t *msg, char *fn, char *vn);
49 static int w_isxflagset(struct sip_msg *msg, char *flag, str *s2);
50 static int w_resetxflag(struct sip_msg *msg, char *flag, str *s2);
51 static int w_setxflag(struct sip_msg *msg, char *flag, char *s2);
52 static int w_set_send_socket(sip_msg_t *msg, char *psock, char *p2);
53 static int w_set_recv_socket(sip_msg_t *msg, char *psock, char *p2);
54
55 static int fixup_file_op(void** param, int param_no);
56
57 int corex_alias_subdomains_param(modparam_t type, void *val);
58
59 static int  mod_init(void);
60 static int  child_init(int);
61 static void mod_destroy(void);
62
63 static pv_export_t mod_pvs[] = {
64         { {"cfg", (sizeof("cfg")-1)}, PVT_OTHER, pv_get_cfg, 0,
65                 pv_parse_cfg_name, 0, 0, 0 },
66
67         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
68 };
69
70 static cmd_export_t cmds[]={
71         {"append_branch", (cmd_function)w_append_branch, 0, 0,
72                 0, REQUEST_ROUTE | FAILURE_ROUTE },
73         {"append_branch", (cmd_function)w_append_branch, 1, fixup_spve_null,
74                 0, REQUEST_ROUTE | FAILURE_ROUTE },
75         {"append_branch", (cmd_function)w_append_branch, 2, fixup_spve_spve,
76                 0, REQUEST_ROUTE | FAILURE_ROUTE },
77         {"send", (cmd_function)w_send, 0, 0,
78                 0, REQUEST_ROUTE | FAILURE_ROUTE },
79         {"send", (cmd_function)w_send, 1, fixup_spve_spve,
80                 0, REQUEST_ROUTE | FAILURE_ROUTE },
81         {"send_tcp", (cmd_function)w_send_tcp, 0, 0,
82                 0, REQUEST_ROUTE | FAILURE_ROUTE },
83         {"send_tcp", (cmd_function)w_send_tcp, 1, fixup_spve_null,
84                 0, REQUEST_ROUTE | FAILURE_ROUTE },
85         {"send_data", (cmd_function)w_send_data, 2, fixup_spve_spve,
86                 0, ANY_ROUTE },
87         {"is_incoming",    (cmd_function)nio_check_incoming, 0, 0,
88                 0, ANY_ROUTE },
89         {"msg_iflag_set", (cmd_function)w_msg_iflag_set,       1, fixup_spve_null,
90                 0, ANY_ROUTE },
91         {"msg_iflag_reset", (cmd_function)w_msg_iflag_reset,   1, fixup_spve_null,
92                 0, ANY_ROUTE },
93         {"msg_iflag_is_set", (cmd_function)w_msg_iflag_is_set, 1, fixup_spve_null,
94                 0, ANY_ROUTE },
95         {"file_read", (cmd_function)w_file_read,   2, fixup_file_op,
96                 0, ANY_ROUTE },
97         {"file_write", (cmd_function)w_file_write, 2, fixup_spve_spve,
98                 0, ANY_ROUTE },
99         {"setxflag", (cmd_function)w_setxflag,          1,fixup_igp_null,
100                 0, ANY_ROUTE },
101         {"resetxflag", (cmd_function)w_resetxflag,      1,fixup_igp_null,
102                 0, ANY_ROUTE },
103         {"isxflagset", (cmd_function)w_isxflagset,      1,fixup_igp_null,
104                 0, ANY_ROUTE },
105         {"set_send_socket", (cmd_function)w_set_send_socket, 1, fixup_spve_null,
106                 0, ANY_ROUTE },
107         {"set_recv_socket", (cmd_function)w_set_recv_socket, 1, fixup_spve_null,
108                 0, ANY_ROUTE },
109
110         {0, 0, 0, 0, 0, 0}
111 };
112
113 static param_export_t params[]={
114         {"alias_subdomains",            STR_PARAM|USE_FUNC_PARAM,
115                 (void*)corex_alias_subdomains_param},
116         {"network_io_intercept",        INT_PARAM, &nio_intercept},
117         {"min_msg_len",                         INT_PARAM, &nio_min_msg_len},
118         {"msg_avp",                                     PARAM_STR, &nio_msg_avp_param},
119
120         {0, 0, 0}
121 };
122
123 struct module_exports exports = {
124         "corex",
125         DEFAULT_DLFLAGS, /* dlopen flags */
126         cmds,
127         params,
128         0,
129         0,              /* exported MI functions */
130         mod_pvs,        /* exported pseudo-variables */
131         0,              /* extra processes */
132         mod_init,       /* module initialization function */
133         0,              /* response function */
134         mod_destroy,    /* destroy function */
135         child_init      /* per child init function */
136 };
137
138
139
140 /**
141  * init module function
142  */
143 static int mod_init(void)
144 {
145         if(corex_init_rpc()<0)
146         {
147                 LM_ERR("failed to register RPC commands\n");
148                 return -1;
149         }
150
151         if(corex_register_check_self()<0)
152         {
153                 LM_ERR("failed to register check self callback\n");
154                 return -1;
155         }
156
157         if((nio_intercept > 0) && (nio_intercept_init() < 0))
158         {
159                 LM_ERR("failed to register network io intercept callback\n");
160                 return -1;
161         }
162
163         return 0;
164 }
165
166 /**
167  * @brief Initialize async module children
168  */
169 static int child_init(int rank)
170 {
171         if (rank!=PROC_MAIN)
172                 return 0;
173
174         return 0;
175 }
176 /**
177  * destroy module function
178  */
179 static void mod_destroy(void)
180 {
181 }
182
183 /**
184  * config wrapper for append branch
185  */
186 static int w_append_branch(sip_msg_t *msg, char *su, char *sq)
187 {
188         if(w_corex_append_branch(msg, (gparam_t*)su, (gparam_t*)sq) < 0)
189                 return -1;
190         return 1;
191 }
192
193 /**
194  * config wrapper for send() and send_tcp()
195  */
196 static int w_send(sip_msg_t *msg, char *su, char *sq)
197 {
198         if(corex_send(msg, (gparam_t*)su, PROTO_UDP) < 0)
199                 return -1;
200         return 1;
201 }
202 static int w_send_tcp(sip_msg_t *msg, char *su, char *sq)
203 {
204         if(corex_send(msg, (gparam_t*)su, PROTO_TCP) < 0)
205                 return -1;
206         return 1;
207 }
208
209 static int w_send_data(sip_msg_t *msg, char *suri, char *sdata)
210 {
211         str uri;
212         str data;
213
214         if (fixup_get_svalue(msg, (gparam_t*)suri, &uri))
215         {
216                 LM_ERR("cannot get the destination parameter\n");
217                 return -1;
218         }
219         if (fixup_get_svalue(msg, (gparam_t*)sdata, &data))
220         {
221                 LM_ERR("cannot get the destination parameter\n");
222                 return -1;
223         }
224         if(corex_send_data(&uri, &data) < 0)
225                 return -1;
226         return 1;
227 }
228
229 int corex_alias_subdomains_param(modparam_t type, void *val)
230 {
231         if(val==NULL)
232                 goto error;
233
234         return corex_add_alias_subdomains((char*)val);
235 error:
236         return -1;
237
238 }
239
240 typedef struct _msg_iflag_name {
241         str name;
242         int value;
243 } msg_iflag_name_t;
244
245 static msg_iflag_name_t _msg_iflag_list[] = {
246         { str_init("USE_UAC_FROM"), FL_USE_UAC_FROM },
247         { str_init("USE_UAC_TO"),   FL_USE_UAC_TO   },
248         { str_init("UAC_AUTH"),     FL_UAC_AUTH     },
249         { {0, 0}, 0 }
250 };
251
252
253 /**
254  *
255  */
256 static int msg_lookup_flag(str *fname)
257 {
258         int i;
259         for(i=0; _msg_iflag_list[i].name.len>0; i++) {
260                 if(fname->len==_msg_iflag_list[i].name.len
261                                 && strncasecmp(_msg_iflag_list[i].name.s, fname->s,
262                                         fname->len)==0) {
263                         return _msg_iflag_list[i].value;
264                 }
265         }
266         return -1;
267 }
268 /**
269  *
270  */
271 static int w_msg_iflag_set(sip_msg_t *msg, char *pflag, char *p2)
272 {
273         int fv;
274         str fname;
275         if (fixup_get_svalue(msg, (gparam_t*)pflag, &fname))
276         {
277                 LM_ERR("cannot get the msg flag name parameter\n");
278                 return -1;
279         }
280         fv =  msg_lookup_flag(&fname);
281         if(fv==1) {
282                 LM_ERR("unsupported flag name [%.*s]\n", fname.len, fname.s);
283                 return -1;
284         }
285         msg->msg_flags |= fv;
286         return 1;
287 }
288
289 /**
290  *
291  */
292 static int w_msg_iflag_reset(sip_msg_t *msg, char *pflag, char *p2)
293 {
294         int fv;
295         str fname;
296         if (fixup_get_svalue(msg, (gparam_t*)pflag, &fname))
297         {
298                 LM_ERR("cannot get the msg flag name parameter\n");
299                 return -1;
300         }
301         fv =  msg_lookup_flag(&fname);
302         if(fv<0) {
303                 LM_ERR("unsupported flag name [%.*s]\n", fname.len, fname.s);
304                 return -1;
305         }
306         msg->msg_flags &= ~fv;
307         return 1;
308 }
309
310 /**
311  *
312  */
313 static int w_msg_iflag_is_set(sip_msg_t *msg, char *pflag, char *p2)
314 {
315         int fv;
316         str fname;
317         if (fixup_get_svalue(msg, (gparam_t*)pflag, &fname))
318         {
319                 LM_ERR("cannot get the msg flag name parameter\n");
320                 return -1;
321         }
322         fv =  msg_lookup_flag(&fname);
323         if(fv<0) {
324                 LM_ERR("unsupported flag name [%.*s]\n", fname.len, fname.s);
325                 return -1;
326         }
327         if(msg->msg_flags & fv)
328                 return 1;
329         return -2;
330 }
331
332 /**
333  *
334  */
335 static int w_file_read(sip_msg_t *msg, char *fn, char *vn)
336 {
337         str fname;
338         pv_spec_t *vp;
339         pv_value_t val;
340
341         FILE *f;
342         long fsize;
343         char *content;
344
345         fname.len = 0;
346         if (fixup_get_svalue(msg, (gparam_p)fn, &fname) != 0 || fname.len<=0) {
347                 LM_ERR("cannot get file path\n");
348                 return -1;
349         }
350         LM_DBG("reading from file: %.*s\n", fname.len, fname.s);
351         vp = (pv_spec_t*)vn;
352
353         f = fopen(fname.s, "r");
354         if(f==NULL) {
355                 LM_ERR("cannot open file: %.*s\n", fname.len, fname.s);
356                 return -1;
357         }
358         fseek(f, 0, SEEK_END);
359         fsize = ftell(f);
360         if(fsize<0) {
361                 LM_ERR("ftell failed on file: %.*s\n", fname.len, fname.s);
362                 fclose(f);
363                 return -1;
364         }
365         fseek(f, 0, SEEK_SET);
366
367         content = pkg_malloc(fsize + 1);
368         if(content==NULL) {
369                 LM_ERR("no more pkg memory\n");
370                 fclose(f);
371                 return -1;
372         }
373         if(fread(content, fsize, 1, f) != fsize) {
374                 if(ferror(f)) {
375                         LM_ERR("error reading from file: %.*s\n",
376                                 fname.len, fname.s);
377                 }
378         }
379         fclose(f);
380         content[fsize] = 0;
381
382
383         val.rs.s = content;
384         val.rs.len = fsize;
385         LM_DBG("file content: [[%.*s]]\n", val.rs.len, val.rs.s);
386         val.flags = PV_VAL_STR;
387         vp->setf(msg, &vp->pvp, (int)EQ_T, &val);
388         pkg_free(content);
389
390         return 1;
391 }
392
393 /**
394  *
395  */
396 static int w_file_write(sip_msg_t *msg, char *fn, char *vn)
397 {
398         str fname;
399         str content;
400         FILE *f;
401
402         fname.len = 0;
403         if (fixup_get_svalue(msg, (gparam_p)fn, &fname) != 0 || fname.len<=0) {
404                 LM_ERR("cannot get file path\n");
405                 return -1;
406         }
407         content.len = 0;
408         if (fixup_get_svalue(msg, (gparam_p)vn, &content) != 0 || content.len<=0) {
409                 LM_ERR("cannot get the content\n");
410                 return -1;
411         }
412
413         LM_DBG("writing to file: %.*s\n", fname.len, fname.s);
414         f = fopen(fname.s, "w");
415         if(f==NULL) {
416                 LM_ERR("cannot open file: %.*s\n", fname.len, fname.s);
417                 return -1;
418         }
419         fwrite(content.s, 1, content.len, f);
420         fclose(f);
421
422         return 1;
423 }
424
425 /**
426  *
427  */
428 static int fixup_file_op(void** param, int param_no)
429 {
430         if (param_no == 1) {
431                 return fixup_spve_null(param, 1);
432         }
433
434         if (param_no == 2) {
435                 if (fixup_pvar_null(param, 1) != 0) {
436                         LM_ERR("failed to fixup result pvar\n");
437                         return -1;
438                 }
439                 if (((pv_spec_t *)(*param))->setf == NULL) {
440                         LM_ERR("result pvar is not writeble\n");
441                         return -1;
442                 }
443                 return 0;
444         }
445
446         LM_ERR("invalid parameter number <%d>\n", param_no);
447         return -1;
448 }
449
450 /**
451  *
452  */
453 static int ki_append_branch(sip_msg_t *msg)
454 {
455         if(corex_append_branch(msg, NULL, NULL) < 0)
456                 return -1;
457         return 1;
458 }
459
460 /**
461  *
462  */
463 static int ki_append_branch_uri(sip_msg_t *msg, str *uri)
464 {
465         if(corex_append_branch(msg, uri, NULL) < 0)
466                 return -1;
467         return 1;
468 }
469
470 /**
471  *
472  */
473 static int ki_append_branch_uri_q(sip_msg_t *msg, str *uri, str *q)
474 {
475         if(corex_append_branch(msg, uri, q) < 0)
476                 return -1;
477         return 1;
478 }
479
480 /**
481  *
482  */
483 static int ki_isxflagset(sip_msg_t *msg, int fval)
484 {
485         if((flag_t)fval>KSR_MAX_XFLAG)
486                 return -1;
487         return isxflagset(msg, (flag_t)fval);
488 }
489
490 /**
491  *
492  */
493 static int w_isxflagset(sip_msg_t *msg, char *flag, str *s2)
494 {
495         int fval=0;
496         if(fixup_get_ivalue(msg, (gparam_t*)flag, &fval)!=0) {
497                 LM_ERR("no flag value\n");
498                 return -1;
499         }
500         return ki_isxflagset(msg, fval);
501 }
502
503 /**
504  *
505  */
506 static int ki_resetxflag(sip_msg_t *msg, int fval)
507 {
508         if((flag_t)fval>KSR_MAX_XFLAG)
509                 return -1;
510         return resetxflag(msg, (flag_t)fval);
511 }
512
513 /**
514  *
515  */
516 static int w_resetxflag(sip_msg_t *msg, char *flag, str *s2)
517 {
518         int fval=0;
519         if(fixup_get_ivalue(msg, (gparam_t*)flag, &fval)!=0) {
520                 LM_ERR("no flag value\n");
521                 return -1;
522         }
523         return ki_resetxflag(msg, fval);
524 }
525
526 /**
527  *
528  */
529 static int ki_setxflag(sip_msg_t *msg, int fval)
530 {
531         if((flag_t)fval>KSR_MAX_XFLAG)
532                 return -1;
533         return setxflag(msg, (flag_t)fval);
534 }
535
536 /**
537  *
538  */
539 static int w_setxflag(sip_msg_t *msg, char *flag, char *s2)
540 {
541         int fval=0;
542         if(fixup_get_ivalue(msg, (gparam_t*)flag, &fval)!=0) {
543                 LM_ERR("no flag value\n");
544                 return -1;
545         }
546         return ki_setxflag(msg, fval);
547 }
548
549 /**
550  *
551  */
552 static int ki_set_socket_helper(sip_msg_t *msg, str *ssock, int smode)
553 {
554         socket_info_t *si;
555         receive_info_t ri;
556         int port, proto;
557         str host;
558
559         if(msg==NULL) {
560                 LM_ERR("bad parameters\n");
561                 return -1;
562         }
563
564         if(ssock==NULL || ssock->len<=0) {
565                 reset_force_socket(msg);
566                 return 1;
567         }
568
569         if (parse_phostport(ssock->s, &host.s, &host.len, &port, &proto) < 0) {
570                 LM_ERR("invalid socket specification [%.*s] (%d)\n",
571                                 ssock->len, ssock->s, smode);
572                 goto error;
573         }
574         si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto);
575         if (si!=NULL) {
576                 if(smode==0) {
577                         /* send socket */
578                         set_force_socket(msg, si);
579                 } else {
580                         /* recv socket */
581                         msg->rcv.bind_address = si;
582                         msg->rcv.dst_port = si->port_no;
583                         msg->rcv.dst_ip = si->address;
584                         msg->rcv.proto = si->proto;
585                         msg->rcv.proto_reserved1 = 0;
586                         msg->rcv.proto_reserved2 = 0;
587                 }
588         } else {
589                 LM_WARN("no socket found to match [%.*s] (%d)\n",
590                                 ssock->len, ssock->s, smode);
591         }
592         return 1;
593 error:
594         return -1;
595 }
596
597 /**
598  *
599  */
600 static int ki_set_send_socket(sip_msg_t *msg, str *ssock)
601 {
602         return ki_set_socket_helper(msg, ssock, 0);
603 }
604
605 /**
606  *
607  */
608 static int w_set_send_socket(sip_msg_t *msg, char *psock, char *p2)
609 {
610         str ssock;
611         if (fixup_get_svalue(msg, (gparam_t*)psock, &ssock) != 0 || ssock.len<=0) {
612                 LM_ERR("cannot get socket address value\n");
613                 return -1;
614         }
615         return ki_set_send_socket(msg, &ssock);
616 }
617
618 /**
619  *
620  */
621 static int ki_set_recv_socket(sip_msg_t *msg, str *ssock)
622 {
623         return ki_set_socket_helper(msg, ssock, 1);
624 }
625
626 /**
627  *
628  */
629 static int w_set_recv_socket(sip_msg_t *msg, char *psock, char *p2)
630 {
631         str ssock;
632         if (fixup_get_svalue(msg, (gparam_t*)psock, &ssock) != 0 || ssock.len<=0) {
633                 LM_ERR("cannot get socket address value\n");
634                 return -1;
635         }
636         return ki_set_recv_socket(msg, &ssock);
637 }
638
639 /**
640  *
641  */
642 /* clang-format off */
643 static sr_kemi_t sr_kemi_corex_exports[] = {
644         { str_init("corex"), str_init("append_branch"),
645                 SR_KEMIP_INT, ki_append_branch,
646                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
647                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
648         },
649         { str_init("corex"), str_init("append_branch_uri"),
650                 SR_KEMIP_INT, ki_append_branch_uri,
651                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
652                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
653         },
654         { str_init("corex"), str_init("append_branch_uri_q"),
655                 SR_KEMIP_INT, ki_append_branch_uri_q,
656                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
657                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
658         },
659         { str_init("corex"), str_init("setxflag"),
660                 SR_KEMIP_INT, ki_setxflag,
661                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
662                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
663         },
664         { str_init("corex"), str_init("resetxflag"),
665                 SR_KEMIP_INT, ki_resetxflag,
666                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
667                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
668         },
669         { str_init("corex"), str_init("isxflagset"),
670                 SR_KEMIP_INT, ki_isxflagset,
671                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
672                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
673         },
674         { str_init("corex"), str_init("set_send_socket"),
675                 SR_KEMIP_INT, ki_set_send_socket,
676                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
677                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
678         },
679         { str_init("corex"), str_init("set_recv_socket"),
680                 SR_KEMIP_INT, ki_set_recv_socket,
681                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
682                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
683         },
684
685         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
686 };
687 /* clang-format on */
688
689 /**
690  *
691  */
692 int mod_register(char *path, int *dlflags, void *p1, void *p2)
693 {
694         sr_kemi_modules_add(sr_kemi_corex_exports);
695         return 0;
696 }