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