|
@@ -289,13 +289,13 @@ static inline struct socket_info* new_sock_info( char* name,
|
|
|
struct name_lst* addr_l,
|
|
|
unsigned short port, unsigned short proto,
|
|
|
char *usename, unsigned short useport,
|
|
|
- enum si_flags flags)
|
|
|
+ char *sockname, enum si_flags flags)
|
|
|
{
|
|
|
struct socket_info* si;
|
|
|
struct name_lst* n;
|
|
|
struct hostent* he;
|
|
|
char *p;
|
|
|
-
|
|
|
+
|
|
|
si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info));
|
|
|
if (si==0) goto error;
|
|
|
memset(si, 0, sizeof(struct socket_info));
|
|
@@ -315,6 +315,12 @@ static inline struct socket_info* new_sock_info( char* name,
|
|
|
goto error;
|
|
|
}
|
|
|
}
|
|
|
+ if(sockname!=NULL) {
|
|
|
+ si->sockname.len = strlen(sockname);
|
|
|
+ si->sockname.s=(char*)pkg_malloc(si->sockname.len+1); /* include \0 */
|
|
|
+ if (si->sockname.s==0) { goto error; }
|
|
|
+ memcpy(si->sockname.s, sockname, si->sockname.len+1);
|
|
|
+ }
|
|
|
if(usename!=NULL)
|
|
|
{
|
|
|
si->useinfo.name.len=strlen(usename);
|
|
@@ -356,8 +362,12 @@ static inline struct socket_info* new_sock_info( char* name,
|
|
|
error:
|
|
|
PKG_MEM_ERROR;
|
|
|
if (si) {
|
|
|
- if(si->name.s)
|
|
|
+ if(si->name.s) {
|
|
|
pkg_free(si->name.s);
|
|
|
+ }
|
|
|
+ if(si->sockname.s) {
|
|
|
+ pkg_free(si->sockname.s);
|
|
|
+ }
|
|
|
pkg_free(si);
|
|
|
}
|
|
|
return 0;
|
|
@@ -374,6 +384,7 @@ static void free_sock_info(struct socket_info* si)
|
|
|
if(si->port_no_str.s) pkg_free(si->port_no_str.s);
|
|
|
if(si->addr_info_lst) free_addr_info_lst(&si->addr_info_lst);
|
|
|
if(si->sock_str.s) pkg_free(si->sock_str.s);
|
|
|
+ if(si->sockname.s) pkg_free(si->sockname.s);
|
|
|
if(si->useinfo.name.s) pkg_free(si->useinfo.name.s);
|
|
|
if(si->useinfo.port_no_str.s) pkg_free(si->useinfo.port_no_str.s);
|
|
|
if(si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
|
|
@@ -767,12 +778,13 @@ static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
|
|
|
unsigned short port,
|
|
|
unsigned short proto,
|
|
|
char *usename, unsigned short useport,
|
|
|
+ char *sockname,
|
|
|
enum si_flags flags,
|
|
|
struct socket_info** list)
|
|
|
{
|
|
|
struct socket_info* si;
|
|
|
/* allocates si and si->name in new pkg memory */
|
|
|
- si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
|
|
|
+ si=new_sock_info(name, addr_l, port, proto, usename, useport, sockname, flags);
|
|
|
if (si==0){
|
|
|
LM_ERR("new_sock_info failed\n");
|
|
|
goto error;
|
|
@@ -811,12 +823,13 @@ static struct socket_info* new_sock2list_after(char* name,
|
|
|
unsigned short proto,
|
|
|
char *usename,
|
|
|
unsigned short useport,
|
|
|
+ char *sockname,
|
|
|
enum si_flags flags,
|
|
|
struct socket_info* after)
|
|
|
{
|
|
|
struct socket_info* si;
|
|
|
-
|
|
|
- si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
|
|
|
+
|
|
|
+ si=new_sock_info(name, addr_l, port, proto, usename, useport, sockname, flags);
|
|
|
if (si==0){
|
|
|
LM_ERR("new_sock_info failed\n");
|
|
|
goto error;
|
|
@@ -831,22 +844,22 @@ error:
|
|
|
|
|
|
/* adds a sock_info structure to the corresponding proto list
|
|
|
* return 0 on success, -1 on error */
|
|
|
-int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
|
|
|
+int add_listen_advertise_iface_name(char* name, struct name_lst* addr_l,
|
|
|
unsigned short port, unsigned short proto,
|
|
|
- char *usename, unsigned short useport,
|
|
|
+ char *usename, unsigned short useport, char *sockname,
|
|
|
enum si_flags flags)
|
|
|
{
|
|
|
struct socket_info** list;
|
|
|
unsigned short c_proto;
|
|
|
struct name_lst* a_l;
|
|
|
unsigned short c_port;
|
|
|
-
|
|
|
+
|
|
|
c_proto=(proto!=PROTO_NONE)?proto:PROTO_UDP;
|
|
|
do{
|
|
|
list=get_sock_info_list(c_proto);
|
|
|
if (list==0) /* disabled or unknown protocol */
|
|
|
continue;
|
|
|
-
|
|
|
+
|
|
|
if (port==0){ /* use default port */
|
|
|
c_port=
|
|
|
#ifdef USE_TLS
|
|
@@ -865,15 +878,15 @@ int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
|
|
|
}
|
|
|
if (c_proto!=PROTO_SCTP){
|
|
|
if (new_sock2list(name, 0, c_port, c_proto, usename, useport,
|
|
|
- flags & ~SI_IS_MHOMED, list)==0){
|
|
|
+ sockname, flags & ~SI_IS_MHOMED, list)==0){
|
|
|
LM_ERR("new_sock2list failed\n");
|
|
|
goto error;
|
|
|
}
|
|
|
/* add the other addresses in the list as separate sockets
|
|
|
* since only SCTP can bind to multiple addresses */
|
|
|
for (a_l=addr_l; a_l; a_l=a_l->next){
|
|
|
- if (new_sock2list(a_l->name, 0, c_port,
|
|
|
- c_proto, usename, useport,
|
|
|
+ if (new_sock2list(a_l->name, 0, c_port,
|
|
|
+ c_proto, usename, useport, sockname,
|
|
|
flags & ~SI_IS_MHOMED, list)==0){
|
|
|
LM_ERR("new_sock2list failed\n");
|
|
|
goto error;
|
|
@@ -881,7 +894,7 @@ int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
|
|
|
}
|
|
|
}else{
|
|
|
if (new_sock2list(name, addr_l, c_port, c_proto, usename, useport,
|
|
|
- flags, list)==0){
|
|
|
+ sockname, flags, list)==0){
|
|
|
LM_ERR("new_sock2list failed\n");
|
|
|
goto error;
|
|
|
}
|
|
@@ -892,14 +905,37 @@ error:
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
+/* adds a sock_info structure to the corresponding proto list
|
|
|
+ * return 0 on success, -1 on error */
|
|
|
+int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
|
|
|
+ unsigned short port, unsigned short proto,
|
|
|
+ char *usename, unsigned short useport,
|
|
|
+ enum si_flags flags)
|
|
|
+{
|
|
|
+ return add_listen_advertise_iface_name(name, addr_l, port, proto,
|
|
|
+ usename, useport, NULL, flags);
|
|
|
+}
|
|
|
+
|
|
|
/* adds a sock_info structure to the corresponding proto list
|
|
|
* return 0 on success, -1 on error */
|
|
|
int add_listen_iface(char* name, struct name_lst* addr_l,
|
|
|
unsigned short port, unsigned short proto,
|
|
|
enum si_flags flags)
|
|
|
{
|
|
|
- return add_listen_advertise_iface(name, addr_l, port, proto, 0, 0, flags);
|
|
|
+ return add_listen_advertise_iface_name(name, addr_l, port, proto, 0, 0, 0,
|
|
|
+ flags);
|
|
|
+}
|
|
|
+
|
|
|
+/* adds a sock_info structure to the corresponding proto list
|
|
|
+ * return 0 on success, -1 on error */
|
|
|
+int add_listen_iface_name(char* name, struct name_lst* addr_l,
|
|
|
+ unsigned short port, unsigned short proto, char *sockname,
|
|
|
+ enum si_flags flags)
|
|
|
+{
|
|
|
+ return add_listen_advertise_iface_name(name, addr_l, port, proto, 0, 0,
|
|
|
+ sockname, flags);
|
|
|
}
|
|
|
+
|
|
|
#ifdef __OS_linux
|
|
|
|
|
|
#include "linux/types.h"
|
|
@@ -1433,14 +1469,14 @@ error:
|
|
|
*/
|
|
|
static int addr_info_to_si_lst(struct addr_info* ai_lst, unsigned short port,
|
|
|
char proto, char *usename,
|
|
|
- unsigned short useport,
|
|
|
+ unsigned short useport, char *sockname,
|
|
|
enum si_flags flags,
|
|
|
struct socket_info** list)
|
|
|
{
|
|
|
struct addr_info* ail;
|
|
|
-
|
|
|
+
|
|
|
for (ail=ai_lst; ail; ail=ail->next){
|
|
|
- if(new_sock2list(ail->name.s, 0, port, proto, usename, useport,
|
|
|
+ if(new_sock2list(ail->name.s, 0, port, proto, usename, useport, sockname,
|
|
|
ail->flags | flags, list)==0)
|
|
|
return -1;
|
|
|
}
|
|
@@ -1449,7 +1485,7 @@ static int addr_info_to_si_lst(struct addr_info* ai_lst, unsigned short port,
|
|
|
|
|
|
|
|
|
|
|
|
-/* insert new elements to a socket_info list after "el",
|
|
|
+/* insert new elements to a socket_info list after "el",
|
|
|
* each element is created from addr_info_lst + port, * protocol and flags
|
|
|
* return 0 on succes, -1 on error
|
|
|
*/
|
|
@@ -1458,15 +1494,17 @@ static int addr_info_to_si_lst_after(struct addr_info* ai_lst,
|
|
|
char proto,
|
|
|
char *usename,
|
|
|
unsigned short useport,
|
|
|
+ char *sockname,
|
|
|
enum si_flags flags,
|
|
|
struct socket_info* el)
|
|
|
{
|
|
|
struct addr_info* ail;
|
|
|
struct socket_info* new_si;
|
|
|
-
|
|
|
+
|
|
|
for (ail=ai_lst; ail; ail=ail->next){
|
|
|
if((new_si=new_sock2list_after(ail->name.s, 0, port, proto,
|
|
|
- usename, useport, ail->flags | flags, el))==0)
|
|
|
+ usename, useport, sockname,
|
|
|
+ ail->flags | flags, el))==0)
|
|
|
return -1;
|
|
|
el=new_si;
|
|
|
}
|
|
@@ -1475,7 +1513,7 @@ static int addr_info_to_si_lst_after(struct addr_info* ai_lst,
|
|
|
|
|
|
|
|
|
|
|
|
-/* fixes a socket list => resolve addresses,
|
|
|
+/* fixes a socket list => resolve addresses,
|
|
|
* interface names, fills missing members, remove duplicates
|
|
|
* fills type_flags if not null with SOCKET_T_IPV4 and/or SOCKET_T_IPV6*/
|
|
|
static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
@@ -1507,7 +1545,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
if (si->flags & SI_IS_MHOMED){
|
|
|
if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no,
|
|
|
si->proto, si->useinfo.name.s,
|
|
|
- si->useinfo.port_no,
|
|
|
+ si->useinfo.port_no, si->sockname.s,
|
|
|
ai_lst->flags|si->flags, si))==0)
|
|
|
break;
|
|
|
ail=ai_lst;
|
|
@@ -1527,12 +1565,11 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
new_si->addr_info_lst=ail;
|
|
|
si->addr_info_lst=0; /* detached and moved to new_si */
|
|
|
}
|
|
|
-
|
|
|
}else{
|
|
|
/* add all addr. as separate interfaces */
|
|
|
if (addr_info_to_si_lst_after(ai_lst, si->port_no, si->proto,
|
|
|
si->useinfo.name.s, si->useinfo.port_no,
|
|
|
- si->flags, si)!=0)
|
|
|
+ si->sockname.s, si->flags, si)!=0)
|
|
|
goto error;
|
|
|
/* ai_lst not needed anymore */
|
|
|
free_addr_info_lst(&ai_lst);
|
|
@@ -1546,7 +1583,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
new_si=si;
|
|
|
ail=si->addr_info_lst;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (ail){
|
|
|
if (new_si && (new_si->flags & SI_IS_MHOMED)){
|
|
|
ai_lst=0;
|
|
@@ -1592,7 +1629,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
}
|
|
|
strncpy(si->port_no_str.s, tmp, len+1);
|
|
|
si->port_no_str.len=len;
|
|
|
-
|
|
|
+
|
|
|
if (fix_hostname(&si->name, &si->address, &si->address_str,
|
|
|
&si->flags, type_flags, si) !=0 )
|
|
|
goto error;
|
|
@@ -1604,9 +1641,9 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
}
|
|
|
|
|
|
if (fix_sock_str(si) < 0) goto error;
|
|
|
-
|
|
|
+
|
|
|
#ifdef EXTRA_DEBUG
|
|
|
- printf(" %.*s [%s]:%s%s\n", si->name.len,
|
|
|
+ printf(" %.*s [%s]:%s%s\n", si->name.len,
|
|
|
si->name.s, si->address_str.s, si->port_no_str.s,
|
|
|
si->flags & SI_IS_MCAST ? " mcast" : "");
|
|
|
#endif
|
|
@@ -1669,7 +1706,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
/* check for & remove internal duplicates: */
|
|
|
for (ail=si->addr_info_lst; ail;){
|
|
|
ail_next=ail->next;
|
|
|
- /* 1. check if the extra addresses contain a duplicate for the
|
|
|
+ /* 1. check if the extra addresses contain a duplicate for the
|
|
|
* main one */
|
|
|
if ((ail->address.af==si->address.af) &&
|
|
|
(memcmp(ail->address.u.addr, si->address.u.addr,
|
|
@@ -1778,7 +1815,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
){
|
|
|
if (si->flags & SI_IS_MCAST){
|
|
|
LM_WARN("removing entry %s:%s [%s]:%s\n",
|
|
|
- get_valid_proto_name(si->proto), si->name.s,
|
|
|
+ get_valid_proto_name(si->proto), si->name.s,
|
|
|
si->address_str.s, si->port_no_str.s);
|
|
|
l = si;
|
|
|
si=si->next;
|
|
@@ -1790,7 +1827,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
|
|
|
if (ail->flags & SI_IS_MCAST){
|
|
|
LM_WARN("removing mh entry %s:%s"
|
|
|
" [%s]:%s\n",
|
|
|
- get_valid_proto_name(si->proto), ail->name.s,
|
|
|
+ get_valid_proto_name(si->proto), ail->name.s,
|
|
|
ail->address_str.s, si->port_no_str.s);
|
|
|
tmp_ail=ail;
|
|
|
ail=ail->next;
|
|
@@ -1822,9 +1859,9 @@ int fix_all_socket_lists()
|
|
|
struct utsname myname;
|
|
|
int flags;
|
|
|
struct addr_info* ai_lst;
|
|
|
-
|
|
|
+
|
|
|
ai_lst=0;
|
|
|
-
|
|
|
+
|
|
|
if ((udp_listen==0)
|
|
|
#ifdef USE_TCP
|
|
|
&& (tcp_listen==0)
|
|
@@ -1843,7 +1880,7 @@ int fix_all_socket_lists()
|
|
|
#else
|
|
|
&& ( !auto_bind_ipv6 || add_interfaces(0, AF_INET6, 0, PROTO_UDP, &ai_lst) ==0 ) /* add_interface does not work for IPv6 on Linux */
|
|
|
#endif /* __OS_linux */
|
|
|
- ) && (addr_info_to_si_lst(ai_lst, 0, PROTO_UDP, 0, 0, 0, &udp_listen)==0)){
|
|
|
+ ) && (addr_info_to_si_lst(ai_lst, 0, PROTO_UDP, 0, 0, 0, 0, &udp_listen)==0)){
|
|
|
free_addr_info_lst(&ai_lst);
|
|
|
ai_lst=0;
|
|
|
/* if ok, try to add the others too */
|
|
@@ -1855,7 +1892,7 @@ int fix_all_socket_lists()
|
|
|
#else
|
|
|
|| (auto_bind_ipv6 && add_interfaces(0, AF_INET6, 0, PROTO_TCP, &ai_lst) !=0 )
|
|
|
#endif /* __OS_linux */
|
|
|
- ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_TCP, 0, 0, 0,
|
|
|
+ ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_TCP, 0, 0, 0, 0,
|
|
|
&tcp_listen)!=0))
|
|
|
goto error;
|
|
|
free_addr_info_lst(&ai_lst);
|
|
@@ -1869,7 +1906,7 @@ int fix_all_socket_lists()
|
|
|
#else
|
|
|
|| (auto_bind_ipv6 && add_interfaces(0, AF_INET6, 0, PROTO_TLS, &ai_lst)!=0)
|
|
|
#endif /* __OS_linux */
|
|
|
- ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_TLS, 0, 0, 0,
|
|
|
+ ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_TLS, 0, 0, 0, 0,
|
|
|
&tls_listen)!=0))
|
|
|
goto error;
|
|
|
}
|
|
@@ -1886,7 +1923,7 @@ int fix_all_socket_lists()
|
|
|
#else
|
|
|
|| (auto_bind_ipv6 && add_interfaces(0, AF_INET6, 0, PROTO_SCTP, &ai_lst) != 0)
|
|
|
#endif /* __OS_linux */
|
|
|
- ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_SCTP, 0, 0, 0,
|
|
|
+ ) || (addr_info_to_si_lst(ai_lst, 0, PROTO_SCTP, 0, 0, 0, 0,
|
|
|
&sctp_listen)!=0))
|
|
|
goto error;
|
|
|
free_addr_info_lst(&ai_lst);
|
|
@@ -1972,8 +2009,7 @@ void print_all_socket_lists()
|
|
|
struct socket_info** list;
|
|
|
struct addr_info* ai;
|
|
|
unsigned short proto;
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
proto=PROTO_UDP;
|
|
|
do{
|
|
|
list=get_sock_info_list(proto);
|
|
@@ -1982,24 +2018,30 @@ void print_all_socket_lists()
|
|
|
printf(" %s: (%s",
|
|
|
get_valid_proto_name(proto),
|
|
|
si->address_str.s);
|
|
|
- for (ai=si->addr_info_lst; ai; ai=ai->next)
|
|
|
+ for (ai=si->addr_info_lst; ai; ai=ai->next) {
|
|
|
printf(", %s", ai->address_str.s);
|
|
|
+ }
|
|
|
printf("):%s%s%s\n",
|
|
|
- si->port_no_str.s,
|
|
|
+ si->port_no_str.s,
|
|
|
si->flags & SI_IS_MCAST ? " mcast" : "",
|
|
|
si->flags & SI_IS_MHOMED? " mhomed" : "");
|
|
|
}else{
|
|
|
printf(" %s: %s",
|
|
|
get_valid_proto_name(proto),
|
|
|
si->name.s);
|
|
|
- if (!(si->flags & SI_IS_IP))
|
|
|
+ if (!(si->flags & SI_IS_IP)) {
|
|
|
printf(" [%s]", si->address_str.s);
|
|
|
+ }
|
|
|
printf( ":%s%s%s",
|
|
|
- si->port_no_str.s,
|
|
|
+ si->port_no_str.s,
|
|
|
si->flags & SI_IS_MCAST ? " mcast" : "",
|
|
|
si->flags & SI_IS_MHOMED? " mhomed" : "");
|
|
|
- if (si->useinfo.name.s)
|
|
|
+ if (si->sockname.s) {
|
|
|
+ printf(" name %s", si->sockname.s);
|
|
|
+ }
|
|
|
+ if (si->useinfo.name.s) {
|
|
|
printf(" advertise %s:%d", si->useinfo.name.s, si->useinfo.port_no);
|
|
|
+ }
|
|
|
printf("\n");
|
|
|
}
|
|
|
}
|
|
@@ -2011,13 +2053,15 @@ void print_aliases()
|
|
|
{
|
|
|
struct host_alias* a;
|
|
|
|
|
|
- for(a=aliases; a; a=a->next)
|
|
|
- if (a->port)
|
|
|
- printf(" %s: %.*s:%d\n", get_valid_proto_name(a->proto),
|
|
|
+ for(a=aliases; a; a=a->next) {
|
|
|
+ if (a->port) {
|
|
|
+ printf(" %s: %.*s:%d\n", get_valid_proto_name(a->proto),
|
|
|
a->alias.len, a->alias.s, a->port);
|
|
|
- else
|
|
|
- printf(" %s: %.*s:*\n", get_valid_proto_name(a->proto),
|
|
|
+ } else {
|
|
|
+ printf(" %s: %.*s:*\n", get_valid_proto_name(a->proto),
|
|
|
a->alias.len, a->alias.s);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2025,7 +2069,7 @@ void print_aliases()
|
|
|
void init_proto_order()
|
|
|
{
|
|
|
int r;
|
|
|
-
|
|
|
+
|
|
|
/* fix proto list (remove disabled protocols)*/
|
|
|
#ifdef USE_TCP
|
|
|
if (tcp_disable)
|