Explorar o código

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 %!s(int64=9) %!d(string=hai) anos
pai
achega
8b39cb6a3a
Modificáronse 7 ficheiros con 50 adicións e 6 borrados
  1. 3 0
      cfg.lex
  2. 16 0
      cfg.y
  3. 1 0
      globals.h
  4. 3 0
      ip_addr.h
  5. 1 0
      main.c
  6. 8 0
      socket_info.c
  7. 18 6
      udp_server.c

+ 3 - 0
cfg.lex

@@ -427,6 +427,7 @@ RT_TIMER2_PRIO		"rt_timer2_prio"|"rt_stimer_prio"
 RT_TIMER2_POLICY	"rt_timer2_policy"|"rt_stimer_policy"
 MCAST_LOOPBACK		"mcast_loopback"
 MCAST_TTL		"mcast_ttl"
+MCAST		"mcast"
 TOS			"tos"
 PMTU_DISCOVERY	"pmtu_discovery"
 KILL_TIMEOUT	"exit_timeout"|"ser_kill_timeout"
@@ -894,6 +895,8 @@ IMPORTFILE      "import_file"
 									return MCAST_LOOPBACK; }
 <INITIAL>{MCAST_TTL}		{	count(); yylval.strval=yytext;
 									return MCAST_TTL; }
+<INITIAL>{MCAST}		{	count(); yylval.strval=yytext;
+									return MCAST; }
 <INITIAL>{TOS}			{	count(); yylval.strval=yytext;
 									return TOS; }
 <INITIAL>{PMTU_DISCOVERY}		{	count(); yylval.strval=yytext;

+ 16 - 0
cfg.y

@@ -465,6 +465,7 @@ extern char *default_routename;
 %token RT_TIMER2_POLICY
 %token MCAST_LOOPBACK
 %token MCAST_TTL
+%token MCAST
 %token TOS
 %token PMTU_DISCOVERY
 %token KILL_TIMEOUT
@@ -1479,6 +1480,21 @@ assign_stm:
 		#endif
 	}
 	| MCAST_TTL EQUAL error { yyerror("number expected"); }
+	| MCAST EQUAL ID {
+		#ifdef USE_MCAST
+			mcast=$3;
+		#else
+			warn("no multicast support compiled in");
+		#endif
+	}
+	| MCAST EQUAL STRING {
+		#ifdef USE_MCAST
+			mcast=$3;
+		#else
+			warn("no multicast support compiled in");
+		#endif
+	}
+	| MCAST EQUAL error { yyerror("string expected"); }
 	| TOS EQUAL NUMBER { tos=$3; }
 	| TOS EQUAL ID { if (strcasecmp($3,"IPTOS_LOWDELAY")) {
 			tos=IPTOS_LOWDELAY;

+ 1 - 0
globals.h

@@ -136,6 +136,7 @@ extern str version_table;
 #ifdef USE_MCAST
 extern int mcast_loopback;
 extern int mcast_ttl;
+extern char* mcast;
 #endif /* USE_MCAST */
 
 extern int auto_bind_ipv6;

+ 3 - 0
ip_addr.h

@@ -116,6 +116,9 @@ struct socket_info{
 	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 */
+#ifdef USE_MCAST
+	str mcast; /* name of interface that should join multicast group*/
+#endif /* USE_MCAST */
 };
 
 

+ 1 - 0
main.c

@@ -411,6 +411,7 @@ int reply_to_via=0;
 #ifdef USE_MCAST
 int mcast_loopback = 0;
 int mcast_ttl = -1; /* if -1, don't touch it, use the default (usually 1) */
+char* mcast = 0;
 #endif /* USE_MCAST */
 
 int tos = IPTOS_LOWDELAY;

+ 8 - 0
socket_info.c

@@ -712,6 +712,14 @@ static struct socket_info* new_sock2list(char* name, struct name_lst* addr_l,
 		si->workers = socket_workers;
 		socket_workers = 0;
 	}
+#ifdef USE_MCAST
+	if (mcast!=0) {
+		si->mcast.len=strlen(mcast);
+		si->mcast.s=(char*)pkg_malloc(si->mcast.len+1);
+		strcpy(si->mcast.s, mcast);
+		mcast = 0;
+	}
+#endif /* USE_MCAST */
 	sock_listadd(list, si);
 	return si;
 error:

+ 18 - 6
udp_server.c

@@ -55,6 +55,9 @@
 #ifdef USE_RAW_SOCKS
 #include "raw_sock.h"
 #endif /* USE_RAW_SOCKS */
+#ifdef USE_MCAST
+#include <net/if.h>
+#endif /* USE_MCAST */
 
 
 #ifdef DBG_MSG_QA
@@ -210,15 +213,20 @@ int probe_max_receive_buffer( int udp_sock )
 /*
  * Setup multicast receiver
  */
-static int setup_mcast_rcvr(int sock, union sockaddr_union* addr)
+static int setup_mcast_rcvr(int sock, union sockaddr_union* addr, char* interface)
 {
-	struct ip_mreq mreq;
+	struct ip_mreqn mreq;
 	struct ipv6_mreq mreq6;
-	
+
 	if (addr->s.sa_family==AF_INET){
 		memcpy(&mreq.imr_multiaddr, &addr->sin.sin_addr, 
 		       sizeof(struct in_addr));
-		mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+		if (interface!=0) {
+			mreq.imr_ifindex = if_nametoindex(interface);
+		} else {
+			mreq.imr_ifindex = 0;
+		}
+		mreq.imr_address.s_addr = htonl(INADDR_ANY);
 		
 		if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq,
 			       sizeof(mreq))==-1){
@@ -229,7 +237,11 @@ static int setup_mcast_rcvr(int sock, union sockaddr_union* addr)
 	} else if (addr->s.sa_family==AF_INET6){
 		memcpy(&mreq6.ipv6mr_multiaddr, &addr->sin6.sin6_addr, 
 		       sizeof(struct in6_addr));
-		mreq6.ipv6mr_interface = 0;
+		if (interface!=0) {
+			mreq6.ipv6mr_interface = if_nametoindex(interface);
+		} else {
+			mreq6.ipv6mr_interface = 0;
+		}
 #ifdef __OS_linux
 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6,
 #else
@@ -321,7 +333,7 @@ int udp_init(struct socket_info* sock_info)
 
 #ifdef USE_MCAST
 	if ((sock_info->flags & SI_IS_MCAST) 
-	    && (setup_mcast_rcvr(sock_info->socket, addr)<0)){
+	    && (setup_mcast_rcvr(sock_info->socket, addr, sock_info->mcast.s)<0)){
 			goto error;
 	}
 	/* set the multicast options */