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