533e1146996b58e5da5deaad6543676f64629ed4
[kamailio] / src / modules / sipt / sipt.c
1 /*
2  *
3  * Copyright (C) 2015 Voxbone SA
4  *
5  * This file is part of SIP-Router, a free SIP server.
6  *
7  * SIP-Router is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * SIP-Router is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23
24 #include "../../core/sr_module.h"
25 #include "../../core/parser/parse_param.h"
26 #include "../../core/data_lump.h"
27 #include "../../core/mem/mem.h"
28 #include "../../core/mod_fix.h"
29 #include "../../core/parser/parse_content.h"
30 #include "../../core/parser/parse_body.h"
31 #include "../../core/parser/parser_f.h"
32 #include "../../core/trim.h"
33 #include "ss7.h"
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37
38
39 MODULE_VERSION
40
41 static int sipt_set_bci_1(struct sip_msg *msg, char *_charge_indicator, char *_called_status, char * _called_category, char * _e2e_indicator);
42 static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops, char * _nai);
43 static int sipt_destination2(struct sip_msg *msg, char *_destination, char *_hops, char * _nai, char * _terminator);
44 static int sipt_forwarding(struct sip_msg *msg, char *_fwdnumber, char * _nai);
45 static int sipt_set_calling(struct sip_msg *msg, char *_origin, char *_nai, char *_pres, char * _screen);
46 static int sipt_get_hop_counter(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
47 static int sipt_get_event_info(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
48 static int sipt_get_cpc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
49 static int sipt_get_calling_party_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
50 static int sipt_get_calling_party(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
51 static int sipt_get_presentation(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
52 static int sipt_get_screening(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
53 static int sipt_get_called_party_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
54 static int sipt_get_called_party(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
55 static int sipt_get_charge_indicator(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
56
57 static int sipt_get_redirection_info(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
58 static int sipt_get_redirection_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
59 static int sipt_get_redirection_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
60
61 static int sipt_get_redirection_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
62 static int sipt_get_original_redirection_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
63 static int sipt_get_redirecting_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
64 static int sipt_get_redirecting_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
65 static int sipt_get_original_called_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
66 static int sipt_get_original_called_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
67 static int sipt_get_generic_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
68 static int sipt_get_generic_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
69
70 static int sipt_has_isup_body(struct sip_msg *msg, char *type, char *str2 );
71
72 /* New API */
73 int sipt_parse_pv_name(pv_spec_p sp, str *in);
74 static int sipt_get_pv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res);
75
76 typedef struct _sipt_pv {
77         int type;
78         int sub_type;
79 } sipt_pv_t;
80
81 typedef struct sipt_header_map
82 {
83         char * name;
84         unsigned int type;
85         struct sipt_subtype_map
86         {
87                 char * name;
88                 unsigned int type;
89         } subtypes[5];
90 } sipt_header_map_t;
91
92 static sipt_header_map_t sipt_header_mapping[] =
93 {
94         {"CALLING_PARTY_CATEGORY", ISUP_PARM_CALLING_PARTY_CAT, 
95                 {{NULL, 0}} },
96         {"CPC", ISUP_PARM_CALLING_PARTY_CAT, 
97                 {{NULL, 0}} },
98         {"CALLING_PARTY_NUMBER", ISUP_PARM_CALLING_PARTY_NUM, 
99                 {{"NATURE_OF_ADDRESS", 1}, 
100                         {"NAI", 1},
101                         {"SCREENING", 2},
102                         {"PRESENTATION", 3},
103                         {NULL, 0}
104                 }},
105         {"CALLED_PARTY_NUMBER", ISUP_PARM_CALLED_PARTY_NUM,
106                 {{"NATURE_OF_ADDRESS", 1}, 
107                         {"NAI", 1},
108                         {NULL, 0}
109                 }},
110         {"HOP_COUNTER", ISUP_PARM_HOP_COUNTER, 
111                 {{NULL, 0}} },
112         {"EVENT_INFO", ISUP_PARM_EVENT_INFO, 
113                 {{NULL, 0}} },
114         {"BACKWARD_CALL_INDICATOR", ISUP_PARM_BACKWARD_CALL_IND,
115                 {{"CHARGE_INDICATOR", 1}, 
116                         {NULL, 0}
117                 }},
118         {"REDIRECTION_INFO", ISUP_PARM_DIVERSION_INFORMATION,
119                 {{NULL, 0}}  },
120         {"REDIRECTION_NUMBER", ISUP_PARM_REDIRECTION_NUMBER,
121                 {{"NATURE_OF_ADDRESS", 1},
122                         {"NAI", 1},
123                         {NULL, 0}
124                 }},
125         {"REDIRECTION_INFORMATION", ISUP_PARM_REDIRECTION_INFO,
126                 {{"REASON", 1},
127                         {"ORIGINAL_REASON", 2},
128                         {NULL, 0}
129                 }},
130         {"REDIRECTING_NUMBER", ISUP_PARM_REDIRECTING_NUMBER,
131                 {{"NATURE_OF_ADDRESS", 1},
132                         {"NAI", 1},
133                         {NULL, 0}
134                 }},
135         {"ORIGINAL_CALLED_NUMBER", ISUP_PARM_ORIGINAL_CALLED_NUM,
136                 {{"NATURE_OF_ADDRESS", 1},
137                         {"NAI", 1},
138                         {NULL, 0}
139                 }},
140         {"GENERIC_NUMBER", ISUP_PARM_GENERIC_ADDR,
141                 {{"NATURE_OF_ADDRESS", 1},
142                         {"NAI", 1},
143                         {NULL, 0}
144                 }},
145         { NULL, 0, {}}
146 };
147
148
149
150 static int mod_init(void);
151 static void mod_destroy(void);
152
153
154
155 static int fixup_str_str_str(void** param, int param_no)
156 {
157         if(param_no == 1 || param_no == 2 || param_no == 3 || param_no == 4)
158         {
159                 return fixup_str_null(param, 1);
160         }
161         return E_CFG;
162 }
163
164 static int fixup_free_str_str_str(void** param, int param_no)
165 {
166         if(param_no == 1 || param_no == 2 || param_no == 3 || param_no == 4)
167         {
168                 return fixup_free_str_null(param, 1);
169         }
170         return E_CFG;
171 }
172
173
174 static cmd_export_t cmds[]={
175         {"sipt_destination", /* action name as in scripts */
176                 (cmd_function)sipt_destination,  /* C function name */
177                 3,          /* number of parameters */
178                 fixup_str_str_str, fixup_free_str_str_str,         /* */
179                 /* can be applied to original requests */
180                 REQUEST_ROUTE|BRANCH_ROUTE}, 
181         {"sipt_destination", /* action name as in scripts */
182                 (cmd_function)sipt_destination2,  /* C function name */
183                 4,          /* number of parameters */
184                 fixup_str_str_str, fixup_free_str_str_str,         /* */
185                 /* can be applied to original requests */
186                 REQUEST_ROUTE|BRANCH_ROUTE}, 
187         {"sipt_forwarding", /* action name as in scripts */
188                 (cmd_function)sipt_forwarding,  /* C function name */
189                 2,          /* number of parameters */
190                 fixup_str_str_str, fixup_free_str_str_str,         /* */
191                 /* can be applied to original requests */
192                 REQUEST_ROUTE|BRANCH_ROUTE}, 
193         {"sipt_set_calling", /* action name as in scripts */
194                 (cmd_function)sipt_set_calling,  /* C function name */
195                 4,          /* number of parameters */
196                 fixup_str_str_str, fixup_free_str_str_str,         /* */
197                 /* can be applied to original requests */
198                 REQUEST_ROUTE|BRANCH_ROUTE}, 
199         {"sipt_set_bci_1", /* action name as in scripts */
200                 (cmd_function)sipt_set_bci_1,  /* C function name */
201                 4,          /* number of parameters */
202                 fixup_str_str_str, fixup_free_str_str_str,         /* */
203                 /* can be applied to original requests */
204                 ONREPLY_ROUTE},
205         {"sipt_has_isup_body", /* action name as in scripts */
206                 (cmd_function)sipt_has_isup_body,  /* C function name */
207                 0,          /* number of parameters */
208                 0, 0,
209                 /* can be applied to original requests */
210                 ANY_ROUTE},
211         {0, 0, 0, 0, 0, 0}
212 };
213
214 static param_export_t params[]={ 
215         {0,0,0} 
216 };
217
218 static pv_export_t mod_items[] = {
219         { {"sipt_presentation",  sizeof("sipt_presentation")-1}, PVT_OTHER,  sipt_get_presentation,    0,
220                 0, 0, 0, 0 },
221         { {"sipt_screening",  sizeof("sipt_screening")-1}, PVT_OTHER,  sipt_get_screening,    0,
222                 0, 0, 0, 0 },
223         { {"sipt_hop_counter",  sizeof("sipt_hop_counter")-1}, PVT_OTHER,  sipt_get_hop_counter,    0,
224                 0, 0, 0, 0 },
225         { {"sipt_cpc",  sizeof("sipt_cpc")-1}, PVT_OTHER,  sipt_get_cpc,    0,
226                 0, 0, 0, 0 },
227         { {"sipt_calling_party_nai",  sizeof("sipt_calling_party_nai")-1}, PVT_OTHER,  sipt_get_calling_party_nai,    0,
228                 0, 0, 0, 0 },
229         { {"sipt_called_party_nai",  sizeof("sipt_called_party_nai")-1}, PVT_OTHER,  sipt_get_called_party_nai,    0,
230                 0, 0, 0, 0 },
231         { {"sipt",  sizeof("sipt")-1}, PVT_OTHER,  sipt_get_pv,    0,
232                 sipt_parse_pv_name, 0, 0, 0 },
233         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
234 };
235
236 struct module_exports exports = {
237         "sipt",          /* module name */
238         DEFAULT_DLFLAGS, /* dlopen flags */
239         cmds,            /* exported functions */
240         params,          /* exported parameters */
241         0,               /* exported RPC methods */
242         mod_items,       /* exported pseudo-variables */
243         0,               /* response function*/
244         mod_init,        /* module initialization function */
245         0,               /* per-child init function */
246         mod_destroy      /* destroy function */
247 };
248
249 static int sipt_get_hop_counter(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
250 {
251         str body;
252         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
253
254         if(body.s == NULL)
255         {
256                 LM_INFO("No ISUP Message Found");
257                 return -1;
258         }
259
260         if(body.s[0] != ISUP_IAM)
261         {
262                 LM_DBG("message not an IAM\n");
263                 return -1;
264         }
265         
266         pv_get_sintval(msg, param, res, isup_get_hop_counter((unsigned char*)body.s, body.len));
267         return 0;
268 }
269
270 static int sipt_get_event_info(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
271 {
272         str body;
273         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
274
275         if(body.s == NULL)
276         {
277                 LM_INFO("No ISUP Message Found");
278                 return -1;
279         }
280
281         if(body.s[0] != ISUP_CPG)
282         {
283                 LM_DBG("message not an CPG\n");
284                 return -1;
285         }
286         
287         pv_get_sintval(msg, param, res, isup_get_event_info((unsigned char*)body.s, body.len));
288         return 0;
289 }
290
291 static int sipt_get_cpc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
292 {
293         str body;
294         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
295
296         if(body.s == NULL)
297         {
298                 LM_INFO("No ISUP Message Found");
299                 return -1;
300         }
301
302         if(body.s[0] != ISUP_IAM)
303         {
304                 LM_DBG("message not an IAM\n");
305                 return -1;
306         }
307         
308         pv_get_sintval(msg, param, res, isup_get_cpc((unsigned char*)body.s, body.len));
309         return 0;
310 }
311
312 static int sipt_get_calling_party_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
313 {
314         str body;
315         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
316
317         if(body.s == NULL)
318         {
319                 LM_INFO("No ISUP Message Found");
320                 return -1;
321         }
322
323         if(body.s[0] != ISUP_IAM)
324         {
325                 LM_DBG("message not an IAM\n");
326                 return -1;
327         }
328         
329         pv_get_sintval(msg, param, res, isup_get_calling_party_nai((unsigned char*)body.s, body.len));
330         return 0;
331 }
332
333 static int sipt_get_calling_party(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
334 {
335         static char sb_s_buf[26];
336         str body;
337         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
338
339         memset(sb_s_buf, 0, 26);
340         if(body.s == NULL)
341         {
342                 LM_INFO("No ISUP Message Found");
343                 return -1;
344         }
345
346         if((body.s[0] != ISUP_IAM))
347         {
348                 LM_DBG("message not an IAM\n");
349                 return -1;
350         }
351
352         isup_get_calling_party((unsigned char*)body.s, body.len, sb_s_buf);
353
354         if (strlen(sb_s_buf) > 0)
355         {
356                 pv_get_strzval(msg, param, res, sb_s_buf);
357         } else {
358                 pv_get_sintval(msg, param, res, -1);
359         }
360         return 0;
361 }
362
363 static int sipt_get_redirection_info(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
364 {
365         str body;
366         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
367
368         if(body.s == NULL)
369         {
370                 LM_INFO("No ISUP Message Found");
371                 return -1;
372         }
373
374         if((body.s[0] != ISUP_ACM) && (body.s[0] != ISUP_CPG))
375         {
376                 LM_DBG("message not an ACM or CPG\n");
377                 return -1;
378         }
379         
380         pv_get_sintval(msg, param, res, isup_get_redirection_info((unsigned char*)body.s, body.len));
381         return 0;
382 }
383
384 static int sipt_get_redirection_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
385 {
386         str body;
387         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
388
389         if(body.s == NULL)
390         {
391                 LM_INFO("No ISUP Message Found");
392                 return -1;
393         }
394
395         if((body.s[0] != ISUP_ACM) && (body.s[0] != ISUP_CPG))
396         {
397                 LM_DBG("message not an ACM or CPG\n");
398                 return -1;
399         }
400         
401         pv_get_sintval(msg, param, res, isup_get_redirection_number_nai((unsigned char*)body.s, body.len));
402         return 0;
403 }
404
405 static int sipt_get_redirection_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
406 {
407         static char sb_s_buf[26];
408         str body;
409         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
410
411         memset(sb_s_buf, 0, 26);
412         if(body.s == NULL)
413         {
414                 LM_INFO("No ISUP Message Found");
415                 return -1;
416         }
417
418         if((body.s[0] != ISUP_ACM) && (body.s[0] != ISUP_CPG))
419         {
420                 LM_DBG("message not an ACM or CPG\n");
421                 return -1;
422         }
423
424         isup_get_redirection_number((unsigned char*)body.s, body.len, sb_s_buf);
425
426         if (strlen(sb_s_buf) > 0)
427         {
428                 pv_get_strzval(msg, param, res, sb_s_buf);
429         } else {
430                 pv_get_sintval(msg, param, res, -1);
431         }
432         return 0;
433 }
434
435 static int sipt_get_redirection_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
436 {
437         str body;
438         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
439
440         if(body.s == NULL)
441         {
442                 LM_INFO("No ISUP Message Found");
443                 return -1;
444         }
445
446         if((body.s[0] != ISUP_IAM))
447         {
448                 LM_DBG("message not an IAM\n");
449                 return -1;
450         }
451
452         pv_get_sintval(msg, param, res, isup_get_redirection_reason((unsigned char*)body.s, body.len));
453         return 0;
454 }
455
456 static int sipt_get_original_redirection_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
457 {
458         str body;
459         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
460
461         if(body.s == NULL)
462         {
463                 LM_INFO("No ISUP Message Found");
464                 return -1;
465         }
466
467         if((body.s[0] != ISUP_IAM))
468         {
469                 LM_DBG("message not an IAM\n");
470                 return -1;
471         }
472
473         pv_get_sintval(msg, param, res, isup_get_original_redirection_reason((unsigned char*)body.s, body.len));
474         return 0;
475 }
476
477 static int sipt_get_redirecting_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
478 {
479         str body;
480         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
481
482         if(body.s == NULL)
483         {
484                 LM_INFO("No ISUP Message Found");
485                 return -1;
486         }
487
488         if((body.s[0] != ISUP_IAM))
489         {
490                 LM_DBG("message not an IAM\n");
491                 return -1;
492         }
493         
494         pv_get_sintval(msg, param, res, isup_get_redirecting_number_nai((unsigned char*)body.s, body.len));
495         return 0;
496 }
497
498 static int sipt_get_redirecting_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
499 {
500         static char sb_s_buf[26];
501         str body;
502         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
503
504         memset(sb_s_buf, 0, 26);
505         if(body.s == NULL)
506         {
507                 LM_INFO("No ISUP Message Found");
508                 return -1;
509         }
510
511         if((body.s[0] != ISUP_IAM))
512         {
513                 LM_DBG("message not an IAM\n");
514                 return -1;
515         }
516
517         isup_get_redirecting_number((unsigned char*)body.s, body.len, sb_s_buf);
518
519         if (strlen(sb_s_buf) > 0)
520         {
521                 pv_get_strzval(msg, param, res, sb_s_buf);
522         } else {
523                 pv_get_sintval(msg, param, res, -1);
524         }
525         return 0;
526 }
527
528 static int sipt_get_original_called_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
529 {
530         str body;
531         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
532
533         if(body.s == NULL)
534         {
535                 LM_INFO("No ISUP Message Found");
536                 return -1;
537         }
538
539         if((body.s[0] != ISUP_IAM))
540         {
541                 LM_DBG("message not an IAM\n");
542                 return -1;
543         }
544
545         pv_get_sintval(msg, param, res, isup_get_original_called_number_nai((unsigned char*)body.s, body.len));
546         return 0;
547 }
548
549 static int sipt_get_original_called_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
550 {
551         static char sb_s_buf[26];
552         str body;
553         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
554
555         memset(sb_s_buf, 0, 26);
556         if(body.s == NULL)
557         {
558                 LM_INFO("No ISUP Message Found");
559                 return -1;
560         }
561
562         if((body.s[0] != ISUP_IAM))
563         {
564                 LM_DBG("message not an IAM\n");
565                 return -1;
566         }
567
568         isup_get_original_called_number((unsigned char*)body.s, body.len, sb_s_buf);
569
570         if (strlen(sb_s_buf) > 0)
571         {
572                 pv_get_strzval(msg, param, res, sb_s_buf);
573         } else {
574                 pv_get_sintval(msg, param, res, -1);
575         }
576         return 0;
577 }
578
579 static int sipt_get_generic_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
580 {
581         str body;
582         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
583
584         if(body.s == NULL)
585         {
586                 LM_INFO("No ISUP Message Found");
587                 return -1;
588         }
589
590         if((body.s[0] != ISUP_IAM))
591         {
592                 LM_DBG("message not an IAM\n");
593                 return -1;
594         }
595
596         pv_get_sintval(msg, param, res, isup_get_generic_number_nai((unsigned char*)body.s, body.len));
597         return 0;
598 }
599
600 static int sipt_get_generic_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
601 {
602         static char sb_s_buf[26];
603         str body;
604         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
605
606         memset(sb_s_buf, 0, 26);
607         if(body.s == NULL)
608         {
609                 LM_INFO("No ISUP Message Found");
610                 return -1;
611         }
612
613         if((body.s[0] != ISUP_IAM))
614         {
615                 LM_DBG("message not an IAM\n");
616                 return -1;
617         }
618
619         isup_get_generic_number((unsigned char*)body.s, body.len, sb_s_buf);
620
621         if (strlen(sb_s_buf) > 0)
622         {
623                 pv_get_strzval(msg, param, res, sb_s_buf);
624         } else {
625                 pv_get_sintval(msg, param, res, -1);
626         }
627         return 0;
628 }
629
630 static int sipt_get_presentation(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
631 {
632         str body;
633         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
634
635         if(body.s == NULL)
636         {
637                 LM_INFO("No ISUP Message Found");
638                 return -1;
639         }
640
641         if(body.s[0] != ISUP_IAM)
642         {
643                 LM_DBG("message not an IAM\n");
644                 return -1;
645         }
646         
647         pv_get_sintval(msg, param, res, isup_get_presentation((unsigned char*)body.s, body.len));
648         return 0;
649 }
650
651 static int sipt_get_screening(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
652 {
653         str body;
654         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
655
656         if(body.s == NULL)
657         {
658                 LM_INFO("No ISUP Message Found");
659                 return -1;
660         }
661
662         if(body.s[0] != ISUP_IAM)
663         {
664                 LM_DBG("message not an IAM\n");
665                 return -1;
666         }
667         LM_DBG("about to get screening\n");
668         
669         pv_get_sintval(msg, param, res, isup_get_screening((unsigned char*)body.s, body.len));
670         return 0;
671 }
672
673 static int sipt_get_charge_indicator(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
674 {
675         str body;
676         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
677
678         if(body.s == NULL)
679         {
680                 LM_INFO("No ISUP Message Found");
681                 return -1;
682         }
683
684         if(body.s[0] != ISUP_COT && body.s[0] != ISUP_ACM)
685         {
686                 LM_DBG("message not a COT or ACM\n");
687                 return -1;
688         }
689         LM_DBG("about to get charge indicator\n");
690         
691         pv_get_sintval(msg, param, res, isup_get_charging_indicator((unsigned char*)body.s, body.len));
692         return 0;
693 }
694
695 static int sipt_get_called_party_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
696 {
697         str body;
698         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
699
700         if(body.s == NULL)
701         {
702                 LM_INFO("No ISUP Message Found");
703                 return -1;
704         }
705
706         if(body.s[0] != ISUP_IAM)
707         {
708                 LM_DBG("message not an IAM\n");
709                 return -1;
710         }
711         
712         pv_get_sintval(msg, param, res, isup_get_called_party_nai((unsigned char*)body.s, body.len));
713         return 0;
714 }
715
716 static int sipt_get_called_party(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
717 {
718         static char sb_s_buf[26];
719         str body;
720         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
721
722         memset(sb_s_buf, 0, 26);
723         if(body.s == NULL)
724         {
725                 LM_INFO("No ISUP Message Found");
726                 return -1;
727         }
728
729         if((body.s[0] != ISUP_IAM))
730         {
731                 LM_DBG("message not an IAM\n");
732                 return -1;
733         }
734
735         isup_get_called_party((unsigned char*)body.s, body.len, sb_s_buf);
736
737         if (strlen(sb_s_buf) > 0)
738         {
739                 pv_get_strzval(msg, param, res, sb_s_buf);
740         } else {
741                 pv_get_sintval(msg, param, res, -1);
742         }
743         return 0;
744 }
745
746 static int sipt_has_isup_body(struct sip_msg *msg, char* foo, char* bar)
747 {
748         str body;
749         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
750         return (body.s == NULL)?-1:1;
751 }
752
753 int sipt_parse_pv_name(pv_spec_p sp, str *in)
754 {
755         sipt_pv_t *spv=NULL;
756         char *p;
757         str pvtype;
758         str pvsubtype;
759         if(sp==NULL || in==NULL || in->len<=0)
760                 return -1;
761
762         spv = (sipt_pv_t*)pkg_malloc(sizeof(sipt_pv_t));
763         if(spv==NULL)
764                 return -1;
765
766         memset(spv, 0, sizeof(sipt_pv_t));
767
768         p = in->s;
769
770         while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
771                 p++;
772         if(p>in->s+in->len || *p=='\0')
773                 goto error;
774
775         pvtype.s = p;
776
777         while(p < in->s + in->len)
778         {
779                 if(*p=='.' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
780                         break;
781                 p++;
782         }
783         pvtype.len = p - pvtype.s;
784         if(p>in->s+in->len || *p=='\0')
785         {
786                 // only one parameter stop parsing
787                 pvsubtype.len = 0;
788                 pvsubtype.s = NULL;
789                 goto parse_parameters;
790         }
791
792         if(*p!='.')
793         {
794                 while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
795                         p++;
796                 if(p>in->s+in->len || *p=='\0' || *p!='.')
797                 {
798                         // only one parameter w trailing whitespace
799                         pvsubtype.len = 0;
800                         pvsubtype.s = NULL;
801                         goto parse_parameters;
802                 }
803         }
804         p++;
805
806         pvsubtype.len = in->len - (int)(p - in->s);
807         pvsubtype.s = p;
808
809  
810 parse_parameters:
811         LM_DBG("sipt type[%.*s] - subtype[%.*s]\n", pvtype.len, pvtype.s,
812                         pvsubtype.len, pvsubtype.s);
813         int i = 0, j=0;
814
815         for(i=0;sipt_header_mapping[i].name != NULL; i++)
816         {
817                 if(strncasecmp(pvtype.s, sipt_header_mapping[i].name, pvtype.len) == 0)
818                 {
819                         spv->type = sipt_header_mapping[i].type;
820
821                         if(pvsubtype.len == 0)
822                                 break;
823
824                         for(j=0;sipt_header_mapping[i].subtypes[j].name != NULL;j++)
825                         {
826                                 if(strncasecmp(pvsubtype.s, sipt_header_mapping[i].subtypes[j].name, pvsubtype.len) == 0)
827                                 spv->sub_type = sipt_header_mapping[i].subtypes[j].type;
828                         }
829                         if(spv->sub_type == 0)
830                         {
831                                 LM_ERR("Unknown SIPT subtype [%.*s]\n", pvsubtype.len, pvsubtype.s);
832                                 goto error;
833                         }
834                         break;
835                 }
836         }
837
838         LM_DBG("Type=%d subtype=%d\n",spv->type, spv->sub_type);
839         if(spv->type == 0)
840         {
841                 LM_ERR("Unknown SIPT type [%.*s]\n",pvtype.len, pvtype.s);
842                 goto error;
843         }
844
845         sp->pvp.pvn.u.dname = (void*)spv;
846         sp->pvp.pvn.type = PV_NAME_OTHER;
847
848         return 0;
849 error:
850         LM_ERR("error at PV sipt name: %.*s\n", in->len, in->s);
851         pkg_free(spv);
852         return -1;
853
854 }
855
856 static int sipt_get_pv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
857 {
858         sipt_pv_t *spv;
859
860         if(msg==NULL || param==NULL)
861                 return -1;
862
863         spv = (sipt_pv_t*)param->pvn.u.dname;
864         if(spv==NULL)
865                 return -1;
866
867         switch(spv->type)
868         {
869                 case ISUP_PARM_CALLING_PARTY_CAT:
870                         return sipt_get_cpc(msg, param, res);
871                 case ISUP_PARM_CALLING_PARTY_NUM:
872                         switch(spv->sub_type)
873                         {
874                                 case 0: /* NUMBER */
875                                         return sipt_get_calling_party(msg, param, res);
876                                 case 1: /* NAI */
877                                         return sipt_get_calling_party_nai(msg, param, res);
878                                 case 2: /* SCREENIG */
879                                         return sipt_get_screening(msg, param, res);
880                                 case 3: /* PRESENTATION */
881                                         return sipt_get_presentation(msg, param, res);
882                         }
883                         break;
884                 case ISUP_PARM_CALLED_PARTY_NUM:
885                         switch(spv->sub_type)
886                         {
887                                 case 0: /* NUMBER */
888                                         return sipt_get_called_party(msg, param, res);
889                                 case 1: /* NAI */
890                                         return sipt_get_called_party_nai(msg, param, res);
891                         }
892                         break;
893                 case ISUP_PARM_HOP_COUNTER:
894                         return sipt_get_hop_counter(msg, param, res);
895                 case ISUP_PARM_EVENT_INFO:
896                         return sipt_get_event_info(msg, param, res);
897                 case ISUP_PARM_BACKWARD_CALL_IND:
898                         switch(spv->sub_type)
899                         {
900                                 case 1: /* charge_indicator */
901                                 return sipt_get_charge_indicator(msg, param, res);
902                         }
903                         break;
904                 case ISUP_PARM_DIVERSION_INFORMATION:
905                         return sipt_get_redirection_info(msg, param, res);
906                 case ISUP_PARM_REDIRECTION_NUMBER:
907                         switch(spv->sub_type)
908                         {
909                                 case 0: /* NUMBER */
910                                         return sipt_get_redirection_number(msg, param, res);
911                                 case 1: /* NAI */
912                                         return sipt_get_redirection_number_nai(msg, param, res);
913                         }
914                         break;
915                 case ISUP_PARM_REDIRECTION_INFO:
916                         switch(spv->sub_type)
917                         {
918                                 case 1: /* REASON */
919                                         return sipt_get_redirection_reason(msg, param, res);
920                                 case 2: /* ORIGINAL_REASON */
921                                         return sipt_get_original_redirection_reason(msg, param, res);
922                         }
923                         break;
924                 case ISUP_PARM_REDIRECTING_NUMBER:
925                         switch(spv->sub_type)
926                         {
927                                 case 0: /* NUMBER */
928                                         return sipt_get_redirecting_number(msg, param, res);
929                                 case 1: /* NAI */
930                                         return sipt_get_redirecting_number_nai(msg, param, res);
931                         }
932                         break;
933                 case ISUP_PARM_GENERIC_ADDR:
934                         switch(spv->sub_type)
935                         {
936                                 case 0: /* NUMBER */
937                                         return sipt_get_generic_number(msg, param, res);
938                                 case 1: /* NAI */
939                                         return sipt_get_generic_number_nai(msg, param, res);
940                         }
941                         break;
942                 case ISUP_PARM_ORIGINAL_CALLED_NUM:
943                         switch(spv->sub_type)
944                         {
945                                 case 0: /* NUMBER */
946                                         return sipt_get_original_called_number(msg, param, res);
947                                 case 1: /* NAI */
948                                         return sipt_get_original_called_number_nai(msg, param, res);
949                         }
950                         break;
951         }
952
953         return -1;
954 }
955
956 static int sipt_set_bci_1(struct sip_msg *msg, char *_charge_indicator, char *_called_status, char * _called_category, char * _e2e_indicator)
957 {
958         str * str_charge_indicator = (str*)_charge_indicator;
959         unsigned int charge_indicator = 0;
960         str2int(str_charge_indicator, &charge_indicator);
961         str * str_called_status = (str*)_called_status;
962         unsigned int called_status = 0;
963         str2int(str_called_status, &called_status);
964         str * str_called_category = (str*)_called_category;
965         unsigned int called_category = 0;
966         str2int(str_called_category, &called_category);
967         str * str_e2e_indicator = (str*)_e2e_indicator;
968         unsigned int e2e_indicator = 0;
969         str2int(str_e2e_indicator, &e2e_indicator);
970         struct sdp_mangler mangle;
971
972         // update forwarded iam
973         str body;
974         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
975
976         if(body.s == NULL)
977         {
978                 LM_INFO("No ISUP Message Found");
979                 return -1;
980         }
981         str sdp;
982         sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
983         
984         unsigned char newbuf[1024];
985         memset(newbuf, 0, 1024);
986         if (body.s==0) {
987                 LM_ERR("failed to get the message body\n");
988                 return -1;
989         }
990         body.len = msg->len -(int)(body.s-msg->buf);
991         if (body.len==0) {
992                 LM_DBG("message body has zero length\n");
993                 return -1;
994         }
995
996         if(body.s[0] != ISUP_ACM && body.s[0] != ISUP_COT)
997         {
998                 LM_DBG("message not an ACM or COT\n");
999                 return -1;
1000         }
1001
1002         mangle.msg = msg;
1003         mangle.body_offset = (int)(body.s - msg->buf);
1004
1005
1006
1007         int res = isup_update_bci_1(&mangle, charge_indicator, called_status, called_category, e2e_indicator, (unsigned char*)body.s, body.len);
1008         if(res < 0)
1009         {
1010                 LM_DBG("error updating ACM\n");
1011                 return -1;
1012         }
1013
1014         return 1;
1015 }
1016
1017 static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops, char * _nai) {
1018         str terminator = str_init("1");
1019         return sipt_destination2(msg, _destination, _hops, _nai, (char*)&terminator);
1020 }
1021
1022 static int sipt_destination2(struct sip_msg *msg, char *_destination, char *_hops, char * _nai, char * _terminator)
1023 {
1024         str * str_hops = (str*)_hops;
1025         unsigned int hops = 0;
1026         str2int(str_hops, &hops);
1027         str * nai = (str*)_nai;
1028         unsigned int int_nai = 0;
1029         str2int(nai, &int_nai);
1030         str * terminator = (str*)_terminator;
1031         unsigned int int_terminator = 0; /* if the str2int later fail */
1032         str2int(terminator, &int_terminator);
1033         str * destination = (str*)_destination;
1034         struct sdp_mangler mangle;
1035
1036         // update forwarded iam
1037         str body;
1038         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
1039
1040         if(body.s == NULL)
1041         {
1042                 LM_INFO("No ISUP Message Found");
1043                 return -1;
1044         }
1045         str sdp;
1046         sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
1047         
1048         unsigned char newbuf[1024];
1049         memset(newbuf, 0, 1024);
1050         if (body.s==0) {
1051                 LM_ERR("failed to get the message body\n");
1052                 return -1;
1053         }
1054         body.len = msg->len -(int)(body.s-msg->buf);
1055         if (body.len==0) {
1056                 LM_DBG("message body has zero length\n");
1057                 return -1;
1058         }
1059
1060         if(body.s[0] != ISUP_IAM)
1061         {
1062                 LM_DBG("message not an IAM\n");
1063                 return -1;
1064         }
1065
1066         mangle.msg = msg;
1067         mangle.body_offset = (int)(body.s - msg->buf);
1068
1069
1070         char * digits = calloc(1,destination->len+2);
1071         memcpy(digits, destination->s, destination->len);
1072
1073         if (int_terminator) {
1074                 digits[destination->len] = '#';
1075         }
1076
1077         int res = isup_update_destination(&mangle, digits, hops, int_nai, (unsigned char*)body.s, body.len);
1078         free(digits);
1079         if(res < 0)
1080         {
1081                 LM_DBG("error updating IAM\n");
1082                 return -1;
1083         }
1084
1085         return 1;
1086 }
1087
1088 static int sipt_set_calling(struct sip_msg *msg, char *_origin, char *_nai, char * _pres, char *_screen)
1089 {
1090         unsigned int pres = 0;
1091         str * str_pres = (str*)_pres;
1092         str2int(str_pres, &pres);
1093         unsigned int screen = 0;
1094         str * str_screen = (str*)_screen;
1095         str2int(str_screen, &screen);
1096         str * nai = (str*)_nai;
1097         unsigned int int_nai = 0;
1098         str2int(nai, &int_nai);
1099         str * origin = (str*)_origin;
1100         struct sdp_mangler mangle;
1101
1102         // update forwarded iam
1103         str body;
1104         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
1105
1106         if(body.s == NULL)
1107         {
1108                 LM_INFO("No ISUP Message Found");
1109                 return -1;
1110         }
1111
1112         if (body.s==0) {
1113                 LM_ERR("failed to get the message body\n");
1114                 return -1;
1115         }
1116         body.len = msg->len -(int)(body.s-msg->buf);
1117         if (body.len==0) {
1118                 LM_DBG("message body has zero length\n");
1119                 return -1;
1120         }
1121
1122         if(body.s[0] != ISUP_IAM)
1123         {
1124                 LM_DBG("message not an IAM\n");
1125                 return -1;
1126         }
1127
1128
1129         mangle.msg = msg;
1130         mangle.body_offset = (int)(body.s - msg->buf);
1131
1132         char * digits = calloc(1,origin->len+2);
1133         memcpy(digits, origin->s, origin->len);
1134
1135         int res = isup_update_calling(&mangle, digits, int_nai, pres, screen, (unsigned char*)body.s, body.len);
1136         free(digits);
1137         if(res < 0)
1138         {
1139                 LM_DBG("error updating IAM\n");
1140                 return -1;
1141         }
1142
1143         return 1;
1144 }
1145
1146 static int sipt_forwarding(struct sip_msg *msg, char *_fwdnumber, char * _nai)
1147 {
1148         str * nai = (str*)_nai;
1149         unsigned int int_nai = 0;
1150         str2int(nai, &int_nai);
1151         str * fwdnumber = (str*)_fwdnumber;
1152         struct sdp_mangler mangle;
1153
1154         // update forwarded iam
1155         str body;
1156         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
1157
1158         if(body.s == NULL)
1159         {
1160                 LM_INFO("No ISUP Message Found");
1161                 return -1;
1162         }
1163         str sdp;
1164         sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
1165         
1166         unsigned char newbuf[1024];
1167         memset(newbuf, 0, 1024);
1168         if (body.s==0) {
1169                 LM_ERR("failed to get the message body\n");
1170                 return -1;
1171         }
1172         body.len = msg->len -(int)(body.s-msg->buf);
1173         if (body.len==0) {
1174                 LM_DBG("message body has zero length\n");
1175                 return -1;
1176         }
1177
1178         if(body.s[0] != ISUP_IAM)
1179         {
1180                 LM_DBG("message not an IAM\n");
1181                 return -1;
1182         }
1183
1184         mangle.msg = msg;
1185         mangle.body_offset = (int)(body.s - msg->buf);
1186
1187         char * digits = calloc(1,fwdnumber->len+2);
1188         memcpy(digits, fwdnumber->s, fwdnumber->len);
1189
1190         int res = isup_update_forwarding(&mangle, digits, int_nai, (unsigned char*)body.s, body.len);
1191         free(digits);
1192         if(res < 0)
1193         {
1194                 LM_DBG("error updating IAM\n");
1195                 return -1;
1196         }
1197
1198         return 1;
1199 }
1200
1201
1202 static int mod_init(void)
1203 {
1204         return 0;
1205 }
1206
1207
1208 static void mod_destroy(void)
1209 {
1210 }