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