2 * Copyright (C) 2003-2008 Sippy Software, Inc., http://www.sippysoft.com
4 * This file is part of Kamailio, a free SIP server.
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
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.
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
22 #include <sys/types.h>
23 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <netinet/in_systm.h>
30 #include <netinet/ip.h>
34 #include <netinet/udp.h>
35 #include <arpa/inet.h>
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"
87 #if !defined(AF_LOCAL)
88 #define AF_LOCAL AF_UNIX
90 #if !defined(PF_LOCAL)
91 #define PF_LOCAL PF_UNIX
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
105 #define DEFAULT_NATPING_STATE 1
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);
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);
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);
139 static int nathelper_rpc_init(void);
141 static usrloc_api_t ul;
143 static int cblen = 0;
144 static int natping_interval = 0;
145 struct socket_info *force_socket = 0;
147 static int nh_nat_addr_mode = 1;
149 /* clang-format off */
150 typedef struct nh_netaddr {
151 const char *cnetaddr;
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 */
165 static nh_netaddr_t nh_nets_extra[] = {
166 {"192.0.0.0", 0, 0xffffffffu << 8}, /* rfc7335 - IETF Protocol Assignments */
169 /* clang-format on */
172 * If this parameter is set then the natpinger will ping only contacts
173 * that have the NAT flag set in user location database
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;
182 static str nortpproxy_str = str_init("a=nortpproxy:yes");
184 static char *rcv_avp_param = NULL;
185 static unsigned short rcv_avp_type = 0;
186 static int_str rcv_avp_name;
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;
199 /*0-> disabled, 1 ->enabled*/
200 unsigned int *natping_state = NULL;
202 /* clang-format off */
203 static cmd_export_t cmds[] = {
204 {"fix_nated_contact", (cmd_function)fix_nated_contact_f, 0,
206 REQUEST_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
207 {"add_contact_alias", (cmd_function)add_contact_alias_0_f, 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,
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,
220 REQUEST_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
221 {"fix_nated_sdp", (cmd_function)fix_nated_sdp_f, 1,
223 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
224 {"fix_nated_sdp", (cmd_function)fix_nated_sdp_f, 2,
226 REQUEST_ROUTE|ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE},
227 {"nat_uac_test", (cmd_function)nat_uac_test_f, 1,
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,
233 {"add_rcv_param", (cmd_function)add_rcv_param_f, 0,
236 {"add_rcv_param", (cmd_function)add_rcv_param_f, 1,
239 {"is_rfc1918", (cmd_function)is_rfc1918_f, 1,
242 {"set_alias_to_pv", (cmd_function)w_set_alias_to_pv, 1,
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}
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 },
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 */
288 /* clang-format on */
291 static int sel_nathelper(str *res, select_t *s, struct sip_msg *msg)
297 static int sel_rewrite_contact(str *res, select_t *s, struct sip_msg *msg);
299 SELECT_F(select_any_nameaddr)
301 select_row_t sel_declaration[] = {
302 {NULL, SEL_PARAM_STR, STR_STATIC_INIT("nathelper"), sel_nathelper,
304 {sel_nathelper, SEL_PARAM_STR, STR_STATIC_INIT("rewrite_contact"),
305 sel_rewrite_contact, CONSUME_NEXT_INT},
307 {sel_rewrite_contact, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"),
308 select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
310 {NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}};
312 static int fixup_fix_sdp(void **param, int param_no)
316 return fixup_igp_null(param, param_no);
320 return fixup_spve_all(param, param_no);
322 LM_ERR("unexpected param no: %d\n", param_no);
326 static int fixup_fix_nated_register(void **param, int param_no)
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");
336 static int fixup_add_contact_alias(void **param, int param_no)
338 if((param_no >= 1) && (param_no <= 3))
339 return fixup_spve_null(param, 1);
341 LM_ERR("invalid parameter number <%d>\n", param_no);
345 static void nathelper_rpc_enable_ping(rpc_t *rpc, void *ctx)
348 if(natping_state == NULL) {
349 rpc->fault(ctx, 500, "NATping disabled");
353 if(rpc->scan(ctx, "d", &value) < 1) {
354 rpc->fault(ctx, 500, "No parameter");
357 (*natping_state) = value ? 1 : 0;
360 static const char *nathelper_rpc_enable_ping_doc[2] = {
361 "Set (enable/disable) nat ping", 0};
363 rpc_export_t nathelper_rpc[] = {
364 {"nathelper.enable_ping", nathelper_rpc_enable_ping,
365 nathelper_rpc_enable_ping_doc, 0},
368 static int nathelper_rpc_init(void)
370 if(rpc_register_array(nathelper_rpc) != 0) {
371 LM_ERR("failed to register RPC commands\n");
377 static int init_raw_socket(void)
381 raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
383 LM_ERR("cannot create raw socket\n");
387 if(setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) == -1) {
388 LM_ERR("cannot set socket options\n");
396 static int get_natping_socket(
397 char *socket, unsigned int *ip, unsigned short *port)
404 if(parse_phostport(socket, &host.s, &host.len, &lport, &lproto) != 0) {
405 LM_CRIT("invalid natping_socket parameter <%s>\n", natping_socket);
409 if(lproto != PROTO_UDP && lproto != PROTO_NONE) {
410 LM_CRIT("natping_socket can be only UDP <%s>\n", natping_socket);
414 *port = lport ? (unsigned short)lport : SIP_PORT;
416 he = sip_resolvehost(&host, port, (char *)(void *)&lproto);
418 LM_ERR("could not resolve hostname:\"%.*s\"\n", host.len, host.s);
421 if(he->h_addrtype != AF_INET) {
422 LM_ERR("only ipv4 addresses allowed in natping_socket\n");
426 memcpy(ip, he->h_addr_list[0], he->h_length);
432 static int mod_init(void)
435 bind_usrloc_t bind_usrloc;
442 if(nathelper_rpc_init() < 0) {
443 LM_ERR("failed to register RPC commands\n");
447 if(rcv_avp_param && *rcv_avp_param) {
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);
455 if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)
457 LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
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);
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)
479 if(init_raw_socket() < 0)
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--;
490 if(natping_interval > 0) {
491 bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
493 LM_ERR("can't find usrloc module\n");
497 if(bind_usrloc(&ul) < 0) {
501 natping_state = (unsigned int *)shm_malloc(sizeof(unsigned int));
503 LM_ERR("no shmem left\n");
506 *natping_state = DEFAULT_NATPING_STATE;
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");
513 if(natping_processes < 0) {
514 LM_ERR("bad config - natping_processes must be >= 0\n");
517 ul.set_max_partition(natping_processes * natping_interval);
519 sipping_flag = (sipping_flag == -1) ? 0 : (1 << sipping_flag);
520 natping_disable_flag =
521 (natping_disable_flag == -1) ? 0 : (1 << natping_disable_flag);
523 /* set reply function if SIP natping is enabled */
525 if(sipping_from.s == 0 || sipping_from.len <= 0) {
526 LM_ERR("SIP ping enabled, but SIP ping FROM is empty!\n");
529 if(sipping_method.s == 0 || sipping_method.len <= 0) {
530 LM_ERR("SIP ping enabled, but SIP ping method is empty!\n");
533 if(nh_keepalive_timeout > 0 && ul.set_keepalive_timeout != NULL) {
534 ul.set_keepalive_timeout(nh_keepalive_timeout);
537 if(parse_method_name(&sipping_method, &sipping_method_id) < 0) {
538 LM_ERR("invalid SIP ping method [%.*s]!\n", sipping_method.len,
542 exports.response_f = sipping_rpl_filter;
546 register_dummy_timers(natping_processes);
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)
553 nh_nets_1918[i].netaddr = ntohl(addr.s_addr) & nh_nets_1918[i].mask;
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)
560 nh_nets_extra[i].netaddr = ntohl(addr.s_addr) & nh_nets_extra[i].mask;
563 register_select_table(sel_declaration);
569 static int child_init(int rank)
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*/)
578 LM_ERR("failed to register timer routine as process\n");
585 if(rank <= 0 && rank != PROC_TIMER)
592 static void mod_destroy(void)
594 /*free the shared memory*/
596 shm_free(natping_state);
600 static int isnulladdr(str *sx, int pf)
605 for(cp = sx->s; cp < sx->s + sx->len; cp++)
606 if(*cp != '0' && *cp != ':')
610 return (sx->len == 7 && memcmp("0.0.0.0", sx->s, 7) == 0);
614 * Replaces ip:port pair in the Contact: field with the source address
617 static int fix_nated_contact(struct sip_msg *msg)
619 int offset, len, len1;
620 char *cp, *buf, temp[2];
628 if(get_contact_uri(msg, &uri, &c) == -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");
636 offset = c->uri.s - msg->buf;
637 anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T);
643 hostport.len = uri.port.s + uri.port.len - uri.host.s;
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)
649 buf = pkg_malloc(len);
651 LM_ERR("out of pkg memory\n");
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);
662 len1 = snprintf(buf, len, "%s%s:%d%s", c->uri.s, cp,
663 msg->rcv.src_port, hostport.s + hostport.len);
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] == ';'))
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,
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,
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) {
701 static int fix_nated_contact_f(struct sip_msg *msg, char *str1, char *str2)
703 return fix_nated_contact(msg);
707 * Replaces ip:port pair in the Contact: field with the source address
710 static int set_contact_alias(struct sip_msg *msg, int trim)
712 char nbuf[MAX_URI_SIZE];
713 char cbuf[MAX_URI_SIZE];
725 nuri.len = MAX_URI_SIZE;
727 curi.len = MAX_URI_SIZE;
728 if(get_contact_uri(msg, &uri, &c) == -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");
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");
740 if(uri_add_rcv_alias(msg, &c->uri, &nuri) < 0) {
741 LM_DBG("cannot add the alias parameter\n");
747 if(c->uri.s[-1] == '<')
751 len = nuri.len + 2 * br;
752 buf = pkg_malloc(len + 1);
754 LM_ERR("out of pkg memory\n");
759 strncpy(buf + 1, nuri.s, nuri.len);
762 strncpy(buf, nuri.s, nuri.len);
766 offset = c->uri.s - msg->buf;
767 anchor = del_lump(msg, offset, c->uri.len, HDR_CONTACT_T);
773 if(insert_new_lump_after(anchor, buf, len, HDR_CONTACT_T) == 0) {
778 c->uri.len = len - 2 * br;
783 static int ki_set_contact_alias(struct sip_msg *msg)
785 return set_contact_alias(msg, 0);
788 static int ki_set_contact_alias_trim(struct sip_msg *msg)
790 return set_contact_alias(msg, 1);
793 static int set_contact_alias_f(struct sip_msg *msg, char *str1, char *str2)
795 return set_contact_alias(msg, 0);
798 static int w_set_contact_alias_f(struct sip_msg *msg, char *str1, char *str2)
802 if(get_int_fparam(&i, msg, (fparam_t *)str1) < 0)
807 return set_contact_alias(msg, i);
810 #define SALIAS ";alias="
811 #define SALIAS_LEN (sizeof(SALIAS) - 1)
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.
818 static int add_contact_alias_0(struct sip_msg *msg)
820 int len, param_len, ip_len;
825 char *bracket, *lt, *param, *at, *port, *start;
827 /* Do nothing if Contact header does not exist */
829 if(parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
830 LM_ERR("while parsing headers\n");
834 LM_DBG("no contact header\n");
838 if(get_contact_uri(msg, &uri, &c) == -1) {
839 LM_ERR("failed to get contact uri\n");
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");
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");
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");
863 /* Check if Contact URI needs to be enclosed in <>s */
865 bracket = memchr(msg->contact->body.s, '<', msg->contact->body.len);
866 if(bracket == NULL) {
868 lt = (char *)pkg_malloc(1);
870 LM_ERR("no pkg memory left for lt sign\n");
874 anchor = anchor_lump(msg, msg->contact->body.s - msg->buf, 0, 0);
876 LM_ERR("anchor_lump for beginning of contact body failed\n");
879 if(insert_new_lump_before(anchor, lt, 1, 0) == 0) {
880 LM_ERR("insert_new_lump_before for \"<\" failed\n");
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);
891 LM_ERR("no pkg memory left for alias param\n");
896 append_str(at, SALIAS, SALIAS_LEN);
897 if(msg->rcv.src_ip.af == AF_INET6)
899 ip_len = ip_addr2sbuf(&(msg->rcv.src_ip), at, param_len - SALIAS_LEN);
901 LM_ERR("failed to copy source ip\n");
905 if(msg->rcv.src_ip.af == AF_INET6)
909 port = int2str(msg->rcv.src_port, &len);
910 append_str(at, port, len);
913 if((msg->rcv.proto < PROTO_UDP) || (msg->rcv.proto > PROTO_WSS)) {
914 LM_ERR("invalid transport protocol\n");
917 append_chr(at, msg->rcv.proto + '0');
919 if(bracket == NULL) {
922 param_len = at - param;
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;
929 start = uri.host.s + uri.host.len;
931 anchor = anchor_lump(msg, start - msg->buf, 0, 0);
933 LM_ERR("anchor_lump for ;alias param failed\n");
936 if(insert_new_lump_after(anchor, param, param_len, 0) == 0) {
937 LM_ERR("insert_new_lump_after for ;alias param failed\n");
950 static int add_contact_alias_0_f(struct sip_msg *msg, char *str1, char *str2)
952 return add_contact_alias_0(msg);
955 static int proto_type_to_int(char *proto)
957 if(strcasecmp(proto, "udp") == 0)
959 if(strcasecmp(proto, "tcp") == 0)
961 if(strcasecmp(proto, "tls") == 0)
963 if(strcasecmp(proto, "sctp") == 0)
965 if(strcasecmp(proto, "ws") == 0)
967 if(strcasecmp(proto, "wss") == 0)
974 * Adds ;alias=ip~port~proto param to contact uri containing ip, port,
975 * and encoded proto given as parameters.
977 static int add_contact_alias_3(
978 sip_msg_t *msg, str *ip_str, str *port_str, str *proto_str)
980 int param_len, proto;
985 char *bracket, *lt, *param, *at, *start;
987 /* Do nothing if Contact header does not exist */
989 if(parse_headers(msg, HDR_CONTACT_F, 0) == -1) {
990 LM_ERR("while parsing headers\n");
994 LM_DBG("no contact header\n");
998 if(get_contact_uri(msg, &uri, &c) == -1) {
999 LM_ERR("failed to get contact uri\n");
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);
1007 if((str2int(port_str, &tmp) == -1) || (tmp == 0) || (tmp > 65535)) {
1008 LM_ERR("port param value is not valid port\n");
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);
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");
1023 /* Check if Contact URI needs to be enclosed in <>s */
1025 bracket = memchr(msg->contact->body.s, '<', msg->contact->body.len);
1026 if(bracket == NULL) {
1028 lt = (char *)pkg_malloc(1);
1030 LM_ERR("no pkg memory left for lt sign\n");
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");
1039 if(insert_new_lump_before(anchor, lt, 1, 0) == 0) {
1040 LM_ERR("insert_new_lump_before for \"<\" failed\n");
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);
1050 LM_ERR("no pkg memory left for alias param\n");
1055 append_str(at, SALIAS, SALIAS_LEN);
1056 append_str(at, ip_str->s, ip_str->len);
1058 append_chr(at, '~');
1059 append_str(at, port_str->s, port_str->len);
1061 append_chr(at, '~');
1062 append_chr(at, proto + '0');
1064 if(bracket == NULL) {
1065 append_chr(at, '>');
1067 param_len = at - param;
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;
1074 start = uri.host.s + uri.host.len;
1076 anchor = anchor_lump(msg, start - msg->buf, 0, 0);
1077 if(anchor == NULL) {
1078 LM_ERR("anchor_lump for ;alias param failed\n");
1081 if(insert_new_lump_after(anchor, param, param_len, 0) == 0) {
1082 LM_ERR("insert_new_lump_after for ;alias param failed\n");
1095 static int add_contact_alias_3_f(
1096 sip_msg_t *msg, char *_ip, char *_port, char *_proto)
1098 str ip_str, port_str, proto_str;
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");
1105 if(fixup_get_svalue(msg, (gparam_p)_port, &port_str) != 0) {
1106 LM_ERR("cannot get port param value\n");
1109 if(fixup_get_svalue(msg, (gparam_p)_proto, &proto_str) != 0) {
1110 LM_ERR("cannot get proto param value\n");
1113 return add_contact_alias_3(msg, &ip_str, &port_str, &proto_str);
1116 #define ALIAS "alias="
1117 #define ALIAS_LEN (sizeof(ALIAS) - 1)
1120 * Checks if r-uri has alias param and if so, removes it and sets $du
1121 * based on its value.
1123 static int handle_ruri_alias(struct sip_msg *msg)
1126 char buf[MAX_URI_SIZE], *val, *sep, *at, *next, *cur_uri, *rest, *port,
1128 unsigned int len, rest_len, val_len, alias_len, proto_type, cur_uri_len,
1131 if(parse_sip_msg_uri(msg) < 0) {
1132 LM_ERR("while parsing Request-URI\n");
1135 rest = msg->parsed_uri.sip_params.s;
1136 rest_len = msg->parsed_uri.sip_params.len;
1138 LM_DBG("no params\n");
1141 while(rest_len >= ALIAS_LEN) {
1142 if(strncmp(rest, ALIAS, ALIAS_LEN) == 0)
1144 sep = memchr(rest, 59 /* ; */, rest_len);
1146 LM_DBG("no alias param\n");
1149 rest_len = rest_len - (sep - rest + 1);
1154 if(rest_len < ALIAS_LEN) {
1155 LM_DBG("no alias param\n");
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);
1164 LM_ERR("no '~' in alias param value\n");
1168 trans = memchr(port, 126 /* ~ */, val_len - (port - val));
1170 LM_ERR("no second '~' in alias param value\n");
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;
1180 if((ip_port_len + 2 > val_len) || (*trans == ';') || (*trans == '?')) {
1181 LM_ERR("no proto in alias param\n");
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");
1191 append_str(at, ";transport=", 11);
1192 memcpy(at, proto.s, proto.len);
1193 at = at + proto.len;
1196 if((ip_port_len + 2 < val_len) && (*next != ';') && (*next != '?')) {
1197 LM_ERR("invalid alias param value\n");
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");
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;
1213 cur_uri = msg->first_line.u.request.uri.s;
1214 cur_uri_len = msg->first_line.u.request.uri.len;
1217 len = rest - 1 /* ; */ - cur_uri;
1218 memcpy(at, cur_uri, len);
1220 len = cur_uri_len - alias_len - len;
1221 memcpy(at, rest + alias_len - 1, len);
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);
1228 static int handle_ruri_alias_f(struct sip_msg *msg, char *str1, char *str2)
1230 return handle_ruri_alias(msg);
1234 * Counts and return the number of record routes in rr headers of the message.
1236 static int pv_get_rr_count_f(
1237 struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1240 struct hdr_field *header;
1246 if(parse_headers(msg, HDR_EOH_F, 0) == -1) {
1247 LM_ERR("while parsing message\n");
1252 header = msg->record_route;
1255 if(header->type == HDR_RECORDROUTE_T) {
1256 if(parse_rr(header) == -1) {
1257 LM_ERR("while parsing rr header\n");
1260 body = (rr_t *)header->parsed;
1266 header = header->next;
1269 return pv_get_uintval(msg, param, res, (unsigned int)count);
1273 * Return count of topmost record routes in rr headers of the message.
1275 static int pv_get_rr_top_count_f(
1276 struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1279 struct sip_uri puri;
1284 if(!msg->record_route && (parse_headers(msg, HDR_RECORDROUTE_F, 0) == -1)) {
1285 LM_ERR("while parsing Record-Route header\n");
1289 if(!msg->record_route) {
1290 return pv_get_uintval(msg, param, res, 0);
1293 if(parse_rr(msg->record_route) == -1) {
1294 LM_ERR("while parsing rr header\n");
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");
1304 if(puri.r2.len > 0) {
1305 return pv_get_uintval(msg, param, res, 2);
1307 return pv_get_uintval(msg, param, res, 1);
1312 * Test if IP address in netaddr belongs to RFC1918 networks
1313 * netaddr in network byte order
1315 static inline int is1918addr_n(uint32_t netaddr)
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) {
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) {
1337 * Test if IP address pointed to by saddr belongs to RFC1918 networks
1339 static inline int is1918addr(str *saddr)
1341 struct in_addr addr;
1346 backup = saddr->s[saddr->len];
1347 saddr->s[saddr->len] = '\0';
1348 if(inet_aton(saddr->s, &addr) != 1)
1350 rval = is1918addr_n(addr.s_addr);
1353 saddr->s[saddr->len] = backup;
1358 * Test if IP address pointed to by ip belongs to RFC1918 networks
1360 static inline int is1918addr_ip(struct ip_addr *ip)
1362 if(ip->af != AF_INET)
1364 return is1918addr_n(ip->u.addr32[0]);
1368 * test for occurrence of RFC1918 IP address in Contact HF
1370 static int contact_1918(struct sip_msg *msg)
1375 if(get_contact_uri(msg, &uri, &c) == -1)
1378 return (is1918addr(&(uri.host)) == 1) ? 1 : 0;
1382 * test if source port of signaling is different from
1383 * port advertised in Contact
1385 static int contact_rport(struct sip_msg *msg)
1390 if(get_contact_uri(msg, &uri, &c) == -1) {
1394 if(msg->rcv.src_port != (uri.port_no ? uri.port_no : SIP_PORT)) {
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
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;
1413 if(parse_sdp(msg) < 0) {
1414 LM_ERR("Unable to parse sdp body\n");
1419 session = get_sdp_session(msg, sdp_session_num);
1423 if(!(session->ip_addr.len > 0 && session->ip_addr.s))
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");
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");
1437 LM_ERR("Couldn't get sdp address type\n");
1441 if(ip_addr_cmp(&msg->rcv.src_ip,&cline_addr)){
1447 return sdp_session_num - result;
1450 * test for occurrence of RFC1918 IP address in SDP
1452 static int sdp_1918(struct sip_msg *msg)
1456 int sdp_session_num, sdp_stream_num;
1457 sdp_session_cell_t *sdp_session;
1458 sdp_stream_cell_t *sdp_stream;
1460 if(parse_sdp(msg) < 0) {
1461 LM_ERR("Unable to parse sdp body\n");
1465 sdp_session_num = 0;
1467 sdp_session = get_sdp_session(msg, sdp_session_num);
1472 sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
1475 if(sdp_stream->ip_addr.s && sdp_stream->ip_addr.len) {
1476 ip = &(sdp_stream->ip_addr);
1477 pf = sdp_stream->pf;
1479 ip = &(sdp_session->ip_addr);
1480 pf = sdp_session->pf;
1482 if(pf != AF_INET || isnulladdr(ip, pf))
1484 if(is1918addr(ip) == 1)
1494 * test for occurrence of RFC1918 IP address in top Via
1496 static int via_1918(struct sip_msg *msg)
1499 return (is1918addr(&(msg->via1->host)) == 1) ? 1 : 0;
1502 static int nat_uac_test(struct sip_msg *msg, int tests)
1504 /* return true if any of the NAT-UAC tests holds */
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))) {
1513 * test if source address of signaling is different from
1514 * address advertised in Via
1516 if((tests & NAT_UAC_TEST_RCVD) && received_via_test(msg))
1519 * test for occurrences of RFC1918 addresses in Contact
1522 if((tests & NAT_UAC_TEST_C_1918) && (contact_1918(msg) > 0))
1525 * test for occurrences of RFC1918 addresses in SDP body
1527 if((tests & NAT_UAC_TEST_S_1918) && (sdp_1918(msg) > 0))
1530 * test for occurrences of RFC1918 addresses top Via
1532 if((tests & NAT_UAC_TEST_V_1918) && via_1918(msg))
1536 * test for occurrences of RFC1918 addresses in source address
1538 if((tests & NAT_UAC_TEST_O_1918) && is1918addr_ip(&msg->rcv.src_ip))
1542 * test prototype to check whether the message arrived on a WebSocket
1544 if((tests & NAT_UAC_TEST_WS)
1545 && (msg->rcv.proto == PROTO_WS || msg->rcv.proto == PROTO_WSS))
1549 * test if source port of signaling is different from
1550 * port advertised in Contact
1552 if((tests & NAT_UAC_TEST_C_PORT) && (contact_rport(msg) > 0))
1556 * test if sdp c line ip address matches with sip source address
1558 if((tests & NAT_UAC_TEST_SDP_CLINE) && (test_sdp_cline(msg) > 0))
1561 /* no test succeeded */
1565 static int nat_uac_test_f(struct sip_msg *msg, char *str1, char *str2)
1568 if(fixup_get_ivalue(msg, (gparam_t*)str1, &tflags)<0) {
1569 LM_ERR("failed to get the value for flags parameter\n");
1572 return nat_uac_test(msg, tflags);
1575 static int is_rfc1918(struct sip_msg *msg, str *address)
1577 return (is1918addr(address) == 1) ? 1 : -1;
1581 static int is_rfc1918_f(struct sip_msg *msg, char *str1, char *str2)
1585 if(fixup_get_svalue(msg, (gparam_p)str1, &address) != 0
1586 || address.len == 0) {
1587 LM_ERR("invalid address parameter\n");
1591 return is_rfc1918(msg, &address);
1594 #define ADD_ADIRECTION 0x01
1595 #define FIX_MEDIP 0x02
1596 #define ADD_ANORTPPROXY 0x04
1597 #define FIX_ORGIP 0x08
1599 #define ADIRECTION "a=direction:active"
1600 #define ADIRECTION_LEN (sizeof(ADIRECTION) - 1)
1602 #define AOLDMEDIP "a=oldmediaip:"
1603 #define AOLDMEDIP_LEN (sizeof(AOLDMEDIP) - 1)
1605 #define AOLDMEDIP6 "a=oldmediaip6:"
1606 #define AOLDMEDIP6_LEN (sizeof(AOLDMEDIP6) - 1)
1608 #define AOLDMEDPRT "a=oldmediaport:"
1609 #define AOLDMEDPRT_LEN (sizeof(AOLDMEDPRT) - 1)
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)
1616 str body1, oldip, newip;
1617 str body = *org_body;
1618 unsigned hasreplaced = 0;
1621 char *bodylimit = body.s + body.len;
1625 /* Iterate all lines and replace ips in them. */
1627 newip.s = ip_addr2a(&msg->rcv.src_ip);
1628 newip.len = strlen(newip.s);
1634 if(extract_mediaip(&body1, &oldip, &pf, line, linelen) == -1)
1637 LM_ERR("not an IPv4 address in '%s' SDP\n", line);
1642 else if(pf != pf1) {
1643 LM_ERR("mismatching address families in '%s' SDP\n", line);
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);
1651 LM_ERR("can't alter '%s' IP\n", line);
1659 LM_ERR("can't extract '%s' IP from the SDP\n", line);
1666 static int ki_fix_nated_sdp_ip(sip_msg_t *msg, int level, str *ip)
1670 char *buf, *m_start, *m_end;
1671 struct lump *anchor;
1675 if(extract_body(msg, &body) == -1) {
1676 LM_ERR("cannot extract body from msg!\n");
1680 if(level & (ADD_ADIRECTION | ADD_ANORTPPROXY)) {
1682 msg->msg_flags |= FL_FORCE_ACTIVE;
1684 if(level & ADD_ADIRECTION) {
1685 m_start = ser_memmem(body.s, "\r\nm=", body.len, 4);
1686 while(m_start != NULL) {
1688 rest_len = body.len - (m_start - body.s);
1689 m_start = m_end = ser_memmem(m_start, "\r\nm=", rest_len, 4);
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");
1697 buf = pkg_malloc((ADIRECTION_LEN + CRLF_LEN) * sizeof(char));
1699 LM_ERR("out of pkg memory\n");
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)
1707 LM_ERR("insert_new_lump_after failed\n");
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");
1720 buf = pkg_malloc((nortpproxy_str.len + CRLF_LEN) * sizeof(char));
1722 LM_ERR("out of pkg memory\n");
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)
1730 LM_ERR("insert_new_lump_after failed\n");
1737 if(level & (FIX_MEDIP | FIX_ORGIP)) {
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);
1742 LM_DBG("a=rtcp parameter does not exist. nothing to do.\n");
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);
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);
1764 return count > 0 ? 1 : 2;
1767 static int ki_fix_nated_sdp(sip_msg_t *msg, int level)
1769 return ki_fix_nated_sdp_ip(msg, level, NULL);
1772 static int fix_nated_sdp_f(struct sip_msg *msg, char *str1, char *str2)
1777 if(fixup_get_ivalue(msg, (gparam_t *)str1, &level) != 0) {
1778 LM_ERR("failed to get value for first parameter\n");
1781 if(str2 && fixup_get_svalue(msg, (gparam_t *)str2, &ip) != 0) {
1782 LM_ERR("failed to get value for second parameter\n");
1786 return ki_fix_nated_sdp_ip(msg, level, &ip);
1789 static int extract_mediaip(str *body, str *mediaip, int *pf, char *line, int linelen)
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')
1804 mediaip->s = cp1 + linelen;
1806 eat_line(mediaip->s, body->s + body->len - mediaip->s) - mediaip->s;
1807 trim_len(mediaip->len, mediaip->s, *mediaip);
1810 for(cp = mediaip->s; cp < mediaip->s + mediaip->len;) {
1811 len = eat_token_end(cp, mediaip->s + mediaip->len) - cp;
1818 if(len == 3 && memcmp(cp, "IP", 2) == 0) {
1834 cp = eat_space_end(cp + len, mediaip->s + mediaip->len);
1836 if(nextisip != 2 || mediaip->len == 0) {
1837 LM_ERR("no `IP[4|6]' in `%s' field\n", line);
1843 static int alter_mediaip(struct sip_msg *msg, str *body, str *oldip, int oldpf,
1844 str *newip, int newpf, int preserve)
1848 struct lump *anchor;
1851 /* check that updating mediaip is really necessary */
1852 if(oldpf == newpf && isnulladdr(oldip, oldpf))
1854 if(newip->len == oldip->len && memcmp(newip->s, oldip->s, newip->len) == 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");
1863 if(oldpf == AF_INET6) {
1864 omip.s = AOLDMEDIP6;
1865 omip.len = AOLDMEDIP6_LEN;
1868 omip.len = AOLDMEDIP_LEN;
1870 buf = pkg_malloc(omip.len + oldip->len + CRLF_LEN);
1872 LM_ERR("out of pkg memory\n");
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)
1881 LM_ERR("insert_new_lump_after failed\n");
1887 if(oldpf == newpf) {
1888 nip.len = newip->len;
1889 nip.s = pkg_malloc(nip.len);
1891 LM_ERR("out of pkg memory\n");
1894 memcpy(nip.s, newip->s, newip->len);
1896 nip.len = newip->len + 2;
1897 nip.s = pkg_malloc(nip.len);
1899 LM_ERR("out of pkg memory\n");
1902 memcpy(nip.s + 2, newip->s, newip->len);
1903 nip.s[0] = (newpf == AF_INET6) ? '6' : '4';
1908 if(oldpf != newpf) {
1912 } while(*oip.s != '6' && *oip.s != '4');
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");
1922 if(insert_new_lump_after(anchor, nip.s, nip.len, 0) == 0) {
1923 LM_ERR("insert_new_lump_after failed\n");
1931 static u_short raw_checksum(unsigned char *buffer, int len)
1936 sum += *buffer << 8;
1943 sum += *buffer << 8;
1945 sum = (sum >> 16) + (sum & 0xffff);
1946 sum = (sum >> 16) + (sum);
1948 return (u_short)~sum;
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)
1957 unsigned char packet[50];
1958 int len = sizeof(struct ip) + sizeof(struct udphdr) + buf_len;
1960 if(len > sizeof(packet)) {
1961 LM_ERR("payload too big\n");
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);
1970 ip->ip_hl = sizeof(struct ip) / 4; // no options
1972 ip->ip_len = htons(len);
1977 ip->ip_src.s_addr = s_ip;
1978 ip->ip_dst.s_addr = to->sin.sin_addr.s_addr;
1980 ip->ip_sum = raw_checksum((unsigned char *)ip, sizeof(struct ip));
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);
1987 return sendto(raw_sock, packet, len, 0, (struct sockaddr *)to,
1988 sizeof(struct sockaddr_in));
1992 * quick function to extract ip:port from path
1994 static char *extract_last_path_ip(str path)
1996 /* used for raw UDP ping which works only on IPv4 */
1998 char *start = NULL, *end = NULL, *p;
2003 max_path_depth = udpping_from_path - 1;
2005 if(!path.len || !path.s)
2009 for(i = 0; i < path.len; i++) {
2010 if(!strncmp("<sip:", p, 5) && i < path.len - 4) {
2015 if((*p == ';' || *p == '>') && !end) {
2017 if(max_path_depth) {
2019 if(path_depth >= max_path_depth) {
2027 int len = end - start;
2028 if(len > sizeof(ip) - 1) {
2031 memcpy(ip, start, len);
2040 static void nh_timer(unsigned int ticks, void *timer_idx)
2042 static unsigned int iteration = 0;
2051 unsigned int aorhash;
2052 struct sip_uri curi;
2054 struct socket_info *send_sock;
2057 struct dest_info dst;
2058 char *path_ip_str = NULL;
2059 unsigned int path_ip = 0;
2060 unsigned short path_port = 0;
2062 int send_sip_ping = 0;
2064 if((*natping_state) == 0)
2069 buf = pkg_malloc(cblen);
2071 LM_ERR("out of pkg memory\n");
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
2080 natping_processes * natping_interval, options);
2084 LM_ERR("failed to fetch contacts\n");
2091 buf = pkg_malloc(cblen);
2093 LM_ERR("out of pkg memory\n");
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
2100 natping_processes * natping_interval, options);
2112 memcpy(&(c.len), cp, sizeof(c.len));
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);
2133 if((flags & natping_disable_flag)) /* always 0 if natping_disable_flag not set */
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");
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");
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 "
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");
2164 if(parse_uri(dst_uri->s, dst_uri->len, &curi) < 0) {
2165 LM_ERR("can't parse contact/received uri\n");
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");
2175 if(curi.proto != PROTO_UDP && curi.proto != PROTO_NONE)
2177 if(curi.port_no == 0)
2178 curi.port_no = SIP_PORT;
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);
2184 LM_ERR("can't resolve_host\n");
2187 init_dest_info(&dst);
2188 hostent2su(&dst.to, he, 0, curi.port_no);
2191 send_sock = force_socket;
2193 if(send_sock == 0) {
2194 send_sock = get_send_socket(0, &dst.to, PROTO_UDP);
2196 if(send_sock == NULL) {
2197 LM_ERR("can't get sending socket\n");
2200 dst.proto = PROTO_UDP;
2201 dst.send_sock = send_sock;
2203 send_sip_ping = ((flags & sipping_flag) != 0)
2204 || (ping_nated_only == 0 && sipping_flag != 0);
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");
2212 if(send_raw((char *)sbuf, sizeof(sbuf), &dst.to, raw_ip, raw_port)
2214 LM_ERR("send_raw failed\n");
2216 } else if(udpping_from_path) {
2217 if(send_raw((char *)sbuf, sizeof(sbuf), &dst.to, path_ip, path_port)
2219 LM_ERR("send_raw from path failed\n");
2222 if(udp_send(&dst, (char *)sbuf, sizeof(sbuf)) < 0) {
2223 LM_ERR("udp_send failed\n");
2230 if(iteration == natping_interval)
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
2240 static int create_rcv_uri(str *uri, struct sip_msg *m)
2242 return get_src_uri(m, 0, uri);
2247 * Add received parameter to Contacts for further
2248 * forwarding of the REGISTER requuest
2250 static int ki_add_rcv_param(sip_msg_t *msg, int upos)
2253 struct lump *anchor;
2258 if(msg->rcv.proto != PROTO_UDP) {
2259 LM_ERR("adding received parameter to Contact URI works only for UDP\n");
2264 if(create_rcv_uri(&uri, msg) < 0) {
2268 if(contact_iterator(&c, msg, 0) < 0) {
2273 param = (char *)pkg_malloc(RECEIVED_LEN + 2 + uri.len);
2275 LM_ERR("no pkg memory left\n");
2278 memcpy(param, RECEIVED, RECEIVED_LEN);
2280 memcpy(param + RECEIVED_LEN, uri.s, uri.len);
2282 param[RECEIVED_LEN] = '\"';
2283 memcpy(param + RECEIVED_LEN + 1, uri.s, uri.len);
2284 param[RECEIVED_LEN + 1 + uri.len] = '\"';
2288 /* add the param as uri param */
2289 anchor = anchor_lump(msg, c->uri.s + c->uri.len - msg->buf, 0, 0);
2291 /* add the param as header param */
2292 anchor = anchor_lump(msg, c->name.s + c->len - msg->buf, 0, 0);
2294 if(anchor == NULL) {
2295 LM_ERR("anchor_lump failed\n");
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");
2307 if(contact_iterator(&c, msg, c) < 0) {
2316 * Add received parameter to Contacts for further
2317 * forwarding of the REGISTER requuest
2319 static int add_rcv_param_f(struct sip_msg *msg, char *str1, char *str2)
2324 if(fixup_get_ivalue(msg, (gparam_t*)str1, &hdr_param)<0) {
2325 LM_ERR("failed to get flags parameter\n");
2329 return ki_add_rcv_param(msg, hdr_param);
2333 * Create an AVP to be used by registrar with the source IP and port
2336 static int fix_nated_register(struct sip_msg *msg)
2341 if(rcv_avp_name.n == 0)
2344 if(create_rcv_uri(&uri, msg) < 0) {
2350 if(add_avp(AVP_VAL_STR | rcv_avp_type, rcv_avp_name, val) < 0) {
2351 LM_ERR("failed to create AVP\n");
2358 static int fix_nated_register_f(struct sip_msg *msg, char *str1, char *str2)
2360 return fix_nated_register(msg);
2364 * handle SIP replies
2366 static int nh_sip_reply_received(sip_msg_t *msg)
2371 unsigned int aorhash;
2374 if(nh_keepalive_timeout <= 0)
2376 if(msg->cseq == NULL && ((parse_headers(msg, HDR_CSEQ_F, 0) == -1)
2377 || (msg->cseq == NULL))) {
2378 LM_ERR("no CSEQ header\n");
2381 if(sipping_method_id != METHOD_UNDEF && sipping_method_id != METHOD_OTHER) {
2382 if(get_cseq(msg)->method_id != sipping_method_id)
2385 if(sipping_method_id == METHOD_OTHER) {
2386 if(get_cseq(msg)->method.len != sipping_method.len)
2388 if(strncmp(get_cseq(msg)->method.s, sipping_method.s,
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)))
2401 /* from uri check */
2402 if((parse_from_header(msg)) < 0) {
2403 LM_ERR("cannot parse From header\n");
2408 if(fb->uri.len != sipping_from.len
2409 || strncmp(fb->uri.s, sipping_from.s, sipping_from.len) != 0)
2412 /* from-tag is: ruid-aorhash-counter */
2413 if(fb->tag_value.len <= 0)
2416 LM_DBG("checking nathelper keepalive reply [%.*s]\n", fb->tag_value.len,
2420 p = q_memrchr(fb->tag_value.s, '-', fb->tag_value.len);
2422 LM_DBG("from tag format mismatch [%.*s]\n", fb->tag_value.len,
2427 ah.len = p - fb->tag_value.s;
2429 p = q_memrchr(fb->tag_value.s, '-', ah.len);
2431 LM_DBG("from tag format mismatch [%.*s]!\n", fb->tag_value.len,
2436 ah.len = fb->tag_value.s + ah.len - ah.s;
2438 LM_DBG("aor hash string is [%.*s] (%d)\n", ah.len, ah.s, ah.len);
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,
2445 LM_DBG("aor hash is [%u] string [%.*s]\n", aorhash, ah.len, ah.s);
2447 ruid.s = fb->tag_value.s;
2448 ruid.len = ah.s - ruid.s - 1;
2451 LM_DBG("cannot get ruid in [%.*s]\n", fb->tag_value.len,
2456 LM_DBG("reply for keepalive of [%.*s:%u]\n", ruid.len, ruid.s, aorhash);
2458 ul.refresh_keepalive(aorhash, &ruid);
2460 /* let the core handle further the reply */
2464 static int sel_rewrite_contact(str *res, select_t *s, struct sip_msg *msg)
2466 static char buf[500];
2468 int n, def_port_fl, len;
2474 n = s->params[2].v.i;
2476 LM_ERR("rewrite contact[%d] - zero or negative index not supported\n",
2482 if(contact_iterator(&c, msg, c) < 0 || !c)
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",
2492 len = c->len - uri.host.len;
2493 if(uri.port.len > 0)
2494 len -= uri.port.len;
2496 (msg->rcv.proto == PROTO_TLS && msg->rcv.src_port == SIPS_PORT)
2497 || (msg->rcv.proto != PROTO_TLS && msg->rcv.src_port == SIP_PORT);
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);
2504 hostport = uri.host;
2505 if(uri.port.len > 0)
2506 hostport.len = uri.port.s + uri.port.len - uri.host.s;
2509 res->len = hostport.s - c->name.s;
2510 memcpy(buf, c->name.s, res->len);
2511 cp = ip_addr2a(&msg->rcv.src_ip);
2513 res->len += snprintf(buf + res->len, sizeof(buf) - res->len, "%s", cp);
2515 res->len += snprintf(buf + res->len, sizeof(buf) - res->len, "%s:%d",
2516 cp, msg->rcv.src_port);
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);
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
2530 * @result 1 successful , -1 fail
2532 static int w_set_alias_to_pv(struct sip_msg *msg, char *uri_avp, char *hollow)
2540 dest_avp.len=strlen(dest_avp.s);
2542 return ki_set_alias_to_pv(msg,&dest_avp);
2546 * @function ki_set_alias_to_pv
2547 * @abstract reads from msg then write to given avp uri_avp as sip uri
2549 * @param msg sip message
2550 * @param uri_avp given avp name
2552 * @result 1 successful , -1 fail
2554 static int ki_set_alias_to_pv(struct sip_msg *msg, str *pvname)
2557 str alias_uri={0,0};
2559 if(parse_headers(msg,HDR_CONTACT_F,0) < 0 ) {
2560 LM_ERR("Couldn't find Contact Header\n");
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");
2574 contact.s = ((contact_body_t *)msg->contact->parsed)->contacts->name.s;
2575 contact.len = ((contact_body_t *)msg->contact->parsed)->contacts->len;
2577 if(nh_alias_to_uri(&contact, &alias_uri)<0)
2580 if(nh_write_to_pv(msg, &alias_uri, pvname)<0)
2584 pkg_free(alias_uri.s);
2590 pkg_free(alias_uri.s);
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
2601 static int nh_write_to_pv(struct sip_msg *msg, str *data, str *pvname)
2603 pv_spec_t *pvresult = NULL;
2605 pvresult = pv_cache_get(pvname);
2607 if(pvresult == NULL) {
2608 LM_ERR("Failed to malloc destination pseudo-variable \n");
2612 if(pvresult->setf==NULL) {
2613 LM_ERR("Destination pseudo-variable is not writable: [%.*s] \n",
2614 pvname->len, pvname->s);
2617 memset(&valx, 0, sizeof(pv_value_t));
2620 LM_ERR("There isn't any data to write to the destination\n");
2624 valx.flags = PV_VAL_STR;
2625 valx.rs.s = data->s;
2626 valx.rs.len = data->len;
2628 LM_DBG("result: [%.*s]\n", valx.rs.len, valx.rs.s);
2629 pvresult->setf(msg, &pvresult->pvp, (int)EQ_T, &valx);
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
2640 static int nh_alias_to_uri(str *contact_header, str *alias_uri)
2646 char *memchr_pointer=0;
2651 LM_DBG("Contact header [%.*s] \r\n",contact_header->len,contact_header->s);
2653 for(i=0; i<contact_header->len ;i++){
2654 if(strncmp(&contact_header->s[i], SALIAS, SALIAS_LEN) == 0){
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");
2662 host.len = memchr_pointer - &contact_header->s[i];
2669 if(!memchr_pointer){
2670 LM_ERR("Alias couldn't be found \n");
2673 if(&memchr_pointer[1]){
2674 port.s=&memchr_pointer[1];
2676 LM_ERR("Alias sign couldn't be found for port \n");
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");
2685 port.len = memchr_pointer - port.s;
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);
2692 LM_DBG("Host [%.*s][port: %.*s][proto: %.*s] \r\n",host.len,host.s,port.len,port.s,proto.len,proto.s);
2694 //sip:host:port;transport=udp
2695 alias_uri->s =(char *) pkg_malloc(port.len+host.len+proto.len+16);
2697 LM_ERR("Allocation ERROR\n");
2701 memset(alias_uri->s,0,16+port.len+host.len);
2703 memcpy(alias_uri->s,"sip:",4);
2704 memcpy(&alias_uri->s[4],host.s,host.len);
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);
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);
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
2788 { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
2790 /* clang-format on */
2795 int mod_register(char *path, int *dlflags, void *p1, void *p2)
2797 sr_kemi_modules_add(sr_kemi_nathelper_exports);