diff --git a/cfg.lex b/cfg.lex index e31b5a66817..83c5c8f85ea 100644 --- a/cfg.lex +++ b/cfg.lex @@ -336,6 +336,7 @@ DST_BLST_TCP_IMASK dst_blacklist_tcp_imask DST_BLST_TLS_IMASK dst_blacklist_tls_imask DST_BLST_SCTP_IMASK dst_blacklist_sctp_imask +IP_FREE_BIND ip_free_bind|ip_freebind|ipfreebind PORT port STAT statistics @@ -751,6 +752,7 @@ IMPORTFILE "import_file" return DST_BLST_TLS_IMASK; } {DST_BLST_SCTP_IMASK} { count(); yylval.strval=yytext; return DST_BLST_SCTP_IMASK; } +{IP_FREE_BIND} { count(); yylval.strval=yytext; return IP_FREE_BIND; } {PORT} { count(); yylval.strval=yytext; return PORT; } {STAT} { count(); yylval.strval=yytext; return STAT; } {MAXBUFFER} { count(); yylval.strval=yytext; return MAXBUFFER; } diff --git a/cfg.y b/cfg.y index 05f0de5e6ce..bb4a6865d3d 100644 --- a/cfg.y +++ b/cfg.y @@ -366,6 +366,7 @@ extern char *default_routename; %token DST_BLST_TCP_IMASK %token DST_BLST_TLS_IMASK %token DST_BLST_SCTP_IMASK +%token IP_FREE_BIND %token PORT %token STAT @@ -869,6 +870,8 @@ assign_stm: IF_DST_BLACKLIST(default_core_cfg.blst_sctp_imask=$3); } | DST_BLST_SCTP_IMASK error { yyerror("number(flags) expected"); } + | IP_FREE_BIND EQUAL intno { _sr_ip_free_bind=$3; } + | IP_FREE_BIND EQUAL error { yyerror("int value expected"); } | PORT EQUAL NUMBER { port_no=$3; } | STAT EQUAL STRING { #ifdef STATS diff --git a/globals.h b/globals.h index 60ffd25b4d8..f2950a9773b 100644 --- a/globals.h +++ b/globals.h @@ -213,6 +213,7 @@ extern int rt_timer1_policy; /* "fast" timer, SCHED_OTHER */ extern int rt_timer2_policy; /* "slow" timer, SCHED_OTHER */ extern int http_reply_parse; +extern int _sr_ip_free_bind; #ifdef USE_DNS_CACHE extern int dns_cache_init; /* if 0, the DNS cache is not initialized at startup */ diff --git a/modules/sctp/sctp_server.c b/modules/sctp/sctp_server.c index 0bf6235cad3..378c296a997 100644 --- a/modules/sctp/sctp_server.c +++ b/modules/sctp/sctp_server.c @@ -468,7 +468,18 @@ static int sctp_init_sock_opt_common(int s, int af) /* continue since this is not critical */ } } - + +#if defined(IP_FREEBIND) + /* allow bind to non local address. + * useful when daemon started before network initialized */ + optval = 1; + if (_sr_ip_free_bind && setsockopt(s, IPPROTO_IP, IP_FREEBIND, + (void*)&optval, sizeof(optval)) ==-1) { + LM_WARN("setsockopt freebind failed: %s\n", strerror(errno)); + /* continue since this is not critical */ + } +#endif + /* set receive buffer: SO_RCVBUF*/ if (cfg_get(sctp, sctp_cfg, so_rcvbuf)){ optval=cfg_get(sctp, sctp_cfg, so_rcvbuf); @@ -479,7 +490,7 @@ static int sctp_init_sock_opt_common(int s, int af) /* continue, non-critical */ } } - + /* set send buffer: SO_SNDBUF */ if (cfg_get(sctp, sctp_cfg, so_sndbuf)){ optval=cfg_get(sctp, sctp_cfg, so_sndbuf); diff --git a/receive.c b/receive.c index 0904de13b63..f5bb9759d70 100644 --- a/receive.c +++ b/receive.c @@ -59,6 +59,8 @@ #include #endif +int _sr_ip_free_bind = 0; + unsigned int msg_no=0; /* address preset vars */ str default_global_address={0,0}; diff --git a/tcp_main.c b/tcp_main.c index 5b647e17cd5..c0925498982 100644 --- a/tcp_main.c +++ b/tcp_main.c @@ -2762,6 +2762,17 @@ int tcp_init(struct socket_info* sock_info) /* continue since this is not critical */ } } + +#if defined(IP_FREEBIND) + /* allow bind to non local address. + * useful when daemon started before network initialized */ + if (_sr_ip_free_bind && setsockopt(sock_info->socket, IPPROTO_IP, + IP_FREEBIND, (void*)&optval, sizeof(optval)) ==-1) { + LM_WARN("setsockopt freebind failed: %s\n", strerror(errno)); + /* continue since this is not critical */ + } +#endif + #ifdef HAVE_TCP_DEFER_ACCEPT /* linux only */ if ((optval=cfg_get(tcp, tcp_cfg, defer_accept))){ diff --git a/udp_server.c b/udp_server.c index 5105456fdea..2e5004bb1bc 100644 --- a/udp_server.c +++ b/udp_server.c @@ -319,6 +319,16 @@ int udp_init(struct socket_info* sock_info) } #endif +#if defined(IP_FREEBIND) + /* allow bind to non local address. + * useful when daemon started before network initialized */ + optval = 1; + if (_sr_ip_free_bind && setsockopt(sock_info->socket, IPPROTO_IP, + IP_FREEBIND, (void*)&optval, sizeof(optval)) ==-1) { + LM_WARN("setsockopt freebind failed: %s\n", strerror(errno)); + /* continue since this is not critical */ + } +#endif #ifdef USE_MCAST if ((sock_info->flags & SI_IS_MCAST) && (setup_mcast_rcvr(sock_info->socket, addr)<0)){