a01a72f7a3244137a97a2589760587121f7f4da8
[sip-router] / src / modules / kemix / kemix_mod.c
1 /**
2  * Copyright (C) 2019 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 #include <string.h>
26
27 #include "../../core/sr_module.h"
28 #include "../../core/dprint.h"
29 #include "../../core/kemi.h"
30 #include "../../core/parser/parse_uri.h"
31 #include "../../core/parser/parse_from.h"
32 #include "../../core/parser/parse_to.h"
33
34 MODULE_VERSION
35
36 struct module_exports exports = {
37         "kemix",         /* module name */
38         DEFAULT_DLFLAGS, /* dlopen flags */
39         0,               /* cmd (cfg function) exports */
40         0,               /* param exports */
41         0,               /* RPC method exports */
42         0,               /* pseudo-variables exports */
43         0,               /* response handling function */
44         0,               /* module init function */
45         0,               /* per-child init function */
46         0                /* module destroy function */
47 };
48
49
50 /**
51  *
52  */
53 static sr_kemi_xval_t _sr_kemi_kx_xval = {0};
54
55 /**
56  *
57  */
58 static sr_kemi_xval_t* ki_kx_get_ruri(sip_msg_t *msg)
59 {
60         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
61
62         if(msg==NULL) {
63                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
64                 return &_sr_kemi_kx_xval;
65         }
66
67         if(msg->first_line.type == SIP_REPLY) {
68                 /* REPLY doesnt have a ruri */
69                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
70                 return &_sr_kemi_kx_xval;
71         }
72
73         if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) {
74                 LM_ERR("failed to parse the R-URI\n");
75                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
76                 return &_sr_kemi_kx_xval;
77         }
78
79         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
80         if (msg->new_uri.s!=NULL) {
81                 _sr_kemi_kx_xval.v.s = msg->new_uri;
82         } else {
83                 _sr_kemi_kx_xval.v.s = msg->first_line.u.request.uri;
84         }
85         return &_sr_kemi_kx_xval;
86 }
87
88 /**
89  *
90  */
91 static sr_kemi_xval_t* ki_kx_get_ouri(sip_msg_t *msg)
92 {
93         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
94
95         if(msg==NULL) {
96                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
97                 return &_sr_kemi_kx_xval;
98         }
99
100         if(msg->first_line.type == SIP_REPLY) {
101                 /* REPLY doesnt have a ruri */
102                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
103                 return &_sr_kemi_kx_xval;
104         }
105
106         if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) {
107                 LM_ERR("failed to parse the R-URI\n");
108                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
109                 return &_sr_kemi_kx_xval;
110         }
111
112         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
113         _sr_kemi_kx_xval.v.s = msg->first_line.u.request.uri;
114         return &_sr_kemi_kx_xval;
115 }
116
117 /**
118  *
119  */
120 static sr_kemi_xval_t* ki_kx_get_furi(sip_msg_t *msg)
121 {
122         to_body_t *xto = NULL;
123
124         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
125
126         if(msg==NULL) {
127                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
128                 return &_sr_kemi_kx_xval;
129         }
130         if(parse_from_header(msg)<0) {
131                 LM_ERR("cannot parse From header\n");
132                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
133                 return &_sr_kemi_kx_xval;
134         }
135         if(msg->from==NULL || get_from(msg)==NULL) {
136                 LM_DBG("no From header\n");
137                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
138                 return &_sr_kemi_kx_xval;
139         }
140
141         xto = get_from(msg);
142         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
143         _sr_kemi_kx_xval.v.s = xto->uri;
144         return &_sr_kemi_kx_xval;
145 }
146
147 /**
148  *
149  */
150 static sr_kemi_xval_t* ki_kx_get_turi(sip_msg_t *msg)
151 {
152         to_body_t *xto = NULL;
153
154         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
155
156         if(msg==NULL) {
157                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
158                 return &_sr_kemi_kx_xval;
159         }
160         if(parse_to_header(msg)<0) {
161                 LM_ERR("cannot parse To header\n");
162                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
163                 return &_sr_kemi_kx_xval;
164         }
165         if(msg->to==NULL || get_to(msg)==NULL) {
166                 LM_DBG("no To header\n");
167                 sr_kemi_xval_null(&_sr_kemi_kx_xval, 0);
168                 return &_sr_kemi_kx_xval;
169         }
170
171         xto = get_to(msg);
172         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
173         _sr_kemi_kx_xval.v.s = xto->uri;
174         return &_sr_kemi_kx_xval;
175 }
176
177 /**
178  *
179  */
180 static sr_kemi_xval_t* ki_kx_get_xuri_attr(sip_msg_t *msg, sip_uri_t *puri,
181                 int iattr, int xmode)
182 {
183         if(iattr==1) {
184                 /* username */
185                 if(puri->user.s==NULL || puri->user.len<=0) {
186                         sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
187                         return &_sr_kemi_kx_xval;
188                 }
189                 _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
190                 _sr_kemi_kx_xval.v.s = puri->user;
191                 return &_sr_kemi_kx_xval;
192         } else if(iattr==2) {
193                 /* domain */
194                 if(puri->host.s==NULL || puri->host.len<=0) {
195                         sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
196                         return &_sr_kemi_kx_xval;
197                 }
198                 _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
199                 _sr_kemi_kx_xval.v.s = puri->host;
200                 return &_sr_kemi_kx_xval;
201         }
202         LM_ERR("unknown attribute id: %d\n", iattr);
203         sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
204         return &_sr_kemi_kx_xval;
205 }
206
207 /**
208  *
209  */
210 static sr_kemi_xval_t* ki_kx_get_ruri_attr(sip_msg_t *msg, int iattr, int xmode)
211 {
212         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
213
214         if(msg==NULL || msg->first_line.type == SIP_REPLY) {
215                 sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
216                 return &_sr_kemi_kx_xval;
217         }
218
219         if(msg->parsed_uri_ok==0 /* R-URI not parsed*/ && parse_sip_msg_uri(msg)<0) {
220                 LM_ERR("failed to parse the R-URI\n");
221                 sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
222                 return &_sr_kemi_kx_xval;
223         }
224         return ki_kx_get_xuri_attr(msg, &(msg->parsed_uri), iattr, xmode);
225 }
226
227 /**
228  *
229  */
230 static sr_kemi_xval_t* ki_kx_get_ruser(sip_msg_t *msg)
231 {
232         return ki_kx_get_ruri_attr(msg, 1, SR_KEMI_XVAL_NULL_NONE);
233 }
234
235 /**
236  *
237  */
238 static sr_kemi_xval_t* ki_kx_getw_ruser(sip_msg_t *msg)
239 {
240         return ki_kx_get_ruri_attr(msg, 1, SR_KEMI_XVAL_NULL_PRINT);
241 }
242
243 /**
244  *
245  */
246 static sr_kemi_xval_t* ki_kx_gete_ruser(sip_msg_t *msg)
247 {
248         return ki_kx_get_ruri_attr(msg, 1, SR_KEMI_XVAL_NULL_EMPTY);
249 }
250
251 /**
252  *
253  */
254 static sr_kemi_xval_t* ki_kx_get_rhost(sip_msg_t *msg)
255 {
256         return ki_kx_get_ruri_attr(msg, 2, SR_KEMI_XVAL_NULL_NONE);
257 }
258
259 /**
260  *
261  */
262 static sr_kemi_xval_t* ki_kx_getw_rhost(sip_msg_t *msg)
263 {
264         return ki_kx_get_ruri_attr(msg, 2, SR_KEMI_XVAL_NULL_PRINT);
265 }
266
267 /**
268  *
269  */
270 static sr_kemi_xval_t* ki_kx_gete_rhost(sip_msg_t *msg)
271 {
272         return ki_kx_get_ruri_attr(msg, 2, SR_KEMI_XVAL_NULL_EMPTY);
273 }
274
275 /**
276  *
277  */
278 static sr_kemi_xval_t* ki_kx_get_furi_attr(sip_msg_t *msg, int iattr, int xmode)
279 {
280         sip_uri_t *uri;
281
282         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
283         uri=parse_from_uri(msg);
284         if(uri==NULL) {
285                 sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
286                 return &_sr_kemi_kx_xval;
287         }
288
289         return ki_kx_get_xuri_attr(msg, uri, iattr, xmode);
290 }
291
292 /**
293  *
294  */
295 static sr_kemi_xval_t* ki_kx_get_fuser(sip_msg_t *msg)
296 {
297         return ki_kx_get_furi_attr(msg, 1, SR_KEMI_XVAL_NULL_NONE);
298 }
299
300 /**
301  *
302  */
303 static sr_kemi_xval_t* ki_kx_getw_fuser(sip_msg_t *msg)
304 {
305         return ki_kx_get_furi_attr(msg, 1, SR_KEMI_XVAL_NULL_PRINT);
306 }
307
308 /**
309  *
310  */
311 static sr_kemi_xval_t* ki_kx_gete_fuser(sip_msg_t *msg)
312 {
313         return ki_kx_get_furi_attr(msg, 1, SR_KEMI_XVAL_NULL_EMPTY);
314 }
315
316 /**
317  *
318  */
319 static sr_kemi_xval_t* ki_kx_get_fhost(sip_msg_t *msg)
320 {
321         return ki_kx_get_furi_attr(msg, 2, SR_KEMI_XVAL_NULL_NONE);
322 }
323
324 /**
325  *
326  */
327 static sr_kemi_xval_t* ki_kx_getw_fhost(sip_msg_t *msg)
328 {
329         return ki_kx_get_furi_attr(msg, 2, SR_KEMI_XVAL_NULL_PRINT);
330 }
331
332 /**
333  *
334  */
335 static sr_kemi_xval_t* ki_kx_gete_fhost(sip_msg_t *msg)
336 {
337         return ki_kx_get_furi_attr(msg, 2, SR_KEMI_XVAL_NULL_EMPTY);
338 }
339
340 /**
341  *
342  */
343 static sr_kemi_xval_t* ki_kx_get_ua_mode(sip_msg_t *msg, int rmode)
344 {
345         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
346         if(msg==NULL) {
347                 sr_kemi_xval_null(&_sr_kemi_kx_xval, rmode);
348                 return &_sr_kemi_kx_xval;
349         }
350         if(msg->user_agent==NULL && ((parse_headers(msg, HDR_USERAGENT_F, 0)==-1)
351                         || (msg->user_agent==NULL))) {
352                 sr_kemi_xval_null(&_sr_kemi_kx_xval, rmode);
353                 return &_sr_kemi_kx_xval;
354         }
355
356         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
357         _sr_kemi_kx_xval.v.s = msg->user_agent->body;
358         return &_sr_kemi_kx_xval;
359 }
360
361 /**
362  *
363  */
364 static sr_kemi_xval_t* ki_kx_get_ua(sip_msg_t *msg)
365 {
366         return ki_kx_get_ua_mode(msg, SR_KEMI_XVAL_NULL_NONE);
367 }
368
369 /**
370  *
371  */
372 static sr_kemi_xval_t* ki_kx_gete_ua(sip_msg_t *msg)
373 {
374         return ki_kx_get_ua_mode(msg, SR_KEMI_XVAL_NULL_EMPTY);
375 }
376
377 /**
378  *
379  */
380 static sr_kemi_xval_t* ki_kx_getw_ua(sip_msg_t *msg)
381 {
382         return ki_kx_get_ua_mode(msg, SR_KEMI_XVAL_NULL_PRINT);
383 }
384
385 /**
386  *
387  */
388 static sr_kemi_xval_t* ki_kx_get_srcip(sip_msg_t *msg)
389 {
390         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
391         if(msg==NULL) {
392                 sr_kemi_xval_null(&_sr_kemi_kx_xval, SR_KEMI_XVAL_NULL_NONE);
393                 return &_sr_kemi_kx_xval;
394         }
395
396         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
397         _sr_kemi_kx_xval.v.s.s = ip_addr2a(&msg->rcv.src_ip);
398         _sr_kemi_kx_xval.v.s.len = strlen(_sr_kemi_kx_xval.v.s.s);
399         return &_sr_kemi_kx_xval;
400 }
401
402 /**
403  *
404  */
405 static sr_kemi_xval_t* ki_kx_get_srcport(sip_msg_t *msg)
406 {
407         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
408         if(msg==NULL) {
409                 _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
410                 _sr_kemi_kx_xval.v.n = 0;
411                 return &_sr_kemi_kx_xval;
412         }
413
414         _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
415         _sr_kemi_kx_xval.v.n = (int)msg->rcv.src_port;
416         return &_sr_kemi_kx_xval;
417 }
418
419 /**
420  *
421  */
422 static sr_kemi_xval_t* ki_kx_get_rcvip(sip_msg_t *msg)
423 {
424         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
425         if(msg==NULL || msg->rcv.bind_address==NULL
426                         || msg->rcv.bind_address->address_str.s==NULL) {
427                 sr_kemi_xval_null(&_sr_kemi_kx_xval, SR_KEMI_XVAL_NULL_NONE);
428                 return &_sr_kemi_kx_xval;
429         }
430
431         _sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
432         _sr_kemi_kx_xval.v.s = msg->rcv.bind_address->address_str;
433         return &_sr_kemi_kx_xval;
434 }
435
436 /**
437  *
438  */
439 static sr_kemi_xval_t* ki_kx_get_rcvport(sip_msg_t *msg)
440 {
441         memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
442         if(msg==NULL || msg->rcv.bind_address==NULL) {
443                 _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
444                 _sr_kemi_kx_xval.v.n = 0;
445                 return &_sr_kemi_kx_xval;
446         }
447
448         _sr_kemi_kx_xval.vtype = SR_KEMIP_INT;
449         _sr_kemi_kx_xval.v.n = (int)msg->rcv.bind_address->port_no;
450         return &_sr_kemi_kx_xval;
451 }
452
453 /**
454  *
455  */
456 /* clang-format off */
457 static sr_kemi_t sr_kemi_kx_exports[] = {
458         { str_init("kx"), str_init("get_ruri"),
459                 SR_KEMIP_XVAL, ki_kx_get_ruri,
460                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
461                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
462         },
463         { str_init("kx"), str_init("get_ouri"),
464                 SR_KEMIP_XVAL, ki_kx_get_ouri,
465                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
466                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
467         },
468         { str_init("kx"), str_init("get_furi"),
469                 SR_KEMIP_XVAL, ki_kx_get_furi,
470                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
471                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
472         },
473         { str_init("kx"), str_init("get_turi"),
474                 SR_KEMIP_XVAL, ki_kx_get_turi,
475                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
476                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
477         },
478         { str_init("kx"), str_init("get_ruser"),
479                 SR_KEMIP_XVAL, ki_kx_get_ruser,
480                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
481                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
482         },
483         { str_init("kx"), str_init("getw_ruser"),
484                 SR_KEMIP_XVAL, ki_kx_getw_ruser,
485                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
486                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
487         },
488         { str_init("kx"), str_init("gete_ruser"),
489                 SR_KEMIP_XVAL, ki_kx_gete_ruser,
490                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
491                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
492         },
493         { str_init("kx"), str_init("get_rhost"),
494                 SR_KEMIP_XVAL, ki_kx_get_rhost,
495                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
496                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
497         },
498         { str_init("kx"), str_init("getw_rhost"),
499                 SR_KEMIP_XVAL, ki_kx_getw_rhost,
500                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
501                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
502         },
503         { str_init("kx"), str_init("gete_rhost"),
504                 SR_KEMIP_XVAL, ki_kx_gete_rhost,
505                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
506                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
507         },
508         { str_init("kx"), str_init("get_ua"),
509                 SR_KEMIP_XVAL, ki_kx_get_ua,
510                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
511                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
512         },
513         { str_init("kx"), str_init("gete_ua"),
514                 SR_KEMIP_XVAL, ki_kx_gete_ua,
515                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
516                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
517         },
518         { str_init("kx"), str_init("getw_ua"),
519                 SR_KEMIP_XVAL, ki_kx_getw_ua,
520                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
521                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
522         },
523         { str_init("kx"), str_init("get_srcip"),
524                 SR_KEMIP_XVAL, ki_kx_get_srcip,
525                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
526                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
527         },
528         { str_init("kx"), str_init("get_srcport"),
529                 SR_KEMIP_XVAL, ki_kx_get_srcport,
530                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
531                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
532         },
533         { str_init("kx"), str_init("get_rcvip"),
534                 SR_KEMIP_XVAL, ki_kx_get_rcvip,
535                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
536                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
537         },
538         { str_init("kx"), str_init("get_rcvport"),
539                 SR_KEMIP_XVAL, ki_kx_get_rcvport,
540                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
541                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
542         },
543
544         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
545 };
546
547 /**
548  *
549  */
550 int mod_register(char *path, int *dlflags, void *p1, void *p2)
551 {
552         sr_kemi_modules_add(sr_kemi_kx_exports);
553         return 0;
554 }