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