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