Browse code

- added Jan's multicast support patch

Andrei Pelinescu-Onciul authored on 03/05/2004 11:32:19
Showing 9 changed files
... ...
@@ -278,6 +278,7 @@ DEFS+= $(extra_defs) \
278 278
 	 -DSHM_MEM  -DSHM_MMAP \
279 279
 	 -DDNS_IP_HACK \
280 280
 	 -DUSE_IPV6 \
281
+	 -DUSE_MCAST \
281 282
 	 -DUSE_TCP \
282 283
 	 -DDISABLE_NAGLE \
283 284
 	 -DF_MALLOC \
... ...
@@ -210,6 +210,8 @@ ADVERTISED_ADDRESS	"advertised_address"
210 210
 ADVERTISED_PORT		"advertised_port"
211 211
 DISABLE_CORE		"disable_core_dump"
212 212
 OPEN_FD_LIMIT		"open_files_limit"
213
+MCAST_LOOPBACK		"mcast_loopback"
214
+MCAST_TTL			"mcast_ttl"
213 215
 
214 216
 LOADMODULE	loadmodule
215 217
 MODPARAM        modparam
... ...
@@ -392,6 +394,10 @@ EAT_ABLE	[\ \t\b\r]
392 392
 									return DISABLE_CORE; }
393 393
 <INITIAL>{OPEN_FD_LIMIT}		{	count(); yylval.strval=yytext;
394 394
 									return OPEN_FD_LIMIT; }
395
+<INITIAL>{MCAST_LOOPBACK}		{	count(); yylval.strval=yytext;
396
+									return MCAST_LOOPBACK; }
397
+<INITIAL>{MCAST_TTL}		{	count(); yylval.strval=yytext;
398
+									return MCAST_TTL; }
395 399
 <INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
396 400
 <INITIAL>{MODPARAM}     { count(); yylval.strval=yytext; return MODPARAM; }
397 401
 
... ...
@@ -242,7 +242,7 @@ static struct id_list* mk_listen_id(char*, int, int);
242 242
 %token ADVERTISED_PORT
243 243
 %token DISABLE_CORE
244 244
 %token OPEN_FD_LIMIT
245
-
245
+%token MCAST_LOOPBACK
246 246
 
247 247
 
248 248
 
... ...
@@ -658,6 +658,15 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
658 658
 										open_files_limit=$3;
659 659
 									}
660 660
 		| OPEN_FD_LIMIT EQUAL error { yyerror("number expected"); }
661
+		| MCAST_LOOPBACK EQUAL NUMBER {
662
+								#ifdef USE_MCAST
663
+										mcast_loopback=$3;
664
+								#else
665
+									warn("no multicast support compiled in");
666
+								#endif
667
+		  }
668
+                | MCAST_LOOPBACK EQUAL error { yyerror("boolean value expected"); }
669
+
661 670
 		| error EQUAL { yyerror("unknown config variable"); }
662 671
 	;
663 672
 
... ...
@@ -102,6 +102,10 @@ extern int sock_mode;
102 102
 extern char* chroot_dir;
103 103
 extern char* working_dir;
104 104
 
105
+#ifdef USE_MCAST
106
+extern int mcast_loopback;
107
+#endif /* USE_MCAST */
108
+
105 109
 /*
106 110
  * debug & log_stderr moved to dprint.h*/
107 111
 
... ...
@@ -160,3 +160,28 @@ void print_net(struct net* net)
160 160
 	}
161 161
 	print_ip("", &net->ip, "/"); print_ip("", &net->mask, "");
162 162
 }
163
+
164
+
165
+#ifdef USE_MCAST
166
+
167
+/* Returns 1 if the given address is a multicast address */
168
+int is_mcast(struct ip_addr* ip)
169
+{
170
+	if (!ip){
171
+		LOG(L_ERR, "ERROR: is_mcast: Invalid parameter value\n");
172
+		return -1;
173
+	}
174
+
175
+	if (ip->af==AF_INET){
176
+		return IN_MULTICAST(htonl(ip->u.addr32[0]));
177
+#ifdef USE_IPV6
178
+	} else if (ip->af==AF_INET6){
179
+		return IN6_IS_ADDR_MULTICAST(ip->u.addr);
180
+#endif /* USE_IPV6 */
181
+	} else {
182
+		LOG(L_ERR, "ERROR: is_mcast: Unsupported protocol family\n");
183
+		return -1;
184
+	}
185
+}
186
+
187
+#endif /* USE_MCAST */
... ...
@@ -78,7 +78,7 @@ union sockaddr_union{
78 78
 
79 79
 
80 80
 
81
-enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2 };
81
+enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4 };
82 82
 
83 83
 struct socket_info{
84 84
 	int socket;
... ...
@@ -87,7 +87,7 @@ struct socket_info{
87 87
 	str address_str;        /* ip address converted to string -- optimization*/
88 88
 	unsigned short port_no;  /* port number */
89 89
 	str port_no_str; /* port number converted to string -- optimization*/
90
-	enum si_flags flags; /* SI_IS_IP | SI_IS_LO */
90
+	enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
91 91
 	union sockaddr_union su; 
92 92
 	int proto; /* tcp or udp*/
93 93
 	struct socket_info* next;
... ...
@@ -165,8 +165,10 @@ void print_ip(char* prefix, struct ip_addr* ip, char* suffix);
165 165
 void stdout_print_ip(struct ip_addr* ip);
166 166
 void print_net(struct net* net);
167 167
 
168
-
169
-
168
+#ifdef USE_MCAST
169
+/* Returns 1 if the given address is a multicast address */
170
+int is_mcast(struct ip_addr* ip);
171
+#endif /* USE_MCAST */
170 172
 
171 173
 /* returns 1 if ip & net.mask == net.ip ; 0 otherwise & -1 on error 
172 174
 	[ diff. adress fams ]) */
... ...
@@ -346,6 +346,10 @@ int open_files_limit=-1; /* don't touch it by default */
346 346
 */
347 347
 int reply_to_via=0;
348 348
 
349
+#ifdef USE_MCAST
350
+int mcast_loopback = 0;
351
+#endif /* USE_MCAST */
352
+
349 353
 #if 0
350 354
 char* names[MAX_LISTEN];              /* our names */
351 355
 int names_len[MAX_LISTEN];            /* lengths of the names*/
... ...
@@ -472,9 +472,20 @@ static int fix_socket_list(struct socket_info **list)
472 472
 						}
473 473
 				}
474 474
 		}
475
+
476
+#ifdef USE_MCAST
477
+		     /* Check if it is an multicast address and
478
+		      * set the flag if so
479
+		      */
480
+		if (is_mcast(&si->address)) {
481
+			si->flags |= SI_IS_MCAST;
482
+		}
483
+#endif /* USE_MCAST */
484
+
475 485
 #ifdef EXTRA_DEBUG
476
-		printf("              %.*s [%s]:%s\n", si->name.len, 
477
-				si->name.s, si->address_str.s, si->port_no_str.s);
486
+		printf("              %.*s [%s]:%s%s\n", si->name.len, 
487
+				si->name.s, si->address_str.s, si->port_no_str.s,
488
+		                si->flags & SI_IS_MCAST ? " mcast" : "");
478 489
 #endif
479 490
 	}
480 491
 	/* removing duplicate addresses*/
... ...
@@ -505,6 +516,30 @@ static int fix_socket_list(struct socket_info **list)
505 505
 			l=next;
506 506
 		}
507 507
 	}
508
+
509
+#ifdef USE_MCAST
510
+	     /* Remove invalid multicast entries */
511
+	si=*list;
512
+	while(si){
513
+		if ((si->flags & SI_IS_MCAST) && 
514
+		    ((si->proto == PROTO_TCP)
515
+#ifdef USE_TLS
516
+		    || (si->proto == PROTO_TLS)
517
+#endif /* USE_TLS */
518
+		    )){
519
+			LOG(L_WARN, "WARNING: removing entry %s:%s [%s]:%s\n",
520
+			    get_proto_name(si->proto), si->name.s, 
521
+			    si->address_str.s, si->port_no_str.s);
522
+			l = si;
523
+			si=si->next;
524
+			sock_listrm(list, l);
525
+			free_sock_info(l);
526
+		} else {
527
+			si=si->next;
528
+		}
529
+	}
530
+#endif /* USE_MCAST */
531
+
508 532
 	return 0;
509 533
 error:
510 534
 	return -1;
... ...
@@ -600,8 +635,9 @@ void print_all_socket_lists()
600 600
 	do{
601 601
 		list=get_sock_info_list(proto);
602 602
 		for(si=list?*list:0; si; si=si->next){
603
-			printf("             %s: %s [%s]:%s\n", get_proto_name(proto),
604
-						si->name.s, si->address_str.s, si->port_no_str.s);
603
+			printf("             %s: %s [%s]:%s%s\n", get_proto_name(proto),
604
+			       si->name.s, si->address_str.s, si->port_no_str.s, 
605
+			       si->flags & SI_IS_MCAST ? " mcast" : "");
605 606
 		}
606 607
 	}while((proto=next_proto(proto)));
607 608
 }
... ...
@@ -206,11 +206,71 @@ int probe_max_receive_buffer( int udp_sock )
206 206
 	/* EoJKU */
207 207
 }
208 208
 
209
+
210
+#ifdef USE_MCAST
211
+
212
+/*
213
+ * Setup multicast receiver
214
+ */
215
+static int setup_mcast_rcvr(int sock, union sockaddr_union* addr)
216
+{
217
+	struct ip_mreq mreq;
218
+#ifdef USE_IPV6
219
+	struct ipv6_mreq mreq6;
220
+#endif /* USE_IPV6 */
221
+	
222
+	if (addr->s.sa_family==AF_INET){
223
+		memcpy(&mreq.imr_multiaddr, &addr->sin.sin_addr, 
224
+		       sizeof(struct in_addr));
225
+		mreq.imr_interface.s_addr = htonl(INADDR_ANY);
226
+		
227
+		if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq,
228
+			       sizeof(mreq))==-1){
229
+			LOG(L_ERR, "ERROR: setup_mcast_rcvr: setsockopt: %s\n",
230
+			    strerror(errno));
231
+			return -1;
232
+		}
233
+		
234
+		if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, 
235
+			       &mcast_loopback, sizeof(mcast_loopback))==-1){
236
+			LOG(L_ERR, "ERROR: setup_mcast_rcvr: setsockopt: %s\n",
237
+			    strerror(errno));
238
+			return -1;
239
+		}
240
+#ifdef USE_IPV6
241
+	} else if (addr->s.sa_family==AF_INET6){
242
+		memcpy(&mreq6.ipv6mr_multiaddr, &addr->sin6.sin6_addr, 
243
+		       sizeof(struct in6_addr));
244
+		mreq6.ipv6mr_interface = 0;
245
+		
246
+		if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6,
247
+			       sizeof(mreq6))==-1){
248
+			LOG(L_ERR, "ERROR: setup_mcast_rcvr: setsockopt:%s\n",
249
+			    strerror(errno));
250
+			return -1;
251
+		}
252
+		
253
+		if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 
254
+			       &mcast_loopback, sizeof(mcast_loopback))==-1){
255
+			LOG(L_ERR, "ERROR: udp_init: setsockopt: %s\n", 
256
+			    strerror(errno));
257
+			return -1;
258
+		}
259
+#endif /* USE_IPV6 */
260
+	} else {
261
+		LOG(L_ERR, "ERROR: udp_init: Unsupported protocol family\n");
262
+		return -1;
263
+	}
264
+	return 0;
265
+}
266
+
267
+#endif /* USE_MCAST */
268
+
269
+
209 270
 int udp_init(struct socket_info* sock_info)
210 271
 {
211 272
 	union sockaddr_union* addr;
212 273
 	int optval;
213
-
214 274
 	addr=&sock_info->su;
215 275
 /*
216 276
 	addr=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
... ...
@@ -254,6 +314,12 @@ int udp_init(struct socket_info* sock_info)
254 254
 	}
255 255
 #endif
256 256
 
257
+#ifdef USE_MCAST
258
+	if ((sock_info->flags & SI_IS_MCAST) 
259
+	    && (setup_mcast_rcvr(sock_info->socket, addr)<0)){
260
+			goto error;
261
+	}
262
+#endif /* USE_MCAST */
257 263
 
258 264
 	if ( probe_max_receive_buffer(sock_info->socket)==-1) goto error;
259 265