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 715
 <INITIAL>{LOGFACILITY}	{ yylval.strval=yytext; return LOGFACILITY; }
715 716
 <INITIAL>{LOGNAME}	{ yylval.strval=yytext; return LOGNAME; }
716 717
 <INITIAL>{LISTEN}	{ count(); yylval.strval=yytext; return LISTEN; }
718
+<INITIAL>{ADVERTISE}	{ count(); yylval.strval=yytext; return ADVERTISE; }
717 719
 <INITIAL>{ALIAS}	{ count(); yylval.strval=yytext; return ALIAS; }
718 720
 <INITIAL>{SR_AUTO_ALIASES}	{ count(); yylval.strval=yytext;
719 721
 									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 1541
 		}
1541 1542
 		free_socket_id_lst($3);
1542 1543
 	}
1544
+	| LISTEN EQUAL id_lst ADVERTISE listen_id COLON NUMBER {
1545
+		for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next) {
1546
+			if (add_listen_advertise_iface(	lst_tmp->addr_lst->name,
1547
+									lst_tmp->addr_lst->next,
1548
+									lst_tmp->port, lst_tmp->proto,
1549
+									$5, $7,
1550
+									lst_tmp->flags)!=0) {
1551
+				LOG(L_CRIT,  "ERROR: cfg. parser: failed to add listen"
1552
+								" address\n");
1553
+				break;
1554
+			}
1555
+		}
1556
+		free_socket_id_lst($3);
1557
+	}
1543 1558
 	| LISTEN EQUAL  error { yyerror("ip address, interface name or"
1544 1559
 									" hostname expected"); }
1545 1560
 	| 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 127
 	struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
119 128
 	int workers; /* number of worker processes for this socket */
120 129
 	int workers_tcpidx; /* index of workers in tcp children array */
130
+	struct advertise_info useinfo; /* details to be used in SIP msg */
121 131
 };
122 132
 
123 133
 
... ...
@@ -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 626
 		switch((subst_l)->u.subst){ \
624 627
 			case SUBST_RCV_IP: \
625 628
 				if (msg->rcv.bind_address){ \
626
-					new_len+=msg->rcv.bind_address->address_str.len; \
629
+					new_len+=recv_address_str->len; \
627 630
 					if (msg->rcv.bind_address->address.af!=AF_INET) \
628 631
 						new_len+=2; \
629 632
 				}else{ \
... ...
@@ -633,7 +636,7 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
633 636
 				break; \
634 637
 			case SUBST_RCV_PORT: \
635 638
 				if (msg->rcv.bind_address){ \
636
-					new_len+=msg->rcv.bind_address->port_no_str.len; \
639
+					new_len+=recv_port_str->len; \
637 640
 				}else{ \
638 641
 					/* FIXME */ \
639 642
 					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 665
 				break; \
663 666
 			case SUBST_RCV_ALL: \
664 667
 				if (msg->rcv.bind_address){ \
665
-					new_len+=msg->rcv.bind_address->address_str.len; \
668
+					new_len+=recv_address_str->len; \
666 669
 					if (msg->rcv.bind_address->address.af!=AF_INET) \
667 670
 						new_len+=2; \
668
-					if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
671
+					if (recv_port_no!=SIP_PORT){ \
669 672
 						/* add :port_no */ \
670
-						new_len+=1+msg->rcv.bind_address->port_no_str.len; \
673
+						new_len+=1+recv_port_str->len; \
671 674
 					}\
672 675
 						/*add;transport=xxx*/ \
673 676
 					switch(msg->rcv.bind_address->proto){ \
... ...
@@ -780,15 +783,32 @@ static inline int lumps_len(struct sip_msg* msg, struct lump* lumps,
780 783
 	s_offset=0;
781 784
 	new_len=0;
782 785
 	/* init send_address_str & send_port_str */
783
-	if (msg->set_global_address.len)
786
+	if(send_sock && send_sock->useinfo.name.len>0)
787
+		send_address_str=&(send_sock->useinfo.name);
788
+	else if (msg->set_global_address.len)
784 789
 		send_address_str=&(msg->set_global_address);
785 790
 	else
786 791
 		send_address_str=&(send_sock->address_str);
787
-	if (msg->set_global_port.len)
792
+	if(send_sock && send_sock->useinfo.port_no>0)
793
+		send_port_str=&(send_sock->useinfo.port_no_str);
794
+	else if (msg->set_global_port.len)
788 795
 		send_port_str=&(msg->set_global_port);
789 796
 	else
790 797
 		send_port_str=&(send_sock->port_no_str);
791
-
798
+	/* init recv_address_str, recv_port_str & recv_port_no */
799
+	if(msg->rcv.bind_address) {
800
+		if(msg->rcv.bind_address->useinfo.name.len>0)
801
+			recv_address_str=&(msg->rcv.bind_address->useinfo.name);
802
+		else
803
+			recv_address_str=&(msg->rcv.bind_address->address_str);
804
+		if(msg->rcv.bind_address->useinfo.port_no>0) {
805
+			recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
806
+			recv_port_no = msg->rcv.bind_address->useinfo.port_no;
807
+		} else {
808
+			recv_port_str=&(msg->rcv.bind_address->port_no_str);
809
+			recv_port_no = msg->rcv.bind_address->port_no;
810
+		}
811
+	}
792 812
 
793 813
 	for(t=lumps;t;t=t->next){
794 814
 		/* 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 918
 	int s_offset;
899 919
 	str* send_address_str;
900 920
 	str* send_port_str;
921
+	str* recv_address_str;
922
+	str* recv_port_str;
923
+	int  recv_port_no;
901 924
 	struct socket_info* send_sock;
902 925
 
903 926
 #ifdef USE_COMP
... ...
@@ -958,9 +981,9 @@ static inline void process_lumps(	struct sip_msg* msg,
958 981
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
959 982
 					new_buf[offset]='['; offset++; \
960 983
 				}\
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; \
984
+				memcpy(new_buf+offset, recv_address_str->s, \
985
+						recv_address_str->len); \
986
+				offset+=recv_address_str->len; \
964 987
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
965 988
 					new_buf[offset]=']'; offset++; \
966 989
 				}\
... ...
@@ -971,9 +994,9 @@ static inline void process_lumps(	struct sip_msg* msg,
971 994
 			break; \
972 995
 		case SUBST_RCV_PORT: \
973 996
 			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; \
997
+				memcpy(new_buf+offset, recv_port_str->s, \
998
+						recv_port_str->len); \
999
+				offset+=recv_port_str->len; \
977 1000
 			}else{  \
978 1001
 				/*FIXME*/ \
979 1002
 				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
... ...
@@ -985,19 +1008,19 @@ static inline void process_lumps(	struct sip_msg* msg,
985 1008
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
986 1009
 					new_buf[offset]='['; offset++; \
987 1010
 				}\
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; \
1011
+				memcpy(new_buf+offset, recv_address_str->s, \
1012
+						recv_address_str->len); \
1013
+				offset+=recv_address_str->len; \
991 1014
 				if (msg->rcv.bind_address->address.af!=AF_INET){\
992 1015
 					new_buf[offset]=']'; offset++; \
993 1016
 				}\
994 1017
 				/* :port */ \
995
-				if (msg->rcv.bind_address->port_no!=SIP_PORT){ \
1018
+				if (recv_port_no!=SIP_PORT){ \
996 1019
 					new_buf[offset]=':'; offset++; \
997 1020
 					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; \
1021
+							recv_port_str->s, \
1022
+							recv_port_str->len); \
1023
+					offset+=recv_port_str->len; \
1001 1024
 				}\
1002 1025
 				switch(msg->rcv.bind_address->proto){ \
1003 1026
 					case PROTO_NONE: \
... ...
@@ -1200,7 +1223,33 @@ static inline void process_lumps(	struct sip_msg* msg,
1200 1223
 		send_port_str=&(msg->set_global_port);
1201 1224
 	else
1202 1225
 		send_port_str=&(send_sock->port_no_str);
1203
-
1226
+	/* init send_address_str & send_port_str */
1227
+	if(send_sock && send_sock->useinfo.name.len>0)
1228
+		send_address_str=&(send_sock->useinfo.name);
1229
+	else if (msg->set_global_address.len)
1230
+		send_address_str=&(msg->set_global_address);
1231
+	else
1232
+		send_address_str=&(send_sock->address_str);
1233
+	if(send_sock && send_sock->useinfo.port_no>0)
1234
+		send_port_str=&(send_sock->useinfo.port_no_str);
1235
+	else if (msg->set_global_port.len)
1236
+		send_port_str=&(msg->set_global_port);
1237
+	else
1238
+		send_port_str=&(send_sock->port_no_str);
1239
+	/* init recv_address_str, recv_port_str & recv_port_no */
1240
+	if(msg->rcv.bind_address) {
1241
+		if(msg->rcv.bind_address->useinfo.name.len>0)
1242
+			recv_address_str=&(msg->rcv.bind_address->useinfo.name);
1243
+		else
1244
+			recv_address_str=&(msg->rcv.bind_address->address_str);
1245
+		if(msg->rcv.bind_address->useinfo.port_no>0) {
1246
+			recv_port_str=&(msg->rcv.bind_address->useinfo.port_no_str);
1247
+			recv_port_no = msg->rcv.bind_address->useinfo.port_no;
1248
+		} else {
1249
+			recv_port_str=&(msg->rcv.bind_address->port_no_str);
1250
+			recv_port_no = msg->rcv.bind_address->port_no;
1251
+		}
1252
+	}
1204 1253
 
1205 1254
 	orig=msg->buf;
1206 1255
 	offset=*new_buf_offs;
... ...
@@ -2276,13 +2325,17 @@ char* via_builder( unsigned int *len,
2276 2325
 #endif /* USE_COMP */
2277 2326
 
2278 2327
 	send_sock=send_info->send_sock;
2279
-	/* use pre-set address in via or the outbound socket one */
2280
-	if ( hp && hp->host->len)
2328
+	/* use pre-set address in via, the outbound socket alias or address one */
2329
+	if (hp && hp->host->len)
2281 2330
 		address_str=hp->host;
2331
+	else if(send_sock->useinfo.name.len>0)
2332
+		address_str=&(send_sock->useinfo.name);
2282 2333
 	else
2283 2334
 		address_str=&(send_sock->address_str);
2284 2335
 	if (hp && hp->port->len)
2285 2336
 		port_str=hp->port;
2337
+	else if(send_sock->useinfo.port_no>0)
2338
+		port_str=&(send_sock->useinfo.port_no_str);
2286 2339
 	else
2287 2340
 		port_str=&(send_sock->port_no_str);
2288 2341
 	
... ...
@@ -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 262
 			goto error;
260 263
 		}
261 264
 	}
265
+	if(usename!=NULL)
266
+	{
267
+		si->useinfo.name.len=strlen(usename);
268
+		si->useinfo.name.s=(char*)pkg_malloc(si->useinfo.name.len+1);
269
+		if (si->useinfo.name.s==0)
270
+			goto error;
271
+		strcpy(si->useinfo.name.s, usename);
272
+		if(usename[0]=='[' && usename[si->useinfo.name.len-1]==']')
273
+		{
274
+			si->useinfo.address_str.len = si->useinfo.name.len - 2;
275
+			p = si->useinfo.name.s + 1;
276
+		} else {
277
+			si->useinfo.address_str.len = si->useinfo.name.len;
278
+			p = si->useinfo.name.s;
279
+		}
280
+		si->useinfo.address_str.s=(char*)pkg_malloc(si->useinfo.address_str.len+1);
281
+		if(si->useinfo.address_str.s==NULL)
282
+			goto error;
283
+		strncpy(si->useinfo.address_str.s, p, si->useinfo.address_str.len);
284
+		si->useinfo.address_str.s[si->useinfo.address_str.len] = '\0';
285
+
286
+		p = int2str(useport, &si->useinfo.port_no_str.len);
287
+		if(p==NULL)
288
+			goto error;
289
+		si->useinfo.port_no_str.s=(char*)pkg_malloc(si->useinfo.port_no_str.len+1);
290
+		if(si->useinfo.port_no_str.s==NULL)
291
+			goto error;
292
+		strcpy(si->useinfo.port_no_str.s, p);
293
+		si->useinfo.port_no = useport;
294
+
295
+		he=resolvehost(si->useinfo.name.s);
296
+		if (he==0){
297
+			LM_ERR(" unable to resolve advertised name %s\n", si->useinfo.name.s);
298
+			goto error;
299
+		}
300
+		hostent2ip_addr(&si->useinfo.address, he, 0);
301
+	}
262 302
 	return si;
263 303
 error:
264 304
 	LOG(L_ERR, "ERROR: new_sock_info: memory allocation error\n");
265
-	if (si) pkg_free(si);
305
+	if (si) {
306
+		if(si->name.s)
307
+			pkg_free(si->name.s);
308
+		pkg_free(si);
309
+	}
266 310
 	return 0;
267 311
 }
268 312
 
... ...
@@ -275,8 +319,11 @@ static void free_sock_info(struct socket_info* si)
275 319
 		if(si->name.s) pkg_free(si->name.s);
276 320
 		if(si->address_str.s) pkg_free(si->address_str.s);
277 321
 		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);
322
+		if(si->addr_info_lst) free_addr_info_lst(&si->addr_info_lst);
279 323
 		if(si->sock_str.s) pkg_free(si->sock_str.s);
324
+		if(si->useinfo.name.s) pkg_free(si->useinfo.name.s);
325
+		if(si->useinfo.port_no_str.s) pkg_free(si->useinfo.port_no_str.s);
326
+		if(si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
280 327
 	}
281 328
 }
282 329
 
... ...
@@ -321,6 +368,11 @@ static char* get_valid_proto_name(unsigned short proto)
321 368
  * @return -1 on error and 0 on success
322 369
  */
323 370
 int socket2str(char* s, int* len, struct socket_info* si)
371
+{
372
+	return socketinfo2str(s, len, si, 0);
373
+}
374
+
375
+int socketinfo2str(char* s, int* len, struct socket_info* si, int mode)
324 376
 {
325 377
 	str proto;
326 378
 	int l;
... ...
@@ -328,13 +380,16 @@ int socket2str(char* s, int* len, struct socket_info* si)
328 380
 	proto.s = get_valid_proto_name(si->proto);
329 381
 	proto.len = strlen(proto.s);
330 382
 	
331
-	l = proto.len + si->address_str.len + si->port_no_str.len + 2;
383
+	if(mode==1)
384
+		l = proto.len + si->useinfo.name.len + si->useinfo.port_no_str.len + 2;
385
+	else
386
+		l = proto.len + si->address_str.len + si->port_no_str.len + 2;
332 387
 
333 388
 	if(si->address.af==AF_INET6)
334 389
 		l += 2;
335 390
 	
336 391
 	if (*len < l) {
337
-		ERR("socket2str: Destionation buffer too short\n");
392
+		LM_ERR("Destionation buffer too short\n");
338 393
 		*len = l;
339 394
 		return -1;
340 395
 	}
... ...
@@ -342,17 +397,25 @@ int socket2str(char* s, int* len, struct socket_info* si)
342 397
 	memcpy(s, proto.s, proto.len);
343 398
 	s += proto.len;
344 399
 	*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++;
400
+	if(mode==1){
401
+		memcpy(s, si->useinfo.name.s, si->useinfo.name.len);
402
+		s += si->useinfo.name.len;
403
+		*s = ':'; s++;
404
+		memcpy(s, si->useinfo.port_no_str.s, si->useinfo.port_no_str.len);
405
+		s += si->useinfo.port_no_str.len;
406
+	} else {
407
+		if(si->address.af==AF_INET6) {
408
+			*s = '['; s++;
409
+		}
410
+		memcpy(s, si->address_str.s, si->address_str.len);
411
+		s += si->address_str.len;
412
+		if(si->address.af==AF_INET6) {
413
+			*s = ']'; s++;
414
+		}
415
+		*s = ':'; s++;
416
+		memcpy(s, si->port_no_str.s, si->port_no_str.len);
417
+		s += si->port_no_str.len;
352 418
 	}
353
-	*s = ':'; s++;
354
-	memcpy(s, si->port_no_str.s, si->port_no_str.len);
355
-	s += si->port_no_str.len;
356 419
 
357 420
 	*len = l;
358 421
 	return 0;
... ...
@@ -375,12 +438,30 @@ static int fix_sock_str(struct socket_info* si)
375 438
 		ERR("fix_sock_str: No memory left\n");
376 439
 		return -1;
377 440
 	}
378
-	if (socket2str(si->sock_str.s, &len, si) < 0) {
379
-		BUG("fix_sock_str: Error in socket2str\n");
441
+	if (socketinfo2str(si->sock_str.s, &len, si, 0) < 0) {
442
+		BUG("fix_sock_str: Error in socket to str\n");
380 443
 		return -1;
381 444
 	}
382 445
 	si->sock_str.s[len] = '\0';
383 446
 	si->sock_str.len = len;
447
+	if(si->useinfo.name.s!=NULL)
448
+	{
449
+		len = MAX_SOCKET_STR;
450
+
451
+		if (si->useinfo.sock_str.s) pkg_free(si->useinfo.sock_str.s);
452
+
453
+		si->useinfo.sock_str.s = pkg_malloc(len + 1);
454
+		if (si->useinfo.sock_str.s == NULL) {
455
+			ERR("fix_sock_str: No memory left\n");
456
+			return -1;
457
+		}
458
+		if (socketinfo2str(si->useinfo.sock_str.s, &len, si, 1) < 0) {
459
+			BUG("fix_sock_str: Error in socket to str\n");
460
+			return -1;
461
+		}
462
+		si->useinfo.sock_str.s[len] = '\0';
463
+		si->useinfo.sock_str.len = len;
464
+	}
384 465
 	return 0;
385 466
 }
386 467
 
... ...
@@ -493,23 +574,38 @@ struct socket_info* grep_sock_info(str* host, unsigned short port,
493 574
 		if (list==0) /* disabled or unknown protocol */
494 575
 			continue;
495 576
 		for (si=*list; si; si=si->next){
496
-			DBG("grep_sock_info - checking if host==us: %d==%d && "
497
-					" [%.*s] == [%.*s]\n", 
577
+			DBG("grep_sock_info - checking if host==us: %d==%d &&"
578
+					" [%.*s] == [%.*s]\n",
498 579
 						hname.len,
499 580
 						si->name.len,
500 581
 						hname.len, hname.s,
501 582
 						si->name.len, si->name.s
502 583
 				);
503 584
 			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) {
585
+				DBG("grep_sock_info - checking if port %d (advertise %d)"
586
+						" matches port %d\n",
587
+						si->port_no, si->useinfo.port_no, port);
588
+				if (si->port_no!=port && si->useinfo.port_no!=port) {
507 589
 					continue;
508 590
 				}
509 591
 			}
510 592
 			if (si_hname_cmp(&hname, &si->name, &si->address_str, 
511 593
 								&si->address, si->flags)==0)
512 594
 				goto found;
595
+			if(si->useinfo.name.s!=NULL)
596
+			{
597
+				DBG("grep_sock_info - checking advertise if host==us:"
598
+						" %d==%d && [%.*s] == [%.*s]\n",
599
+						hname.len,
600
+						si->useinfo.name.len,
601
+						hname.len, hname.s,
602
+						si->useinfo.name.len, si->useinfo.name.s
603
+				);
604
+				if (si_hname_cmp(&hname, &si->useinfo.name,
605
+							&si->useinfo.address_str, &si->useinfo.address,
606
+							si->flags)==0)
607
+					goto found;
608
+			}
513 609
 			/* try among the extra addresses */
514 610
 			for (ai=si->addr_info_lst; ai; ai=ai->next)
515 611
 				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 689
 					continue;
594 690
 				}
595 691
 			}
596
-			if (ip_addr_cmp(ip, &si->address))
692
+			if (ip_addr_cmp(ip, &si->address)
693
+					|| ip_addr_cmp(ip, &si->useinfo.address))
597 694
 				goto found;
598 695
 			for (ai=si->addr_info_lst; ai; ai=ai->next)
599 696
 				if (ip_addr_cmp(ip, &ai->address))
... ...
@@ -612,12 +709,14 @@ found:
612 709
  * return  new sock info on success, 0 on error */
613 710
 static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
614 711
 									unsigned short port,
615
-									unsigned short proto, enum si_flags flags,
712
+									unsigned short proto,
713
+									char *usename, unsigned short useport,
714
+									enum si_flags flags,
616 715
 									struct socket_info** list)
617 716
 {
618 717
 	struct socket_info* si;
619 718
 	
620
-	si=new_sock_info(name, addr_l, port, proto, flags);
719
+	si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
621 720
 	if (si==0){
622 721
 		LOG(L_ERR, "ERROR: new_sock2list: new_sock_info failed\n");
623 722
 		goto error;
... ...
@@ -639,12 +738,15 @@ error:
639 738
 static struct socket_info* new_sock2list_after(char* name,
640 739
 									struct name_lst* addr_l,
641 740
 									unsigned short port,
642
-									unsigned short proto, enum si_flags flags,
741
+									unsigned short proto,
742
+									char *usename,
743
+									unsigned short useport,
744
+									enum si_flags flags,
643 745
 									struct socket_info* after)
644 746
 {
645 747
 	struct socket_info* si;
646 748
 	
647
-	si=new_sock_info(name, addr_l, port, proto, flags);
749
+	si=new_sock_info(name, addr_l, port, proto, usename, useport, flags);
648 750
 	if (si==0){
649 751
 		LOG(L_ERR, "ERROR: new_sock2list_after: new_sock_info failed\n");
650 752
 		goto error;
... ...
@@ -659,8 +761,9 @@ error:
659 761
 
660 762
 /* adds a sock_info structure to the corresponding proto list
661 763
  * return  0 on success, -1 on error */
662
-int add_listen_iface(char* name, struct name_lst* addr_l,
764
+int add_listen_advertise_iface(char* name, struct name_lst* addr_l,
663 765
 						unsigned short port, unsigned short proto,
766
+						char *usename, unsigned short useport,
664 767
 						enum si_flags flags)
665 768
 {
666 769
 	struct socket_info** list;
... ...
@@ -691,7 +794,7 @@ int add_listen_iface(char* name, struct name_lst* addr_l,
691 794
 			c_port=port;
692 795
 		}
693 796
 		if (c_proto!=PROTO_SCTP){
694
-			if (new_sock2list(name, 0, c_port, c_proto,
797
+			if (new_sock2list(name, 0, c_port, c_proto, usename, useport,
695 798
 								flags & ~SI_IS_MHOMED, list)==0){
696 799
 				LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
697 800
 				goto error;
... ...
@@ -700,14 +803,16 @@ int add_listen_iface(char* name, struct name_lst* addr_l,
700 803
 			 * since only SCTP can bind to multiple addresses */
701 804
 			for (a_l=addr_l; a_l; a_l=a_l->next){
702 805
 				if (new_sock2list(a_l->name, 0, c_port, 
703
-									c_proto, flags & ~SI_IS_MHOMED, list)==0){
806
+									c_proto, usename, useport,
807
+									flags & ~SI_IS_MHOMED, list)==0){
704 808
 					LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list"
705 809
 								" failed\n");
706 810
 					goto error;
707 811
 				}
708 812
 			}
709 813
 		}else{
710
-			if (new_sock2list(name, addr_l, c_port, c_proto, flags, list)==0){
814
+			if (new_sock2list(name, addr_l, c_port, c_proto, usename, useport,
815
+						flags, list)==0){
711 816
 				LOG(L_ERR, "ERROR: add_listen_iface: new_sock2list failed\n");
712 817
 				goto error;
713 818
 			}
... ...
@@ -718,6 +823,14 @@ error:
718 823
 	return -1;
719 824
 }
720 825
 
826
+/* adds a sock_info structure to the corresponding proto list
827
+ * return  0 on success, -1 on error */
828
+int add_listen_iface(char* name, struct name_lst* addr_l,
829
+						unsigned short port, unsigned short proto,
830
+						enum si_flags flags)
831
+{
832
+	return add_listen_advertise_iface(name, addr_l, port, proto, 0, 0, flags);
833
+}
721 834
 #ifdef __OS_linux
722 835
 
723 836
 #include "linux/netlink.h"
... ...
@@ -1323,8 +1436,8 @@ static int addr_info_to_si_lst(struct addr_info* ai_lst, unsigned short port,
1323 1436
 	struct addr_info* ail;
1324 1437
 	
1325 1438
 	for (ail=ai_lst; ail; ail=ail->next){
1326
-		if(new_sock2list(ail->name.s, 0, port, proto, ail->flags | flags,
1327
-							list)==0)
1439
+		if(new_sock2list(ail->name.s, 0, port, proto, 0, 0,
1440
+					ail->flags | flags, list)==0)
1328 1441
 			return -1;
1329 1442
 	}
1330 1443
 	return 0;
... ...
@@ -1346,7 +1459,7 @@ static int addr_info_to_si_lst_after(struct addr_info* ai_lst,
1346 1459
 	
1347 1460
 	for (ail=ai_lst; ail; ail=ail->next){
1348 1461
 		if((new_si=new_sock2list_after(ail->name.s, 0, port, proto,
1349
-								ail->flags | flags, el))==0)
1462
+								0, 0, ail->flags | flags, el))==0)
1350 1463
 			return -1;
1351 1464
 		el=new_si;
1352 1465
 	}
... ...
@@ -1386,7 +1499,8 @@ static int fix_socket_list(struct socket_info **list, int* type_flags)
1386 1499
 							si->proto, &ai_lst)!=-1){
1387 1500
 			if (si->flags & SI_IS_MHOMED){
1388 1501
 				if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no,
1389
-											si->proto,
1502
+											si->proto, si->useinfo.name.s,
1503
+											si->useinfo.port_no,
1390 1504
 											ai_lst->flags|si->flags, si))==0)
1391 1505
 					break;
1392 1506
 				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 85
 int add_listen_iface(char* name, struct name_lst* nlst,
85 86
 						unsigned short port, unsigned short proto,
86 87
 						enum si_flags flags);
88
+int add_listen_advertise_iface(char* name, struct name_lst* nlst,
89
+						unsigned short port, unsigned short proto,
90
+						char *useaddr, unsigned short useport,
91
+						enum si_flags flags);
87 92
 int fix_all_socket_lists();
88 93
 void print_all_socket_lists();
89 94
 void print_aliases();