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