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