Re: Multicast & Tunnel devices

From: Rodney W. Grimes <freebsd-rwg_at_gndrsh.dnsmgr.net>
Date: Mon, 29 Apr 2024 01:09:17 UTC
> Would anyone know if there is something special with tunnel devices and multicast ? 
> 
> I?ve got some code that happily processes multicast packets on a normal interface; but appears not to do this on a tunnel interface. Tun0 shows multicast enabled:
> 	
> 	tun0: flags=8043<UP,BROADCAST,RUNNING,MULTICAST> metric 0 mtu 1500
> 
> Tcpdump on that interface gives the expected thing (here with mDNS):
> 
> 	tcpdump -n -i tun0 port 5353
> 	listening on tun0, link-type NULL (BSD loopback), capture size 262144 bytes
> 	19:26:03.976259 IP 10.31.0.6.5353 > 224.0.0.251.5353: 0 PTR (QM)? _raop._tcp.local. (34)
> 
> And code, with a simple IP_ADD_MEMBERSHIP  of the MC group on the IP of the local interface below works on a normal interface (e.g. igb0/10.0.0.1/24). 
> 
> 	./listener 10.0.0.1 224.0.0.251 5353

Is 10.0.0.1 the IP address of tun0, or is it the address of some other interface?
I suspect that the IP address of the tun0 interface is 10.31.0.6 from your tcpdump above.

IIRC you have to join multicast group on all interfaces you expect to receive mustcast packets on.

> 	Received packet, len=128
> 	etc
> 
> But yields no output if ran against above tun0 interface (while tcpdump on same is fine). Does that ring a bell with anyone ?
> 
> Dw
> 
> 
> int main(int argc, char *argv[])
> {
>     struct sockaddr_in addr;
>     struct ip_mreq mreq;
> 
> 	// skip error trapping command line arguments
> 
>     char* ip = argv[1]; 
>     char* group = argv[2]; 
>     int port = atoi(argv[3]); // 0 if error, which is an invalid port
> 
>     memset(&addr, 0, sizeof(addr));
>     addr.sin_family = AF_INET;
>     addr.sin_addr.s_addr = htonl(INADDR_ANY);
>     addr.sin_port = htons(port);
> 
>     mreq.imr_interface.s_addr = inet_addr(ip); 
>     mreq.imr_multiaddr.s_addr = inet_addr(group);
> 
> 	// skip error trapping on inet_addr
> 
>     int fd = socket(AF_INET, SOCK_DGRAM, 0);
> 	// skip error trapping socket
> 
>     if (bind(fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
> 	// skip error trapping
> 
>     if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mreq, sizeof(mreq)) < 0 ){
> 	// skip error trapping argumetns
> 
>     while (1) {
> 	..
>         int nbytes = recvfrom(fd,msgbuf,MSGBUFSIZE,0,(struct sockaddr *) &addr,&addrlen);
>         if (nbytes < 0) {
>             perror("recvfrom");
>             return 1;
>         }
> 	printf(?Received packet, len=%d\n", nbytes);
>      }
> 

-- 
Rod Grimes                                                 rgrimes@freebsd.org