소스 검색

- added Jan's multicast support patch

Andrei Pelinescu-Onciul 21 년 전
부모
커밋
2ba731171e
9개의 변경된 파일163개의 추가작업 그리고 10개의 파일을 삭제
  1. 1 0
      Makefile.defs
  2. 6 0
      cfg.lex
  3. 10 1
      cfg.y
  4. 4 0
      globals.h
  5. 25 0
      ip_addr.c
  6. 6 4
      ip_addr.h
  7. 4 0
      main.c
  8. 40 4
      socket_info.c
  9. 67 1
      udp_server.c

+ 1 - 0
Makefile.defs

@@ -278,6 +278,7 @@ DEFS+= $(extra_defs) \
 	 -DSHM_MEM  -DSHM_MMAP \
 	 -DDNS_IP_HACK \
 	 -DUSE_IPV6 \
+	 -DUSE_MCAST \
 	 -DUSE_TCP \
 	 -DDISABLE_NAGLE \
 	 -DF_MALLOC \

+ 6 - 0
cfg.lex

@@ -210,6 +210,8 @@ ADVERTISED_ADDRESS	"advertised_address"
 ADVERTISED_PORT		"advertised_port"
 DISABLE_CORE		"disable_core_dump"
 OPEN_FD_LIMIT		"open_files_limit"
+MCAST_LOOPBACK		"mcast_loopback"
+MCAST_TTL			"mcast_ttl"
 
 LOADMODULE	loadmodule
 MODPARAM        modparam
@@ -392,6 +394,10 @@ EAT_ABLE	[\ \t\b\r]
 									return DISABLE_CORE; }
 <INITIAL>{OPEN_FD_LIMIT}		{	count(); yylval.strval=yytext;
 									return OPEN_FD_LIMIT; }
+<INITIAL>{MCAST_LOOPBACK}		{	count(); yylval.strval=yytext;
+									return MCAST_LOOPBACK; }
+<INITIAL>{MCAST_TTL}		{	count(); yylval.strval=yytext;
+									return MCAST_TTL; }
 <INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
 <INITIAL>{MODPARAM}     { count(); yylval.strval=yytext; return MODPARAM; }
 

+ 10 - 1
cfg.y

@@ -242,7 +242,7 @@ static struct id_list* mk_listen_id(char*, int, int);
 %token ADVERTISED_PORT
 %token DISABLE_CORE
 %token OPEN_FD_LIMIT
-
+%token MCAST_LOOPBACK
 
 
 
@@ -658,6 +658,15 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 										open_files_limit=$3;
 									}
 		| OPEN_FD_LIMIT EQUAL error { yyerror("number expected"); }
+		| MCAST_LOOPBACK EQUAL NUMBER {
+								#ifdef USE_MCAST
+										mcast_loopback=$3;
+								#else
+									warn("no multicast support compiled in");
+								#endif
+		  }
+                | MCAST_LOOPBACK EQUAL error { yyerror("boolean value expected"); }
+
 		| error EQUAL { yyerror("unknown config variable"); }
 	;
 

+ 4 - 0
globals.h

@@ -102,6 +102,10 @@ extern int sock_mode;
 extern char* chroot_dir;
 extern char* working_dir;
 
+#ifdef USE_MCAST
+extern int mcast_loopback;
+#endif /* USE_MCAST */
+
 /*
  * debug & log_stderr moved to dprint.h*/
 

+ 25 - 0
ip_addr.c

@@ -160,3 +160,28 @@ void print_net(struct net* net)
 	}
 	print_ip("", &net->ip, "/"); print_ip("", &net->mask, "");
 }
+
+
+#ifdef USE_MCAST
+
+/* Returns 1 if the given address is a multicast address */
+int is_mcast(struct ip_addr* ip)
+{
+	if (!ip){
+		LOG(L_ERR, "ERROR: is_mcast: Invalid parameter value\n");
+		return -1;
+	}
+
+	if (ip->af==AF_INET){
+		return IN_MULTICAST(htonl(ip->u.addr32[0]));
+#ifdef USE_IPV6
+	} else if (ip->af==AF_INET6){
+		return IN6_IS_ADDR_MULTICAST(ip->u.addr);
+#endif /* USE_IPV6 */
+	} else {
+		LOG(L_ERR, "ERROR: is_mcast: Unsupported protocol family\n");
+		return -1;
+	}
+}
+
+#endif /* USE_MCAST */

+ 6 - 4
ip_addr.h

@@ -78,7 +78,7 @@ union sockaddr_union{
 
 
 
-enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2 };
+enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4 };
 
 struct socket_info{
 	int socket;
@@ -87,7 +87,7 @@ struct socket_info{
 	str address_str;        /* ip address converted to string -- optimization*/
 	unsigned short port_no;  /* port number */
 	str port_no_str; /* port number converted to string -- optimization*/
-	enum si_flags flags; /* SI_IS_IP | SI_IS_LO */
+	enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
 	union sockaddr_union su; 
 	int proto; /* tcp or udp*/
 	struct socket_info* next;
@@ -165,8 +165,10 @@ void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
 void stdout_print_ip(struct ip_addr* ip);
 void print_net(struct net* net);
 
-
-
+#ifdef USE_MCAST
+/* Returns 1 if the given address is a multicast address */
+int is_mcast(struct ip_addr* ip);
+#endif /* USE_MCAST */
 
 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
 	[ diff. adress fams ]) */

+ 4 - 0
main.c

@@ -346,6 +346,10 @@ int open_files_limit=-1; /* don't touch it by default */
 */
 int reply_to_via=0;
 
+#ifdef USE_MCAST
+int mcast_loopback = 0;
+#endif /* USE_MCAST */
+
 #if 0
 char* names[MAX_LISTEN];              /* our names */
 int names_len[MAX_LISTEN];            /* lengths of the names*/

+ 40 - 4
socket_info.c

@@ -472,9 +472,20 @@ static int fix_socket_list(struct socket_info **list)
 						}
 				}
 		}
+
+#ifdef USE_MCAST
+		     /* Check if it is an multicast address and
+		      * set the flag if so
+		      */
+		if (is_mcast(&si->address)) {
+			si->flags |= SI_IS_MCAST;
+		}
+#endif /* USE_MCAST */
+
 #ifdef EXTRA_DEBUG
-		printf("              %.*s [%s]:%s\n", si->name.len, 
-				si->name.s, si->address_str.s, si->port_no_str.s);
+		printf("              %.*s [%s]:%s%s\n", si->name.len, 
+				si->name.s, si->address_str.s, si->port_no_str.s,
+		                si->flags & SI_IS_MCAST ? " mcast" : "");
 #endif
 	}
 	/* removing duplicate addresses*/
@@ -505,6 +516,30 @@ static int fix_socket_list(struct socket_info **list)
 			l=next;
 		}
 	}
+
+#ifdef USE_MCAST
+	     /* Remove invalid multicast entries */
+	si=*list;
+	while(si){
+		if ((si->flags & SI_IS_MCAST) && 
+		    ((si->proto == PROTO_TCP)
+#ifdef USE_TLS
+		    || (si->proto == PROTO_TLS)
+#endif /* USE_TLS */
+		    )){
+			LOG(L_WARN, "WARNING: removing entry %s:%s [%s]:%s\n",
+			    get_proto_name(si->proto), si->name.s, 
+			    si->address_str.s, si->port_no_str.s);
+			l = si;
+			si=si->next;
+			sock_listrm(list, l);
+			free_sock_info(l);
+		} else {
+			si=si->next;
+		}
+	}
+#endif /* USE_MCAST */
+
 	return 0;
 error:
 	return -1;
@@ -600,8 +635,9 @@ void print_all_socket_lists()
 	do{
 		list=get_sock_info_list(proto);
 		for(si=list?*list:0; si; si=si->next){
-			printf("             %s: %s [%s]:%s\n", get_proto_name(proto),
-						si->name.s, si->address_str.s, si->port_no_str.s);
+			printf("             %s: %s [%s]:%s%s\n", get_proto_name(proto),
+			       si->name.s, si->address_str.s, si->port_no_str.s, 
+			       si->flags & SI_IS_MCAST ? " mcast" : "");
 		}
 	}while((proto=next_proto(proto)));
 }

+ 67 - 1
udp_server.c

@@ -206,11 +206,71 @@ int probe_max_receive_buffer( int udp_sock )
 	/* EoJKU */
 }
 
+
+#ifdef USE_MCAST
+
+/*
+ * Setup multicast receiver
+ */
+static int setup_mcast_rcvr(int sock, union sockaddr_union* addr)
+{
+	struct ip_mreq mreq;
+#ifdef USE_IPV6
+	struct ipv6_mreq mreq6;
+#endif /* USE_IPV6 */
+	
+	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 (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq,
+			       sizeof(mreq))==-1){
+			LOG(L_ERR, "ERROR: setup_mcast_rcvr: setsockopt: %s\n",
+			    strerror(errno));
+			return -1;
+		}
+		
+		if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, 
+			       &mcast_loopback, sizeof(mcast_loopback))==-1){
+			LOG(L_ERR, "ERROR: setup_mcast_rcvr: setsockopt: %s\n",
+			    strerror(errno));
+			return -1;
+		}
+#ifdef USE_IPV6
+	} 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 (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6,
+			       sizeof(mreq6))==-1){
+			LOG(L_ERR, "ERROR: setup_mcast_rcvr: setsockopt:%s\n",
+			    strerror(errno));
+			return -1;
+		}
+		
+		if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
+			       &mcast_loopback, sizeof(mcast_loopback))==-1){
+			LOG(L_ERR, "ERROR: udp_init: setsockopt: %s\n", 
+			    strerror(errno));
+			return -1;
+		}
+#endif /* USE_IPV6 */
+	} else {
+		LOG(L_ERR, "ERROR: udp_init: Unsupported protocol family\n");
+		return -1;
+	}
+	return 0;
+}
+
+#endif /* USE_MCAST */
+
+
 int udp_init(struct socket_info* sock_info)
 {
 	union sockaddr_union* addr;
 	int optval;
-
 	addr=&sock_info->su;
 /*
 	addr=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
@@ -254,6 +314,12 @@ int udp_init(struct socket_info* sock_info)
 	}
 #endif
 
+#ifdef USE_MCAST
+	if ((sock_info->flags & SI_IS_MCAST) 
+	    && (setup_mcast_rcvr(sock_info->socket, addr)<0)){
+			goto error;
+	}
+#endif /* USE_MCAST */
 
 	if ( probe_max_receive_buffer(sock_info->socket)==-1) goto error;