mtest.c revision 36440
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
18int
19main( 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