Browse code

core: added mcast to select interface for multicast

- You can now define a mcast parameter before a listen parameter that
contains a multicast address. After each listen parameter mcast gets
reset. mcast must contain the name of an interface, eg `eth1`.

Issue GH#813

Timmo Verlaan authored on 07/10/2016 09:53:30
Showing 7 changed files
... ...
@@ -427,6 +427,7 @@ RT_TIMER2_PRIO		"rt_timer2_prio"|"rt_stimer_prio"
427 427
 RT_TIMER2_POLICY	"rt_timer2_policy"|"rt_stimer_policy"
428 428
 MCAST_LOOPBACK		"mcast_loopback"
429 429
 MCAST_TTL		"mcast_ttl"
430
+MCAST		"mcast"
430 431
 TOS			"tos"
431 432
 PMTU_DISCOVERY	"pmtu_discovery"
432 433
 KILL_TIMEOUT	"exit_timeout"|"ser_kill_timeout"
... ...
@@ -894,6 +895,8 @@ IMPORTFILE      "import_file"
894 895
 									return MCAST_LOOPBACK; }
895 896
 <INITIAL>{MCAST_TTL}		{	count(); yylval.strval=yytext;
896 897
 									return MCAST_TTL; }
898
+<INITIAL>{MCAST}		{	count(); yylval.strval=yytext;
899
+									return MCAST; }
897 900
 <INITIAL>{TOS}			{	count(); yylval.strval=yytext;
898 901
 									return TOS; }
899 902
 <INITIAL>{PMTU_DISCOVERY}		{	count(); yylval.strval=yytext;
... ...
@@ -465,6 +465,7 @@ extern char *default_routename;
465 465
 %token RT_TIMER2_POLICY
466 466
 %token MCAST_LOOPBACK
467 467
 %token MCAST_TTL
468
+%token MCAST
468 469
 %token TOS
469 470
 %token PMTU_DISCOVERY
470 471
 %token KILL_TIMEOUT
... ...
@@ -1479,6 +1480,21 @@ assign_stm:
1479 1480
 		#endif
1480 1481
 	}
1481 1482
 	| MCAST_TTL EQUAL error { yyerror("number expected"); }
1483
+	| MCAST EQUAL ID {
1484
+		#ifdef USE_MCAST
1485
+			mcast=$3;
1486
+		#else
1487
+			warn("no multicast support compiled in");
1488
+		#endif
1489
+	}
1490
+	| MCAST EQUAL STRING {
1491
+		#ifdef USE_MCAST
1492
+			mcast=$3;
1493
+		#else
1494
+			warn("no multicast support compiled in");
1495
+		#endif
1496
+	}
1497
+	| MCAST EQUAL error { yyerror("string expected"); }
1482 1498
 	| TOS EQUAL NUMBER { tos=$3; }
1483 1499
 	| TOS EQUAL ID { if (strcasecmp($3,"IPTOS_LOWDELAY")) {
1484 1500
 			tos=IPTOS_LOWDELAY;
... ...
@@ -136,6 +136,7 @@ extern str version_table;
136 136
 #ifdef USE_MCAST
137 137
 extern int mcast_loopback;
138 138
 extern int mcast_ttl;
139
+extern char* mcast;
139 140
 #endif /* USE_MCAST */
140 141
 
141 142
 extern int auto_bind_ipv6;
... ...
@@ -116,6 +116,9 @@ struct socket_info{
116 116
 	int workers; /* number of worker processes for this socket */
117 117
 	int workers_tcpidx; /* index of workers in tcp children array */
118 118
 	struct advertise_info useinfo; /* details to be used in SIP msg */
119
+#ifdef USE_MCAST
120
+	str mcast; /* name of interface that should join multicast group*/
121
+#endif /* USE_MCAST */
119 122
 };
120 123
 
121 124
 
... ...
@@ -411,6 +411,7 @@ int reply_to_via=0;
411 411
 #ifdef USE_MCAST
412 412
 int mcast_loopback = 0;
413 413
 int mcast_ttl = -1; /* if -1, don't touch it, use the default (usually 1) */
414
+char* mcast = 0;
414 415
 #endif /* USE_MCAST */
415 416
 
416 417
 int tos = IPTOS_LOWDELAY;
... ...
@@ -712,6 +712,14 @@ static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
712 712
 		si->workers = socket_workers;
713 713
 		socket_workers = 0;
714 714
 	}
715
+#ifdef USE_MCAST
716
+	if (mcast!=0) {
717
+		si->mcast.len=strlen(mcast);
718
+		si->mcast.s=(char*)pkg_malloc(si->mcast.len+1);
719
+		strcpy(si->mcast.s, mcast);
720
+		mcast = 0;
721
+	}
722
+#endif /* USE_MCAST */
715 723
 	sock_listadd(list, si);
716 724
 	return si;
717 725
 error:
... ...
@@ -55,6 +55,9 @@
55 55
 #ifdef USE_RAW_SOCKS
56 56
 #include "raw_sock.h"
57 57
 #endif /* USE_RAW_SOCKS */
58
+#ifdef USE_MCAST
59
+#include <net/if.h>
60
+#endif /* USE_MCAST */
58 61
 
59 62
 
60 63
 #ifdef DBG_MSG_QA
... ...
@@ -210,15 +213,20 @@ int probe_max_receive_buffer( int udp_sock )
210 213
 /*
211 214
  * Setup multicast receiver
212 215
  */
213
-static int setup_mcast_rcvr(int sock, union sockaddr_union* addr)
216
+static int setup_mcast_rcvr(int sock, union sockaddr_union* addr, char* interface)
214 217
 {
215
-	struct ip_mreq mreq;
218
+	struct ip_mreqn mreq;
216 219
 	struct ipv6_mreq mreq6;
217
-	
220
+
218 221
 	if (addr->s.sa_family==AF_INET){
219 222
 		memcpy(&mreq.imr_multiaddr, &addr->sin.sin_addr, 
220 223
 		       sizeof(struct in_addr));
221
-		mreq.imr_interface.s_addr = htonl(INADDR_ANY);
224
+		if (interface!=0) {
225
+			mreq.imr_ifindex = if_nametoindex(interface);
226
+		} else {
227
+			mreq.imr_ifindex = 0;
228
+		}
229
+		mreq.imr_address.s_addr = htonl(INADDR_ANY);
222 230
 		
223 231
 		if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq,
224 232
 			       sizeof(mreq))==-1){
... ...
@@ -229,7 +237,11 @@ static int setup_mcast_rcvr(int sock, union sockaddr_union* addr)
229 237
 	} else if (addr->s.sa_family==AF_INET6){
230 238
 		memcpy(&mreq6.ipv6mr_multiaddr, &addr->sin6.sin6_addr, 
231 239
 		       sizeof(struct in6_addr));
232
-		mreq6.ipv6mr_interface = 0;
240
+		if (interface!=0) {
241
+			mreq6.ipv6mr_interface = if_nametoindex(interface);
242
+		} else {
243
+			mreq6.ipv6mr_interface = 0;
244
+		}
233 245
 #ifdef __OS_linux
234 246
 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6,
235 247
 #else
... ...
@@ -321,7 +333,7 @@ int udp_init(struct socket_info* sock_info)
321 333
 
322 334
 #ifdef USE_MCAST
323 335
 	if ((sock_info->flags & SI_IS_MCAST) 
324
-	    && (setup_mcast_rcvr(sock_info->socket, addr)<0)){
336
+	    && (setup_mcast_rcvr(sock_info->socket, addr, sock_info->mcast.s)<0)){
325 337
 			goto error;
326 338
 	}
327 339
 	/* set the multicast options */