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 <sys/cdefs.h> 9 __FBSDID("$FreeBSD$"); 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