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