Bladeren bron

core: option to set advertised address and port per socket

- listen parameter can be like:

listen=proto:ip:port advertise ip1:port1

- ip1 and port1 will be used to build Via and Route headers for messages
  using the socket
Daniel-Constantin Mierla 13 jaren geleden
bovenliggende
commit
574daa6d46
7 gewijzigde bestanden met toevoegingen van 275 en 64 verwijderingen
  1. 2 0
      cfg.lex
  2. 15 0
      cfg.y
  3. 10 0
      ip_addr.h
  4. 18 6
      main.c
  5. 77 24
      msg_translator.c
  6. 148 34
      socket_info.c
  7. 5 0
      socket_info.h

+ 2 - 0
cfg.lex

@@ -344,6 +344,7 @@ LOGSTDERROR	log_stderror
 LOGFACILITY	log_facility
 LOGNAME		log_name
 LISTEN		listen
+ADVERTISE	advertise|ADVERTISE
 ALIAS		alias
 SR_AUTO_ALIASES	auto_aliases
 DNS		 dns
@@ -714,6 +715,7 @@ IMPORTFILE      "import_file"
 <INITIAL>{LOGFACILITY}	{ yylval.strval=yytext; return LOGFACILITY; }
 <INITIAL>{LOGNAME}	{ yylval.strval=yytext; return LOGNAME; }
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
+<INITIAL>{ADVERTISE}	{ count(); yylval.strval=yytext; return ADVERTISE; }
 <INITIAL>{ALIAS}	{ count(); yylval.strval=yytext; return ALIAS; }
 <INITIAL>{SR_AUTO_ALIASES}	{ count(); yylval.strval=yytext;
 									return SR_AUTO_ALIASES; }

+ 15 - 0
cfg.y

@@ -400,6 +400,7 @@ extern char *finame;
 %token LOGFACILITY
 %token LOGNAME
 %token LISTEN
+%token ADVERTISE
 %token ALIAS
 %token SR_AUTO_ALIASES
 %token DNS
@@ -1540,6 +1541,20 @@ assign_stm:
 		}
 		free_socket_id_lst($3);
 	}
+	| LISTEN EQUAL id_lst ADVERTISE listen_id COLON NUMBER {
+		for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next) {
+			if (add_listen_advertise_iface(	lst_tmp->addr_lst->name,
+									lst_tmp->addr_lst->next,
+									lst_tmp->port, lst_tmp->proto,
+									$5, $7,
+									lst_tmp->flags)!=0) {
+				LOG(L_CRIT,  "ERROR: cfg. parser: failed to add listen"
+								" address\n");
+				break;
+			}
+		}
+		free_socket_id_lst($3);
+	}
 	| LISTEN EQUAL  error { yyerror("ip address, interface name or"
 									" hostname expected"); }
 	| ALIAS EQUAL  id_lst {

+ 10 - 0
ip_addr.h

@@ -102,6 +102,15 @@ struct addr_info{
 	struct addr_info* prev;
 };
 
+struct advertise_info {
+	str name; /* name - eg.: foo.bar or 10.0.0.1 */
+	unsigned short port_no;  /* port number */
+	str port_no_str; /* port number converted to string -- optimization*/
+	str address_str;        /*ip address converted to string -- optimization*/
+	struct ip_addr address; /* ip address */
+	str sock_str; /* Socket proto, ip, and port as string */
+};
+
 struct socket_info{
 	int socket;
 	str name; /* name - eg.: foo.bar or 10.0.0.1 */
@@ -118,6 +127,7 @@ struct socket_info{
 	struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
 	int workers; /* number of worker processes for this socket */
 	int workers_tcpidx; /* index of workers in tcp children array */
+	struct advertise_info useinfo; /* details to be used in SIP msg */
 };
 
 

+ 18 - 6
main.c

@@ -1596,13 +1596,25 @@ int main_loop()
 			nrprocs = (si->workers>0)?si->workers:children_no;
 			for(i=0;i<nrprocs;i++){
 				if(si->address.af==AF_INET6) {
-					snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
-						"sock=[%s]:%s",
-						i, si->name.s, si->port_no_str.s);
+					if(si->useinfo.name.s)
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
+							"sock=[%s]:%s (%s:%s)",
+							i, si->name.s, si->port_no_str.s,
+							si->useinfo.name.s, si->useinfo.port_no_str.s);
+					else
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
+							"sock=[%s]:%s",
+							i, si->name.s, si->port_no_str.s);
 				} else {
-					snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
-						"sock=%s:%s",
-						i, si->name.s, si->port_no_str.s);
+					if(si->useinfo.name.s)
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
+							"sock=%s:%s (%s:%s)",
+							i, si->name.s, si->port_no_str.s,
+							si->useinfo.name.s, si->useinfo.port_no_str.s);
+					else
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
+							"sock=%s:%s",
+							i, si->name.s, si->port_no_str.s);
 				}
 				child_rank++;
 				pid = fork_process(child_rank, si_desc, 1);

+ 77 - 24
msg_translator.c

@@ -579,6 +579,9 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
 	struct lump* r;
 	str* send_address_str;
 	str* send_port_str;
+	str* recv_address_str;
+	str* recv_port_str;
+	int  recv_port_no;
 	struct socket_info* send_sock;
 	
 
@@ -623,7 +626,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
 		switch((subst_l)->u.subst){ \
 			case SUBST_RCV_IP: \
 				if (msg->rcv.bind_address){ \
-					new_len+=msg->rcv.bind_address->address_str.len; \
+					new_len+=recv_address_str->len; \
 					if (msg->rcv.bind_address->address.af!=AF_INET) \
 						new_len+=2; \
 				}else{ \
@@ -633,7 +636,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
 				break; \
 			case SUBST_RCV_PORT: \
 				if (msg->rcv.bind_address){ \
-					new_len+=msg->rcv.bind_address->port_no_str.len; \
+					new_len+=recv_port_str->len; \
 				}else{ \
 					/* FIXME */ \
 					LOG(L_CRIT, "FIXME: null bind_address\n"); \
@@ -662,12 +665,12 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
 				break; \
 			case SUBST_RCV_ALL: \
 				if (msg->rcv.bind_address){ \
-					new_len+=msg->rcv.bind_address->address_str.len; \
+					new_len+=recv_address_str->len; \
 					if (msg->rcv.bind_address->address.af!=AF_INET) \
 						new_len+=2; \
-					if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
+					if (recv_port_no!=SIP_PORT){ \
 						/* add :port_no */ \
-						new_len+=1+msg->rcv.bind_address->port_no_str.len; \
+						new_len+=1+recv_port_str->len; \
 					}\
 						/*add;transport=xxx*/ \
 					switch(msg->rcv.bind_address->proto){ \
@@ -780,15 +783,32 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
 	s_offset=0;
 	new_len=0;
 	/* init send_address_str & send_port_str */
-	if (msg->set_global_address.len)
+	if(send_sock && send_sock->useinfo.name.len>0)
+		send_address_str=&(send_sock->useinfo.name);
+	else if (msg->set_global_address.len)
 		send_address_str=&(msg->set_global_address);
 	else
 		send_address_str=&(send_sock->address_str);
-	if (msg->set_global_port.len)
+	if(send_sock && send_sock->useinfo.port_no>0)
+		send_port_str=&(send_sock->useinfo.port_no_str);
+	else if (msg->set_global_port.len)
 		send_port_str=&(msg->set_global_port);
 	else
 		send_port_str=&(send_sock->port_no_str);
-
+	/* init recv_address_str, recv_port_str & recv_port_no */
+	if(msg->rcv.bind_address) {
+		if(msg->rcv.bind_address->useinfo.name.len>0)
+			recv_address_str=&(msg->rcv.bind_address->useinfo.name);
+		else
+			recv_address_str=&(msg->rcv.bind_address->address_str);
+		if(msg->rcv.bind_address->useinfo.port_no>0) {
+			recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
+			recv_port_no = msg->rcv.bind_address->useinfo.port_no;
+		} else {
+			recv_port_str=&(msg->rcv.bind_address->port_no_str);
+			recv_port_no = msg->rcv.bind_address->port_no;
+		}
+	}
 
 	for(t=lumps;t;t=t->next){
 		/* skip if this is an OPT lump and the condition is not satisfied */
@@ -898,6 +918,9 @@ static inline void process_lumps(	struct sip_msg* msg,
 	int s_offset;
 	str* send_address_str;
 	str* send_port_str;
+	str* recv_address_str;
+	str* recv_port_str;
+	int  recv_port_no;
 	struct socket_info* send_sock;
 
 #ifdef USE_COMP
@@ -958,9 +981,9 @@ static inline void process_lumps(	struct sip_msg* msg,
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
 					new_buf[offset]='['; offset++; \
 				}\
-				memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
-						msg->rcv.bind_address->address_str.len); \
-				offset+=msg->rcv.bind_address->address_str.len; \
+				memcpy(new_buf+offset, recv_address_str->s, \
+						recv_address_str->len); \
+				offset+=recv_address_str->len; \
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
 					new_buf[offset]=']'; offset++; \
 				}\
@@ -971,9 +994,9 @@ static inline void process_lumps(	struct sip_msg* msg,
 			break; \
 		case SUBST_RCV_PORT: \
 			if (msg->rcv.bind_address){  \
-				memcpy(new_buf+offset, msg->rcv.bind_address->port_no_str.s, \
-						msg->rcv.bind_address->port_no_str.len); \
-				offset+=msg->rcv.bind_address->port_no_str.len; \
+				memcpy(new_buf+offset, recv_port_str->s, \
+						recv_port_str->len); \
+				offset+=recv_port_str->len; \
 			}else{  \
 				/*FIXME*/ \
 				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
@@ -985,19 +1008,19 @@ static inline void process_lumps(	struct sip_msg* msg,
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
 					new_buf[offset]='['; offset++; \
 				}\
-				memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
-						msg->rcv.bind_address->address_str.len); \
-				offset+=msg->rcv.bind_address->address_str.len; \
+				memcpy(new_buf+offset, recv_address_str->s, \
+						recv_address_str->len); \
+				offset+=recv_address_str->len; \
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
 					new_buf[offset]=']'; offset++; \
 				}\
 				/* :port */ \
-				if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
+				if (recv_port_no!=SIP_PORT){ \
 					new_buf[offset]=':'; offset++; \
 					memcpy(new_buf+offset, \
-							msg->rcv.bind_address->port_no_str.s, \
-							msg->rcv.bind_address->port_no_str.len); \
-					offset+=msg->rcv.bind_address->port_no_str.len; \
+							recv_port_str->s, \
+							recv_port_str->len); \
+					offset+=recv_port_str->len; \
 				}\
 				switch(msg->rcv.bind_address->proto){ \
 					case PROTO_NONE: \
@@ -1200,7 +1223,33 @@ static inline void process_lumps(	struct sip_msg* msg,
 		send_port_str=&(msg->set_global_port);
 	else
 		send_port_str=&(send_sock->port_no_str);
-
+	/* init send_address_str & send_port_str */
+	if(send_sock && send_sock->useinfo.name.len>0)
+		send_address_str=&(send_sock->useinfo.name);
+	else if (msg->set_global_address.len)
+		send_address_str=&(msg->set_global_address);
+	else
+		send_address_str=&(send_sock->address_str);
+	if(send_sock && send_sock->useinfo.port_no>0)
+		send_port_str=&(send_sock->useinfo.port_no_str);
+	else if (msg->set_global_port.len)
+		send_port_str=&(msg->set_global_port);
+	else
+		send_port_str=&(send_sock->port_no_str);
+	/* init recv_address_str, recv_port_str & recv_port_no */
+	if(msg->rcv.bind_address) {
+		if(msg->rcv.bind_address->useinfo.name.len>0)
+			recv_address_str=&(msg->rcv.bind_address->useinfo.name);
+		else
+			recv_address_str=&(msg->rcv.bind_address->address_str);
+		if(msg->rcv.bind_address->useinfo.port_no>0) {
+			recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
+			recv_port_no = msg->rcv.bind_address->useinfo.port_no;
+		} else {
+			recv_port_str=&(msg->rcv.bind_address->port_no_str);
+			recv_port_no = msg->rcv.bind_address->port_no;
+		}
+	}
 
 	orig=msg->buf;
 	offset=*new_buf_offs;
@@ -2276,13 +2325,17 @@ char* via_builder( unsigned int *len,
 #endif /* USE_COMP */
 
 	send_sock=send_info->send_sock;
-	/* use pre-set address in via or the outbound socket one */
-	if ( hp && hp->host->len)
+	/* use pre-set address in via, the outbound socket alias or address one */
+	if (hp && hp->host->len)
 		address_str=hp->host;
+	else if(send_sock->useinfo.name.len>0)
+		address_str=&(send_sock->useinfo.name);
 	else
 		address_str=&(send_sock->address_str);
 	if (hp && hp->port->len)
 		port_str=hp->port;
+	else if(send_sock->useinfo.port_no>0)
+		port_str=&(send_sock->useinfo.port_no_str);
 	else
 		port_str=&(send_sock->port_no_str);
 	

+ 148 - 34
socket_info.c

@@ -235,10 +235,13 @@ error:
 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)
 {
 	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;
@@ -259,10 +262,51 @@ static inline struct socket_info* new_sock_info(	char* name,
 			goto error;
 		}
 	}
+	if(usename!=NULL)
+	{
+		si->useinfo.name.len=strlen(usename);
+		si->useinfo.name.s=(char*)pkg_malloc(si->useinfo.name.len+1);
+		if (si->useinfo.name.s==0)
+			goto error;
+		strcpy(si->useinfo.name.s, usename);
+		if(usename[0]=='[' && usename[si->useinfo.name.len-1]==']')
+		{
+			si->useinfo.address_str.len = si->useinfo.name.len - 2;
+			p = si->useinfo.name.s + 1;
+		} else {
+			si->useinfo.address_str.len = si->useinfo.name.len;
+			p = si->useinfo.name.s;
+		}
+		si->useinfo.address_str.s=(char*)pkg_malloc(si->useinfo.address_str.len+1);
+		if(si->useinfo.address_str.s==NULL)
+			goto error;
+		strncpy(si->useinfo.address_str.s, p, si->useinfo.address_str.len);
+		si->useinfo.address_str.s[si->useinfo.address_str.len] = '\0';
+
+		p = int2str(useport, &si->useinfo.port_no_str.len);
+		if(p==NULL)
+			goto error;
+		si->useinfo.port_no_str.s=(char*)pkg_malloc(si->useinfo.port_no_str.len+1);
+		if(si->useinfo.port_no_str.s==NULL)
+			goto error;
+		strcpy(si->useinfo.port_no_str.s, p);
+		si->useinfo.port_no = useport;
+
+		he=resolvehost(si->useinfo.name.s);
+		if (he==0){
+			LM_ERR(" unable to resolve advertised name %s\n", si->useinfo.name.s);
+			goto error;
+		}
+		hostent2ip_addr(&si->useinfo.address, he, 0);
+	}
 	return si;
 error:
 	LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n");
-	if (si) pkg_free(si);
+	if (si) {
+		if(si->name.s)
+			pkg_free(si->name.s);
+		pkg_free(si);
+	}
 	return 0;
 }
 
@@ -275,8 +319,11 @@ static void free_sock_info(struct socket_info* si)
 		if(si->name.s) pkg_free(si->name.s);
 		if(si->address_str.s) pkg_free(si->address_str.s);
 		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->addr_info_lst) free_addr_info_lst(&si->addr_info_lst);
 		if(si->sock_str.s) pkg_free(si->sock_str.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);
 	}
 }
 
@@ -321,6 +368,11 @@ static char* get_valid_proto_name(unsigned short proto)
  * @return -1 on error and 0 on success
  */
 int socket2str(char* s, int* len, struct socket_info* si)
+{
+	return socketinfo2str(s, len, si, 0);
+}
+
+int socketinfo2str(char* s, int* len, struct socket_info* si, int mode)
 {
 	str proto;
 	int l;
@@ -328,13 +380,16 @@ int socket2str(char* s, int* len, struct socket_info* si)
 	proto.s = get_valid_proto_name(si->proto);
 	proto.len = strlen(proto.s);
 	
-	l = proto.len + si->address_str.len + si->port_no_str.len + 2;
+	if(mode==1)
+		l = proto.len + si->useinfo.name.len + si->useinfo.port_no_str.len + 2;
+	else
+		l = proto.len + si->address_str.len + si->port_no_str.len + 2;
 
 	if(si->address.af==AF_INET6)
 		l += 2;
 	
 	if (*len < l) {
-		ERR("socket2str: Destionation buffer too short\n");
+		LM_ERR("Destionation buffer too short\n");
 		*len = l;
 		return -1;
 	}
@@ -342,17 +397,25 @@ int socket2str(char* s, int* len, struct socket_info* si)
 	memcpy(s, proto.s, proto.len);
 	s += proto.len;
 	*s = ':'; s++;
-	if(si->address.af==AF_INET6) {
-		*s = '['; s++;
-	}
-	memcpy(s, si->address_str.s, si->address_str.len);
-	s += si->address_str.len;
-	if(si->address.af==AF_INET6) {
-		*s = ']'; s++;
+	if(mode==1){
+		memcpy(s, si->useinfo.name.s, si->useinfo.name.len);
+		s += si->useinfo.name.len;
+		*s = ':'; s++;
+		memcpy(s, si->useinfo.port_no_str.s, si->useinfo.port_no_str.len);
+		s += si->useinfo.port_no_str.len;
+	} else {
+		if(si->address.af==AF_INET6) {
+			*s = '['; s++;
+		}
+		memcpy(s, si->address_str.s, si->address_str.len);
+		s += si->address_str.len;
+		if(si->address.af==AF_INET6) {
+			*s = ']'; s++;
+		}
+		*s = ':'; s++;
+		memcpy(s, si->port_no_str.s, si->port_no_str.len);
+		s += si->port_no_str.len;
 	}
-	*s = ':'; s++;
-	memcpy(s, si->port_no_str.s, si->port_no_str.len);
-	s += si->port_no_str.len;
 
 	*len = l;
 	return 0;
@@ -375,12 +438,30 @@ static int fix_sock_str(struct socket_info* si)
 		ERR("fix_sock_str: No memory left\n");
 		return -1;
 	}
-	if (socket2str(si->sock_str.s, &len, si) < 0) {
-		BUG("fix_sock_str: Error in socket2str\n");
+	if (socketinfo2str(si->sock_str.s, &len, si, 0) < 0) {
+		BUG("fix_sock_str: Error in socket to str\n");
 		return -1;
 	}
 	si->sock_str.s[len] = '\0';
 	si->sock_str.len = len;
+	if(si->useinfo.name.s!=NULL)
+	{
+		len = MAX_SOCKET_STR;
+
+		if (si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
+
+		si->useinfo.sock_str.s = pkg_malloc(len + 1);
+		if (si->useinfo.sock_str.s == NULL) {
+			ERR("fix_sock_str: No memory left\n");
+			return -1;
+		}
+		if (socketinfo2str(si->useinfo.sock_str.s, &len, si, 1) < 0) {
+			BUG("fix_sock_str: Error in socket to str\n");
+			return -1;
+		}
+		si->useinfo.sock_str.s[len] = '\0';
+		si->useinfo.sock_str.len = len;
+	}
 	return 0;
 }
 
@@ -493,23 +574,38 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
 		if (list==0) /* disabled or unknown protocol */
 			continue;
 		for (si=*list; si; si=si->next){
-			DBG("grep_sock_info - checking if host==us: %d==%d && "
-					" [%.*s] == [%.*s]\n", 
+			DBG("grep_sock_info - checking if host==us: %d==%d &&"
+					" [%.*s] == [%.*s]\n",
 						hname.len,
 						si->name.len,
 						hname.len, hname.s,
 						si->name.len, si->name.s
 				);
 			if (port) {
-				DBG("grep_sock_info - checking if port %d matches port %d\n", 
-						si->port_no, port);
-				if (si->port_no!=port) {
+				DBG("grep_sock_info - checking if port %d (advertise %d)"
+						" matches port %d\n",
+						si->port_no, si->useinfo.port_no, port);
+				if (si->port_no!=port && si->useinfo.port_no!=port) {
 					continue;
 				}
 			}
 			if (si_hname_cmp(&hname, &si->name, &si->address_str, 
 								&si->address, si->flags)==0)
 				goto found;
+			if(si->useinfo.name.s!=NULL)
+			{
+				DBG("grep_sock_info - checking advertise if host==us:"
+						" %d==%d && [%.*s] == [%.*s]\n",
+						hname.len,
+						si->useinfo.name.len,
+						hname.len, hname.s,
+						si->useinfo.name.len, si->useinfo.name.s
+				);
+				if (si_hname_cmp(&hname, &si->useinfo.name,
+							&si->useinfo.address_str, &si->useinfo.address,
+							si->flags)==0)
+					goto found;
+			}
 			/* try among the extra addresses */
 			for (ai=si->addr_info_lst; ai; ai=ai->next)
 				if (si_hname_cmp(&hname, &ai->name, &ai->address_str, 
@@ -593,7 +689,8 @@ struct socket_info* find_si(struct ip_addr* ip, unsigned short port,
 					continue;
 				}
 			}
-			if (ip_addr_cmp(ip, &si->address))
+			if (ip_addr_cmp(ip, &si->address)
+					|| ip_addr_cmp(ip, &si->useinfo.address))
 				goto found;
 			for (ai=si->addr_info_lst; ai; ai=ai->next)
 				if (ip_addr_cmp(ip, &ai->address))
@@ -612,12 +709,14 @@ found:
  * return  new sock info on success, 0 on error */
 static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
 									unsigned short port,
-									unsigned short proto, enum si_flags flags,
+									unsigned short proto,
+									char *usename, unsigned short useport,
+									enum si_flags flags,
 									struct socket_info** list)
 {
 	struct socket_info* si;
 	
-	si=new_sock_info(name, addr_l, port, proto, flags);
+	si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
 	if (si==0){
 		LOG(L_ERR, "ERROR: new_sock2list: new_sock_info failed\n");
 		goto error;
@@ -639,12 +738,15 @@ error:
 static struct socket_info* new_sock2list_after(char* name,
 									struct name_lst* addr_l,
 									unsigned short port,
-									unsigned short proto, enum si_flags flags,
+									unsigned short proto,
+									char *usename,
+									unsigned short useport,
+									enum si_flags flags,
 									struct socket_info* after)
 {
 	struct socket_info* si;
 	
-	si=new_sock_info(name, addr_l, port, proto, flags);
+	si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
 	if (si==0){
 		LOG(L_ERR, "ERROR: new_sock2list_after: new_sock_info failed\n");
 		goto error;
@@ -659,8 +761,9 @@ error:
 
 /* 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,
+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)
 {
 	struct socket_info** list;
@@ -691,7 +794,7 @@ int add_listen_iface(char* name, struct name_lst* addr_l,
 			c_port=port;
 		}
 		if (c_proto!=PROTO_SCTP){
-			if (new_sock2list(name, 0, c_port, c_proto,
+			if (new_sock2list(name, 0, c_port, c_proto, usename, useport,
 								flags & ~SI_IS_MHOMED, list)==0){
 				LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
 				goto error;
@@ -700,14 +803,16 @@ int add_listen_iface(char* name, struct name_lst* addr_l,
 			 * 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, flags & ~SI_IS_MHOMED, list)==0){
+									c_proto, usename, useport,
+									flags & ~SI_IS_MHOMED, list)==0){
 					LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list"
 								" failed\n");
 					goto error;
 				}
 			}
 		}else{
-			if (new_sock2list(name, addr_l, c_port, c_proto, flags, list)==0){
+			if (new_sock2list(name, addr_l, c_port, c_proto, usename, useport,
+						flags, list)==0){
 				LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
 				goto error;
 			}
@@ -718,6 +823,14 @@ error:
 	return -1;
 }
 
+/* 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);
+}
 #ifdef __OS_linux
 
 #include "linux/netlink.h"
@@ -1323,8 +1436,8 @@ static int addr_info_to_si_lst(struct addr_info* ai_lst, unsigned short port,
 	struct addr_info* ail;
 	
 	for (ail=ai_lst; ail; ail=ail->next){
-		if(new_sock2list(ail->name.s, 0, port, proto, ail->flags | flags,
-							list)==0)
+		if(new_sock2list(ail->name.s, 0, port, proto, 0, 0,
+					ail->flags | flags, list)==0)
 			return -1;
 	}
 	return 0;
@@ -1346,7 +1459,7 @@ static int addr_info_to_si_lst_after(struct addr_info* ai_lst,
 	
 	for (ail=ai_lst; ail; ail=ail->next){
 		if((new_si=new_sock2list_after(ail->name.s, 0, port, proto,
-								ail->flags | flags, el))==0)
+								0, 0, ail->flags | flags, el))==0)
 			return -1;
 		el=new_si;
 	}
@@ -1386,7 +1499,8 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
 							si->proto, &ai_lst)!=-1){
 			if (si->flags & SI_IS_MHOMED){
 				if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no,
-											si->proto,
+											si->proto, si->useinfo.name.s,
+											si->useinfo.port_no,
 											ai_lst->flags|si->flags, si))==0)
 					break;
 				ail=ai_lst;

+ 5 - 0
socket_info.h

@@ -50,6 +50,7 @@
 	INT2STR_MAX_LEN + 2 + 2)
 
 int socket2str(char* s, int* len, struct socket_info* si);
+int socketinfo2str(char* s, int* len, struct socket_info* si, int mode);
 
 
 /* struct socket_info is defined in ip_addr.h */
@@ -84,6 +85,10 @@ void init_proto_order();
 int add_listen_iface(char* name, struct name_lst* nlst,
 						unsigned short port, unsigned short proto,
 						enum si_flags flags);
+int add_listen_advertise_iface(char* name, struct name_lst* nlst,
+						unsigned short port, unsigned short proto,
+						char *useaddr, unsigned short useport,
+						enum si_flags flags);
 int fix_all_socket_lists();
 void print_all_socket_lists();
 void print_aliases();