3a295e206757fc5eac96c4aa549da5c516a2894f
[kamailio] / src / modules / nathelper / nathelper.c
1 /*
2  * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/time.h>
25 #include <netinet/in.h>
26 #include <netinet/in_systm.h>
27 #ifndef __USE_BSD
28 #define __USE_BSD
29 #endif
30 #include <netinet/ip.h>
31 #ifndef __FAVOR_BSD
32 #define __FAVOR_BSD
33 #endif
34 #include <netinet/udp.h>
35 #include <arpa/inet.h>
36 #include <sys/uio.h>
37 #include <sys/un.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <netdb.h>
41 #include <poll.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 #include "../../core/flags.h"
48 #include "../../core/sr_module.h"
49 #include "../../core/dprint.h"
50 #include "../../core/data_lump.h"
51 #include "../../core/data_lump_rpl.h"
52 #include "../../core/error.h"
53 #include "../../core/forward.h"
54 #include "../../core/ip_addr.h"
55 #include "../../core/mem/mem.h"
56 #include "../../core/parser/parse_from.h"
57 #include "../../core/parser/parse_to.h"
58 #include "../../core/parser/parse_uri.h"
59 #include "../../core/parser/parser_f.h"
60 #include "../../core/parser/parse_methods.h"
61 #include "../../core/parser/sdp/sdp.h"
62 #include "../../core/resolve.h"
63 #include "../../core/timer.h"
64 #include "../../core/trim.h"
65 #include "../../core/ut.h"
66 #include "../../core/pt.h"
67 #include "../../core/timer_proc.h"
68 #include "../../core/pvar.h"
69 #include "../../core/lvalue.h"
70 #include "../../core/msg_translator.h"
71 #include "../../core/usr_avp.h"
72 #include "../../core/socket_info.h"
73 #include "../../core/mod_fix.h"
74 #include "../../core/dset.h"
75 #include "../../core/select.h"
76 #include "../../core/kemi.h"
77 #include "../../core/rpc.h"
78 #include "../../core/rpc_lookup.h"
79 #include "../registrar/sip_msg.h"
80 #include "../usrloc/usrloc.h"
81 #include "nathelper.h"
82 #include "nhelpr_funcs.h"
83 #include "sip_pinger.h"
84
85 MODULE_VERSION
86
87 #if !defined(AF_LOCAL)
88 #define AF_LOCAL AF_UNIX
89 #endif
90 #if !defined(PF_LOCAL)
91 #define PF_LOCAL PF_UNIX
92 #endif
93
94 /* NAT UAC test constants */
95 #define NAT_UAC_TEST_C_1918 0x01
96 #define NAT_UAC_TEST_RCVD 0x02
97 #define NAT_UAC_TEST_V_1918 0x04
98 #define NAT_UAC_TEST_S_1918 0x08
99 #define NAT_UAC_TEST_RPORT 0x10
100 #define NAT_UAC_TEST_O_1918 0x20
101 #define NAT_UAC_TEST_WS 0x40
102 #define NAT_UAC_TEST_C_PORT 0x80
103 #define NAT_UAC_TEST_SDP_CLINE 0x100
104
105 #define DEFAULT_NATPING_STATE 1
106
107
108 static int nat_uac_test_f(struct sip_msg *msg, char *str1, char *str2);
109 static int fix_nated_contact_f(struct sip_msg *, char *, char *);
110 static int add_contact_alias_0_f(struct sip_msg *, char *, char *);
111 static int add_contact_alias_3_f(struct sip_msg *, char *, char *, char *);
112 static int set_contact_alias_f(struct sip_msg *msg, char *str1, char *str2);
113 static int w_set_contact_alias_f(struct sip_msg *msg, char *str1, char *str2);
114 static int handle_ruri_alias_f(struct sip_msg *, char *, char *);
115 static int pv_get_rr_count_f(struct sip_msg *, pv_param_t *, pv_value_t *);
116 static int pv_get_rr_top_count_f(struct sip_msg *, pv_param_t *, pv_value_t *);
117 static int fix_nated_sdp_f(struct sip_msg *, char *, char *);
118 static int is_rfc1918_f(struct sip_msg *, char *, char *);
119 static int extract_mediaip(str *, str *, int *, char *, int);
120 static int alter_mediaip(struct sip_msg *, str *, str *, int, str *, int, int);
121 static int fix_nated_register_f(struct sip_msg *, char *, char *);
122 static int fixup_fix_nated_register(void **param, int param_no);
123 static int fixup_fix_sdp(void **param, int param_no);
124 static int fixup_add_contact_alias(void **param, int param_no);
125 static int add_rcv_param_f(struct sip_msg *, char *, char *);
126 static int nh_sip_reply_received(sip_msg_t *msg);
127 static int test_sdp_cline(struct sip_msg *msg);
128
129 static int w_set_alias_to_pv(struct sip_msg *msg, char *uri_avp, char *hollow);
130 static int ki_set_alias_to_pv(struct sip_msg *msg, str *uri_avp);
131 static int nh_alias_to_uri(str *contact_header, str *alias_uri);
132 static int nh_write_to_pv(struct sip_msg *msg, str *data, str *pvname);
133
134 static void nh_timer(unsigned int, void *);
135 static int mod_init(void);
136 static int child_init(int);
137 static void mod_destroy(void);
138
139 static int nathelper_rpc_init(void);
140
141 static usrloc_api_t ul;
142
143 static int cblen = 0;
144 static int natping_interval = 0;
145 struct socket_info *force_socket = 0;
146
147 static int nh_nat_addr_mode = 1;
148
149 /* clang-format off */
150 typedef struct nh_netaddr {
151         const char *cnetaddr;
152         uint32_t netaddr;
153         uint32_t mask;
154 } nh_netaddr_t;
155
156 static nh_netaddr_t nh_nets_1918[] = {
157         {"10.0.0.0",    0, 0xffffffffu << 24},
158         {"172.16.0.0",  0, 0xffffffffu << 20},
159         {"192.168.0.0", 0, 0xffffffffu << 16},
160         {"100.64.0.0",  0, 0xffffffffu << 22}, /* rfc6598 - cg-nat */
161         {"192.0.0.0",   0, 0xffffffffu <<  3}, /* rfc7335 - IPv4 Service Continuity Prefix */
162         {NULL, 0, 0}
163 };
164
165 static nh_netaddr_t nh_nets_extra[] = {
166         {"192.0.0.0",   0, 0xffffffffu <<  8}, /* rfc7335 - IETF Protocol Assignments */
167         {NULL, 0, 0}
168 };
169 /* clang-format on */
170
171 /*
172  * If this parameter is set then the natpinger will ping only contacts
173  * that have the NAT flag set in user location database
174  */
175 static int ping_nated_only = 0;
176 static const char sbuf[4] = {0, 0, 0, 0};
177 static str force_socket_str = STR_NULL;
178 static int sipping_flag = -1;
179 static int natping_disable_flag = -1;
180 static int natping_processes = 1;
181
182 static str nortpproxy_str = str_init("a=nortpproxy:yes");
183
184 static char *rcv_avp_param = NULL;
185 static unsigned short rcv_avp_type = 0;
186 static int_str rcv_avp_name;
187
188 static char *natping_socket = NULL;
189 static int udpping_from_path = 0;
190 static int sdp_oldmediaip = 1;
191 static int raw_sock = -1;
192 static unsigned int raw_ip = 0;
193 static unsigned short raw_port = 0;
194 static int nh_keepalive_timeout = 0;
195 static request_method_t sipping_method_id = 0;
196 /* filter contacts by server_id */
197 static int nh_filter_srvid = 0;
198
199 /*0-> disabled, 1 ->enabled*/
200 unsigned int *natping_state = NULL;
201
202 /* clang-format off */
203 static cmd_export_t cmds[] = {
204         {"fix_nated_contact",  (cmd_function)fix_nated_contact_f,    0,
205                 0, 0,
206                 REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
207         {"add_contact_alias",  (cmd_function)add_contact_alias_0_f,  0,
208                 0, 0,
209                 REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
210         {"add_contact_alias",  (cmd_function)add_contact_alias_3_f,  3,
211                 fixup_add_contact_alias, 0,
212                 REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
213         {"set_contact_alias",  (cmd_function)set_contact_alias_f,  0,
214                 0, 0,
215                 REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
216         {"set_contact_alias",  (cmd_function)w_set_contact_alias_f, 1,
217                 fixup_int_1, 0, REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
218         {"handle_ruri_alias",  (cmd_function)handle_ruri_alias_f,    0,
219                 0, 0,
220                 REQUEST_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
221         {"fix_nated_sdp",      (cmd_function)fix_nated_sdp_f,        1,
222                 fixup_fix_sdp,  0,
223                 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
224         {"fix_nated_sdp",      (cmd_function)fix_nated_sdp_f,        2,
225                 fixup_fix_sdp, 0,
226                 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
227         {"nat_uac_test",       (cmd_function)nat_uac_test_f,         1,
228                 fixup_igp_null, 0,
229                 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
230         {"fix_nated_register", (cmd_function)fix_nated_register_f,   0,
231                 fixup_fix_nated_register, 0,
232                 REQUEST_ROUTE },
233         {"add_rcv_param",      (cmd_function)add_rcv_param_f,        0,
234                 0, 0,
235                 REQUEST_ROUTE },
236         {"add_rcv_param",      (cmd_function)add_rcv_param_f,        1,
237                 fixup_igp_null, 0,
238                 REQUEST_ROUTE },
239         {"is_rfc1918",         (cmd_function)is_rfc1918_f,           1,
240                 fixup_spve_null, 0,
241                 ANY_ROUTE },
242                 {"set_alias_to_pv",   (cmd_function)w_set_alias_to_pv,     1,
243                 0, 0, ANY_ROUTE },
244         {0, 0, 0, 0, 0, 0}
245 };
246
247 static pv_export_t mod_pvs[] = {
248         {{"rr_count", (sizeof("rr_count")-1)}, /* number of records routes */
249                 PVT_CONTEXT, pv_get_rr_count_f, 0, 0, 0, 0, 0},
250         {{"rr_top_count", (sizeof("rr_top_count")-1)}, /* number of topmost rrs */
251                 PVT_CONTEXT, pv_get_rr_top_count_f, 0, 0, 0, 0, 0},
252         {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
253 };
254
255 static param_export_t params[] = {
256         {"natping_interval",      INT_PARAM, &natping_interval      },
257         {"ping_nated_only",       INT_PARAM, &ping_nated_only       },
258         {"nortpproxy_str",        PARAM_STR, &nortpproxy_str      },
259         {"received_avp",          PARAM_STRING, &rcv_avp_param         },
260         {"force_socket",          PARAM_STR, &force_socket_str      },
261         {"sipping_from",          PARAM_STR, &sipping_from        },
262         {"sipping_method",        PARAM_STR, &sipping_method      },
263         {"sipping_bflag",         INT_PARAM, &sipping_flag          },
264         {"natping_disable_bflag", INT_PARAM, &natping_disable_flag  },
265         {"natping_processes",     INT_PARAM, &natping_processes     },
266         {"natping_socket",        PARAM_STRING, &natping_socket        },
267         {"keepalive_timeout",     INT_PARAM, &nh_keepalive_timeout  },
268         {"udpping_from_path",     INT_PARAM, &udpping_from_path     },
269         {"append_sdp_oldmediaip", INT_PARAM, &sdp_oldmediaip        },
270         {"filter_server_id",      INT_PARAM, &nh_filter_srvid },
271         {"nat_addr_mode",         INT_PARAM, &nh_nat_addr_mode },
272
273         {0, 0, 0}
274 };
275
276 struct module_exports exports = {
277         "nathelper",           /* module name */
278         DEFAULT_DLFLAGS,       /* dlopen flags */
279         cmds,                  /* cmd (cfg function) exports */
280         params,                /* param exports */
281         0,                     /* RPC method exports */
282         mod_pvs,               /* pseudo-variables exports */
283         nh_sip_reply_received, /* response handling function */
284         mod_init,              /* module init function */
285         child_init,            /* per-child init function */
286         mod_destroy            /* module destroy function */
287 };
288 /* clang-format on */
289
290
291 static int sel_nathelper(str *res, select_t *s, struct sip_msg *msg)
292 {
293         /* dummy */
294         return 0;
295 }
296
297 static int sel_rewrite_contact(str *res, select_t *s, struct sip_msg *msg);
298
299 SELECT_F(select_any_nameaddr)
300
301 select_row_t sel_declaration[] = {
302                 {NULL, SEL_PARAM_STR, STR_STATIC_INIT("nathelper"), sel_nathelper,
303                                 SEL_PARAM_EXPECTED},
304                 {sel_nathelper, SEL_PARAM_STR, STR_STATIC_INIT("rewrite_contact"),
305                                 sel_rewrite_contact, CONSUME_NEXT_INT},
306
307                 {sel_rewrite_contact, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"),
308                                 select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
309
310                 {NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}};
311
312 static int fixup_fix_sdp(void **param, int param_no)
313 {
314         if(param_no == 1) {
315                 /* flags */
316                 return fixup_igp_null(param, param_no);
317         }
318         if(param_no == 2) {
319                 /* new IP */
320                 return fixup_spve_all(param, param_no);
321         }
322         LM_ERR("unexpected param no: %d\n", param_no);
323         return -1;
324 }
325
326 static int fixup_fix_nated_register(void **param, int param_no)
327 {
328         if(rcv_avp_name.n == 0) {
329                 LM_ERR("you must set 'received_avp' parameter. Must be same value as"
330                            " parameter 'received_avp' of registrar module\n");
331                 return -1;
332         }
333         return 0;
334 }
335
336 static int fixup_add_contact_alias(void **param, int param_no)
337 {
338         if((param_no >= 1) && (param_no <= 3))
339                 return fixup_spve_null(param, 1);
340
341         LM_ERR("invalid parameter number <%d>\n", param_no);
342         return -1;
343 }
344
345 static void nathelper_rpc_enable_ping(rpc_t *rpc, void *ctx)
346 {
347         int value = 0;
348         if(natping_state == NULL) {
349                 rpc->fault(ctx, 500, "NATping disabled");
350                 return;
351         }
352
353         if(rpc->scan(ctx, "d", &value) < 1) {
354                 rpc->fault(ctx, 500, "No parameter");
355                 return;
356         }
357         (*natping_state) = value ? 1 : 0;
358 }
359
360 static const char *nathelper_rpc_enable_ping_doc[2] = {
361                 "Set (enable/disable) nat ping", 0};
362
363 rpc_export_t nathelper_rpc[] = {
364                 {"nathelper.enable_ping", nathelper_rpc_enable_ping,
365                                 nathelper_rpc_enable_ping_doc, 0},
366                 {0, 0, 0, 0}};
367
368 static int nathelper_rpc_init(void)
369 {
370         if(rpc_register_array(nathelper_rpc) != 0) {
371                 LM_ERR("failed to register RPC commands\n");
372                 return -1;
373         }
374         return 0;
375 }
376
377 static int init_raw_socket(void)
378 {
379         int on = 1;
380
381         raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
382         if(raw_sock == -1) {
383                 LM_ERR("cannot create raw socket\n");
384                 return -1;
385         }
386
387         if(setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
388                 LM_ERR("cannot set socket options\n");
389                 return -1;
390         }
391
392         return raw_sock;
393 }
394
395
396 static int get_natping_socket(
397                 char *socket, unsigned int *ip, unsigned short *port)
398 {
399         struct hostent *he;
400         str host;
401         int lport;
402         int lproto;
403
404         if(parse_phostport(socket, &host.s, &host.len, &lport, &lproto) != 0) {
405                 LM_CRIT("invalid natping_socket parameter <%s>\n", natping_socket);
406                 return -1;
407         }
408
409         if(lproto != PROTO_UDP && lproto != PROTO_NONE) {
410                 LM_CRIT("natping_socket can be only UDP <%s>\n", natping_socket);
411                 return 0;
412         }
413         lproto = PROTO_UDP;
414         *port = lport ? (unsigned short)lport : SIP_PORT;
415
416         he = sip_resolvehost(&host, port, (char *)(void *)&lproto);
417         if(he == 0) {
418                 LM_ERR("could not resolve hostname:\"%.*s\"\n", host.len, host.s);
419                 return -1;
420         }
421         if(he->h_addrtype != AF_INET) {
422                 LM_ERR("only ipv4 addresses allowed in natping_socket\n");
423                 return -1;
424         }
425
426         memcpy(ip, he->h_addr_list[0], he->h_length);
427
428         return 0;
429 }
430
431
432 static int mod_init(void)
433 {
434         int i;
435         bind_usrloc_t bind_usrloc;
436         struct in_addr addr;
437         pv_spec_t avp_spec;
438         str s;
439         int port, proto;
440         str host;
441
442         if(nathelper_rpc_init() < 0) {
443                 LM_ERR("failed to register RPC commands\n");
444                 return -1;
445         }
446
447         if(rcv_avp_param && *rcv_avp_param) {
448                 s.s = rcv_avp_param;
449                 s.len = strlen(s.s);
450                 if(pv_parse_spec(&s, &avp_spec) == 0 || avp_spec.type != PVT_AVP) {
451                         LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
452                         return -1;
453                 }
454
455                 if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)
456                                 != 0) {
457                         LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
458                         return -1;
459                 }
460         } else {
461                 rcv_avp_name.n = 0;
462                 rcv_avp_type = 0;
463         }
464
465         if(force_socket_str.s && force_socket_str.len > 0) {
466                 if(parse_phostport(force_socket_str.s, &host.s, &host.len, &port, &proto) == 0) {
467                         force_socket = grep_sock_info(&host, port, proto);
468                         if(force_socket == 0) {
469                                 LM_ERR("non-local force_socket <%s>\n", force_socket_str.s);
470                         }
471                 }
472         }
473
474         /* create raw socket? */
475         if((natping_socket && natping_socket[0]) || udpping_from_path) {
476                 if((!udpping_from_path)
477                                 && get_natping_socket(natping_socket, &raw_ip, &raw_port) != 0)
478                         return -1;
479                 if(init_raw_socket() < 0)
480                         return -1;
481         }
482
483         if(nortpproxy_str.s && nortpproxy_str.len > 0) {
484                 while(nortpproxy_str.len > 0
485                                 && (nortpproxy_str.s[nortpproxy_str.len - 1] == '\r'
486                                                    || nortpproxy_str.s[nortpproxy_str.len - 1] == '\n'))
487                         nortpproxy_str.len--;
488         }
489
490         if(natping_interval > 0) {
491                 bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
492                 if(!bind_usrloc) {
493                         LM_ERR("can't find usrloc module\n");
494                         return -1;
495                 }
496
497                 if(bind_usrloc(&ul) < 0) {
498                         return -1;
499                 }
500
501                 natping_state = (unsigned int *)shm_malloc(sizeof(unsigned int));
502                 if(!natping_state) {
503                         LM_ERR("no shmem left\n");
504                         return -1;
505                 }
506                 *natping_state = DEFAULT_NATPING_STATE;
507
508                 if(ping_nated_only && ul.nat_flag == 0) {
509                         LM_ERR("bad config - ping_nated_only enabled, but no nat bflag"
510                                    " set in usrloc module\n");
511                         return -1;
512                 }
513                 if(natping_processes < 0) {
514                         LM_ERR("bad config - natping_processes must be >= 0\n");
515                         return -1;
516                 }
517                 ul.set_max_partition(natping_processes * natping_interval);
518
519                 sipping_flag = (sipping_flag == -1) ? 0 : (1 << sipping_flag);
520                 natping_disable_flag =
521                                 (natping_disable_flag == -1) ? 0 : (1 << natping_disable_flag);
522
523                 /* set reply function if SIP natping is enabled */
524                 if(sipping_flag) {
525                         if(sipping_from.s == 0 || sipping_from.len <= 0) {
526                                 LM_ERR("SIP ping enabled, but SIP ping FROM is empty!\n");
527                                 return -1;
528                         }
529                         if(sipping_method.s == 0 || sipping_method.len <= 0) {
530                                 LM_ERR("SIP ping enabled, but SIP ping method is empty!\n");
531                                 return -1;
532                         }
533                         if(nh_keepalive_timeout > 0 && ul.set_keepalive_timeout != NULL) {
534                                 ul.set_keepalive_timeout(nh_keepalive_timeout);
535                         }
536
537                         if(parse_method_name(&sipping_method, &sipping_method_id) < 0) {
538                                 LM_ERR("invalid SIP ping method [%.*s]!\n", sipping_method.len,
539                                                 sipping_method.s);
540                                 return -1;
541                         }
542                         exports.response_f = sipping_rpl_filter;
543                         init_sip_ping();
544                 }
545
546                 register_dummy_timers(natping_processes);
547         }
548
549         /* Prepare 1918 networks list */
550         for(i = 0; nh_nets_1918[i].cnetaddr != NULL; i++) {
551                 if(inet_aton(nh_nets_1918[i].cnetaddr, &addr) != 1)
552                         abort();
553                 nh_nets_1918[i].netaddr = ntohl(addr.s_addr) & nh_nets_1918[i].mask;
554         }
555
556         /* Prepare reserved/extra networks list */
557         for(i = 0; nh_nets_extra[i].cnetaddr != NULL; i++) {
558                 if(inet_aton(nh_nets_extra[i].cnetaddr, &addr) != 1)
559                         abort();
560                 nh_nets_extra[i].netaddr = ntohl(addr.s_addr) & nh_nets_extra[i].mask;
561         }
562
563         register_select_table(sel_declaration);
564
565         return 0;
566 }
567
568
569 static int child_init(int rank)
570 {
571         int i;
572
573         if(rank == PROC_MAIN && natping_interval > 0) {
574                 for(i = 0; i < natping_processes; i++) {
575                         if(fork_dummy_timer(PROC_TIMER, "TIMER NH", 1 /*socks flag*/,
576                                            nh_timer, (void *)(unsigned long)i, 1 /*sec*/)
577                                         < 0) {
578                                 LM_ERR("failed to register timer routine as process\n");
579                                 return -1;
580                                 /* error */
581                         }
582                 }
583         }
584
585         if(rank <= 0 && rank != PROC_TIMER)
586                 return 0;
587
588         return 0;
589 }
590
591
592 static void mod_destroy(void)
593 {
594         /*free the shared memory*/
595         if(natping_state)
596                 shm_free(natping_state);
597 }
598
599
600 static int isnulladdr(str *sx, int pf)
601 {
602         char *cp;
603
604         if(pf == AF_INET6) {
605                 for(cp = sx->s; cp < sx->s + sx->len; cp++)
606                         if(*cp != '0' && *cp != ':')
607                                 return 0;
608                 return 1;
609         }
610         return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);
611 }
612
613 /*
614  * Replaces ip:port pair in the Contact: field with the source address
615  * of the packet.
616  */
617 static int fix_nated_contact(struct sip_msg *msg)
618 {
619         int offset, len, len1;
620         char *cp, *buf, temp[2];
621         contact_t *c;
622         struct lump *anchor;
623         struct sip_uri uri;
624         str hostport;
625         str params1 = {0};
626         str params2 = {0};
627
628         if(get_contact_uri(msg, &uri, &c) == -1)
629                 return -1;
630         if((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
631                 LM_ERR("you can't call fix_nated_contact twice, "
632                            "check your config!\n");
633                 return -1;
634         }
635
636         offset = c->uri.s - msg->buf;
637         anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T);
638         if(anchor == 0)
639                 return -1;
640
641         hostport = uri.host;
642         if(uri.port.len > 0)
643                 hostport.len = uri.port.s + uri.port.len - uri.host.s;
644
645         cp = ip_addr2a(&msg->rcv.src_ip);
646         len = c->uri.len + strlen(cp) + 6 /* :port */ - hostport.len + 1;
647         if(msg->rcv.src_ip.af == AF_INET6)
648                 len += 2;
649         buf = pkg_malloc(len);
650         if(buf == NULL) {
651                 LM_ERR("out of pkg memory\n");
652                 return -1;
653         }
654         temp[0] = hostport.s[0];
655         temp[1] = c->uri.s[c->uri.len];
656         c->uri.s[c->uri.len] = hostport.s[0] = '\0';
657         if(uri.maddr.len <= 0) {
658                 if(msg->rcv.src_ip.af == AF_INET6) {
659                         len1 = snprintf(buf, len, "%s[%s]:%d%s", c->uri.s, cp,
660                                         msg->rcv.src_port, hostport.s + hostport.len);
661                 } else {
662                         len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp,
663                                         msg->rcv.src_port, hostport.s + hostport.len);
664                 }
665         } else {
666                 /* skip maddr parameter - makes no sense anymore */
667                 LM_DBG("removing maddr parameter from contact uri: [%.*s]\n",
668                                 uri.maddr.len, uri.maddr.s);
669                 params1.s = hostport.s + hostport.len;
670                 params1.len = uri.maddr.s - params1.s;
671                 while(params1.len > 0 && (params1.s[params1.len - 1] == ' '
672                                                                                  || params1.s[params1.len - 1] == '\t'
673                                                                                  || params1.s[params1.len - 1] == ';'))
674                         params1.len--;
675                 params2.s = uri.maddr.s + uri.maddr.len;
676                 params2.len = c->uri.s + c->uri.len - params2.s;
677                 if(msg->rcv.src_ip.af == AF_INET6) {
678                         len1 = snprintf(buf, len, "%s[%s]:%d%.*s%.*s", c->uri.s, cp,
679                                         msg->rcv.src_port, params1.len, params1.s, params2.len,
680                                         params2.s);
681                 } else {
682                         len1 = snprintf(buf, len, "%s%s:%d%.*s%.*s", c->uri.s, cp,
683                                         msg->rcv.src_port, params1.len, params1.s, params2.len,
684                                         params2.s);
685                 }
686         }
687         if(len1 < len)
688                 len = len1;
689         hostport.s[0] = temp[0];
690         c->uri.s[c->uri.len] = temp[1];
691         if(insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) {
692                 pkg_free(buf);
693                 return -1;
694         }
695         c->uri.s = buf;
696         c->uri.len = len;
697
698         return 1;
699 }
700
701 static int fix_nated_contact_f(struct sip_msg *msg, char *str1, char *str2)
702 {
703         return fix_nated_contact(msg);
704 }
705
706 /*
707  * Replaces ip:port pair in the Contact: field with the source address
708  * of the packet.
709  */
710 static int set_contact_alias(struct sip_msg *msg, int trim)
711 {
712         char nbuf[MAX_URI_SIZE];
713         char cbuf[MAX_URI_SIZE];
714         str nuri;
715         str curi;
716         int br;
717
718         int offset, len;
719         char *buf;
720         contact_t *c;
721         struct lump *anchor;
722         struct sip_uri uri;
723
724         nuri.s = nbuf;
725         nuri.len = MAX_URI_SIZE;
726         curi.s = cbuf;
727         curi.len = MAX_URI_SIZE;
728         if(get_contact_uri(msg, &uri, &c) == -1)
729                 return -1;
730         if((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
731                 LM_ERR("you can't update contact twice, check your config!\n");
732                 return -1;
733         }
734         if(trim > 0 && uri_trim_rcv_alias(&c->uri, &curi) > 0) {
735                 if(uri_add_rcv_alias(msg, &curi, &nuri) < 0) {
736                         LM_DBG("cannot add the alias parameter\n");
737                         return -1;
738                 }
739         } else {
740                 if(uri_add_rcv_alias(msg, &c->uri, &nuri) < 0) {
741                         LM_DBG("cannot add the alias parameter\n");
742                         return -1;
743                 }
744         }
745
746         br = 1;
747         if(c->uri.s[-1] == '<')
748                 br = 0;
749
750
751         len = nuri.len + 2 * br;
752         buf = pkg_malloc(len + 1);
753         if(buf == NULL) {
754                 LM_ERR("out of pkg memory\n");
755                 return -1;
756         }
757         if(br == 1) {
758                 buf[0] = '<';
759                 strncpy(buf + 1, nuri.s, nuri.len);
760                 buf[len - 1] = '>';
761         } else {
762                 strncpy(buf, nuri.s, nuri.len);
763         }
764         buf[len] = '\0';
765
766         offset = c->uri.s - msg->buf;
767         anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T);
768         if(anchor == 0) {
769                 pkg_free(buf);
770                 return -1;
771         }
772
773         if(insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) {
774                 pkg_free(buf);
775                 return -1;
776         }
777         c->uri.s = buf + br;
778         c->uri.len = len - 2 * br;
779
780         return 1;
781 }
782
783 static int ki_set_contact_alias(struct sip_msg *msg)
784 {
785         return set_contact_alias(msg, 0);
786 }
787
788 static int ki_set_contact_alias_trim(struct sip_msg *msg)
789 {
790         return set_contact_alias(msg, 1);
791 }
792
793 static int set_contact_alias_f(struct sip_msg *msg, char *str1, char *str2)
794 {
795         return set_contact_alias(msg, 0);
796 }
797
798 static int w_set_contact_alias_f(struct sip_msg *msg, char *str1, char *str2)
799 {
800         int i = 0;
801         if(str1) {
802                 if(get_int_fparam(&i, msg, (fparam_t *)str1) < 0)
803                         return -1;
804         }
805         if(i > 1)
806                 i = 1;
807         return set_contact_alias(msg, i);
808 }
809
810 #define SALIAS ";alias="
811 #define SALIAS_LEN (sizeof(SALIAS) - 1)
812
813 /*
814  * Adds ;alias=ip~port~proto param to contact uri containing received ip,
815  * port, and transport proto if contact uri ip and port do not match
816  * received ip and port.
817  */
818 static int add_contact_alias_0(struct sip_msg *msg)
819 {
820         int len, param_len, ip_len;
821         contact_t *c;
822         struct lump *anchor;
823         struct sip_uri uri;
824         struct ip_addr *ip;
825         char *bracket, *lt, *param, *at, *port, *start;
826
827         /* Do nothing if Contact header does not exist */
828         if(!msg->contact) {
829                 if(parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
830                         LM_ERR("while parsing headers\n");
831                         return -1;
832                 }
833                 if(!msg->contact) {
834                         LM_DBG("no contact header\n");
835                         return 2;
836                 }
837         }
838         if(get_contact_uri(msg, &uri, &c) == -1) {
839                 LM_ERR("failed to get contact uri\n");
840                 return -1;
841         }
842
843         /* Compare source ip and port against contact uri */
844         if(((ip = str2ip(&(uri.host))) == NULL)
845                         && ((ip = str2ip6(&(uri.host))) == NULL)) {
846                 LM_DBG("contact uri host is not an ip address\n");
847         } else {
848                 if (ip_addr_cmp(ip, &(msg->rcv.src_ip)) &&
849                     ((msg->rcv.src_port == uri.port_no) ||
850                      ((uri.port.len == 0) && (msg->rcv.src_port == 5060))) &&
851                     (uri.proto == msg->rcv.proto)) {
852                         LM_DBG("no need to add alias param\n");
853                         return 2;
854                 }
855         }
856
857         /* Check if function has been called already */
858         if((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
859                 LM_ERR("you can't call add_contact_alias twice, check your config!\n");
860                 return -1;
861         }
862
863         /* Check if Contact URI needs to be enclosed in <>s */
864         lt = param = NULL;
865         bracket = memchr(msg->contact->body.s, '<', msg->contact->body.len);
866         if(bracket == NULL) {
867                 /* add opening < */
868                 lt = (char *)pkg_malloc(1);
869                 if(!lt) {
870                         LM_ERR("no pkg memory left for lt sign\n");
871                         goto err;
872                 }
873                 *lt = '<';
874                 anchor = anchor_lump(msg, msg->contact->body.s - msg->buf, 0, 0);
875                 if(anchor == NULL) {
876                         LM_ERR("anchor_lump for beginning of contact body failed\n");
877                         goto err;
878                 }
879                 if(insert_new_lump_before(anchor, lt, 1, 0) == 0) {
880                         LM_ERR("insert_new_lump_before for \"<\" failed\n");
881                         goto err;
882                 }
883         }
884
885         /* Create  ;alias param */
886         param_len = SALIAS_LEN + 1 /* [ */ + IP6_MAX_STR_SIZE
887                                 + 1 /* ] */ + 1 /* ~ */ + 5 /* port */ + 1 /* ~ */
888                                 + 1 /* proto */ + 1 /* > */;
889         param = (char *)pkg_malloc(param_len);
890         if(!param) {
891                 LM_ERR("no pkg memory left for alias param\n");
892                 goto err;
893         }
894         at = param;
895         /* ip address */
896         append_str(at, SALIAS, SALIAS_LEN);
897         if(msg->rcv.src_ip.af == AF_INET6)
898                 append_chr(at, '[');
899         ip_len = ip_addr2sbuf(&(msg->rcv.src_ip), at, param_len - SALIAS_LEN);
900         if(ip_len <= 0) {
901                 LM_ERR("failed to copy source ip\n");
902                 goto err;
903         }
904         at = at + ip_len;
905         if(msg->rcv.src_ip.af == AF_INET6)
906                 append_chr(at, ']');
907         /* port */
908         append_chr(at, '~');
909         port = int2str(msg->rcv.src_port, &len);
910         append_str(at, port, len);
911         /* proto */
912         append_chr(at, '~');
913         if((msg->rcv.proto < PROTO_UDP) || (msg->rcv.proto > PROTO_WSS)) {
914                 LM_ERR("invalid transport protocol\n");
915                 goto err;
916         }
917         append_chr(at, msg->rcv.proto + '0');
918         /* closing > */
919         if(bracket == NULL) {
920                 append_chr(at, '>');
921         }
922         param_len = at - param;
923
924         /* Add  ;alias param */
925         LM_DBG("adding param <%.*s>\n", param_len, param);
926         if(uri.port.len > 0) {
927                 start = uri.port.s + uri.port.len;
928         } else {
929                 start = uri.host.s + uri.host.len;
930         }
931         anchor = anchor_lump(msg, start - msg->buf, 0, 0);
932         if(anchor == NULL) {
933                 LM_ERR("anchor_lump for ;alias param failed\n");
934                 goto err;
935         }
936         if(insert_new_lump_after(anchor, param, param_len, 0) == 0) {
937                 LM_ERR("insert_new_lump_after for ;alias param failed\n");
938                 goto err;
939         }
940         return 1;
941
942 err:
943         if(lt)
944                 pkg_free(lt);
945         if(param)
946                 pkg_free(param);
947         return -1;
948 }
949
950 static int add_contact_alias_0_f(struct sip_msg *msg, char *str1, char *str2)
951 {
952         return add_contact_alias_0(msg);
953 }
954
955 static int proto_type_to_int(char *proto)
956 {
957         if(strcasecmp(proto, "udp") == 0)
958                 return PROTO_UDP;
959         if(strcasecmp(proto, "tcp") == 0)
960                 return PROTO_TCP;
961         if(strcasecmp(proto, "tls") == 0)
962                 return PROTO_TLS;
963         if(strcasecmp(proto, "sctp") == 0)
964                 return PROTO_SCTP;
965         if(strcasecmp(proto, "ws") == 0)
966                 return PROTO_WS;
967         if(strcasecmp(proto, "wss") == 0)
968                 return PROTO_WSS;
969         return PROTO_OTHER;
970 }
971
972
973 /*
974  * Adds ;alias=ip~port~proto param to contact uri containing ip, port,
975  * and encoded proto given as parameters.
976  */
977 static int add_contact_alias_3(
978                 sip_msg_t *msg, str *ip_str, str *port_str, str *proto_str)
979 {
980         int param_len, proto;
981         unsigned int tmp;
982         contact_t *c;
983         struct lump *anchor;
984         struct sip_uri uri;
985         char *bracket, *lt, *param, *at, *start;
986
987         /* Do nothing if Contact header does not exist */
988         if(!msg->contact) {
989                 if(parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
990                         LM_ERR("while parsing headers\n");
991                         return -1;
992                 }
993                 if(!msg->contact) {
994                         LM_DBG("no contact header\n");
995                         return 2;
996                 }
997         }
998         if(get_contact_uri(msg, &uri, &c) == -1) {
999                 LM_ERR("failed to get contact uri\n");
1000                 return -1;
1001         }
1002
1003         if((str2ip(ip_str) == NULL) && (str2ip6(ip_str) == NULL)) {
1004                 LM_ERR("ip param value %s is not valid IP address\n", ip_str->s);
1005                 return -1;
1006         }
1007         if((str2int(port_str, &tmp) == -1) || (tmp == 0) || (tmp > 65535)) {
1008                 LM_ERR("port param value is not valid port\n");
1009                 return -1;
1010         }
1011         proto = proto_type_to_int(proto_str->s);
1012         if(proto == PROTO_OTHER) {
1013                 LM_ERR("proto param value %s is not a known protocol\n", proto_str->s);
1014                 return -1;
1015         }
1016
1017         /* Check if function has been called already */
1018         if((c->uri.s < msg->buf) || (c->uri.s > (msg->buf + msg->len))) {
1019                 LM_ERR("you can't call alias_contact twice, check your config!\n");
1020                 return -1;
1021         }
1022
1023         /* Check if Contact URI needs to be enclosed in <>s */
1024         lt = param = NULL;
1025         bracket = memchr(msg->contact->body.s, '<', msg->contact->body.len);
1026         if(bracket == NULL) {
1027                 /* add opening < */
1028                 lt = (char *)pkg_malloc(1);
1029                 if(!lt) {
1030                         LM_ERR("no pkg memory left for lt sign\n");
1031                         goto err;
1032                 }
1033                 *lt = '<';
1034                 anchor = anchor_lump(msg, msg->contact->body.s - msg->buf, 0, 0);
1035                 if(anchor == NULL) {
1036                         LM_ERR("anchor_lump for beginning of contact body failed\n");
1037                         goto err;
1038                 }
1039                 if(insert_new_lump_before(anchor, lt, 1, 0) == 0) {
1040                         LM_ERR("insert_new_lump_before for \"<\" failed\n");
1041                         goto err;
1042                 }
1043         }
1044
1045         /* Create  ;alias param */
1046         param_len = SALIAS_LEN + IP6_MAX_STR_SIZE + 1 /* ~ */ + 5 /* port */
1047                                 + 1 /* ~ */ + 1 /* proto */ + 1 /* closing > */;
1048         param = (char *)pkg_malloc(param_len);
1049         if(!param) {
1050                 LM_ERR("no pkg memory left for alias param\n");
1051                 goto err;
1052         }
1053         at = param;
1054         /* ip address */
1055         append_str(at, SALIAS, SALIAS_LEN);
1056         append_str(at, ip_str->s, ip_str->len);
1057         /* port */
1058         append_chr(at, '~');
1059         append_str(at, port_str->s, port_str->len);
1060         /* proto */
1061         append_chr(at, '~');
1062         append_chr(at, proto + '0');
1063         /* closing > */
1064         if(bracket == NULL) {
1065                 append_chr(at, '>');
1066         }
1067         param_len = at - param;
1068
1069         /* Add  ;alias param */
1070         LM_DBG("adding param <%.*s>\n", param_len, param);
1071         if(uri.port.len > 0) {
1072                 start = uri.port.s + uri.port.len;
1073         } else {
1074                 start = uri.host.s + uri.host.len;
1075         }
1076         anchor = anchor_lump(msg, start - msg->buf, 0, 0);
1077         if(anchor == NULL) {
1078                 LM_ERR("anchor_lump for ;alias param failed\n");
1079                 goto err;
1080         }
1081         if(insert_new_lump_after(anchor, param, param_len, 0) == 0) {
1082                 LM_ERR("insert_new_lump_after for ;alias param failed\n");
1083                 goto err;
1084         }
1085         return 1;
1086
1087 err:
1088         if(lt)
1089                 pkg_free(lt);
1090         if(param)
1091                 pkg_free(param);
1092         return -1;
1093 }
1094
1095 static int add_contact_alias_3_f(
1096                 sip_msg_t *msg, char *_ip, char *_port, char *_proto)
1097 {
1098         str ip_str, port_str, proto_str;
1099
1100         /* Get and check param values */
1101         if(fixup_get_svalue(msg, (gparam_p)_ip, &ip_str) != 0) {
1102                 LM_ERR("cannot get ip param value\n");
1103                 return -1;
1104         }
1105         if(fixup_get_svalue(msg, (gparam_p)_port, &port_str) != 0) {
1106                 LM_ERR("cannot get port param value\n");
1107                 return -1;
1108         }
1109         if(fixup_get_svalue(msg, (gparam_p)_proto, &proto_str) != 0) {
1110                 LM_ERR("cannot get proto param value\n");
1111                 return -1;
1112         }
1113         return add_contact_alias_3(msg, &ip_str, &port_str, &proto_str);
1114 }
1115
1116 #define ALIAS "alias="
1117 #define ALIAS_LEN (sizeof(ALIAS) - 1)
1118
1119 /*
1120  * Checks if r-uri has alias param and if so, removes it and sets $du
1121  * based on its value.
1122  */
1123 static int handle_ruri_alias(struct sip_msg *msg)
1124 {
1125         str uri, proto;
1126         char buf[MAX_URI_SIZE], *val, *sep, *at, *next, *cur_uri, *rest, *port,
1127                         *trans;
1128         unsigned int len, rest_len, val_len, alias_len, proto_type, cur_uri_len,
1129                         ip_port_len;
1130
1131         if(parse_sip_msg_uri(msg) < 0) {
1132                 LM_ERR("while parsing Request-URI\n");
1133                 return -1;
1134         }
1135         rest = msg->parsed_uri.sip_params.s;
1136         rest_len = msg->parsed_uri.sip_params.len;
1137         if(rest_len == 0) {
1138                 LM_DBG("no params\n");
1139                 return 2;
1140         }
1141         while(rest_len >= ALIAS_LEN) {
1142                 if(strncmp(rest, ALIAS, ALIAS_LEN) == 0)
1143                         break;
1144                 sep = memchr(rest, 59 /* ; */, rest_len);
1145                 if(sep == NULL) {
1146                         LM_DBG("no alias param\n");
1147                         return 2;
1148                 } else {
1149                         rest_len = rest_len - (sep - rest + 1);
1150                         rest = sep + 1;
1151                 }
1152         }
1153
1154         if(rest_len < ALIAS_LEN) {
1155                 LM_DBG("no alias param\n");
1156                 return 2;
1157         }
1158
1159         /* set dst uri based on alias param value */
1160         val = rest + ALIAS_LEN;
1161         val_len = rest_len - ALIAS_LEN;
1162         port = memchr(val, 126 /* ~ */, val_len);
1163         if(port == NULL) {
1164                 LM_ERR("no '~' in alias param value\n");
1165                 return -1;
1166         }
1167         *(port++) = ':';
1168         trans = memchr(port, 126 /* ~ */, val_len - (port - val));
1169         if(trans == NULL) {
1170                 LM_ERR("no second '~' in alias param value\n");
1171                 return -1;
1172         }
1173         at = &(buf[0]);
1174         append_str(at, "sip:", 4);
1175         ip_port_len = trans - val;
1176         alias_len = SALIAS_LEN + ip_port_len + 2 /* ~n */;
1177         memcpy(at, val, ip_port_len);
1178         at = at + ip_port_len;
1179         trans = trans + 1;
1180         if((ip_port_len + 2 > val_len) || (*trans == ';') || (*trans == '?')) {
1181                 LM_ERR("no proto in alias param\n");
1182                 return -1;
1183         }
1184         proto_type = *trans - 48 /* char 0 */;
1185         if(proto_type != PROTO_UDP) {
1186                 proto_type_to_str(proto_type, &proto);
1187                 if(proto.len == 0) {
1188                         LM_ERR("unknown proto in alias param\n");
1189                         return -1;
1190                 }
1191                 append_str(at, ";transport=", 11);
1192                 memcpy(at, proto.s, proto.len);
1193                 at = at + proto.len;
1194         }
1195         next = trans + 1;
1196         if((ip_port_len + 2 < val_len) && (*next != ';') && (*next != '?')) {
1197                 LM_ERR("invalid alias param value\n");
1198                 return -1;
1199         }
1200         uri.s = &(buf[0]);
1201         uri.len = at - &(buf[0]);
1202         LM_DBG("setting dst_uri to <%.*s>\n", uri.len, uri.s);
1203         if(set_dst_uri(msg, &uri) == -1) {
1204                 LM_ERR("failed to set dst uri\n");
1205                 return -1;
1206         }
1207
1208         /* remove alias param */
1209         if(msg->new_uri.s) {
1210                 cur_uri = msg->new_uri.s;
1211                 cur_uri_len = msg->new_uri.len;
1212         } else {
1213                 cur_uri = msg->first_line.u.request.uri.s;
1214                 cur_uri_len = msg->first_line.u.request.uri.len;
1215         }
1216         at = &(buf[0]);
1217         len = rest - 1 /* ; */ - cur_uri;
1218         memcpy(at, cur_uri, len);
1219         at = at + len;
1220         len = cur_uri_len - alias_len - len;
1221         memcpy(at, rest + alias_len - 1, len);
1222         uri.s = &(buf[0]);
1223         uri.len = cur_uri_len - alias_len;
1224         LM_DBG("rewriting r-uri to <%.*s>\n", uri.len, uri.s);
1225         return rewrite_uri(msg, &uri);
1226 }
1227
1228 static int handle_ruri_alias_f(struct sip_msg *msg, char *str1, char *str2)
1229 {
1230         return handle_ruri_alias(msg);
1231 }
1232
1233 /*
1234  * Counts and return the number of record routes in rr headers of the message.
1235  */
1236 static int pv_get_rr_count_f(
1237                 struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1238 {
1239         unsigned int count;
1240         struct hdr_field *header;
1241         rr_t *body;
1242
1243         if(msg == NULL)
1244                 return -1;
1245
1246         if(parse_headers(msg, HDR_EOH_F, 0) == -1) {
1247                 LM_ERR("while parsing message\n");
1248                 return -1;
1249         }
1250
1251         count = 0;
1252         header = msg->record_route;
1253
1254         while(header) {
1255                 if(header->type == HDR_RECORDROUTE_T) {
1256                         if(parse_rr(header) == -1) {
1257                                 LM_ERR("while parsing rr header\n");
1258                                 return -1;
1259                         }
1260                         body = (rr_t *)header->parsed;
1261                         while(body) {
1262                                 count++;
1263                                 body = body->next;
1264                         }
1265                 }
1266                 header = header->next;
1267         }
1268
1269         return pv_get_uintval(msg, param, res, (unsigned int)count);
1270 }
1271
1272 /*
1273  * Return count of topmost record routes in rr headers of the message.
1274  */
1275 static int pv_get_rr_top_count_f(
1276                 struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1277 {
1278         str uri;
1279         struct sip_uri puri;
1280
1281         if(msg == NULL)
1282                 return -1;
1283
1284         if(!msg->record_route && (parse_headers(msg, HDR_RECORDROUTE_F, 0) == -1)) {
1285                 LM_ERR("while parsing Record-Route header\n");
1286                 return -1;
1287         }
1288
1289         if(!msg->record_route) {
1290                 return pv_get_uintval(msg, param, res, 0);
1291         }
1292
1293         if(parse_rr(msg->record_route) == -1) {
1294                 LM_ERR("while parsing rr header\n");
1295                 return -1;
1296         }
1297
1298         uri = ((rr_t *)msg->record_route->parsed)->nameaddr.uri;
1299         if(parse_uri(uri.s, uri.len, &puri) < 0) {
1300                 LM_ERR("while parsing rr uri\n");
1301                 return -1;
1302         }
1303
1304         if(puri.r2.len > 0) {
1305                 return pv_get_uintval(msg, param, res, 2);
1306         } else {
1307                 return pv_get_uintval(msg, param, res, 1);
1308         }
1309 }
1310
1311 /*
1312  * Test if IP address in netaddr belongs to RFC1918 networks
1313  * netaddr in network byte order
1314  */
1315 static inline int is1918addr_n(uint32_t netaddr)
1316 {
1317         int i;
1318         uint32_t hl;
1319
1320         hl = ntohl(netaddr);
1321         for(i = 0; nh_nets_1918[i].cnetaddr != NULL; i++) {
1322                 if((hl & nh_nets_1918[i].mask) == nh_nets_1918[i].netaddr) {
1323                         return 1;
1324                 }
1325         }
1326         if(nh_nat_addr_mode==1) {
1327                 for(i = 0; nh_nets_extra[i].cnetaddr != NULL; i++) {
1328                         if((hl & nh_nets_extra[i].mask) == nh_nets_extra[i].netaddr) {
1329                                 return 1;
1330                         }
1331                 }
1332         }
1333         return 0;
1334 }
1335
1336 /*
1337  * Test if IP address pointed to by saddr belongs to RFC1918 networks
1338  */
1339 static inline int is1918addr(str *saddr)
1340 {
1341         struct in_addr addr;
1342         int rval;
1343         char backup;
1344
1345         rval = -1;
1346         backup = saddr->s[saddr->len];
1347         saddr->s[saddr->len] = '\0';
1348         if(inet_aton(saddr->s, &addr) != 1)
1349                 goto theend;
1350         rval = is1918addr_n(addr.s_addr);
1351
1352 theend:
1353         saddr->s[saddr->len] = backup;
1354         return rval;
1355 }
1356
1357 /*
1358  * Test if IP address pointed to by ip belongs to RFC1918 networks
1359  */
1360 static inline int is1918addr_ip(struct ip_addr *ip)
1361 {
1362         if(ip->af != AF_INET)
1363                 return 0;
1364         return is1918addr_n(ip->u.addr32[0]);
1365 }
1366
1367 /*
1368  * test for occurrence of RFC1918 IP address in Contact HF
1369  */
1370 static int contact_1918(struct sip_msg *msg)
1371 {
1372         struct sip_uri uri;
1373         contact_t *c;
1374
1375         if(get_contact_uri(msg, &uri, &c) == -1)
1376                 return -1;
1377
1378         return (is1918addr(&(uri.host)) == 1) ? 1 : 0;
1379 }
1380
1381 /*
1382  * test if source port of signaling is different from
1383  * port advertised in Contact
1384  */
1385 static int contact_rport(struct sip_msg *msg)
1386 {
1387         struct sip_uri uri;
1388         contact_t *c;
1389
1390         if(get_contact_uri(msg, &uri, &c) == -1) {
1391                 return -1;
1392         }
1393
1394         if(msg->rcv.src_port != (uri.port_no ? uri.port_no : SIP_PORT)) {
1395                 return 1;
1396         } else {
1397                 return 0;
1398         }
1399 }
1400
1401 /**
1402 * test SDP C line ip address and source IP address match
1403 * if all ip address matches, return 0
1404 * returns unmatched ip address count
1405 * on parse error, returns -1
1406 */
1407 static int test_sdp_cline(struct sip_msg *msg){
1408         sdp_session_cell_t* session;
1409         struct ip_addr cline_addr;
1410         int sdp_session_num = 0;
1411         int result = 0;
1412
1413         if(parse_sdp(msg) < 0) {
1414                 LM_ERR("Unable to parse sdp body\n");
1415                 return -1;
1416         }
1417
1418         for(;;){
1419                 session = get_sdp_session(msg, sdp_session_num);
1420                 if(!session)
1421                         break;
1422
1423                 if(!(session->ip_addr.len > 0 && session->ip_addr.s))
1424                         break;
1425
1426                 if(session->pf==AF_INET){
1427                         if(str2ipbuf(&session->ip_addr,&cline_addr)<0){
1428                                 LM_ERR("Couldn't get sdp c line IP address\n");
1429                                 return -1;
1430                         }
1431                 }else if(session->pf==AF_INET6){
1432                         if(str2ip6buf(&session->ip_addr, &cline_addr)<0){
1433                                 LM_ERR("Couldn't get sdp c line IP address\n");
1434                                 return -1;
1435                         }
1436                 }else{
1437                         LM_ERR("Couldn't get sdp address type\n");
1438                         return -1;
1439                 }
1440
1441                 if(ip_addr_cmp(&msg->rcv.src_ip,&cline_addr)){
1442                         result++;
1443                 }
1444                 sdp_session_num++;
1445         }
1446
1447         return sdp_session_num - result;
1448 }
1449 /*
1450  * test for occurrence of RFC1918 IP address in SDP
1451  */
1452 static int sdp_1918(struct sip_msg *msg)
1453 {
1454         str *ip;
1455         int pf;
1456         int sdp_session_num, sdp_stream_num;
1457         sdp_session_cell_t *sdp_session;
1458         sdp_stream_cell_t *sdp_stream;
1459
1460         if(parse_sdp(msg) < 0) {
1461                 LM_ERR("Unable to parse sdp body\n");
1462                 return -1;
1463         }
1464
1465         sdp_session_num = 0;
1466         for(;;) {
1467                 sdp_session = get_sdp_session(msg, sdp_session_num);
1468                 if(!sdp_session)
1469                         break;
1470                 sdp_stream_num = 0;
1471                 for(;;) {
1472                         sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
1473                         if(!sdp_stream)
1474                                 break;
1475                         if(sdp_stream->ip_addr.s && sdp_stream->ip_addr.len) {
1476                                 ip = &(sdp_stream->ip_addr);
1477                                 pf = sdp_stream->pf;
1478                         } else {
1479                                 ip = &(sdp_session->ip_addr);
1480                                 pf = sdp_session->pf;
1481                         }
1482                         if(pf != AF_INET || isnulladdr(ip, pf))
1483                                 break;
1484                         if(is1918addr(ip) == 1)
1485                                 return 1;
1486                         sdp_stream_num++;
1487                 }
1488                 sdp_session_num++;
1489         }
1490         return 0;
1491 }
1492
1493 /*
1494  * test for occurrence of RFC1918 IP address in top Via
1495  */
1496 static int via_1918(struct sip_msg *msg)
1497 {
1498
1499         return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0;
1500 }
1501
1502 static int nat_uac_test(struct sip_msg *msg, int tests)
1503 {
1504         /* return true if any of the NAT-UAC tests holds */
1505
1506         /* test if the source port is different from the port in Via */
1507         if((tests & NAT_UAC_TEST_RPORT)
1508                         && (msg->rcv.src_port
1509                                            != (msg->via1->port ? msg->via1->port : SIP_PORT))) {
1510                 return 1;
1511         }
1512         /*
1513          * test if source address of signaling is different from
1514          * address advertised in Via
1515          */
1516         if((tests & NAT_UAC_TEST_RCVD) && received_via_test(msg))
1517                 return 1;
1518         /*
1519          * test for occurrences of RFC1918 addresses in Contact
1520          * header field
1521          */
1522         if((tests & NAT_UAC_TEST_C_1918) && (contact_1918(msg) > 0))
1523                 return 1;
1524         /*
1525          * test for occurrences of RFC1918 addresses in SDP body
1526          */
1527         if((tests & NAT_UAC_TEST_S_1918) && (sdp_1918(msg) > 0))
1528                 return 1;
1529         /*
1530          * test for occurrences of RFC1918 addresses top Via
1531          */
1532         if((tests & NAT_UAC_TEST_V_1918) && via_1918(msg))
1533                 return 1;
1534
1535         /*
1536          * test for occurrences of RFC1918 addresses in source address
1537          */
1538         if((tests & NAT_UAC_TEST_O_1918) && is1918addr_ip(&msg->rcv.src_ip))
1539                 return 1;
1540
1541         /*
1542          * test prototype to check whether the message arrived on a WebSocket
1543          */
1544         if((tests & NAT_UAC_TEST_WS)
1545                         && (msg->rcv.proto == PROTO_WS || msg->rcv.proto == PROTO_WSS))
1546                 return 1;
1547
1548         /*
1549          * test if source port of signaling is different from
1550          * port advertised in Contact
1551          */
1552         if((tests & NAT_UAC_TEST_C_PORT) && (contact_rport(msg) > 0))
1553                 return 1;
1554
1555         /**
1556         * test if sdp c line ip address matches with sip source address
1557         */
1558         if((tests & NAT_UAC_TEST_SDP_CLINE) && (test_sdp_cline(msg) > 0))
1559                 return 1;
1560
1561         /* no test succeeded */
1562         return -1;
1563 }
1564
1565 static int nat_uac_test_f(struct sip_msg *msg, char *str1, char *str2)
1566 {
1567         int tflags = 0;
1568         if(fixup_get_ivalue(msg, (gparam_t*)str1, &tflags)<0) {
1569                 LM_ERR("failed to get the value for flags parameter\n");
1570                 return -1;
1571         }
1572         return nat_uac_test(msg, tflags);
1573 }
1574
1575 static int is_rfc1918(struct sip_msg *msg, str *address)
1576 {
1577         return (is1918addr(address) == 1) ? 1 : -1;
1578 }
1579
1580
1581 static int is_rfc1918_f(struct sip_msg *msg, char *str1, char *str2)
1582 {
1583         str address;
1584
1585         if(fixup_get_svalue(msg, (gparam_p)str1, &address) != 0
1586                         || address.len == 0) {
1587                 LM_ERR("invalid address parameter\n");
1588                 return -2;
1589         }
1590
1591         return is_rfc1918(msg, &address);
1592 }
1593
1594 #define ADD_ADIRECTION 0x01
1595 #define FIX_MEDIP 0x02
1596 #define ADD_ANORTPPROXY 0x04
1597 #define FIX_ORGIP 0x08
1598
1599 #define ADIRECTION "a=direction:active"
1600 #define ADIRECTION_LEN (sizeof(ADIRECTION) - 1)
1601
1602 #define AOLDMEDIP "a=oldmediaip:"
1603 #define AOLDMEDIP_LEN (sizeof(AOLDMEDIP) - 1)
1604
1605 #define AOLDMEDIP6 "a=oldmediaip6:"
1606 #define AOLDMEDIP6_LEN (sizeof(AOLDMEDIP6) - 1)
1607
1608 #define AOLDMEDPRT "a=oldmediaport:"
1609 #define AOLDMEDPRT_LEN (sizeof(AOLDMEDPRT) - 1)
1610
1611
1612 /* replace ip addresses in SDP and return umber of replacements */
1613 static inline int replace_sdp_ip(
1614                 struct sip_msg *msg, str *org_body, char *line, str *ip, int linelen)
1615 {
1616         str body1, oldip, newip;
1617         str body = *org_body;
1618         unsigned hasreplaced = 0;
1619         int pf, pf1 = 0;
1620         str body2;
1621         char *bodylimit = body.s + body.len;
1622         int ret;
1623         int count = 0;
1624
1625         /* Iterate all lines and replace ips in them. */
1626         if(!ip) {
1627                 newip.s = ip_addr2a(&msg->rcv.src_ip);
1628                 newip.len = strlen(newip.s);
1629         } else {
1630                 newip = *ip;
1631         }
1632         body1 = body;
1633         for(;;) {
1634                 if(extract_mediaip(&body1, &oldip, &pf, line, linelen) == -1)
1635                         break;
1636                 if(pf != AF_INET) {
1637                         LM_ERR("not an IPv4 address in '%s' SDP\n", line);
1638                         return -1;
1639                 }
1640                 if(!pf1)
1641                         pf1 = pf;
1642                 else if(pf != pf1) {
1643                         LM_ERR("mismatching address families in '%s' SDP\n", line);
1644                         return -1;
1645                 }
1646                 body2.s = oldip.s + oldip.len;
1647                 body2.len = bodylimit - body2.s;
1648                 ret = alter_mediaip(
1649                                 msg, &body1, &oldip, pf, &newip, pf, sdp_oldmediaip);
1650                 if(ret == -1) {
1651                         LM_ERR("can't alter '%s' IP\n", line);
1652                         return -1;
1653                 }
1654                 count += ret;
1655                 hasreplaced = 1;
1656                 body1 = body2;
1657         }
1658         if(!hasreplaced) {
1659                 LM_ERR("can't extract '%s' IP from the SDP\n", line);
1660                 return -1;
1661         }
1662
1663         return count;
1664 }
1665
1666 static int ki_fix_nated_sdp_ip(sip_msg_t *msg, int level, str *ip)
1667 {
1668         str body;
1669         int rest_len;
1670         char *buf, *m_start, *m_end;
1671         struct lump *anchor;
1672         int ret;
1673         int count = 0;
1674
1675         if(extract_body(msg, &body) == -1) {
1676                 LM_ERR("cannot extract body from msg!\n");
1677                 return -1;
1678         }
1679
1680         if(level & (ADD_ADIRECTION | ADD_ANORTPPROXY)) {
1681
1682                 msg->msg_flags |= FL_FORCE_ACTIVE;
1683
1684                 if(level & ADD_ADIRECTION) {
1685                         m_start = ser_memmem(body.s, "\r\nm=", body.len, 4);
1686                         while(m_start != NULL) {
1687                                 m_start += 4;
1688                                 rest_len = body.len - (m_start - body.s);
1689                                 m_start = m_end = ser_memmem(m_start, "\r\nm=", rest_len, 4);
1690                                 if(!m_end)
1691                                         m_end = body.s + body.len; /* just before the final \r\n */
1692                                 anchor = anchor_lump(msg, m_end - msg->buf, 0, 0);
1693                                 if(anchor == NULL) {
1694                                         LM_ERR("anchor_lump failed\n");
1695                                         return -1;
1696                                 }
1697                                 buf = pkg_malloc((ADIRECTION_LEN + CRLF_LEN) * sizeof(char));
1698                                 if(buf == NULL) {
1699                                         LM_ERR("out of pkg memory\n");
1700                                         return -1;
1701                                 }
1702                                 memcpy(buf, CRLF, CRLF_LEN);
1703                                 memcpy(buf + CRLF_LEN, ADIRECTION, ADIRECTION_LEN);
1704                                 if(insert_new_lump_after(
1705                                                    anchor, buf, ADIRECTION_LEN + CRLF_LEN, 0)
1706                                                 == NULL) {
1707                                         LM_ERR("insert_new_lump_after failed\n");
1708                                         pkg_free(buf);
1709                                         return -1;
1710                                 }
1711                         }
1712                 }
1713
1714                 if((level & ADD_ANORTPPROXY) && nortpproxy_str.len) {
1715                         anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0);
1716                         if(anchor == NULL) {
1717                                 LM_ERR("anchor_lump failed\n");
1718                                 return -1;
1719                         }
1720                         buf = pkg_malloc((nortpproxy_str.len + CRLF_LEN) * sizeof(char));
1721                         if(buf == NULL) {
1722                                 LM_ERR("out of pkg memory\n");
1723                                 return -1;
1724                         }
1725                         memcpy(buf, CRLF, CRLF_LEN);
1726                         memcpy(buf + CRLF_LEN, nortpproxy_str.s, nortpproxy_str.len);
1727                         if(insert_new_lump_after(
1728                                            anchor, buf, nortpproxy_str.len + CRLF_LEN, 0)
1729                                         == NULL) {
1730                                 LM_ERR("insert_new_lump_after failed\n");
1731                                 pkg_free(buf);
1732                                 return -1;
1733                         }
1734                 }
1735         }
1736
1737         if(level & (FIX_MEDIP | FIX_ORGIP)) {
1738
1739                 /* Iterate all a=rtcp and replace ips in them. rfc3605 */
1740                 ret = replace_sdp_ip(msg, &body, "a=rtcp", (ip && ip->len>0) ? ip : 0, 6);
1741                 if(ret == -1)
1742                         LM_DBG("a=rtcp parameter does not exist. nothing to do.\n");
1743                 else 
1744                         count += ret;
1745
1746                 if(level & FIX_MEDIP) {
1747                         /* Iterate all c= and replace ips in them. */
1748                         ret = replace_sdp_ip(msg, &body, "c=", (ip && ip->len>0) ? ip : 0, 2);
1749                         if(ret == -1)
1750                                 return -1;
1751                         count += ret;
1752                 }
1753
1754                 if(level & FIX_ORGIP) {
1755                         /* Iterate all o= and replace ips in them. */
1756                         ret = replace_sdp_ip(msg, &body, "o=",  (ip && ip->len>0) ? ip : 0, 2);
1757                         if(ret == -1)
1758                                 return -1;
1759                         count += ret;
1760                 }
1761
1762         }
1763
1764         return count > 0 ? 1 : 2;
1765 }
1766
1767 static int ki_fix_nated_sdp(sip_msg_t *msg, int level)
1768 {
1769         return ki_fix_nated_sdp_ip(msg, level, NULL);
1770 }
1771
1772 static int fix_nated_sdp_f(struct sip_msg *msg, char *str1, char *str2)
1773 {
1774         int level;
1775         str ip = {0,0};
1776
1777         if(fixup_get_ivalue(msg, (gparam_t *)str1, &level) != 0) {
1778                 LM_ERR("failed to get value for first parameter\n");
1779                 return -1;
1780         }
1781         if(str2 && fixup_get_svalue(msg, (gparam_t *)str2, &ip) != 0) {
1782                 LM_ERR("failed to get value for second parameter\n");
1783                 return -1;
1784         }
1785
1786         return ki_fix_nated_sdp_ip(msg, level, &ip);
1787 }
1788
1789 static int extract_mediaip(str *body, str *mediaip, int *pf, char *line, int linelen)
1790 {
1791         char *cp, *cp1;
1792         int len, nextisip;
1793
1794         cp1 = NULL;
1795         for(cp = body->s; (len = body->s + body->len - cp) > 0;) {
1796                 cp1 = ser_memmem(cp, line, len, linelen);
1797                 if(cp1 == NULL || cp1[-1] == '\n' || cp1[-1] == '\r')
1798                         break;
1799                 cp = cp1 + linelen;
1800         }
1801         if(cp1 == NULL)
1802                 return -1;
1803
1804         mediaip->s = cp1 + linelen;
1805         mediaip->len =
1806                         eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
1807         trim_len(mediaip->len, mediaip->s, *mediaip);
1808
1809         nextisip = 0;
1810         for(cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
1811                 len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
1812                 if(nextisip == 1) {
1813                         mediaip->s = cp;
1814                         mediaip->len = len;
1815                         nextisip++;
1816                         break;
1817                 }
1818                 if(len == 3 && memcmp(cp, "IP", 2) == 0) {
1819                         switch(cp[2]) {
1820                                 case '4':
1821                                         nextisip = 1;
1822                                         *pf = AF_INET;
1823                                         break;
1824
1825                                 case '6':
1826                                         nextisip = 1;
1827                                         *pf = AF_INET6;
1828                                         break;
1829
1830                                 default:
1831                                         break;
1832                         }
1833                 }
1834                 cp = eat_space_end(cp + len, mediaip->s + mediaip->len);
1835         }
1836         if(nextisip != 2 || mediaip->len == 0) {
1837                 LM_ERR("no `IP[4|6]' in `%s' field\n", line);
1838                 return -1;
1839         }
1840         return 1;
1841 }
1842
1843 static int alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
1844                 str *newip, int newpf, int preserve)
1845 {
1846         char *buf;
1847         int offset;
1848         struct lump *anchor;
1849         str omip, nip, oip;
1850
1851         /* check that updating mediaip is really necessary */
1852         if(oldpf == newpf && isnulladdr(oldip, oldpf))
1853                 return 0;
1854         if(newip->len == oldip->len && memcmp(newip->s, oldip->s, newip->len) == 0)
1855                 return 0;
1856
1857         if(preserve != 0) {
1858                 anchor = anchor_lump(msg, body->s + body->len - msg->buf, 0, 0);
1859                 if(anchor == NULL) {
1860                         LM_ERR("anchor_lump failed\n");
1861                         return -1;
1862                 }
1863                 if(oldpf == AF_INET6) {
1864                         omip.s = AOLDMEDIP6;
1865                         omip.len = AOLDMEDIP6_LEN;
1866                 } else {
1867                         omip.s = AOLDMEDIP;
1868                         omip.len = AOLDMEDIP_LEN;
1869                 }
1870                 buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
1871                 if(buf == NULL) {
1872                         LM_ERR("out of pkg memory\n");
1873                         return -1;
1874                 }
1875                 memcpy(buf, CRLF, CRLF_LEN);
1876                 memcpy(buf + CRLF_LEN, omip.s, omip.len);
1877                 memcpy(buf + CRLF_LEN + omip.len, oldip->s, oldip->len);
1878                 if(insert_new_lump_after(
1879                                    anchor, buf, omip.len + oldip->len + CRLF_LEN, 0)
1880                                 == NULL) {
1881                         LM_ERR("insert_new_lump_after failed\n");
1882                         pkg_free(buf);
1883                         return -1;
1884                 }
1885         }
1886
1887         if(oldpf == newpf) {
1888                 nip.len = newip->len;
1889                 nip.s = pkg_malloc(nip.len);
1890                 if(nip.s == NULL) {
1891                         LM_ERR("out of pkg memory\n");
1892                         return -1;
1893                 }
1894                 memcpy(nip.s, newip->s, newip->len);
1895         } else {
1896                 nip.len = newip->len + 2;
1897                 nip.s = pkg_malloc(nip.len);
1898                 if(nip.s == NULL) {
1899                         LM_ERR("out of pkg memory\n");
1900                         return -1;
1901                 }
1902                 memcpy(nip.s + 2, newip->s, newip->len);
1903                 nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
1904                 nip.s[1] = ' ';
1905         }
1906
1907         oip = *oldip;
1908         if(oldpf != newpf) {
1909                 do {
1910                         oip.s--;
1911                         oip.len++;
1912                 } while(*oip.s != '6' && *oip.s != '4');
1913         }
1914         offset = oip.s - msg->buf;
1915         anchor = del_lump(msg, offset, oip.len, 0);
1916         if(anchor == NULL) {
1917                 LM_ERR("del_lump failed\n");
1918                 pkg_free(nip.s);
1919                 return -1;
1920         }
1921
1922         if(insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
1923                 LM_ERR("insert_new_lump_after failed\n");
1924                 pkg_free(nip.s);
1925                 return -1;
1926         }
1927         return 1;
1928 }
1929
1930
1931 static u_short raw_checksum(unsigned char *buffer, int len)
1932 {
1933         u_long sum = 0;
1934
1935         while(len > 1) {
1936                 sum += *buffer << 8;
1937                 buffer++;
1938                 sum += *buffer;
1939                 buffer++;
1940                 len -= 2;
1941         }
1942         if(len) {
1943                 sum += *buffer << 8;
1944         }
1945         sum = (sum >> 16) + (sum & 0xffff);
1946         sum = (sum >> 16) + (sum);
1947
1948         return (u_short)~sum;
1949 }
1950
1951
1952 static int send_raw(const char *buf, int buf_len, union sockaddr_union *to,
1953                 const unsigned int s_ip, const unsigned int s_port)
1954 {
1955         struct ip *ip;
1956         struct udphdr *udp;
1957         unsigned char packet[50];
1958         int len = sizeof(struct ip) + sizeof(struct udphdr) + buf_len;
1959
1960         if(len > sizeof(packet)) {
1961                 LM_ERR("payload too big\n");
1962                 return -1;
1963         }
1964
1965         ip = (struct ip *)packet;
1966         udp = (struct udphdr *)(packet + sizeof(struct ip));
1967         memcpy(packet + sizeof(struct ip) + sizeof(struct udphdr), buf, buf_len);
1968
1969         ip->ip_v = 4;
1970         ip->ip_hl = sizeof(struct ip) / 4; // no options
1971         ip->ip_tos = 0;
1972         ip->ip_len = htons(len);
1973         ip->ip_id = 23;
1974         ip->ip_off = 0;
1975         ip->ip_ttl = 69;
1976         ip->ip_p = 17;
1977         ip->ip_src.s_addr = s_ip;
1978         ip->ip_dst.s_addr = to->sin.sin_addr.s_addr;
1979
1980         ip->ip_sum = raw_checksum((unsigned char *)ip, sizeof(struct ip));
1981
1982         udp->uh_sport = htons(s_port);
1983         udp->uh_dport = to->sin.sin_port;
1984         udp->uh_ulen = htons((unsigned short)sizeof(struct udphdr) + buf_len);
1985         udp->uh_sum = 0;
1986
1987         return sendto(raw_sock, packet, len, 0, (struct sockaddr *)to,
1988                         sizeof(struct sockaddr_in));
1989 }
1990
1991 /**
1992  * quick function to extract ip:port from path
1993  */
1994 static char *extract_last_path_ip(str path)
1995 {
1996         /* used for raw UDP ping which works only on IPv4 */
1997         static char ip[24];
1998         char *start = NULL, *end = NULL, *p;
1999         int i;
2000         int path_depth = 0;
2001         int max_path_depth;
2002
2003         max_path_depth = udpping_from_path - 1;
2004
2005         if(!path.len || !path.s)
2006                 return NULL;
2007
2008         p = path.s;
2009         for(i = 0; i < path.len; i++) {
2010                 if(!strncmp("<sip:", p, 5) && i < path.len - 4) {
2011                         start = p + 5;
2012
2013                         end = NULL;
2014                 }
2015                 if((*p == ';' || *p == '>') && !end) {
2016                         end = p;
2017                         if(max_path_depth) {
2018                                 path_depth++;
2019                                 if(path_depth >= max_path_depth) {
2020                                         break;
2021                                 }
2022                         }
2023                 }
2024                 p++;
2025         }
2026         if(start && end) {
2027                 int len = end - start;
2028                 if(len > sizeof(ip) - 1) {
2029                         return NULL;
2030                 }
2031                 memcpy(ip, start, len);
2032                 ip[len] = '\0';
2033                 return (char *)ip;
2034         } else {
2035                 return NULL;
2036         }
2037 }
2038
2039
2040 static void nh_timer(unsigned int ticks, void *timer_idx)
2041 {
2042         static unsigned int iteration = 0;
2043         int rval;
2044         void *buf, *cp;
2045         str c;
2046         str recv;
2047         str *dst_uri;
2048         str opt;
2049         str path;
2050         str ruid;
2051         unsigned int aorhash;
2052         struct sip_uri curi;
2053         struct hostent *he;
2054         struct socket_info *send_sock;
2055         unsigned int flags;
2056         char proto;
2057         struct dest_info dst;
2058         char *path_ip_str = NULL;
2059         unsigned int path_ip = 0;
2060         unsigned short path_port = 0;
2061         int options = 0;
2062         int send_sip_ping = 0;
2063
2064         if((*natping_state) == 0)
2065                 goto done;
2066
2067         buf = NULL;
2068         if(cblen > 0) {
2069                 buf = pkg_malloc(cblen);
2070                 if(buf == NULL) {
2071                         LM_ERR("out of pkg memory\n");
2072                         goto done;
2073                 }
2074         }
2075         if(nh_filter_srvid)
2076                 options |= GAU_OPT_SERVER_ID;
2077         rval = ul.get_all_ucontacts(buf, cblen, (ping_nated_only ? ul.nat_flag : 0),
2078                         ((unsigned int)(unsigned long)timer_idx) * natping_interval
2079                                         + iteration,
2080                         natping_processes * natping_interval, options);
2081         if(rval < 0) {
2082                 if(buf != NULL)
2083                         pkg_free(buf);
2084                 LM_ERR("failed to fetch contacts\n");
2085                 goto done;
2086         }
2087         if(rval > 0) {
2088                 if(buf != NULL)
2089                         pkg_free(buf);
2090                 cblen = rval * 2;
2091                 buf = pkg_malloc(cblen);
2092                 if(buf == NULL) {
2093                         LM_ERR("out of pkg memory\n");
2094                         goto done;
2095                 }
2096                 rval = ul.get_all_ucontacts(buf, cblen,
2097                                 (ping_nated_only ? ul.nat_flag : 0),
2098                                 ((unsigned int)(unsigned long)timer_idx) * natping_interval
2099                                                 + iteration,
2100                                 natping_processes * natping_interval, options);
2101                 if(rval != 0) {
2102                         pkg_free(buf);
2103                         goto done;
2104                 }
2105         }
2106
2107         if(buf == NULL)
2108                 goto done;
2109
2110         cp = buf;
2111         while(1) {
2112                 memcpy(&(c.len), cp, sizeof(c.len));
2113                 if(c.len == 0)
2114                         break;
2115                 c.s = (char *)cp + sizeof(c.len);
2116                 cp = (char *)cp + sizeof(c.len) + c.len;
2117                 memcpy(&(recv.len), cp, sizeof(recv.len));
2118                 recv.s = (char *)cp + sizeof(recv.len);
2119                 cp = (char *)cp + sizeof(recv.len) + recv.len;
2120                 memcpy(&send_sock, cp, sizeof(send_sock));
2121                 cp = (char *)cp + sizeof(send_sock);
2122                 memcpy(&flags, cp, sizeof(flags));
2123                 cp = (char *)cp + sizeof(flags);
2124                 memcpy(&(path.len), cp, sizeof(path.len));
2125                 path.s = path.len ? ((char *)cp + sizeof(path.len)) : NULL;
2126                 cp = (char *)cp + sizeof(path.len) + path.len;
2127                 memcpy(&(ruid.len), cp, sizeof(ruid.len));
2128                 ruid.s = ruid.len ? ((char *)cp + sizeof(ruid.len)) : NULL;
2129                 cp = (char *)cp + sizeof(ruid.len) + ruid.len;
2130                 memcpy(&aorhash, cp, sizeof(aorhash));
2131                 cp = (char *)cp + sizeof(aorhash);
2132
2133                 if((flags & natping_disable_flag)) /* always 0 if natping_disable_flag not set */
2134                         continue;
2135
2136                 if(recv.len > 0)
2137                         dst_uri = &recv;
2138                 else
2139                         dst_uri = &c;
2140
2141                 /* determin the destination */
2142                 if(path.len && (flags & sipping_flag) != 0) {
2143                         /* send to first URI in path */
2144                         if(get_path_dst_uri(&path, &opt) < 0) {
2145                                 LM_ERR("failed to get dst_uri for Path\n");
2146                                 continue;
2147                         }
2148                         /* send to the contact/received */
2149                         if(parse_uri(opt.s, opt.len, &curi) < 0) {
2150                                 LM_ERR("can't parse contact dst_uri\n");
2151                                 continue;
2152                         }
2153                 } else if(path.len && udpping_from_path) {
2154                         path_ip_str = extract_last_path_ip(path);
2155                         if(path_ip_str == NULL) {
2156                                 LM_ERR("ERROR:nathelper:nh_timer: unable to parse path from "
2157                                            "location\n");
2158                                 continue;
2159                         }
2160                         if(get_natping_socket(path_ip_str, &path_ip, &path_port)) {
2161                                 LM_ERR("could not parse path host for udpping_from_path\n");
2162                                 continue;
2163                         }
2164                         if(parse_uri(dst_uri->s, dst_uri->len, &curi) < 0) {
2165                                 LM_ERR("can't parse contact/received uri\n");
2166                                 continue;
2167                         }
2168                 } else {
2169                         /* send to the contact/received */
2170                         if(parse_uri(dst_uri->s, dst_uri->len, &curi) < 0) {
2171                                 LM_ERR("can't parse contact/received uri\n");
2172                                 continue;
2173                         }
2174                 }
2175                 if(curi.proto != PROTO_UDP && curi.proto != PROTO_NONE)
2176                         continue;
2177                 if(curi.port_no == 0)
2178                         curi.port_no = SIP_PORT;
2179                 proto = curi.proto;
2180                 /* we sholud get rid of this resolve (to ofen and to slow); for the
2181                  * moment we are lucky since the curi is an IP -bogdan */
2182                 he = sip_resolvehost(&curi.host, &curi.port_no, &proto);
2183                 if(he == NULL) {
2184                         LM_ERR("can't resolve_host\n");
2185                         continue;
2186                 }
2187                 init_dest_info(&dst);
2188                 hostent2su(&dst.to, he, 0, curi.port_no);
2189
2190                 if(force_socket) {
2191                         send_sock = force_socket;
2192                 }
2193                 if(send_sock == 0) {
2194                         send_sock = get_send_socket(0, &dst.to, PROTO_UDP);
2195                 }
2196                 if(send_sock == NULL) {
2197                         LM_ERR("can't get sending socket\n");
2198                         continue;
2199                 }
2200                 dst.proto = PROTO_UDP;
2201                 dst.send_sock = send_sock;
2202
2203                 send_sip_ping = ((flags & sipping_flag) != 0)
2204                                                         || (ping_nated_only == 0 && sipping_flag != 0);
2205
2206                 if ( send_sip_ping && (opt.s = build_sipping(&c, send_sock, &path,
2207                                                 &ruid, aorhash, &opt.len)) != 0) {
2208                         if(udp_send(&dst, opt.s, opt.len) < 0) {
2209                                 LM_ERR("sip udp_send failed\n");
2210                         }
2211                 } else if(raw_ip) {
2212                         if(send_raw((char *)sbuf, sizeof(sbuf), &dst.to, raw_ip, raw_port)
2213                                         < 0) {
2214                                 LM_ERR("send_raw failed\n");
2215                         }
2216                 } else if(udpping_from_path) {
2217                         if(send_raw((char *)sbuf, sizeof(sbuf), &dst.to, path_ip, path_port)
2218                                         < 0) {
2219                                 LM_ERR("send_raw from path failed\n");
2220                         }
2221                 } else {
2222                         if(udp_send(&dst, (char *)sbuf, sizeof(sbuf)) < 0) {
2223                                 LM_ERR("udp_send failed\n");
2224                         }
2225                 }
2226         }
2227         pkg_free(buf);
2228 done:
2229         iteration++;
2230         if(iteration == natping_interval)
2231                 iteration = 0;
2232 }
2233
2234
2235 /*
2236  * Create received SIP uri that will be either
2237  * passed to registrar in an AVP or apended
2238  * to Contact header field as a parameter
2239  */
2240 static int create_rcv_uri(str *uri, struct sip_msg *m)
2241 {
2242         return get_src_uri(m, 0, uri);
2243 }
2244
2245
2246 /*
2247  * Add received parameter to Contacts for further
2248  * forwarding of the REGISTER requuest
2249  */
2250 static int ki_add_rcv_param(sip_msg_t *msg, int upos)
2251 {
2252         contact_t *c;
2253         struct lump *anchor;
2254         char *param;
2255         str uri;
2256
2257         if(upos) {
2258                 if(msg->rcv.proto != PROTO_UDP) {
2259                         LM_ERR("adding received parameter to Contact URI works only for UDP\n");
2260                         return -1;
2261                 }
2262         }
2263
2264         if(create_rcv_uri(&uri, msg) < 0) {
2265                 return -1;
2266         }
2267
2268         if(contact_iterator(&c, msg, 0) < 0) {
2269                 return -1;
2270         }
2271
2272         while(c) {
2273                 param = (char *)pkg_malloc(RECEIVED_LEN + 2 + uri.len);
2274                 if(!param) {
2275                         LM_ERR("no pkg memory left\n");
2276                         return -1;
2277                 }
2278                 memcpy(param, RECEIVED, RECEIVED_LEN);
2279                 if(upos) {
2280                         memcpy(param + RECEIVED_LEN, uri.s, uri.len);
2281                 } else {
2282                         param[RECEIVED_LEN] = '\"';
2283                         memcpy(param + RECEIVED_LEN + 1, uri.s, uri.len);
2284                         param[RECEIVED_LEN + 1 + uri.len] = '\"';
2285                 }
2286
2287                 if(upos) {
2288                         /* add the param as uri param */
2289                         anchor = anchor_lump(msg, c->uri.s + c->uri.len - msg->buf, 0, 0);
2290                 } else {
2291                         /* add the param as header param */
2292                         anchor = anchor_lump(msg, c->name.s + c->len - msg->buf, 0, 0);
2293                 }
2294                 if(anchor == NULL) {
2295                         LM_ERR("anchor_lump failed\n");
2296                         pkg_free(param);
2297                         return -1;
2298                 }
2299
2300                 if(insert_new_lump_after(anchor, param,
2301                                         RECEIVED_LEN + 1 + uri.len + 1 - ((upos)?2:0), 0) == 0) {
2302                         LM_ERR("insert_new_lump_after failed\n");
2303                         pkg_free(param);
2304                         return -1;
2305                 }
2306
2307                 if(contact_iterator(&c, msg, c) < 0) {
2308                         return -1;
2309                 }
2310         }
2311
2312         return 1;
2313 }
2314
2315 /*
2316  * Add received parameter to Contacts for further
2317  * forwarding of the REGISTER requuest
2318  */
2319 static int add_rcv_param_f(struct sip_msg *msg, char *str1, char *str2)
2320 {
2321         int hdr_param = 0;
2322
2323         if(str1) {
2324                 if(fixup_get_ivalue(msg, (gparam_t*)str1, &hdr_param)<0) {
2325                         LM_ERR("failed to get flags parameter\n");
2326                         return -1;
2327                 }
2328         }
2329         return ki_add_rcv_param(msg, hdr_param);
2330 }
2331
2332 /*
2333  * Create an AVP to be used by registrar with the source IP and port
2334  * of the REGISTER
2335  */
2336 static int fix_nated_register(struct sip_msg *msg)
2337 {
2338         str uri;
2339         int_str val;
2340
2341         if(rcv_avp_name.n == 0)
2342                 return 1;
2343
2344         if(create_rcv_uri(&uri, msg) < 0) {
2345                 return -1;
2346         }
2347
2348         val.s = uri;
2349
2350         if(add_avp(AVP_VAL_STR | rcv_avp_type, rcv_avp_name, val) < 0) {
2351                 LM_ERR("failed to create AVP\n");
2352                 return -1;
2353         }
2354
2355         return 1;
2356 }
2357
2358 static int fix_nated_register_f(struct sip_msg *msg, char *str1, char *str2)
2359 {
2360         return fix_nated_register(msg);
2361 }
2362
2363 /**
2364  * handle SIP replies
2365  */
2366 static int nh_sip_reply_received(sip_msg_t *msg)
2367 {
2368         to_body_t *fb;
2369         str ruid;
2370         str ah;
2371         unsigned int aorhash;
2372         char *p;
2373
2374         if(nh_keepalive_timeout <= 0)
2375                 return 1;
2376         if(msg->cseq == NULL && ((parse_headers(msg, HDR_CSEQ_F, 0) == -1)
2377                                                                         || (msg->cseq == NULL))) {
2378                 LM_ERR("no CSEQ header\n");
2379                 goto done;
2380         }
2381         if(sipping_method_id != METHOD_UNDEF && sipping_method_id != METHOD_OTHER) {
2382                 if(get_cseq(msg)->method_id != sipping_method_id)
2383                         goto done;
2384         } else {
2385                 if(sipping_method_id == METHOD_OTHER) {
2386                         if(get_cseq(msg)->method.len != sipping_method.len)
2387                                 goto done;
2388                         if(strncmp(get_cseq(msg)->method.s, sipping_method.s,
2389                                            sipping_method.len)
2390                                         != 0)
2391                                 goto done;
2392                 } else {
2393                         goto done;
2394                 }
2395         }
2396         /* there must be no second via */
2397         if(!(parse_headers(msg, HDR_VIA2_F, 0) == -1 || (msg->via2 == 0)
2398                            || (msg->via2->error != PARSE_OK)))
2399                 goto done;
2400
2401         /* from uri check */
2402         if((parse_from_header(msg)) < 0) {
2403                 LM_ERR("cannot parse From header\n");
2404                 goto done;
2405         }
2406
2407         fb = get_from(msg);
2408         if(fb->uri.len != sipping_from.len
2409                         || strncmp(fb->uri.s, sipping_from.s, sipping_from.len) != 0)
2410                 goto done;
2411
2412         /* from-tag is: ruid-aorhash-counter */
2413         if(fb->tag_value.len <= 0)
2414                 goto done;
2415
2416         LM_DBG("checking nathelper keepalive reply [%.*s]\n", fb->tag_value.len,
2417                         fb->tag_value.s);
2418
2419         /* skip counter */
2420         p = q_memrchr(fb->tag_value.s, '-', fb->tag_value.len);
2421         if(p == NULL) {
2422                 LM_DBG("from tag format mismatch [%.*s]\n", fb->tag_value.len,
2423                                 fb->tag_value.s);
2424                 goto done;
2425         }
2426         /* aor hash */
2427         ah.len = p - fb->tag_value.s;
2428         aorhash = 0;
2429         p = q_memrchr(fb->tag_value.s, '-', ah.len);
2430         if(p == NULL) {
2431                 LM_DBG("from tag format mismatch [%.*s]!\n", fb->tag_value.len,
2432                                 fb->tag_value.s);
2433                 goto done;
2434         }
2435         ah.s = p + 1;
2436         ah.len = fb->tag_value.s + ah.len - ah.s;
2437
2438         LM_DBG("aor hash string is [%.*s] (%d)\n", ah.len, ah.s, ah.len);
2439
2440         if(ah.len <= 0 || reverse_hex2int(ah.s, ah.len, &aorhash) < 0) {
2441                 LM_DBG("cannot get aor hash in [%.*s]\n", fb->tag_value.len,
2442                                 fb->tag_value.s);
2443                 goto done;
2444         }
2445         LM_DBG("aor hash is [%u] string [%.*s]\n", aorhash, ah.len, ah.s);
2446
2447         ruid.s = fb->tag_value.s;
2448         ruid.len = ah.s - ruid.s - 1;
2449
2450         if(ruid.len <= 0) {
2451                 LM_DBG("cannot get ruid in [%.*s]\n", fb->tag_value.len,
2452                                 fb->tag_value.s);
2453                 goto done;
2454         }
2455
2456         LM_DBG("reply for keepalive of [%.*s:%u]\n", ruid.len, ruid.s, aorhash);
2457
2458         ul.refresh_keepalive(aorhash, &ruid);
2459 done:
2460         /* let the core handle further the reply */
2461         return 1;
2462 }
2463
2464 static int sel_rewrite_contact(str *res, select_t *s, struct sip_msg *msg)
2465 {
2466         static char buf[500];
2467         contact_t *c;
2468         int n, def_port_fl, len;
2469         char *cp;
2470         str hostport;
2471         struct sip_uri uri;
2472
2473         res->len = 0;
2474         n = s->params[2].v.i;
2475         if(n <= 0) {
2476                 LM_ERR("rewrite contact[%d] - zero or negative index not supported\n",
2477                                 n);
2478                 return -1;
2479         }
2480         c = 0;
2481         do {
2482                 if(contact_iterator(&c, msg, c) < 0 || !c)
2483                         return -1;
2484                 n--;
2485         } while(n > 0);
2486
2487         if(parse_uri(c->uri.s, c->uri.len, &uri) < 0 || uri.host.len <= 0) {
2488                 LM_ERR("rewrite contact[%d] - error while parsing Contact URI\n",
2489                                 s->params[2].v.i);
2490                 return -1;
2491         }
2492         len = c->len - uri.host.len;
2493         if(uri.port.len > 0)
2494                 len -= uri.port.len;
2495         def_port_fl =
2496                         (msg->rcv.proto == PROTO_TLS && msg->rcv.src_port == SIPS_PORT)
2497                         || (msg->rcv.proto != PROTO_TLS && msg->rcv.src_port == SIP_PORT);
2498         if(!def_port_fl)
2499                 len += 1 /*:*/ + 5 /*port*/;
2500         if(len > sizeof(buf)) {
2501                 LM_ERR("rewrite contact[%d] - contact too long\n", s->params[2].v.i);
2502                 return -1;
2503         }
2504         hostport = uri.host;
2505         if(uri.port.len > 0)
2506                 hostport.len = uri.port.s + uri.port.len - uri.host.s;
2507
2508         res->s = buf;
2509         res->len = hostport.s - c->name.s;
2510         memcpy(buf, c->name.s, res->len);
2511         cp = ip_addr2a(&msg->rcv.src_ip);
2512         if(def_port_fl) {
2513                 res->len += snprintf(buf + res->len, sizeof(buf) - res->len, "%s", cp);
2514         } else {
2515                 res->len += snprintf(buf + res->len, sizeof(buf) - res->len, "%s:%d",
2516                                 cp, msg->rcv.src_port);
2517         }
2518         memcpy(buf + res->len, hostport.s + hostport.len,
2519                         c->len - (hostport.s + hostport.len - c->name.s));
2520         res->len += c->len - (hostport.s + hostport.len - c->name.s);
2521
2522         return 0;
2523 }
2524 /*!
2525 * @function w_set_alias_to_pv
2526 * @abstract wrapper of set_alias_to_avp_f
2527 * @param msg sip message
2528 * @param uri_avp given avp name
2529 *
2530 * @result 1 successful  , -1 fail
2531 */
2532 static int w_set_alias_to_pv(struct sip_msg *msg, char *uri_avp, char *hollow)
2533 {
2534         str dest_avp={0,0};
2535
2536         if(!uri_avp)
2537                 return -1;
2538
2539         dest_avp.s=uri_avp;
2540         dest_avp.len=strlen(dest_avp.s);
2541
2542         return ki_set_alias_to_pv(msg,&dest_avp);
2543 }
2544
2545 /*!
2546 * @function ki_set_alias_to_pv
2547 * @abstract reads from  msg then write to given avp uri_avp as sip uri
2548 *
2549 * @param msg sip message
2550 * @param uri_avp given avp name
2551 *
2552 * @result 1 successful  , -1 fail
2553 */
2554 static int ki_set_alias_to_pv(struct sip_msg *msg, str *pvname)
2555 {
2556         str contact;
2557         str alias_uri={0,0};
2558
2559         if(parse_headers(msg,HDR_CONTACT_F,0) < 0 ) {
2560                 LM_ERR("Couldn't find Contact Header\n");
2561                 return -1;
2562         }
2563
2564         if(!msg->contact)
2565                 return -1;
2566
2567         if(parse_contact(msg->contact)<0 || !msg->contact->parsed ||
2568         ((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
2569         ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL){
2570                 LM_ERR("Couldn't parse Contact Header\n");
2571                 return -1;
2572         }
2573
2574         contact.s = ((contact_body_t *)msg->contact->parsed)->contacts->name.s;
2575         contact.len = ((contact_body_t *)msg->contact->parsed)->contacts->len;
2576
2577         if(nh_alias_to_uri(&contact, &alias_uri)<0)
2578                 return -1;
2579
2580         if(nh_write_to_pv(msg, &alias_uri, pvname)<0)
2581                 goto error;
2582
2583         if(alias_uri.s)
2584                 pkg_free(alias_uri.s);
2585
2586         return 1;
2587
2588         error :
2589                 if(alias_uri.s)
2590                         pkg_free(alias_uri.s);
2591
2592         return -1;
2593 }
2594 /*!
2595 * @function nh_write_to_pv
2596 * @abstract nh_write_to_pv function writes data to given avp
2597 * @param data  source data
2598 * @param uri_avp destination avp name
2599 * @result 1 successful  , -1 fail
2600 */
2601 static int nh_write_to_pv(struct sip_msg *msg, str *data, str *pvname)
2602 {
2603         pv_spec_t *pvresult = NULL;
2604         pv_value_t valx;
2605         pvresult = pv_cache_get(pvname);
2606
2607         if(pvresult == NULL) {
2608                 LM_ERR("Failed to malloc destination pseudo-variable \n");
2609                 return -1;
2610         }
2611
2612         if(pvresult->setf==NULL) {
2613                 LM_ERR("Destination pseudo-variable is not writable: [%.*s] \n",
2614                                 pvname->len, pvname->s);
2615                 return -1;
2616         }
2617         memset(&valx, 0, sizeof(pv_value_t));
2618
2619         if(!data->s){
2620                 LM_ERR("There isn't any data to write to the destination\n");
2621                 return -1;
2622         }
2623
2624         valx.flags      =       PV_VAL_STR;
2625         valx.rs.s       =       data->s;
2626         valx.rs.len     =       data->len;
2627
2628         LM_DBG("result: [%.*s]\n", valx.rs.len, valx.rs.s);
2629         pvresult->setf(msg, &pvresult->pvp, (int)EQ_T, &valx);
2630         return 1;
2631 }
2632 /*!
2633 * @function nh_alias_to_uri
2634 * @abstract select alias paramter from contact_header
2635 *                                       then writes to alias_uri
2636 * @param contact_header  Source contact header
2637 * @param alias_uri Destination string
2638 * @result 1 successful  , -1 fail
2639 */
2640 static int nh_alias_to_uri(str *contact_header, str *alias_uri)
2641 {
2642         int i=0; // index
2643         str host={0,0};
2644         str port={0,0};
2645         str proto={0,0};
2646         char *memchr_pointer=0;
2647
2648         if(!contact_header)
2649                 return -1;
2650
2651         LM_DBG("Contact header [%.*s] \r\n",contact_header->len,contact_header->s);
2652
2653         for(i=0; i<contact_header->len  ;i++){
2654                 if(strncmp(&contact_header->s[i], SALIAS, SALIAS_LEN) == 0){
2655                         i=i+SALIAS_LEN;
2656                         host.s = &contact_header->s[i];
2657                         memchr_pointer = memchr(host.s , 126 /* ~ */,contact_header->len-i);
2658                                 if(memchr_pointer == NULL) {
2659                                         LM_ERR("No alias parameter found for host\n");
2660                                         return -1;
2661                                 } else {
2662                                         host.len = memchr_pointer - &contact_header->s[i];
2663                                         i=i+host.len;
2664                                 }
2665                         break;
2666                         }
2667         }
2668
2669         if(!memchr_pointer){
2670                 LM_ERR("Alias couldn't be found \n");
2671                 return -1;
2672         }
2673         if(&memchr_pointer[1]){
2674                 port.s=&memchr_pointer[1];
2675         }else{
2676                 LM_ERR("Alias sign couldn't be found for port \n");
2677                 return -1;
2678         }
2679
2680         memchr_pointer = memchr(port.s , 126 /* ~ */,contact_header->len-i);
2681         if(memchr_pointer == NULL) {
2682                 LM_ERR("Alias sign couldn't be found for proto \n");
2683                 return -1;
2684         } else {
2685                 port.len = memchr_pointer - port.s;
2686                 i=i+port.len;
2687         }
2688         //last char is proto 0,1,2,3,4..7
2689         proto.s= &port.s[port.len+1];
2690         proto_type_to_str((unsigned short)atoi(proto.s), &proto);
2691
2692         LM_DBG("Host [%.*s][port: %.*s][proto: %.*s] \r\n",host.len,host.s,port.len,port.s,proto.len,proto.s);
2693
2694         //sip:host:port;transport=udp
2695         alias_uri->s =(char *) pkg_malloc(port.len+host.len+proto.len+16);
2696         if(!alias_uri->s){
2697                 LM_ERR("Allocation ERROR\n");
2698                 return -1;
2699         }
2700
2701         memset(alias_uri->s,0,16+port.len+host.len);
2702
2703         memcpy(alias_uri->s,"sip:",4);
2704         memcpy(&alias_uri->s[4],host.s,host.len);
2705
2706         memcpy(&alias_uri->s[4+host.len],":",1);
2707         memcpy(&alias_uri->s[4+host.len+1],port.s,port.len);
2708         memcpy(&alias_uri->s[4+host.len+1+port.len],";transport=",11);
2709         memcpy(&alias_uri->s[4+host.len+1+port.len+11],proto.s,proto.len);
2710
2711         alias_uri->len=port.len+host.len+16+proto.len;
2712         LM_DBG("Alias uri [%.*s][len: %d] \r\n",alias_uri->len,alias_uri->s,alias_uri->len);
2713
2714         return 1;
2715 }
2716
2717 /**
2718  *
2719  */
2720 /* clang-format off */
2721 static sr_kemi_t sr_kemi_nathelper_exports[] = {
2722         { str_init("nathelper"), str_init("nat_uac_test"),
2723                 SR_KEMIP_INT, nat_uac_test,
2724                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
2725                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2726         },
2727         { str_init("nathelper"), str_init("fix_nated_contact"),
2728                 SR_KEMIP_INT, fix_nated_contact,
2729                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2730                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2731         },
2732         { str_init("nathelper"), str_init("fix_nated_register"),
2733                 SR_KEMIP_INT, fix_nated_register,
2734                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2735                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2736         },
2737         { str_init("nathelper"), str_init("set_contact_alias"),
2738                 SR_KEMIP_INT, ki_set_contact_alias,
2739                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2740                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2741         },
2742         { str_init("nathelper"), str_init("set_contact_alias_trim"),
2743                 SR_KEMIP_INT, ki_set_contact_alias_trim,
2744                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2745                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2746         },
2747         { str_init("nathelper"), str_init("handle_ruri_alias"),
2748                 SR_KEMIP_INT, handle_ruri_alias,
2749                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2750                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2751         },
2752         { str_init("nathelper"), str_init("is_rfc1918"),
2753                 SR_KEMIP_INT, is_rfc1918,
2754                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2755                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2756         },
2757         { str_init("nathelper"), str_init("add_contact_alias"),
2758                 SR_KEMIP_INT, add_contact_alias_0,
2759                 { SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
2760                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2761         },
2762         { str_init("nathelper"), str_init("add_contact_alias_addr"),
2763                 SR_KEMIP_INT, add_contact_alias_3,
2764                 { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
2765                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2766         },
2767         { str_init("nathelper"), str_init("add_rcv_param"),
2768                 SR_KEMIP_INT, ki_add_rcv_param,
2769                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
2770                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2771         },
2772         { str_init("nathelper"), str_init("fix_nated_sdp"),
2773                 SR_KEMIP_INT, ki_fix_nated_sdp,
2774                 { SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
2775                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2776         },
2777         { str_init("nathelper"), str_init("fix_nated_sdp_ip"),
2778                 SR_KEMIP_INT, ki_fix_nated_sdp_ip,
2779                 { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE,
2780                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2781         },
2782         { str_init("nathelper"), str_init("set_alias_to_pv"),
2783                 SR_KEMIP_INT, ki_set_alias_to_pv,
2784                 { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
2785                         SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
2786         },
2787
2788         { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
2789 };
2790 /* clang-format on */
2791
2792 /**
2793  *
2794  */
2795 int mod_register(char *path, int *dlflags, void *p1, void *p2)
2796 {
2797         sr_kemi_modules_add(sr_kemi_nathelper_exports);
2798         return 0;
2799 }