xref: /freebsd/usr.sbin/mtest/mtest.c (revision 4a71a2e71bdc472ecfe5390957894b3e6427fc93)
1fc3cc3f5SBill Fenner /*
2fc3cc3f5SBill Fenner  * Program to test new [sg]etsockopts and ioctls for manipulating IP and
3fc3cc3f5SBill Fenner  * Ethernet multicast address filters.
4fc3cc3f5SBill Fenner  *
5fc3cc3f5SBill Fenner  * Written by Steve Deering, Stanford University, February 1989.
6fc3cc3f5SBill Fenner  */
7fc3cc3f5SBill Fenner 
8a89409a2SPhilippe Charnier #include <err.h>
9fc3cc3f5SBill Fenner #include <stdio.h>
10fc3cc3f5SBill Fenner #include <sys/types.h>
11fc3cc3f5SBill Fenner #include <sys/socket.h>
12cf20f871SBill Fenner #include <sys/time.h>
13fc3cc3f5SBill Fenner #include <net/if.h>
144a71a2e7SJulian Elischer #include <net/if_dl.h>
15fc3cc3f5SBill Fenner #include <sys/ioctl.h>
16fc3cc3f5SBill Fenner #include <netinet/in.h>
17fc3cc3f5SBill Fenner 
18a89409a2SPhilippe Charnier int
19fc3cc3f5SBill Fenner main( argc, argv )
20fc3cc3f5SBill Fenner     int argc;
21fc3cc3f5SBill Fenner     char **argv;
22fc3cc3f5SBill Fenner   {
23fc3cc3f5SBill Fenner     int so;
24fc3cc3f5SBill Fenner     char line[80];
25fc3cc3f5SBill Fenner     char *lineptr;
26fc3cc3f5SBill Fenner     struct ip_mreq imr;
27fc3cc3f5SBill Fenner     struct ifreq ifr;
28fc3cc3f5SBill Fenner     int n, f;
29fc3cc3f5SBill Fenner     unsigned i1, i2, i3, i4, g1, g2, g3, g4;
30fc3cc3f5SBill Fenner     unsigned e1, e2, e3, e4, e5, e6;
31fc3cc3f5SBill Fenner 
32fc3cc3f5SBill Fenner     if( (so = socket( AF_INET, SOCK_DGRAM, 0 )) == -1)
33a89409a2SPhilippe Charnier 	err( 1, "can't open socket" );
34fc3cc3f5SBill Fenner 
35fc3cc3f5SBill Fenner     printf( "multicast membership test program; " );
36fc3cc3f5SBill Fenner     printf( "enter ? for list of commands\n" );
37fc3cc3f5SBill Fenner 
38fc3cc3f5SBill Fenner     while( fgets( line, 79, stdin ) != NULL )
39fc3cc3f5SBill Fenner       {
40fc3cc3f5SBill Fenner 	lineptr = line;
41fc3cc3f5SBill Fenner 	while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
42fc3cc3f5SBill Fenner 	switch( *lineptr )
43fc3cc3f5SBill Fenner 	  {
44fc3cc3f5SBill Fenner 	    case '?':
45fc3cc3f5SBill Fenner 	      {
46fc3cc3f5SBill Fenner 		printf( "%s%s%s%s%s%s%s",
47fc3cc3f5SBill Fenner 		" j g.g.g.g i.i.i.i      - join  IP  multicast group     \n",
48fc3cc3f5SBill Fenner 		" l g.g.g.g i.i.i.i      - leave IP  multicast group     \n",
49fc3cc3f5SBill Fenner 		" a ifname e.e.e.e.e.e   - add ether multicast address   \n",
50fc3cc3f5SBill Fenner 		" d ifname e.e.e.e.e.e   - del ether multicast address   \n",
51fc3cc3f5SBill Fenner 		" m ifname 1/0           - set/clear ether allmulti flag \n",
52fc3cc3f5SBill Fenner 		" p ifname 1/0           - set/clear ether promisc flag  \n",
53fc3cc3f5SBill Fenner 		" q                      - quit                      \n\n" );
54fc3cc3f5SBill Fenner 		break;
55fc3cc3f5SBill Fenner 	      }
56fc3cc3f5SBill Fenner 
57fc3cc3f5SBill Fenner 	    case 'j':
58fc3cc3f5SBill Fenner 	      {
59fc3cc3f5SBill Fenner 		++lineptr;
60fc3cc3f5SBill Fenner 		while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
61a89409a2SPhilippe Charnier 		if( (n = sscanf( lineptr, "%u.%u.%u.%u %u.%u.%u.%u",
62fc3cc3f5SBill Fenner 		    &g1, &g2, &g3, &g4, &i1, &i2, &i3, &i4 )) != 8 )
63fc3cc3f5SBill Fenner 		  {
64fc3cc3f5SBill Fenner 		    printf( "bad args\n" );
65fc3cc3f5SBill Fenner 		    break;
66fc3cc3f5SBill Fenner 		  }
67fc3cc3f5SBill Fenner 		imr.imr_multiaddr.s_addr = (g1<<24) | (g2<<16) | (g3<<8) | g4;
68fc3cc3f5SBill Fenner 		imr.imr_multiaddr.s_addr = htonl(imr.imr_multiaddr.s_addr);
69fc3cc3f5SBill Fenner 		imr.imr_interface.s_addr = (i1<<24) | (i2<<16) | (i3<<8) | i4;
70fc3cc3f5SBill Fenner 		imr.imr_interface.s_addr = htonl(imr.imr_interface.s_addr);
71fc3cc3f5SBill Fenner 		if( setsockopt( so, IPPROTO_IP, IP_ADD_MEMBERSHIP,
72fc3cc3f5SBill Fenner 				&imr, sizeof(struct ip_mreq) ) == -1 )
73a89409a2SPhilippe Charnier 		     warn( "can't join group" );
74fc3cc3f5SBill Fenner 		else printf( "group joined\n" );
75fc3cc3f5SBill Fenner 		break;
76fc3cc3f5SBill Fenner 	      }
77fc3cc3f5SBill Fenner 
78fc3cc3f5SBill Fenner 	    case 'l':
79fc3cc3f5SBill Fenner 	      {
80fc3cc3f5SBill Fenner 		++lineptr;
81fc3cc3f5SBill Fenner 		while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
82a89409a2SPhilippe Charnier 		if( (n = sscanf( lineptr, "%u.%u.%u.%u %u.%u.%u.%u",
83fc3cc3f5SBill Fenner 		    &g1, &g2, &g3, &g4, &i1, &i2, &i3, &i4 )) != 8 )
84fc3cc3f5SBill Fenner 		  {
85fc3cc3f5SBill Fenner 		    printf( "bad args\n" );
86fc3cc3f5SBill Fenner 		    break;
87fc3cc3f5SBill Fenner 		  }
88fc3cc3f5SBill Fenner 		imr.imr_multiaddr.s_addr = (g1<<24) | (g2<<16) | (g3<<8) | g4;
89fc3cc3f5SBill Fenner 		imr.imr_multiaddr.s_addr = htonl(imr.imr_multiaddr.s_addr);
90fc3cc3f5SBill Fenner 		imr.imr_interface.s_addr = (i1<<24) | (i2<<16) | (i3<<8) | i4;
91fc3cc3f5SBill Fenner 		imr.imr_interface.s_addr = htonl(imr.imr_interface.s_addr);
92fc3cc3f5SBill Fenner 		if( setsockopt( so, IPPROTO_IP, IP_DROP_MEMBERSHIP,
93fc3cc3f5SBill Fenner 				&imr, sizeof(struct ip_mreq) ) == -1 )
94a89409a2SPhilippe Charnier 		     warn( "can't leave group" );
95fc3cc3f5SBill Fenner 		else printf( "group left\n" );
96fc3cc3f5SBill Fenner 		break;
97fc3cc3f5SBill Fenner 	      }
98fc3cc3f5SBill Fenner 
99fc3cc3f5SBill Fenner 	    case 'a':
100fc3cc3f5SBill Fenner 	      {
1014a71a2e7SJulian Elischer 		struct sockaddr_dl *dlp;
1024a71a2e7SJulian Elischer 		unsigned char *bp;
103fc3cc3f5SBill Fenner 		++lineptr;
104fc3cc3f5SBill Fenner 		while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
105fc3cc3f5SBill Fenner 		if( (n = sscanf( lineptr, "%s %x.%x.%x.%x.%x.%x",
106fc3cc3f5SBill Fenner 			ifr.ifr_name, &e1, &e2, &e3, &e4, &e5, &e6 )) != 7 )
107fc3cc3f5SBill Fenner 		  {
108fc3cc3f5SBill Fenner 		    printf( "bad args\n" );
109fc3cc3f5SBill Fenner 		    break;
110fc3cc3f5SBill Fenner 		  }
1114a71a2e7SJulian Elischer 		dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
1124a71a2e7SJulian Elischer 		dlp->sdl_len = sizeof(struct sockaddr_dl);
1134a71a2e7SJulian Elischer 		dlp->sdl_family = AF_LINK;
1144a71a2e7SJulian Elischer 		dlp->sdl_index = 0;
1154a71a2e7SJulian Elischer 		dlp->sdl_nlen = 0;
1164a71a2e7SJulian Elischer 		dlp->sdl_alen = 6;
1174a71a2e7SJulian Elischer 		dlp->sdl_slen = 0;
1184a71a2e7SJulian Elischer 		bp = LLADDR(dlp);
1194a71a2e7SJulian Elischer 		bp[0] = e1;
1204a71a2e7SJulian Elischer 		bp[1] = e2;
1214a71a2e7SJulian Elischer 		bp[2] = e3;
1224a71a2e7SJulian Elischer 		bp[3] = e4;
1234a71a2e7SJulian Elischer 		bp[4] = e5;
1244a71a2e7SJulian Elischer 		bp[5] = e6;
125fc3cc3f5SBill Fenner 		if( ioctl( so, SIOCADDMULTI, &ifr ) == -1 )
126a89409a2SPhilippe Charnier 		     warn( "can't add ether address" );
127fc3cc3f5SBill Fenner 		else printf( "ether address added\n" );
128fc3cc3f5SBill Fenner 		break;
129fc3cc3f5SBill Fenner 	      }
130fc3cc3f5SBill Fenner 
131fc3cc3f5SBill Fenner 	    case 'd':
132fc3cc3f5SBill Fenner 	      {
1334a71a2e7SJulian Elischer 		struct sockaddr_dl *dlp;
1344a71a2e7SJulian Elischer 		unsigned char *bp;
135fc3cc3f5SBill Fenner 		++lineptr;
136fc3cc3f5SBill Fenner 		while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
137fc3cc3f5SBill Fenner 		if( (n = sscanf( lineptr, "%s %x.%x.%x.%x.%x.%x",
138fc3cc3f5SBill Fenner 			ifr.ifr_name, &e1, &e2, &e3, &e4, &e5, &e6 )) != 7 )
139fc3cc3f5SBill Fenner 		  {
140fc3cc3f5SBill Fenner 		    printf( "bad args\n" );
141fc3cc3f5SBill Fenner 		    break;
142fc3cc3f5SBill Fenner 		  }
1434a71a2e7SJulian Elischer 		dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
1444a71a2e7SJulian Elischer 		dlp->sdl_len = sizeof(struct sockaddr_dl);
1454a71a2e7SJulian Elischer 		dlp->sdl_family = AF_LINK;
1464a71a2e7SJulian Elischer 		dlp->sdl_index = 0;
1474a71a2e7SJulian Elischer 		dlp->sdl_nlen = 0;
1484a71a2e7SJulian Elischer 		dlp->sdl_alen = 6;
1494a71a2e7SJulian Elischer 		dlp->sdl_slen = 0;
1504a71a2e7SJulian Elischer 		bp = LLADDR(dlp);
1514a71a2e7SJulian Elischer 		bp[0] = e1;
1524a71a2e7SJulian Elischer 		bp[1] = e2;
1534a71a2e7SJulian Elischer 		bp[2] = e3;
1544a71a2e7SJulian Elischer 		bp[3] = e4;
1554a71a2e7SJulian Elischer 		bp[4] = e5;
1564a71a2e7SJulian Elischer 		bp[5] = e6;
157fc3cc3f5SBill Fenner 		if( ioctl( so, SIOCDELMULTI, &ifr ) == -1 )
158a89409a2SPhilippe Charnier 		     warn( "can't delete ether address" );
159fc3cc3f5SBill Fenner 		else printf( "ether address deleted\n" );
160fc3cc3f5SBill Fenner 		break;
161fc3cc3f5SBill Fenner 	      }
162fc3cc3f5SBill Fenner 
163fc3cc3f5SBill Fenner 	    case 'm':
164fc3cc3f5SBill Fenner 	      {
165fc3cc3f5SBill Fenner 		++lineptr;
166fc3cc3f5SBill Fenner 		while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
167fc3cc3f5SBill Fenner 		if( (n = sscanf( lineptr, "%s %u", ifr.ifr_name, &f )) != 2 )
168fc3cc3f5SBill Fenner 		  {
169fc3cc3f5SBill Fenner 		    printf( "bad args\n" );
170fc3cc3f5SBill Fenner 		    break;
171fc3cc3f5SBill Fenner 		  }
172fc3cc3f5SBill Fenner 		if( ioctl( so, SIOCGIFFLAGS, &ifr ) == -1 )
173fc3cc3f5SBill Fenner 		  {
174a89409a2SPhilippe Charnier 		    warn( "can't get interface flags" );
175fc3cc3f5SBill Fenner 		    break;
176fc3cc3f5SBill Fenner 		  }
177fc3cc3f5SBill Fenner 		printf( "interface flags %x, ", ifr.ifr_flags );
178fc3cc3f5SBill Fenner 		fflush( stdout );
179fc3cc3f5SBill Fenner 		if( f ) ifr.ifr_flags |=  IFF_ALLMULTI;
180fc3cc3f5SBill Fenner 		else    ifr.ifr_flags &= ~IFF_ALLMULTI;
181fc3cc3f5SBill Fenner 		if( ioctl( so, SIOCSIFFLAGS, &ifr ) == -1 )
182a89409a2SPhilippe Charnier 		     warn( "can't set" );
183fc3cc3f5SBill Fenner 		else printf( "changed to %x\n", ifr.ifr_flags );
184fc3cc3f5SBill Fenner 		break;
185fc3cc3f5SBill Fenner 	      }
186fc3cc3f5SBill Fenner 
187fc3cc3f5SBill Fenner 	    case 'p':
188fc3cc3f5SBill Fenner 	      {
189fc3cc3f5SBill Fenner 		++lineptr;
190fc3cc3f5SBill Fenner 		while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
191fc3cc3f5SBill Fenner 		if( (n = sscanf( lineptr, "%s %u", ifr.ifr_name, &f )) != 2 )
192fc3cc3f5SBill Fenner 		  {
193fc3cc3f5SBill Fenner 		    printf( "bad args\n" );
194fc3cc3f5SBill Fenner 		    break;
195fc3cc3f5SBill Fenner 		  }
196fc3cc3f5SBill Fenner 		if( ioctl( so, SIOCGIFFLAGS, &ifr ) == -1 )
197fc3cc3f5SBill Fenner 		  {
198a89409a2SPhilippe Charnier 		    warn( "can't get interface flags" );
199fc3cc3f5SBill Fenner 		    break;
200fc3cc3f5SBill Fenner 		  }
201fc3cc3f5SBill Fenner 		printf( "interface flags %x, ", ifr.ifr_flags );
202fc3cc3f5SBill Fenner 		fflush( stdout );
203fc3cc3f5SBill Fenner 		if( f ) ifr.ifr_flags |=  IFF_PROMISC;
204fc3cc3f5SBill Fenner 		else    ifr.ifr_flags &= ~IFF_PROMISC;
205fc3cc3f5SBill Fenner 		if( ioctl( so, SIOCSIFFLAGS, &ifr ) == -1 )
206a89409a2SPhilippe Charnier 		     warn( "can't set" );
207fc3cc3f5SBill Fenner 		else printf( "changed to %x\n", ifr.ifr_flags );
208fc3cc3f5SBill Fenner 		break;
209fc3cc3f5SBill Fenner 	      }
210fc3cc3f5SBill Fenner 
211fc3cc3f5SBill Fenner 	    case 'q': exit( 0 );
212fc3cc3f5SBill Fenner 
213fc3cc3f5SBill Fenner 	    case 0:
214fc3cc3f5SBill Fenner 	    case '\n': break;
215fc3cc3f5SBill Fenner 
216fc3cc3f5SBill Fenner 	    default:
217fc3cc3f5SBill Fenner 	      {
218fc3cc3f5SBill Fenner 		printf( "bad command\n" );
219fc3cc3f5SBill Fenner 		break;
220fc3cc3f5SBill Fenner 	      }
221fc3cc3f5SBill Fenner 	  }
222fc3cc3f5SBill Fenner       }
223a89409a2SPhilippe Charnier   return(0);
224fc3cc3f5SBill Fenner   }
225