corex: added via_add_srvid() function
[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/socket_info.h"
29 #include "../../core/resolve.h"
30 #include "../../core/lvalue.h"
31 #include "../../core/pvar.h"
32 #include "../../core/kemi.h"
33
34 #include "corex_lib.h"
35 #include "corex_rpc.h"
36 #include "corex_var.h"
37 #include "corex_nio.h"
38
39 MODULE_VERSION
40
41 static int nio_intercept = 0;
42 static int w_append_branch(sip_msg_t *msg, char *su, char *sq);
43 static int w_send(sip_msg_t *msg, char *su, char *sq);
44 static int w_send_tcp(sip_msg_t *msg, char *su, char *sq);
45 static int w_send_data(sip_msg_t *msg, char *suri, char *sdata);
46 static int w_msg_iflag_set(sip_msg_t *msg, char *pflag, char *p2);
47 static int w_msg_iflag_reset(sip_msg_t *msg, char *pflag, char *p2);
48 static int w_msg_iflag_is_set(sip_msg_t *msg, char *pflag, char *p2);
49 static int w_file_read(sip_msg_t *msg, char *fn, char *vn);
50 static int w_file_write(sip_msg_t *msg, char *fn, char *vn);
51 static int w_isxflagset(struct sip_msg *msg, char *flag, str *s2);
52 static int w_resetxflag(struct sip_msg *msg, char *flag, str *s2);
53 static int w_setxflag(struct sip_msg *msg, char *flag, char *s2);
54 static int w_set_send_socket(sip_msg_t *msg, char *psock, char *p2);
55 static int w_set_recv_socket(sip_msg_t *msg, char *psock, char *p2);
56 static int w_set_source_address(sip_msg_t *msg, char *paddr, char *p2);
57 static int w_via_add_srvid(sip_msg_t *msg, char *pflags, char *p2);
58
59 static int fixup_file_op(void** param, int param_no);
60
61 int corex_alias_subdomains_param(modparam_t type, void *val);
62
63 static int  mod_init(void);
64 static int  child_init(int);
65 static void mod_destroy(void);
66
67 static pv_export_t mod_pvs[] = {
68         { {"cfg", (sizeof("cfg")-1)}, PVT_OTHER, pv_get_cfg, 0,
69                 pv_parse_cfg_name, 0, 0, 0 },
70
71         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
72 };
73
74 static cmd_export_t cmds[]={
75         {"append_branch", (cmd_function)w_append_branch, 0, 0,
76                 0, REQUEST_ROUTE | FAILURE_ROUTE },
77         {"append_branch", (cmd_function)w_append_branch, 1, fixup_spve_null,
78                 0, REQUEST_ROUTE | FAILURE_ROUTE },
79         {"append_branch", (cmd_function)w_append_branch, 2, fixup_spve_spve,
80                 0, REQUEST_ROUTE | FAILURE_ROUTE },
81         {"send", (cmd_function)w_send, 0, 0,
82                 0, REQUEST_ROUTE | FAILURE_ROUTE },
83         {"send", (cmd_function)w_send, 1, fixup_spve_spve,
84                 0, REQUEST_ROUTE | FAILURE_ROUTE },
85         {"send_tcp", (cmd_function)w_send_tcp, 0, 0,
86                 0, REQUEST_ROUTE | FAILURE_ROUTE },
87         {"send_tcp", (cmd_function)w_send_tcp, 1, fixup_spve_null,
88                 0, REQUEST_ROUTE | FAILURE_ROUTE },
89         {"send_data", (cmd_function)w_send_data, 2, fixup_spve_spve,
90                 0, ANY_ROUTE },
91         {"is_incoming",    (cmd_function)nio_check_incoming, 0, 0,
92                 0, ANY_ROUTE },
93         {"msg_iflag_set", (cmd_function)w_msg_iflag_set,       1, fixup_spve_null,
94                 0, ANY_ROUTE },
95         {"msg_iflag_reset", (cmd_function)w_msg_iflag_reset,   1, fixup_spve_null,
96                 0, ANY_ROUTE },
97         {"msg_iflag_is_set", (cmd_function)w_msg_iflag_is_set, 1, fixup_spve_null,
98                 0, ANY_ROUTE },
99         {"file_read", (cmd_function)w_file_read,   2, fixup_file_op,
100                 0, ANY_ROUTE },
101         {"file_write", (cmd_function)w_file_write, 2, fixup_spve_spve,
102                 0, ANY_ROUTE },
103         {"setxflag", (cmd_function)w_setxflag,          1,fixup_igp_null,
104                 0, ANY_ROUTE },
105         {"resetxflag", (cmd_function)w_resetxflag,      1,fixup_igp_null,
106                 0, ANY_ROUTE },
107         {"isxflagset", (cmd_function)w_isxflagset,      1,fixup_igp_null,
108                 0, ANY_ROUTE },
109         {"set_send_socket", (cmd_function)w_set_send_socket, 1, fixup_spve_null,
110                 0, ANY_ROUTE },
111         {"set_recv_socket", (cmd_function)w_set_recv_socket, 1, fixup_spve_null,
112                 0, ANY_ROUTE },
113         {"set_source_address", (cmd_function)w_set_source_address, 1, fixup_spve_null,
114                 0, ANY_ROUTE },
115         {"via_add_srvid", (cmd_function)w_via_add_srvid, 1, fixup_igp_null,
116                 0, ANY_ROUTE },
117
118         {0, 0, 0, 0, 0, 0}
119 };
120
121 static param_export_t params[]={
122         {"alias_subdomains",            STR_PARAM|USE_FUNC_PARAM,
123                 (void*)corex_alias_subdomains_param},
124         {"network_io_intercept",        INT_PARAM, &nio_intercept},
125         {"min_msg_len",                         INT_PARAM, &nio_min_msg_len},
126         {"msg_avp",                                     PARAM_STR, &nio_msg_avp_param},
127
128         {0, 0, 0}
129 };
130
131 struct module_exports exports = {
132         "corex",
133         DEFAULT_DLFLAGS, /* dlopen flags */
134         cmds,
135         params,
136         0,
137         0,              /* exported MI functions */
138         mod_pvs,        /* exported pseudo-variables */
139         0,              /* extra processes */
140         mod_init,       /* module initialization function */
141         0,              /* response function */
142         mod_destroy,    /* destroy function */
143         child_init      /* per child init function */
144 };
145
146
147
148 /**
149  * init module function
150  */
151 static int mod_init(void)
152 {
153         if(corex_init_rpc()<0)
154         {
155                 LM_ERR("failed to register RPC commands\n");
156                 return -1;
157         }
158
159         if(corex_register_check_self()<0)
160         {
161                 LM_ERR("failed to register check self callback\n");
162                 return -1;
163         }
164
165         if((nio_intercept > 0) && (nio_intercept_init() < 0))
166         {
167                 LM_ERR("failed to register network io intercept callback\n");
168                 return -1;
169         }
170
171         return 0;
172 }
173
174 /**
175  * @brief Initialize async module children
176  */
177 static int child_init(int rank)
178 {
179         if (rank!=PROC_MAIN)
180                 return 0;
181
182         return 0;
183 }
184 /**
185  * destroy module function
186  */
187 static void mod_destroy(void)
188 {
189 }
190
191 /**
192  * config wrapper for append branch
193  */
194 static int w_append_branch(sip_msg_t *msg, char *su, char *sq)
195 {
196         if(w_corex_append_branch(msg, (gparam_t*)su, (gparam_t*)sq) < 0)
197                 return -1;
198         return 1;
199 }
200
201 /**
202  * config wrapper for send() and send_tcp()
203  */
204 static int w_send(sip_msg_t *msg, char *su, char *sq)
205 {
206         if(corex_send(msg, (gparam_t*)su, PROTO_UDP) < 0)
207                 return -1;
208         return 1;
209 }
210 static int w_send_tcp(sip_msg_t *msg, char *su, char *sq)
211 {
212         if(corex_send(msg, (gparam_t*)su, PROTO_TCP) < 0)
213                 return -1;
214         return 1;
215 }
216
217 static int w_send_data(sip_msg_t *msg, char *suri, char *sdata)
218 {
219         str uri;
220         str data;
221
222         if (fixup_get_svalue(msg, (gparam_t*)suri, &uri))
223         {
224                 LM_ERR("cannot get the destination parameter\n");
225                 return -1;
226         }
227         if (fixup_get_svalue(msg, (gparam_t*)sdata, &data))
228         {
229                 LM_ERR("cannot get the destination parameter\n");
230                 return -1;
231         }
232         if(corex_send_data(&uri, &data) < 0)
233                 return -1;
234         return 1;
235 }
236
237 int corex_alias_subdomains_param(modparam_t type, void *val)
238 {
239         if(val==NULL)
240                 goto error;
241
242         return corex_add_alias_subdomains((char*)val);
243 error:
244         return -1;
245
246 }
247
248 typedef struct _msg_iflag_name {
249         str name;
250         int value;
251 } msg_iflag_name_t;
252
253 static msg_iflag_name_t _msg_iflag_list[] = {
254         { str_init("USE_UAC_FROM"), FL_USE_UAC_FROM },
255         { str_init("USE_UAC_TO"),   FL_USE_UAC_TO   },
256         { str_init("UAC_AUTH"),     FL_UAC_AUTH     },
257         { {0, 0}, 0 }
258 };
259
260
261 /**
262  *
263  */
264 static int msg_lookup_flag(str *fname)
265 {
266         int i;
267         for(i=0; _msg_iflag_list[i].name.len>0; i++) {
268                 if(fname->len==_msg_iflag_list[i].name.len
269                                 && strncasecmp(_msg_iflag_list[i].name.s, fname->s,
270                                         fname->len)==0) {
271                         return _msg_iflag_list[i].value;
272                 }
273         }
274         return -1;
275 }
276 /**
277  *
278  */
279 static int w_msg_iflag_set(sip_msg_t *msg, char *pflag, char *p2)
280 {
281         int fv;
282         str fname;
283         if (fixup_get_svalue(msg, (gparam_t*)pflag, &fname))
284         {
285                 LM_ERR("cannot get the msg flag name parameter\n");
286                 return -1;
287         }
288         fv =  msg_lookup_flag(&fname);
289         if(fv==1) {
290                 LM_ERR("unsupported flag name [%.*s]\n", fname.len, fname.s);
291                 return -1;
292         }
293         msg->msg_flags |= fv;
294         return 1;
295 }
296
297 /**
298  *
299  */
300 static int w_msg_iflag_reset(sip_msg_t *msg, char *pflag, char *p2)
301 {
302         int fv;
303         str fname;
304         if (fixup_get_svalue(msg, (gparam_t*)pflag, &fname))
305         {
306                 LM_ERR("cannot get the msg flag name parameter\n");
307                 return -1;
308         }
309         fv =  msg_lookup_flag(&fname);
310         if(fv<0) {
311                 LM_ERR("unsupported flag name [%.*s]\n", fname.len, fname.s);
312                 return -1;
313         }
314         msg->msg_flags &= ~fv;
315         return 1;
316 }
317
318 /**
319  *
320  */
321 static int w_msg_iflag_is_set(sip_msg_t *msg, char *pflag, char *p2)
322 {
323         int fv;
324         str fname;
325         if (fixup_get_svalue(msg, (gparam_t*)pflag, &fname))
326         {
327                 LM_ERR("cannot get the msg flag name parameter\n");
328                 return -1;
329         }
330         fv =  msg_lookup_flag(&fname);
331         if(fv<0) {
332                 LM_ERR("unsupported flag name [%.*s]\n", fname.len, fname.s);
333                 return -1;
334         }
335         if(msg->msg_flags & fv)
336                 return 1;
337         return -2;
338 }
339
340 /**
341  *
342  */
343 static int w_file_read(sip_msg_t *msg, char *fn, char *vn)
344 {
345         str fname;
346         pv_spec_t *vp;
347         pv_value_t val;
348
349         FILE *f;
350         long fsize;
351         char *content;
352
353         fname.len = 0;
354         if (fixup_get_svalue(msg, (gparam_p)fn, &fname) != 0 || fname.len<=0) {
355                 LM_ERR("cannot get file path\n");
356                 return -1;
357         }
358         LM_DBG("reading from file: %.*s\n", fname.len, fname.s);
359         vp = (pv_spec_t*)vn;
360
361         f = fopen(fname.s, "r");
362         if(f==NULL) {
363                 LM_ERR("cannot open file: %.*s\n", fname.len, fname.s);
364                 return -1;
365         }
366         fseek(f, 0, SEEK_END);
367         fsize = ftell(f);
368         if(fsize<0) {
369                 LM_ERR("ftell failed on file: %.*s\n", fname.len, fname.s);
370                 fclose(f);
371                 return -1;
372         }
373         fseek(f, 0, SEEK_SET);
374
375         content = pkg_malloc(fsize + 1);
376         if(content==NULL) {
377                 LM_ERR("no more pkg memory\n");
378                 fclose(f);
379                 return -1;
380         }
381         if(fread(content, fsize, 1, f) != fsize) {
382                 if(ferror(f)) {
383                         LM_ERR("error reading from file: %.*s\n",
384                                 fname.len, fname.s);
385                 }
386         }
387         fclose(f);
388         content[fsize] = 0;
389
390
391         val.rs.s = content;
392         val.rs.len = fsize;
393         LM_DBG("file content: [[%.*s]]\n", val.rs.len, val.rs.s);
394         val.flags = PV_VAL_STR;
395         vp->setf(msg, &vp->pvp, (int)EQ_T, &val);
396         pkg_free(content);
397
398         return 1;
399 }
400
401 /**
402  *
403  */
404 static int w_file_write(sip_msg_t *msg, char *fn, char *vn)
405 {
406         str fname;
407         str content;
408         FILE *f;
409
410         fname.len = 0;
411         if (fixup_get_svalue(msg, (gparam_p)fn, &fname) != 0 || fname.len<=0) {
412                 LM_ERR("cannot get file path\n");
413                 return -1;
414         }
415         content.len = 0;
416         if (fixup_get_svalue(msg, (gparam_p)vn, &content) != 0 || content.len<=0) {
417                 LM_ERR("cannot get the content\n");
418                 return -1;
419         }
420
421         LM_DBG("writing to file: %.*s\n", fname.len, fname.s);
422         f = fopen(fname.s, "w");
423         if(f==NULL) {
424                 LM_ERR("cannot open file: %.*s\n", fname.len, fname.s);
425                 return -1;
426         }
427         fwrite(content.s, 1, content.len, f);
428         fclose(f);
429
430         return 1;
431 }
432
433 /**
434  *
435  */
436 static int fixup_file_op(void** param, int param_no)
437 {
438         if (param_no == 1) {
439                 return fixup_spve_null(param, 1);
440         }
441
442         if (param_no == 2) {
443                 if (fixup_pvar_null(param, 1) != 0) {
444                         LM_ERR("failed to fixup result pvar\n");
445                         return -1;
446                 }
447                 if (((pv_spec_t *)(*param))->setf == NULL) {
448                         LM_ERR("result pvar is not writeble\n");
449                         return -1;
450                 }
451                 return 0;
452         }
453
454         LM_ERR("invalid parameter number <%d>\n", param_no);
455         return -1;
456 }
457
458 /**
459  *
460  */
461 static int ki_append_branch(sip_msg_t *msg)
462 {
463         if(corex_append_branch(msg, NULL, NULL) < 0)
464                 return -1;
465         return 1;
466 }
467
468 /**
469  *
470  */
471 static int ki_append_branch_uri(sip_msg_t *msg, str *uri)
472 {
473         if(corex_append_branch(msg, uri, NULL) < 0)
474                 return -1;
475         return 1;
476 }
477
478 /**
479  *
480  */
481 static int ki_append_branch_uri_q(sip_msg_t *msg, str *uri, str *q)
482 {
483         if(corex_append_branch(msg, uri, q) < 0)
484                 return -1;
485         return 1;
486 }
487
488 /**
489  *
490  */
491 static int ki_isxflagset(sip_msg_t *msg, int fval)
492 {
493         if((flag_t)fval>KSR_MAX_XFLAG)
494                 return -1;
495         return isxflagset(msg, (flag_t)fval);
496 }
497
498 /**
499  *
500  */
501 static int w_isxflagset(sip_msg_t *msg, char *flag, str *s2)
502 {
503         int fval=0;
504         if(fixup_get_ivalue(msg, (gparam_t*)flag, &fval)!=0) {
505                 LM_ERR("no flag value\n");
506                 return -1;
507         }
508         return ki_isxflagset(msg, fval);
509 }
510
511 /**
512  *
513  */
514 static int ki_resetxflag(sip_msg_t *msg, int fval)
515 {
516         if((flag_t)fval>KSR_MAX_XFLAG)
517                 return -1;
518         return resetxflag(msg, (flag_t)fval);
519 }
520
521 /**
522  *
523  */
524 static int w_resetxflag(sip_msg_t *msg, char *flag, str *s2)
525 {
526         int fval=0;
527         if(fixup_get_ivalue(msg, (gparam_t*)flag, &fval)!=0) {
528                 LM_ERR("no flag value\n");
529                 return -1;
530         }
531         return ki_resetxflag(msg, fval);
532 }
533
534 /**
535  *
536  */
537 static int ki_setxflag(sip_msg_t *msg, int fval)
538 {
539         if((flag_t)fval>KSR_MAX_XFLAG)
540                 return -1;
541         return setxflag(msg, (flag_t)fval);
542 }
543
544 /**
545  *
546  */
547 static int w_setxflag(sip_msg_t *msg, char *flag, char *s2)
548 {
549         int fval=0;
550         if(fixup_get_ivalue(msg, (gparam_t*)flag, &fval)!=0) {
551                 LM_ERR("no flag value\n");
552                 return -1;
553         }
554         return ki_setxflag(msg, fval);
555 }
556
557 /**
558  *
559  */
560 static int ki_set_socket_helper(sip_msg_t *msg, str *ssock, int smode)
561 {
562         socket_info_t *si;
563         int port, proto;
564         str host;
565
566         if(msg==NULL) {
567                 LM_ERR("bad parameters\n");
568                 return -1;
569         }
570
571         if(ssock==NULL || ssock->len<=0) {
572                 reset_force_socket(msg);
573                 return 1;
574         }
575
576         if (parse_phostport(ssock->s, &host.s, &host.len, &port, &proto) < 0) {
577                 LM_ERR("invalid socket specification [%.*s] (%d)\n",
578                                 ssock->len, ssock->s, smode);
579                 goto error;
580         }
581         si = grep_sock_info(&host, (unsigned short)port, (unsigned short)proto);
582         if (si!=NULL) {
583                 if(smode==0) {
584                         /* send socket */
585                         set_force_socket(msg, si);
586                 } else {
587                         /* recv socket */
588                         msg->rcv.bind_address = si;
589                         msg->rcv.dst_port = si->port_no;
590                         msg->rcv.dst_ip = si->address;
591                         msg->rcv.proto = si->proto;
592                         msg->rcv.proto_reserved1 = 0;
593                         msg->rcv.proto_reserved2 = 0;
594                 }
595         } else {
596                 LM_WARN("no socket found to match [%.*s] (%d)\n",
597                                 ssock->len, ssock->s, smode);
598         }
599         return 1;
600 error:
601         return -1;
602 }
603
604 /**
605  *
606  */
607 static int ki_set_send_socket(sip_msg_t *msg, str *ssock)
608 {
609         return ki_set_socket_helper(msg, ssock, 0);
610 }
611
612 /**
613  *
614  */
615 static int w_set_send_socket(sip_msg_t *msg, char *psock, char *p2)
616 {
617         str ssock;
618         if (fixup_get_svalue(msg, (gparam_t*)psock, &ssock) != 0 || ssock.len<=0) {
619                 LM_ERR("cannot get socket address value\n");
620                 return -1;
621         }
622         return ki_set_send_socket(msg, &ssock);
623 }
624
625 /**
626  *
627  */
628 static int ki_set_recv_socket(sip_msg_t *msg, str *ssock)
629 {
630         return ki_set_socket_helper(msg, ssock, 1);
631 }
632
633 /**
634  *
635  */
636 static int w_set_recv_socket(sip_msg_t *msg, char *psock, char *p2)
637 {
638         str ssock;
639         if (fixup_get_svalue(msg, (gparam_t*)psock, &ssock) != 0 || ssock.len<=0) {
640                 LM_ERR("cannot get socket address value\n");
641                 return -1;
642         }
643         return ki_set_recv_socket(msg, &ssock);
644 }
645
646 /**
647  *
648  */
649 static int ki_set_source_address(sip_msg_t *msg, str *saddr)
650 {
651         sr_phostp_t rp;
652         union sockaddr_union faddr;
653         char cproto;
654         int ret;
655
656         if(msg==NULL || saddr==NULL || saddr->len<=0) {
657                 LM_ERR("bad parameters\n");
658                 return -1;
659         }
660
661         if(parse_protohostport(saddr, &rp)<0) {
662                 LM_ERR("failed to parse the address [%.*s]\n", saddr->len, saddr->s);
663                 return -1;
664         }
665
666         cproto = (char)rp.proto;
667         ret = sip_hostport2su(&faddr, &rp.host, (unsigned short)rp.port, &cproto);
668         if(ret!=0) {
669                 LM_ERR("failed to resolve address [%.*s]\n", saddr->len, saddr->s);
670                 return -1;
671         }
672
673         msg->rcv.src_su=faddr;
674         su2ip_addr(&msg->rcv.src_ip, &faddr);
675         msg->rcv.src_port=rp.port;
676
677         return 1;
678 }
679
680 /**
681  *
682  */
683 static int w_set_source_address(sip_msg_t *msg, char *paddr, char *p2)
684 {
685         str saddr;
686         if (fixup_get_svalue(msg, (gparam_t*)paddr, &saddr) != 0 || saddr.len<=0) {
687                 LM_ERR("cannot get source address value\n");
688                 return -1;
689         }
690         return ki_set_source_address(msg, &saddr);
691 }
692
693 /**
694  *
695  */
696 static int ki_via_add_srvid(sip_msg_t *msg, int fval)
697 {
698         if(msg==NULL)
699                 return -1;
700         if(fval) {
701                 msg->msg_flags |= FL_ADD_SRVID;
702         } else {
703                 msg->msg_flags &= ~(FL_ADD_SRVID);
704         }
705         return 1;
706 }
707
708 /**
709  *
710  */
711 static int w_via_add_srvid(sip_msg_t *msg, char *pflags, char *s2)
712 {
713         int fval=0;
714         if(fixup_get_ivalue(msg, (gparam_t*)pflags, &fval)!=0) {
715                 LM_ERR("no flag value\n");
716                 return -1;
717         }
718         return ki_via_add_srvid(msg, fval);
719 }
720
721 /**
722  *
723  */
724 /* clang-format off */
725 static sr_kemi_t sr_kemi_corex_exports[] = {
726         { str_init("corex"), str_init("append_branch"),
727                 SR_KEMIP_INT, ki_append_branch,
728                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
729                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
730         },
731         { str_init("corex"), str_init("append_branch_uri"),
732                 SR_KEMIP_INT, ki_append_branch_uri,
733                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
734                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
735         },
736         { str_init("corex"), str_init("append_branch_uri_q"),
737                 SR_KEMIP_INT, ki_append_branch_uri_q,
738                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
739                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
740         },
741         { str_init("corex"), str_init("setxflag"),
742                 SR_KEMIP_INT, ki_setxflag,
743                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
744                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
745         },
746         { str_init("corex"), str_init("resetxflag"),
747                 SR_KEMIP_INT, ki_resetxflag,
748                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
749                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
750         },
751         { str_init("corex"), str_init("isxflagset"),
752                 SR_KEMIP_INT, ki_isxflagset,
753                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
754                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
755         },
756         { str_init("corex"), str_init("set_send_socket"),
757                 SR_KEMIP_INT, ki_set_send_socket,
758                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
759                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
760         },
761         { str_init("corex"), str_init("set_recv_socket"),
762                 SR_KEMIP_INT, ki_set_recv_socket,
763                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
764                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
765         },
766         { str_init("corex"), str_init("set_source_address"),
767                 SR_KEMIP_INT, ki_set_source_address,
768                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
769                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
770         },
771         { str_init("corex"), str_init("via_add_srvid"),
772                 SR_KEMIP_INT, ki_via_add_srvid,
773                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
774                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
775         },
776
777         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
778 };
779 /* clang-format on */
780
781 /**
782  *
783  */
784 int mod_register(char *path, int *dlflags, void *p1, void *p2)
785 {
786         sr_kemi_modules_add(sr_kemi_corex_exports);
787         return 0;
788 }