sipt: use helper function to check for valid ISUP/IAM
[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 inline int sipt_check_IAM(struct sip_msg *msg, str *body)
250 {
251         body->s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP, &body->len);
252
253         if(body->s == NULL)
254         {
255                 LM_INFO("No ISUP Message Found");
256                 return -1;
257         }
258
259         if(body->s[0] != ISUP_IAM)
260         {
261                 LM_DBG("message not an IAM\n");
262                 return -1;
263         }
264         return 1;
265 }
266
267 static int sipt_get_hop_counter(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
268 {
269         str body;
270
271         if(sipt_check_IAM(msg, &body) != 1)
272         {
273                 LM_INFO("could not check IAM\n");
274                 return -1;
275         }
276
277         pv_get_sintval(msg, param, res, isup_get_hop_counter((unsigned char*)body.s, body.len));
278         return 0;
279 }
280
281 static int sipt_get_event_info(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
282 {
283         str body;
284         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
285
286         if(body.s == NULL)
287         {
288                 LM_INFO("No ISUP Message Found");
289                 return -1;
290         }
291
292         if(body.s[0] != ISUP_CPG)
293         {
294                 LM_DBG("message not an CPG\n");
295                 return -1;
296         }
297         
298         pv_get_sintval(msg, param, res, isup_get_event_info((unsigned char*)body.s, body.len));
299         return 0;
300 }
301
302 static int sipt_get_cpc(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
303 {
304         str body;
305
306         if(sipt_check_IAM(msg, &body) != 1)
307         {
308                 LM_INFO("could not check IAM\n");
309                 return -1;
310         }
311         
312         pv_get_sintval(msg, param, res, isup_get_cpc((unsigned char*)body.s, body.len));
313         return 0;
314 }
315
316 static int sipt_get_calling_party_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
317 {
318         str body;
319
320         if(sipt_check_IAM(msg, &body) != 1)
321         {
322                 LM_INFO("could not check IAM\n");
323                 return -1;
324         }
325         
326         pv_get_sintval(msg, param, res, isup_get_calling_party_nai((unsigned char*)body.s, body.len));
327         return 0;
328 }
329
330 static int sipt_get_calling_party(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
331 {
332         static char sb_s_buf[26];
333         str body;
334         memset(sb_s_buf, 0, 26);
335
336         if(sipt_check_IAM(msg, &body) != 1)
337         {
338                 LM_INFO("could not check IAM\n");
339                 return -1;
340         }
341
342         isup_get_calling_party((unsigned char*)body.s, body.len, sb_s_buf);
343
344         if (strlen(sb_s_buf) > 0)
345         {
346                 pv_get_strzval(msg, param, res, sb_s_buf);
347         } else {
348                 pv_get_sintval(msg, param, res, -1);
349         }
350         return 0;
351 }
352
353 static int sipt_get_redirection_info(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
354 {
355         str body;
356         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
357
358         if(body.s == NULL)
359         {
360                 LM_INFO("No ISUP Message Found");
361                 return -1;
362         }
363
364         if((body.s[0] != ISUP_ACM) && (body.s[0] != ISUP_CPG))
365         {
366                 LM_DBG("message not an ACM or CPG\n");
367                 return -1;
368         }
369         
370         pv_get_sintval(msg, param, res, isup_get_redirection_info((unsigned char*)body.s, body.len));
371         return 0;
372 }
373
374 static int sipt_get_redirection_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
375 {
376         str body;
377         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
378
379         if(body.s == NULL)
380         {
381                 LM_INFO("No ISUP Message Found");
382                 return -1;
383         }
384
385         if((body.s[0] != ISUP_ACM) && (body.s[0] != ISUP_CPG))
386         {
387                 LM_DBG("message not an ACM or CPG\n");
388                 return -1;
389         }
390         
391         pv_get_sintval(msg, param, res, isup_get_redirection_number_nai((unsigned char*)body.s, body.len));
392         return 0;
393 }
394
395 static int sipt_get_redirection_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
396 {
397         static char sb_s_buf[26];
398         str body;
399         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
400
401         memset(sb_s_buf, 0, 26);
402         if(body.s == NULL)
403         {
404                 LM_INFO("No ISUP Message Found");
405                 return -1;
406         }
407
408         if((body.s[0] != ISUP_ACM) && (body.s[0] != ISUP_CPG))
409         {
410                 LM_DBG("message not an ACM or CPG\n");
411                 return -1;
412         }
413
414         isup_get_redirection_number((unsigned char*)body.s, body.len, sb_s_buf);
415
416         if (strlen(sb_s_buf) > 0)
417         {
418                 pv_get_strzval(msg, param, res, sb_s_buf);
419         } else {
420                 pv_get_sintval(msg, param, res, -1);
421         }
422         return 0;
423 }
424
425 static int sipt_get_redirection_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
426 {
427         str body;
428
429         if(sipt_check_IAM(msg, &body) != 1)
430         {
431                 LM_INFO("could not check IAM\n");
432                 return -1;
433         }
434
435         pv_get_sintval(msg, param, res, isup_get_redirection_reason((unsigned char*)body.s, body.len));
436         return 0;
437 }
438
439 static int sipt_get_original_redirection_reason(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
440 {
441         str body;
442
443         if(sipt_check_IAM(msg, &body) != 1)
444         {
445                 LM_INFO("could not check IAM\n");
446                 return -1;
447         }
448
449         pv_get_sintval(msg, param, res, isup_get_original_redirection_reason((unsigned char*)body.s, body.len));
450         return 0;
451 }
452
453 static int sipt_get_redirecting_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
454 {
455         str body;
456
457         if(sipt_check_IAM(msg, &body) != 1)
458         {
459                 LM_INFO("could not check IAM\n");
460                 return -1;
461         }
462         
463         pv_get_sintval(msg, param, res, isup_get_redirecting_number_nai((unsigned char*)body.s, body.len));
464         return 0;
465 }
466
467 static int sipt_get_redirecting_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
468 {
469         static char sb_s_buf[26];
470         str body;
471         memset(sb_s_buf, 0, 26);
472
473         if(sipt_check_IAM(msg, &body) != 1)
474         {
475                 LM_INFO("could not check IAM\n");
476                 return -1;
477         }
478
479         isup_get_redirecting_number((unsigned char*)body.s, body.len, sb_s_buf);
480
481         if (strlen(sb_s_buf) > 0)
482         {
483                 pv_get_strzval(msg, param, res, sb_s_buf);
484         } else {
485                 pv_get_sintval(msg, param, res, -1);
486         }
487         return 0;
488 }
489
490 static int sipt_get_original_called_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
491 {
492         str body;
493
494         if(sipt_check_IAM(msg, &body) != 1)
495         {
496                 LM_INFO("could not check IAM\n");
497                 return -1;
498         }
499
500         pv_get_sintval(msg, param, res, isup_get_original_called_number_nai((unsigned char*)body.s, body.len));
501         return 0;
502 }
503
504 static int sipt_get_original_called_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
505 {
506         static char sb_s_buf[26];
507         str body;
508         memset(sb_s_buf, 0, 26);
509
510         if(sipt_check_IAM(msg, &body) != 1)
511         {
512                 LM_INFO("could not check IAM\n");
513                 return -1;
514         }
515
516         isup_get_original_called_number((unsigned char*)body.s, body.len, sb_s_buf);
517
518         if (strlen(sb_s_buf) > 0)
519         {
520                 pv_get_strzval(msg, param, res, sb_s_buf);
521         } else {
522                 pv_get_sintval(msg, param, res, -1);
523         }
524         return 0;
525 }
526
527 static int sipt_get_generic_number_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
528 {
529         str body;
530
531         if(sipt_check_IAM(msg, &body) != 1)
532         {
533                 LM_INFO("could not check IAM\n");
534                 return -1;
535         }
536
537         pv_get_sintval(msg, param, res, isup_get_generic_number_nai((unsigned char*)body.s, body.len));
538         return 0;
539 }
540
541 static int sipt_get_generic_number(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
542 {
543         static char sb_s_buf[26];
544         str body;
545         memset(sb_s_buf, 0, 26);
546         if(sipt_check_IAM(msg, &body) != 1)
547         {
548                 LM_INFO("could not check IAM\n");
549                 return -1;
550         }
551         isup_get_generic_number((unsigned char*)body.s, body.len, sb_s_buf);
552
553         if (strlen(sb_s_buf) > 0)
554         {
555                 pv_get_strzval(msg, param, res, sb_s_buf);
556         } else {
557                 pv_get_sintval(msg, param, res, -1);
558         }
559         return 0;
560 }
561
562 static int sipt_get_presentation(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
563 {
564         str body;
565         if(sipt_check_IAM(msg, &body) != 1)
566         {
567                 LM_INFO("could not check IAM\n");
568                 return -1;
569         }
570         
571         pv_get_sintval(msg, param, res, isup_get_presentation((unsigned char*)body.s, body.len));
572         return 0;
573 }
574
575 static int sipt_get_screening(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
576 {
577         str body;
578         if(sipt_check_IAM(msg, &body) != 1)
579         {
580                 LM_INFO("could not check IAM\n");
581                 return -1;
582         }
583
584         LM_DBG("about to get screening\n");
585         
586         pv_get_sintval(msg, param, res, isup_get_screening((unsigned char*)body.s, body.len));
587         return 0;
588 }
589
590 static int sipt_get_charge_indicator(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
591 {
592         str body;
593         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
594
595         if(body.s == NULL)
596         {
597                 LM_INFO("No ISUP Message Found");
598                 return -1;
599         }
600
601         if(body.s[0] != ISUP_COT && body.s[0] != ISUP_ACM)
602         {
603                 LM_DBG("message not a COT or ACM\n");
604                 return -1;
605         }
606         LM_DBG("about to get charge indicator\n");
607         
608         pv_get_sintval(msg, param, res, isup_get_charging_indicator((unsigned char*)body.s, body.len));
609         return 0;
610 }
611
612 static int sipt_get_called_party_nai(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
613 {
614         str body;
615         if(sipt_check_IAM(msg, &body) != 1)
616         {
617                 LM_INFO("could not check IAM\n");
618                 return -1;
619         }
620         
621         pv_get_sintval(msg, param, res, isup_get_called_party_nai((unsigned char*)body.s, body.len));
622         return 0;
623 }
624
625 static int sipt_get_called_party(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
626 {
627         static char sb_s_buf[26];
628         str body;
629         memset(sb_s_buf, 0, 26);
630         if(sipt_check_IAM(msg, &body) != 1)
631         {
632                 LM_INFO("could not check IAM\n");
633                 return -1;
634         }
635
636         isup_get_called_party((unsigned char*)body.s, body.len, sb_s_buf);
637
638         if (strlen(sb_s_buf) > 0)
639         {
640                 pv_get_strzval(msg, param, res, sb_s_buf);
641         } else {
642                 pv_get_sintval(msg, param, res, -1);
643         }
644         return 0;
645 }
646
647 static int sipt_has_isup_body(struct sip_msg *msg, char* foo, char* bar)
648 {
649         str body;
650         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
651         return (body.s == NULL)?-1:1;
652 }
653
654 int sipt_parse_pv_name(pv_spec_p sp, str *in)
655 {
656         sipt_pv_t *spv=NULL;
657         char *p;
658         str pvtype;
659         str pvsubtype;
660         if(sp==NULL || in==NULL || in->len<=0)
661                 return -1;
662
663         spv = (sipt_pv_t*)pkg_malloc(sizeof(sipt_pv_t));
664         if(spv==NULL)
665                 return -1;
666
667         memset(spv, 0, sizeof(sipt_pv_t));
668
669         p = in->s;
670
671         while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
672                 p++;
673         if(p>in->s+in->len || *p=='\0')
674                 goto error;
675
676         pvtype.s = p;
677
678         while(p < in->s + in->len)
679         {
680                 if(*p=='.' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
681                         break;
682                 p++;
683         }
684         pvtype.len = p - pvtype.s;
685         if(p>in->s+in->len || *p=='\0')
686         {
687                 // only one parameter stop parsing
688                 pvsubtype.len = 0;
689                 pvsubtype.s = NULL;
690                 goto parse_parameters;
691         }
692
693         if(*p!='.')
694         {
695                 while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
696                         p++;
697                 if(p>in->s+in->len || *p=='\0' || *p!='.')
698                 {
699                         // only one parameter w trailing whitespace
700                         pvsubtype.len = 0;
701                         pvsubtype.s = NULL;
702                         goto parse_parameters;
703                 }
704         }
705         p++;
706
707         pvsubtype.len = in->len - (int)(p - in->s);
708         pvsubtype.s = p;
709
710  
711 parse_parameters:
712         LM_DBG("sipt type[%.*s] - subtype[%.*s]\n", pvtype.len, pvtype.s,
713                         pvsubtype.len, pvsubtype.s);
714         int i = 0, j=0;
715
716         for(i=0;sipt_header_mapping[i].name != NULL; i++)
717         {
718                 if(strncasecmp(pvtype.s, sipt_header_mapping[i].name, pvtype.len) == 0)
719                 {
720                         spv->type = sipt_header_mapping[i].type;
721
722                         if(pvsubtype.len == 0)
723                                 break;
724
725                         for(j=0;sipt_header_mapping[i].subtypes[j].name != NULL;j++)
726                         {
727                                 if(strncasecmp(pvsubtype.s, sipt_header_mapping[i].subtypes[j].name, pvsubtype.len) == 0)
728                                 spv->sub_type = sipt_header_mapping[i].subtypes[j].type;
729                         }
730                         if(spv->sub_type == 0)
731                         {
732                                 LM_ERR("Unknown SIPT subtype [%.*s]\n", pvsubtype.len, pvsubtype.s);
733                                 goto error;
734                         }
735                         break;
736                 }
737         }
738
739         LM_DBG("Type=%d subtype=%d\n",spv->type, spv->sub_type);
740         if(spv->type == 0)
741         {
742                 LM_ERR("Unknown SIPT type [%.*s]\n",pvtype.len, pvtype.s);
743                 goto error;
744         }
745
746         sp->pvp.pvn.u.dname = (void*)spv;
747         sp->pvp.pvn.type = PV_NAME_OTHER;
748
749         return 0;
750 error:
751         LM_ERR("error at PV sipt name: %.*s\n", in->len, in->s);
752         pkg_free(spv);
753         return -1;
754
755 }
756
757 static int sipt_get_pv(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
758 {
759         sipt_pv_t *spv;
760
761         if(msg==NULL || param==NULL)
762                 return -1;
763
764         spv = (sipt_pv_t*)param->pvn.u.dname;
765         if(spv==NULL)
766                 return -1;
767
768         switch(spv->type)
769         {
770                 case ISUP_PARM_CALLING_PARTY_CAT:
771                         return sipt_get_cpc(msg, param, res);
772                 case ISUP_PARM_CALLING_PARTY_NUM:
773                         switch(spv->sub_type)
774                         {
775                                 case 0: /* NUMBER */
776                                         return sipt_get_calling_party(msg, param, res);
777                                 case 1: /* NAI */
778                                         return sipt_get_calling_party_nai(msg, param, res);
779                                 case 2: /* SCREENIG */
780                                         return sipt_get_screening(msg, param, res);
781                                 case 3: /* PRESENTATION */
782                                         return sipt_get_presentation(msg, param, res);
783                         }
784                         break;
785                 case ISUP_PARM_CALLED_PARTY_NUM:
786                         switch(spv->sub_type)
787                         {
788                                 case 0: /* NUMBER */
789                                         return sipt_get_called_party(msg, param, res);
790                                 case 1: /* NAI */
791                                         return sipt_get_called_party_nai(msg, param, res);
792                         }
793                         break;
794                 case ISUP_PARM_HOP_COUNTER:
795                         return sipt_get_hop_counter(msg, param, res);
796                 case ISUP_PARM_EVENT_INFO:
797                         return sipt_get_event_info(msg, param, res);
798                 case ISUP_PARM_BACKWARD_CALL_IND:
799                         switch(spv->sub_type)
800                         {
801                                 case 1: /* charge_indicator */
802                                 return sipt_get_charge_indicator(msg, param, res);
803                         }
804                         break;
805                 case ISUP_PARM_DIVERSION_INFORMATION:
806                         return sipt_get_redirection_info(msg, param, res);
807                 case ISUP_PARM_REDIRECTION_NUMBER:
808                         switch(spv->sub_type)
809                         {
810                                 case 0: /* NUMBER */
811                                         return sipt_get_redirection_number(msg, param, res);
812                                 case 1: /* NAI */
813                                         return sipt_get_redirection_number_nai(msg, param, res);
814                         }
815                         break;
816                 case ISUP_PARM_REDIRECTION_INFO:
817                         switch(spv->sub_type)
818                         {
819                                 case 1: /* REASON */
820                                         return sipt_get_redirection_reason(msg, param, res);
821                                 case 2: /* ORIGINAL_REASON */
822                                         return sipt_get_original_redirection_reason(msg, param, res);
823                         }
824                         break;
825                 case ISUP_PARM_REDIRECTING_NUMBER:
826                         switch(spv->sub_type)
827                         {
828                                 case 0: /* NUMBER */
829                                         return sipt_get_redirecting_number(msg, param, res);
830                                 case 1: /* NAI */
831                                         return sipt_get_redirecting_number_nai(msg, param, res);
832                         }
833                         break;
834                 case ISUP_PARM_GENERIC_ADDR:
835                         switch(spv->sub_type)
836                         {
837                                 case 0: /* NUMBER */
838                                         return sipt_get_generic_number(msg, param, res);
839                                 case 1: /* NAI */
840                                         return sipt_get_generic_number_nai(msg, param, res);
841                         }
842                         break;
843                 case ISUP_PARM_ORIGINAL_CALLED_NUM:
844                         switch(spv->sub_type)
845                         {
846                                 case 0: /* NUMBER */
847                                         return sipt_get_original_called_number(msg, param, res);
848                                 case 1: /* NAI */
849                                         return sipt_get_original_called_number_nai(msg, param, res);
850                         }
851                         break;
852         }
853
854         return -1;
855 }
856
857 static int sipt_set_bci_1(struct sip_msg *msg, char *_charge_indicator, char *_called_status, char * _called_category, char * _e2e_indicator)
858 {
859         str * str_charge_indicator = (str*)_charge_indicator;
860         unsigned int charge_indicator = 0;
861         str2int(str_charge_indicator, &charge_indicator);
862         str * str_called_status = (str*)_called_status;
863         unsigned int called_status = 0;
864         str2int(str_called_status, &called_status);
865         str * str_called_category = (str*)_called_category;
866         unsigned int called_category = 0;
867         str2int(str_called_category, &called_category);
868         str * str_e2e_indicator = (str*)_e2e_indicator;
869         unsigned int e2e_indicator = 0;
870         str2int(str_e2e_indicator, &e2e_indicator);
871         struct sdp_mangler mangle;
872
873         // update forwarded iam
874         str body;
875         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
876
877         if(body.s == NULL)
878         {
879                 LM_INFO("No ISUP Message Found");
880                 return -1;
881         }
882         str sdp;
883         sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
884         
885         unsigned char newbuf[1024];
886         memset(newbuf, 0, 1024);
887         if (body.s==0) {
888                 LM_ERR("failed to get the message body\n");
889                 return -1;
890         }
891         body.len = msg->len -(int)(body.s-msg->buf);
892         if (body.len==0) {
893                 LM_DBG("message body has zero length\n");
894                 return -1;
895         }
896
897         if(body.s[0] != ISUP_ACM && body.s[0] != ISUP_COT)
898         {
899                 LM_DBG("message not an ACM or COT\n");
900                 return -1;
901         }
902
903         mangle.msg = msg;
904         mangle.body_offset = (int)(body.s - msg->buf);
905
906
907
908         int res = isup_update_bci_1(&mangle, charge_indicator, called_status, called_category, e2e_indicator, (unsigned char*)body.s, body.len);
909         if(res < 0)
910         {
911                 LM_DBG("error updating ACM\n");
912                 return -1;
913         }
914
915         return 1;
916 }
917
918 static int sipt_destination(struct sip_msg *msg, char *_destination, char *_hops, char * _nai) {
919         str terminator = str_init("1");
920         return sipt_destination2(msg, _destination, _hops, _nai, (char*)&terminator);
921 }
922
923 static int sipt_destination2(struct sip_msg *msg, char *_destination, char *_hops, char * _nai, char * _terminator)
924 {
925         str * str_hops = (str*)_hops;
926         unsigned int hops = 0;
927         str2int(str_hops, &hops);
928         str * nai = (str*)_nai;
929         unsigned int int_nai = 0;
930         str2int(nai, &int_nai);
931         str * terminator = (str*)_terminator;
932         unsigned int int_terminator = 0; /* if the str2int later fail */
933         str2int(terminator, &int_terminator);
934         str * destination = (str*)_destination;
935         struct sdp_mangler mangle;
936
937         // update forwarded iam
938         str body;
939         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
940
941         if(body.s == NULL)
942         {
943                 LM_INFO("No ISUP Message Found");
944                 return -1;
945         }
946         str sdp;
947         sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
948         
949         unsigned char newbuf[1024];
950         memset(newbuf, 0, 1024);
951         if (body.s==0) {
952                 LM_ERR("failed to get the message body\n");
953                 return -1;
954         }
955         body.len = msg->len -(int)(body.s-msg->buf);
956         if (body.len==0) {
957                 LM_DBG("message body has zero length\n");
958                 return -1;
959         }
960
961         if(body.s[0] != ISUP_IAM)
962         {
963                 LM_DBG("message not an IAM\n");
964                 return -1;
965         }
966
967         mangle.msg = msg;
968         mangle.body_offset = (int)(body.s - msg->buf);
969
970
971         char * digits = calloc(1,destination->len+2);
972         memcpy(digits, destination->s, destination->len);
973
974         if (int_terminator) {
975                 digits[destination->len] = '#';
976         }
977
978         int res = isup_update_destination(&mangle, digits, hops, int_nai, (unsigned char*)body.s, body.len);
979         free(digits);
980         if(res < 0)
981         {
982                 LM_DBG("error updating IAM\n");
983                 return -1;
984         }
985
986         return 1;
987 }
988
989 static int sipt_set_calling(struct sip_msg *msg, char *_origin, char *_nai, char * _pres, char *_screen)
990 {
991         unsigned int pres = 0;
992         str * str_pres = (str*)_pres;
993         str2int(str_pres, &pres);
994         unsigned int screen = 0;
995         str * str_screen = (str*)_screen;
996         str2int(str_screen, &screen);
997         str * nai = (str*)_nai;
998         unsigned int int_nai = 0;
999         str2int(nai, &int_nai);
1000         str * origin = (str*)_origin;
1001         struct sdp_mangler mangle;
1002
1003         // update forwarded iam
1004         str body;
1005         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
1006
1007         if(body.s == NULL)
1008         {
1009                 LM_INFO("No ISUP Message Found");
1010                 return -1;
1011         }
1012
1013         if (body.s==0) {
1014                 LM_ERR("failed to get the message body\n");
1015                 return -1;
1016         }
1017         body.len = msg->len -(int)(body.s-msg->buf);
1018         if (body.len==0) {
1019                 LM_DBG("message body has zero length\n");
1020                 return -1;
1021         }
1022
1023         if(body.s[0] != ISUP_IAM)
1024         {
1025                 LM_DBG("message not an IAM\n");
1026                 return -1;
1027         }
1028
1029
1030         mangle.msg = msg;
1031         mangle.body_offset = (int)(body.s - msg->buf);
1032
1033         char * digits = calloc(1,origin->len+2);
1034         memcpy(digits, origin->s, origin->len);
1035
1036         int res = isup_update_calling(&mangle, digits, int_nai, pres, screen, (unsigned char*)body.s, body.len);
1037         free(digits);
1038         if(res < 0)
1039         {
1040                 LM_DBG("error updating IAM\n");
1041                 return -1;
1042         }
1043
1044         return 1;
1045 }
1046
1047 static int sipt_forwarding(struct sip_msg *msg, char *_fwdnumber, char * _nai)
1048 {
1049         str * nai = (str*)_nai;
1050         unsigned int int_nai = 0;
1051         str2int(nai, &int_nai);
1052         str * fwdnumber = (str*)_fwdnumber;
1053         struct sdp_mangler mangle;
1054
1055         // update forwarded iam
1056         str body;
1057         body.s = get_body_part(msg, TYPE_APPLICATION,SUBTYPE_ISUP,&body.len);
1058
1059         if(body.s == NULL)
1060         {
1061                 LM_INFO("No ISUP Message Found");
1062                 return -1;
1063         }
1064         str sdp;
1065         sdp.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &sdp.len);
1066         
1067         unsigned char newbuf[1024];
1068         memset(newbuf, 0, 1024);
1069         if (body.s==0) {
1070                 LM_ERR("failed to get the message body\n");
1071                 return -1;
1072         }
1073         body.len = msg->len -(int)(body.s-msg->buf);
1074         if (body.len==0) {
1075                 LM_DBG("message body has zero length\n");
1076                 return -1;
1077         }
1078
1079         if(body.s[0] != ISUP_IAM)
1080         {
1081                 LM_DBG("message not an IAM\n");
1082                 return -1;
1083         }
1084
1085         mangle.msg = msg;
1086         mangle.body_offset = (int)(body.s - msg->buf);
1087
1088         char * digits = calloc(1,fwdnumber->len+2);
1089         memcpy(digits, fwdnumber->s, fwdnumber->len);
1090
1091         int res = isup_update_forwarding(&mangle, digits, int_nai, (unsigned char*)body.s, body.len);
1092         free(digits);
1093         if(res < 0)
1094         {
1095                 LM_DBG("error updating IAM\n");
1096                 return -1;
1097         }
1098
1099         return 1;
1100 }
1101
1102
1103 static int mod_init(void)
1104 {
1105         return 0;
1106 }
1107
1108
1109 static void mod_destroy(void)
1110 {
1111 }