Browse code

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 authored on 29/03/2012 10:27:19
Showing 7 changed files
... ...
@@ -344,6 +344,7 @@ LOGSTDERROR	log_stderror
344 344
 LOGFACILITY	log_facility
345 345
 LOGNAME		log_name
346 346
 LISTEN		listen
347
+ADVERTISE	advertise|ADVERTISE
347 348
 ALIAS		alias
348 349
 SR_AUTO_ALIASES	auto_aliases
349 350
 DNS		 dns
... ...
@@ -714,6 +715,7 @@ IMPORTFILE      "import_file"
714 714
 <INITIAL>{LOGFACILITY}	{ yylval.strval=yytext; return LOGFACILITY; }
715 715
 <INITIAL>{LOGNAME}	{ yylval.strval=yytext; return LOGNAME; }
716 716
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
717
+<INITIAL>{ADVERTISE}	{ count(); yylval.strval=yytext; return ADVERTISE; }
717 718
 <INITIAL>{ALIAS}	{ count(); yylval.strval=yytext; return ALIAS; }
718 719
 <INITIAL>{SR_AUTO_ALIASES}	{ count(); yylval.strval=yytext;
719 720
 									return SR_AUTO_ALIASES; }
... ...
@@ -400,6 +400,7 @@ extern char *finame;
400 400
 %token LOGFACILITY
401 401
 %token LOGNAME
402 402
 %token LISTEN
403
+%token ADVERTISE
403 404
 %token ALIAS
404 405
 %token SR_AUTO_ALIASES
405 406
 %token DNS
... ...
@@ -1540,6 +1541,20 @@ assign_stm:
1540 1540
 		}
1541 1541
 		free_socket_id_lst($3);
1542 1542
 	}
1543
+	| LISTEN EQUAL id_lst ADVERTISE listen_id COLON NUMBER {
1544
+		for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next) {
1545
+			if (add_listen_advertise_iface(	lst_tmp->addr_lst->name,
1546
+									lst_tmp->addr_lst->next,
1547
+									lst_tmp->port, lst_tmp->proto,
1548
+									$5, $7,
1549
+									lst_tmp->flags)!=0) {
1550
+				LOG(L_CRIT,  "ERROR: cfg. parser: failed to add listen"
1551
+								" address\n");
1552
+				break;
1553
+			}
1554
+		}
1555
+		free_socket_id_lst($3);
1556
+	}
1543 1557
 	| LISTEN EQUAL  error { yyerror("ip address, interface name or"
1544 1558
 									" hostname expected"); }
1545 1559
 	| ALIAS EQUAL  id_lst {
... ...
@@ -102,6 +102,15 @@ struct addr_info{
102 102
 	struct addr_info* prev;
103 103
 };
104 104
 
105
+struct advertise_info {
106
+	str name; /* name - eg.: foo.bar or 10.0.0.1 */
107
+	unsigned short port_no;  /* port number */
108
+	str port_no_str; /* port number converted to string -- optimization*/
109
+	str address_str;        /*ip address converted to string -- optimization*/
110
+	struct ip_addr address; /* ip address */
111
+	str sock_str; /* Socket proto, ip, and port as string */
112
+};
113
+
105 114
 struct socket_info{
106 115
 	int socket;
107 116
 	str name; /* name - eg.: foo.bar or 10.0.0.1 */
... ...
@@ -118,6 +127,7 @@ struct socket_info{
118 118
 	struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
119 119
 	int workers; /* number of worker processes for this socket */
120 120
 	int workers_tcpidx; /* index of workers in tcp children array */
121
+	struct advertise_info useinfo; /* details to be used in SIP msg */
121 122
 };
122 123
 
123 124
 
... ...
@@ -1596,13 +1596,25 @@ int main_loop()
1596 1596
 			nrprocs = (si->workers>0)?si->workers:children_no;
1597 1597
 			for(i=0;i<nrprocs;i++){
1598 1598
 				if(si->address.af==AF_INET6) {
1599
-					snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
1600
-						"sock=[%s]:%s",
1601
-						i, si->name.s, si->port_no_str.s);
1599
+					if(si->useinfo.name.s)
1600
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
1601
+							"sock=[%s]:%s (%s:%s)",
1602
+							i, si->name.s, si->port_no_str.s,
1603
+							si->useinfo.name.s, si->useinfo.port_no_str.s);
1604
+					else
1605
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
1606
+							"sock=[%s]:%s",
1607
+							i, si->name.s, si->port_no_str.s);
1602 1608
 				} else {
1603
-					snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
1604
-						"sock=%s:%s",
1605
-						i, si->name.s, si->port_no_str.s);
1609
+					if(si->useinfo.name.s)
1610
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
1611
+							"sock=%s:%s (%s:%s)",
1612
+							i, si->name.s, si->port_no_str.s,
1613
+							si->useinfo.name.s, si->useinfo.port_no_str.s);
1614
+					else
1615
+						snprintf(si_desc, MAX_PT_DESC, "udp receiver child=%d "
1616
+							"sock=%s:%s",
1617
+							i, si->name.s, si->port_no_str.s);
1606 1618
 				}
1607 1619
 				child_rank++;
1608 1620
 				pid = fork_process(child_rank, si_desc, 1);
... ...
@@ -579,6 +579,9 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
579 579
 	struct lump* r;
580 580
 	str* send_address_str;
581 581
 	str* send_port_str;
582
+	str* recv_address_str;
583
+	str* recv_port_str;
584
+	int  recv_port_no;
582 585
 	struct socket_info* send_sock;
583 586
 	
584 587
 
... ...
@@ -623,7 +626,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
623 623
 		switch((subst_l)->u.subst){ \
624 624
 			case SUBST_RCV_IP: \
625 625
 				if (msg->rcv.bind_address){ \
626
-					new_len+=msg->rcv.bind_address->address_str.len; \
626
+					new_len+=recv_address_str->len; \
627 627
 					if (msg->rcv.bind_address->address.af!=AF_INET) \
628 628
 						new_len+=2; \
629 629
 				}else{ \
... ...
@@ -633,7 +636,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
633 633
 				break; \
634 634
 			case SUBST_RCV_PORT: \
635 635
 				if (msg->rcv.bind_address){ \
636
-					new_len+=msg->rcv.bind_address->port_no_str.len; \
636
+					new_len+=recv_port_str->len; \
637 637
 				}else{ \
638 638
 					/* FIXME */ \
639 639
 					LOG(L_CRIT, "FIXME: null bind_address\n"); \
... ...
@@ -662,12 +665,12 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
662 662
 				break; \
663 663
 			case SUBST_RCV_ALL: \
664 664
 				if (msg->rcv.bind_address){ \
665
-					new_len+=msg->rcv.bind_address->address_str.len; \
665
+					new_len+=recv_address_str->len; \
666 666
 					if (msg->rcv.bind_address->address.af!=AF_INET) \
667 667
 						new_len+=2; \
668
-					if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
668
+					if (recv_port_no!=SIP_PORT){ \
669 669
 						/* add :port_no */ \
670
-						new_len+=1+msg->rcv.bind_address->port_no_str.len; \
670
+						new_len+=1+recv_port_str->len; \
671 671
 					}\
672 672
 						/*add;transport=xxx*/ \
673 673
 					switch(msg->rcv.bind_address->proto){ \
... ...
@@ -780,15 +783,32 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
780 780
 	s_offset=0;
781 781
 	new_len=0;
782 782
 	/* init send_address_str & send_port_str */
783
-	if (msg->set_global_address.len)
783
+	if(send_sock && send_sock->useinfo.name.len>0)
784
+		send_address_str=&(send_sock->useinfo.name);
785
+	else if (msg->set_global_address.len)
784 786
 		send_address_str=&(msg->set_global_address);
785 787
 	else
786 788
 		send_address_str=&(send_sock->address_str);
787
-	if (msg->set_global_port.len)
789
+	if(send_sock && send_sock->useinfo.port_no>0)
790
+		send_port_str=&(send_sock->useinfo.port_no_str);
791
+	else if (msg->set_global_port.len)
788 792
 		send_port_str=&(msg->set_global_port);
789 793
 	else
790 794
 		send_port_str=&(send_sock->port_no_str);
791
-
795
+	/* init recv_address_str, recv_port_str & recv_port_no */
796
+	if(msg->rcv.bind_address) {
797
+		if(msg->rcv.bind_address->useinfo.name.len>0)
798
+			recv_address_str=&(msg->rcv.bind_address->useinfo.name);
799
+		else
800
+			recv_address_str=&(msg->rcv.bind_address->address_str);
801
+		if(msg->rcv.bind_address->useinfo.port_no>0) {
802
+			recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
803
+			recv_port_no = msg->rcv.bind_address->useinfo.port_no;
804
+		} else {
805
+			recv_port_str=&(msg->rcv.bind_address->port_no_str);
806
+			recv_port_no = msg->rcv.bind_address->port_no;
807
+		}
808
+	}
792 809
 
793 810
 	for(t=lumps;t;t=t->next){
794 811
 		/* 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,
898 898
 	int s_offset;
899 899
 	str* send_address_str;
900 900
 	str* send_port_str;
901
+	str* recv_address_str;
902
+	str* recv_port_str;
903
+	int  recv_port_no;
901 904
 	struct socket_info* send_sock;
902 905
 
903 906
 #ifdef USE_COMP
... ...
@@ -958,9 +981,9 @@ static inline void process_lumps(	struct sip_msg* msg,
958 958
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
959 959
 					new_buf[offset]='['; offset++; \
960 960
 				}\
961
-				memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
962
-						msg->rcv.bind_address->address_str.len); \
963
-				offset+=msg->rcv.bind_address->address_str.len; \
961
+				memcpy(new_buf+offset, recv_address_str->s, \
962
+						recv_address_str->len); \
963
+				offset+=recv_address_str->len; \
964 964
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
965 965
 					new_buf[offset]=']'; offset++; \
966 966
 				}\
... ...
@@ -971,9 +994,9 @@ static inline void process_lumps(	struct sip_msg* msg,
971 971
 			break; \
972 972
 		case SUBST_RCV_PORT: \
973 973
 			if (msg->rcv.bind_address){  \
974
-				memcpy(new_buf+offset, msg->rcv.bind_address->port_no_str.s, \
975
-						msg->rcv.bind_address->port_no_str.len); \
976
-				offset+=msg->rcv.bind_address->port_no_str.len; \
974
+				memcpy(new_buf+offset, recv_port_str->s, \
975
+						recv_port_str->len); \
976
+				offset+=recv_port_str->len; \
977 977
 			}else{  \
978 978
 				/*FIXME*/ \
979 979
 				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
... ...
@@ -985,19 +1008,19 @@ static inline void process_lumps(	struct sip_msg* msg,
985 985
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
986 986
 					new_buf[offset]='['; offset++; \
987 987
 				}\
988
-				memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
989
-						msg->rcv.bind_address->address_str.len); \
990
-				offset+=msg->rcv.bind_address->address_str.len; \
988
+				memcpy(new_buf+offset, recv_address_str->s, \
989
+						recv_address_str->len); \
990
+				offset+=recv_address_str->len; \
991 991
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
992 992
 					new_buf[offset]=']'; offset++; \
993 993
 				}\
994 994
 				/* :port */ \
995
-				if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
995
+				if (recv_port_no!=SIP_PORT){ \
996 996
 					new_buf[offset]=':'; offset++; \
997 997
 					memcpy(new_buf+offset, \
998
-							msg->rcv.bind_address->port_no_str.s, \
999
-							msg->rcv.bind_address->port_no_str.len); \
1000
-					offset+=msg->rcv.bind_address->port_no_str.len; \
998
+							recv_port_str->s, \
999
+							recv_port_str->len); \
1000
+					offset+=recv_port_str->len; \
1001 1001
 				}\
1002 1002
 				switch(msg->rcv.bind_address->proto){ \
1003 1003
 					case PROTO_NONE: \
... ...
@@ -1200,7 +1223,33 @@ static inline void process_lumps(	struct sip_msg* msg,
1200 1200
 		send_port_str=&(msg->set_global_port);
1201 1201
 	else
1202 1202
 		send_port_str=&(send_sock->port_no_str);
1203
-
1203
+	/* init send_address_str & send_port_str */
1204
+	if(send_sock && send_sock->useinfo.name.len>0)
1205
+		send_address_str=&(send_sock->useinfo.name);
1206
+	else if (msg->set_global_address.len)
1207
+		send_address_str=&(msg->set_global_address);
1208
+	else
1209
+		send_address_str=&(send_sock->address_str);
1210
+	if(send_sock && send_sock->useinfo.port_no>0)
1211
+		send_port_str=&(send_sock->useinfo.port_no_str);
1212
+	else if (msg->set_global_port.len)
1213
+		send_port_str=&(msg->set_global_port);
1214
+	else
1215
+		send_port_str=&(send_sock->port_no_str);
1216
+	/* init recv_address_str, recv_port_str & recv_port_no */
1217
+	if(msg->rcv.bind_address) {
1218
+		if(msg->rcv.bind_address->useinfo.name.len>0)
1219
+			recv_address_str=&(msg->rcv.bind_address->useinfo.name);
1220
+		else
1221
+			recv_address_str=&(msg->rcv.bind_address->address_str);
1222
+		if(msg->rcv.bind_address->useinfo.port_no>0) {
1223
+			recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
1224
+			recv_port_no = msg->rcv.bind_address->useinfo.port_no;
1225
+		} else {
1226
+			recv_port_str=&(msg->rcv.bind_address->port_no_str);
1227
+			recv_port_no = msg->rcv.bind_address->port_no;
1228
+		}
1229
+	}
1204 1230
 
1205 1231
 	orig=msg->buf;
1206 1232
 	offset=*new_buf_offs;
... ...
@@ -2276,13 +2325,17 @@ char* via_builder( unsigned int *len,
2276 2276
 #endif /* USE_COMP */
2277 2277
 
2278 2278
 	send_sock=send_info->send_sock;
2279
-	/* use pre-set address in via or the outbound socket one */
2280
-	if ( hp && hp->host->len)
2279
+	/* use pre-set address in via, the outbound socket alias or address one */
2280
+	if (hp && hp->host->len)
2281 2281
 		address_str=hp->host;
2282
+	else if(send_sock->useinfo.name.len>0)
2283
+		address_str=&(send_sock->useinfo.name);
2282 2284
 	else
2283 2285
 		address_str=&(send_sock->address_str);
2284 2286
 	if (hp && hp->port->len)
2285 2287
 		port_str=hp->port;
2288
+	else if(send_sock->useinfo.port_no>0)
2289
+		port_str=&(send_sock->useinfo.port_no_str);
2286 2290
 	else
2287 2291
 		port_str=&(send_sock->port_no_str);
2288 2292
 	
... ...
@@ -235,10 +235,13 @@ error:
235 235
 static inline struct socket_info* new_sock_info(	char* name,
236 236
 								struct name_lst* addr_l,
237 237
 								unsigned short port, unsigned short proto,
238
+								char *usename, unsigned short useport,
238 239
 								enum si_flags flags)
239 240
 {
240 241
 	struct socket_info* si;
241 242
 	struct name_lst* n;
243
+	struct hostent* he;
244
+	char *p;
242 245
 	
243 246
 	si=(struct socket_info*) pkg_malloc(sizeof(struct socket_info));
244 247
 	if (si==0) goto error;
... ...
@@ -259,10 +262,51 @@ static inline struct socket_info* new_sock_info(	char* name,
259 259
 			goto error;
260 260
 		}
261 261
 	}
262
+	if(usename!=NULL)
263
+	{
264
+		si->useinfo.name.len=strlen(usename);
265
+		si->useinfo.name.s=(char*)pkg_malloc(si->useinfo.name.len+1);
266
+		if (si->useinfo.name.s==0)
267
+			goto error;
268
+		strcpy(si->useinfo.name.s, usename);
269
+		if(usename[0]=='[' && usename[si->useinfo.name.len-1]==']')
270
+		{
271
+			si->useinfo.address_str.len = si->useinfo.name.len - 2;
272
+			p = si->useinfo.name.s + 1;
273
+		} else {
274
+			si->useinfo.address_str.len = si->useinfo.name.len;
275
+			p = si->useinfo.name.s;
276
+		}
277
+		si->useinfo.address_str.s=(char*)pkg_malloc(si->useinfo.address_str.len+1);
278
+		if(si->useinfo.address_str.s==NULL)
279
+			goto error;
280
+		strncpy(si->useinfo.address_str.s, p, si->useinfo.address_str.len);
281
+		si->useinfo.address_str.s[si->useinfo.address_str.len] = '\0';
282
+
283
+		p = int2str(useport, &si->useinfo.port_no_str.len);
284
+		if(p==NULL)
285
+			goto error;
286
+		si->useinfo.port_no_str.s=(char*)pkg_malloc(si->useinfo.port_no_str.len+1);
287
+		if(si->useinfo.port_no_str.s==NULL)
288
+			goto error;
289
+		strcpy(si->useinfo.port_no_str.s, p);
290
+		si->useinfo.port_no = useport;
291
+
292
+		he=resolvehost(si->useinfo.name.s);
293
+		if (he==0){
294
+			LM_ERR(" unable to resolve advertised name %s\n", si->useinfo.name.s);
295
+			goto error;
296
+		}
297
+		hostent2ip_addr(&si->useinfo.address, he, 0);
298
+	}
262 299
 	return si;
263 300
 error:
264 301
 	LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n");
265
-	if (si) pkg_free(si);
302
+	if (si) {
303
+		if(si->name.s)
304
+			pkg_free(si->name.s);
305
+		pkg_free(si);
306
+	}
266 307
 	return 0;
267 308
 }
268 309
 
... ...
@@ -275,8 +319,11 @@ static void free_sock_info(struct socket_info* si)
275 275
 		if(si->name.s) pkg_free(si->name.s);
276 276
 		if(si->address_str.s) pkg_free(si->address_str.s);
277 277
 		if(si->port_no_str.s) pkg_free(si->port_no_str.s);
278
-		if (si->addr_info_lst) free_addr_info_lst(&si->addr_info_lst);
278
+		if(si->addr_info_lst) free_addr_info_lst(&si->addr_info_lst);
279 279
 		if(si->sock_str.s) pkg_free(si->sock_str.s);
280
+		if(si->useinfo.name.s) pkg_free(si->useinfo.name.s);
281
+		if(si->useinfo.port_no_str.s) pkg_free(si->useinfo.port_no_str.s);
282
+		if(si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
280 283
 	}
281 284
 }
282 285
 
... ...
@@ -322,19 +369,27 @@ static char* get_valid_proto_name(unsigned short proto)
322 322
  */
323 323
 int socket2str(char* s, int* len, struct socket_info* si)
324 324
 {
325
+	return socketinfo2str(s, len, si, 0);
326
+}
327
+
328
+int socketinfo2str(char* s, int* len, struct socket_info* si, int mode)
329
+{
325 330
 	str proto;
326 331
 	int l;
327 332
 	
328 333
 	proto.s = get_valid_proto_name(si->proto);
329 334
 	proto.len = strlen(proto.s);
330 335
 	
331
-	l = proto.len + si->address_str.len + si->port_no_str.len + 2;
336
+	if(mode==1)
337
+		l = proto.len + si->useinfo.name.len + si->useinfo.port_no_str.len + 2;
338
+	else
339
+		l = proto.len + si->address_str.len + si->port_no_str.len + 2;
332 340
 
333 341
 	if(si->address.af==AF_INET6)
334 342
 		l += 2;
335 343
 	
336 344
 	if (*len < l) {
337
-		ERR("socket2str: Destionation buffer too short\n");
345
+		LM_ERR("Destionation buffer too short\n");
338 346
 		*len = l;
339 347
 		return -1;
340 348
 	}
... ...
@@ -342,17 +397,25 @@ int socket2str(char* s, int* len, struct socket_info* si)
342 342
 	memcpy(s, proto.s, proto.len);
343 343
 	s += proto.len;
344 344
 	*s = ':'; s++;
345
-	if(si->address.af==AF_INET6) {
346
-		*s = '['; s++;
347
-	}
348
-	memcpy(s, si->address_str.s, si->address_str.len);
349
-	s += si->address_str.len;
350
-	if(si->address.af==AF_INET6) {
351
-		*s = ']'; s++;
345
+	if(mode==1){
346
+		memcpy(s, si->useinfo.name.s, si->useinfo.name.len);
347
+		s += si->useinfo.name.len;
348
+		*s = ':'; s++;
349
+		memcpy(s, si->useinfo.port_no_str.s, si->useinfo.port_no_str.len);
350
+		s += si->useinfo.port_no_str.len;
351
+	} else {
352
+		if(si->address.af==AF_INET6) {
353
+			*s = '['; s++;
354
+		}
355
+		memcpy(s, si->address_str.s, si->address_str.len);
356
+		s += si->address_str.len;
357
+		if(si->address.af==AF_INET6) {
358
+			*s = ']'; s++;
359
+		}
360
+		*s = ':'; s++;
361
+		memcpy(s, si->port_no_str.s, si->port_no_str.len);
362
+		s += si->port_no_str.len;
352 363
 	}
353
-	*s = ':'; s++;
354
-	memcpy(s, si->port_no_str.s, si->port_no_str.len);
355
-	s += si->port_no_str.len;
356 364
 
357 365
 	*len = l;
358 366
 	return 0;
... ...
@@ -375,12 +438,30 @@ static int fix_sock_str(struct socket_info* si)
375 375
 		ERR("fix_sock_str: No memory left\n");
376 376
 		return -1;
377 377
 	}
378
-	if (socket2str(si->sock_str.s, &len, si) < 0) {
379
-		BUG("fix_sock_str: Error in socket2str\n");
378
+	if (socketinfo2str(si->sock_str.s, &len, si, 0) < 0) {
379
+		BUG("fix_sock_str: Error in socket to str\n");
380 380
 		return -1;
381 381
 	}
382 382
 	si->sock_str.s[len] = '\0';
383 383
 	si->sock_str.len = len;
384
+	if(si->useinfo.name.s!=NULL)
385
+	{
386
+		len = MAX_SOCKET_STR;
387
+
388
+		if (si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
389
+
390
+		si->useinfo.sock_str.s = pkg_malloc(len + 1);
391
+		if (si->useinfo.sock_str.s == NULL) {
392
+			ERR("fix_sock_str: No memory left\n");
393
+			return -1;
394
+		}
395
+		if (socketinfo2str(si->useinfo.sock_str.s, &len, si, 1) < 0) {
396
+			BUG("fix_sock_str: Error in socket to str\n");
397
+			return -1;
398
+		}
399
+		si->useinfo.sock_str.s[len] = '\0';
400
+		si->useinfo.sock_str.len = len;
401
+	}
384 402
 	return 0;
385 403
 }
386 404
 
... ...
@@ -493,23 +574,38 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
493 493
 		if (list==0) /* disabled or unknown protocol */
494 494
 			continue;
495 495
 		for (si=*list; si; si=si->next){
496
-			DBG("grep_sock_info - checking if host==us: %d==%d && "
497
-					" [%.*s] == [%.*s]\n", 
496
+			DBG("grep_sock_info - checking if host==us: %d==%d &&"
497
+					" [%.*s] == [%.*s]\n",
498 498
 						hname.len,
499 499
 						si->name.len,
500 500
 						hname.len, hname.s,
501 501
 						si->name.len, si->name.s
502 502
 				);
503 503
 			if (port) {
504
-				DBG("grep_sock_info - checking if port %d matches port %d\n", 
505
-						si->port_no, port);
506
-				if (si->port_no!=port) {
504
+				DBG("grep_sock_info - checking if port %d (advertise %d)"
505
+						" matches port %d\n",
506
+						si->port_no, si->useinfo.port_no, port);
507
+				if (si->port_no!=port && si->useinfo.port_no!=port) {
507 508
 					continue;
508 509
 				}
509 510
 			}
510 511
 			if (si_hname_cmp(&hname, &si->name, &si->address_str, 
511 512
 								&si->address, si->flags)==0)
512 513
 				goto found;
514
+			if(si->useinfo.name.s!=NULL)
515
+			{
516
+				DBG("grep_sock_info - checking advertise if host==us:"
517
+						" %d==%d && [%.*s] == [%.*s]\n",
518
+						hname.len,
519
+						si->useinfo.name.len,
520
+						hname.len, hname.s,
521
+						si->useinfo.name.len, si->useinfo.name.s
522
+				);
523
+				if (si_hname_cmp(&hname, &si->useinfo.name,
524
+							&si->useinfo.address_str, &si->useinfo.address,
525
+							si->flags)==0)
526
+					goto found;
527
+			}
513 528
 			/* try among the extra addresses */
514 529
 			for (ai=si->addr_info_lst; ai; ai=ai->next)
515 530
 				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,
593 593
 					continue;
594 594
 				}
595 595
 			}
596
-			if (ip_addr_cmp(ip, &si->address))
596
+			if (ip_addr_cmp(ip, &si->address)
597
+					|| ip_addr_cmp(ip, &si->useinfo.address))
597 598
 				goto found;
598 599
 			for (ai=si->addr_info_lst; ai; ai=ai->next)
599 600
 				if (ip_addr_cmp(ip, &ai->address))
... ...
@@ -612,12 +709,14 @@ found:
612 612
  * return  new sock info on success, 0 on error */
613 613
 static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
614 614
 									unsigned short port,
615
-									unsigned short proto, enum si_flags flags,
615
+									unsigned short proto,
616
+									char *usename, unsigned short useport,
617
+									enum si_flags flags,
616 618
 									struct socket_info** list)
617 619
 {
618 620
 	struct socket_info* si;
619 621
 	
620
-	si=new_sock_info(name, addr_l, port, proto, flags);
622
+	si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
621 623
 	if (si==0){
622 624
 		LOG(L_ERR, "ERROR: new_sock2list: new_sock_info failed\n");
623 625
 		goto error;
... ...
@@ -639,12 +738,15 @@ error:
639 639
 static struct socket_info* new_sock2list_after(char* name,
640 640
 									struct name_lst* addr_l,
641 641
 									unsigned short port,
642
-									unsigned short proto, enum si_flags flags,
642
+									unsigned short proto,
643
+									char *usename,
644
+									unsigned short useport,
645
+									enum si_flags flags,
643 646
 									struct socket_info* after)
644 647
 {
645 648
 	struct socket_info* si;
646 649
 	
647
-	si=new_sock_info(name, addr_l, port, proto, flags);
650
+	si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
648 651
 	if (si==0){
649 652
 		LOG(L_ERR, "ERROR: new_sock2list_after: new_sock_info failed\n");
650 653
 		goto error;
... ...
@@ -659,8 +761,9 @@ error:
659 659
 
660 660
 /* adds a sock_info structure to the corresponding proto list
661 661
  * return  0 on success, -1 on error */
662
-int add_listen_iface(char* name, struct name_lst* addr_l,
662
+int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
663 663
 						unsigned short port, unsigned short proto,
664
+						char *usename, unsigned short useport,
664 665
 						enum si_flags flags)
665 666
 {
666 667
 	struct socket_info** list;
... ...
@@ -691,7 +794,7 @@ int add_listen_iface(char* name, struct name_lst* addr_l,
691 691
 			c_port=port;
692 692
 		}
693 693
 		if (c_proto!=PROTO_SCTP){
694
-			if (new_sock2list(name, 0, c_port, c_proto,
694
+			if (new_sock2list(name, 0, c_port, c_proto, usename, useport,
695 695
 								flags & ~SI_IS_MHOMED, list)==0){
696 696
 				LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
697 697
 				goto error;
... ...
@@ -700,14 +803,16 @@ int add_listen_iface(char* name, struct name_lst* addr_l,
700 700
 			 * since only SCTP can bind to multiple addresses */
701 701
 			for (a_l=addr_l; a_l; a_l=a_l->next){
702 702
 				if (new_sock2list(a_l->name, 0, c_port, 
703
-									c_proto, flags & ~SI_IS_MHOMED, list)==0){
703
+									c_proto, usename, useport,
704
+									flags & ~SI_IS_MHOMED, list)==0){
704 705
 					LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list"
705 706
 								" failed\n");
706 707
 					goto error;
707 708
 				}
708 709
 			}
709 710
 		}else{
710
-			if (new_sock2list(name, addr_l, c_port, c_proto, flags, list)==0){
711
+			if (new_sock2list(name, addr_l, c_port, c_proto, usename, useport,
712
+						flags, list)==0){
711 713
 				LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
712 714
 				goto error;
713 715
 			}
... ...
@@ -718,6 +823,14 @@ error:
718 718
 	return -1;
719 719
 }
720 720
 
721
+/* adds a sock_info structure to the corresponding proto list
722
+ * return  0 on success, -1 on error */
723
+int add_listen_iface(char* name, struct name_lst* addr_l,
724
+						unsigned short port, unsigned short proto,
725
+						enum si_flags flags)
726
+{
727
+	return add_listen_advertise_iface(name, addr_l, port, proto, 0, 0, flags);
728
+}
721 729
 #ifdef __OS_linux
722 730
 
723 731
 #include "linux/netlink.h"
... ...
@@ -1323,8 +1436,8 @@ static int addr_info_to_si_lst(struct addr_info* ai_lst, unsigned short port,
1323 1323
 	struct addr_info* ail;
1324 1324
 	
1325 1325
 	for (ail=ai_lst; ail; ail=ail->next){
1326
-		if(new_sock2list(ail->name.s, 0, port, proto, ail->flags | flags,
1327
-							list)==0)
1326
+		if(new_sock2list(ail->name.s, 0, port, proto, 0, 0,
1327
+					ail->flags | flags, list)==0)
1328 1328
 			return -1;
1329 1329
 	}
1330 1330
 	return 0;
... ...
@@ -1346,7 +1459,7 @@ static int addr_info_to_si_lst_after(struct addr_info* ai_lst,
1346 1346
 	
1347 1347
 	for (ail=ai_lst; ail; ail=ail->next){
1348 1348
 		if((new_si=new_sock2list_after(ail->name.s, 0, port, proto,
1349
-								ail->flags | flags, el))==0)
1349
+								0, 0, ail->flags | flags, el))==0)
1350 1350
 			return -1;
1351 1351
 		el=new_si;
1352 1352
 	}
... ...
@@ -1386,7 +1499,8 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
1386 1386
 							si->proto, &ai_lst)!=-1){
1387 1387
 			if (si->flags & SI_IS_MHOMED){
1388 1388
 				if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no,
1389
-											si->proto,
1389
+											si->proto, si->useinfo.name.s,
1390
+											si->useinfo.port_no,
1390 1391
 											ai_lst->flags|si->flags, si))==0)
1391 1392
 					break;
1392 1393
 				ail=ai_lst;
... ...
@@ -50,6 +50,7 @@
50 50
 	INT2STR_MAX_LEN + 2 + 2)
51 51
 
52 52
 int socket2str(char* s, int* len, struct socket_info* si);
53
+int socketinfo2str(char* s, int* len, struct socket_info* si, int mode);
53 54
 
54 55
 
55 56
 /* struct socket_info is defined in ip_addr.h */
... ...
@@ -84,6 +85,10 @@ void init_proto_order();
84 84
 int add_listen_iface(char* name, struct name_lst* nlst,
85 85
 						unsigned short port, unsigned short proto,
86 86
 						enum si_flags flags);
87
+int add_listen_advertise_iface(char* name, struct name_lst* nlst,
88
+						unsigned short port, unsigned short proto,
89
+						char *useaddr, unsigned short useport,
90
+						enum si_flags flags);
87 91
 int fix_all_socket_lists();
88 92
 void print_all_socket_lists();
89 93
 void print_aliases();