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