1fc3cc3f5SBill Fenner /* 2fc3cc3f5SBill Fenner * Program to test new [sg]etsockopts and ioctls for manipulating IP and 3fc3cc3f5SBill Fenner * Ethernet multicast address filters. 4fc3cc3f5SBill Fenner * 5fc3cc3f5SBill Fenner * Written by Steve Deering, Stanford University, February 1989. 6fc3cc3f5SBill Fenner */ 7fc3cc3f5SBill Fenner 8a89409a2SPhilippe Charnier #include <err.h> 9fc3cc3f5SBill Fenner #include <stdio.h> 10fc3cc3f5SBill Fenner #include <sys/types.h> 11fc3cc3f5SBill Fenner #include <sys/socket.h> 12cf20f871SBill Fenner #include <sys/time.h> 13fc3cc3f5SBill Fenner #include <net/if.h> 144a71a2e7SJulian Elischer #include <net/if_dl.h> 15fc3cc3f5SBill Fenner #include <sys/ioctl.h> 16fc3cc3f5SBill Fenner #include <netinet/in.h> 17fc3cc3f5SBill Fenner 18a89409a2SPhilippe Charnier int 19fc3cc3f5SBill Fenner main( argc, argv ) 20fc3cc3f5SBill Fenner int argc; 21fc3cc3f5SBill Fenner char **argv; 22fc3cc3f5SBill Fenner { 23fc3cc3f5SBill Fenner int so; 24fc3cc3f5SBill Fenner char line[80]; 25fc3cc3f5SBill Fenner char *lineptr; 26fc3cc3f5SBill Fenner struct ip_mreq imr; 27fc3cc3f5SBill Fenner struct ifreq ifr; 28fc3cc3f5SBill Fenner int n, f; 29fc3cc3f5SBill Fenner unsigned i1, i2, i3, i4, g1, g2, g3, g4; 30fc3cc3f5SBill Fenner unsigned e1, e2, e3, e4, e5, e6; 31fc3cc3f5SBill Fenner 32fc3cc3f5SBill Fenner if( (so = socket( AF_INET, SOCK_DGRAM, 0 )) == -1) 33a89409a2SPhilippe Charnier err( 1, "can't open socket" ); 34fc3cc3f5SBill Fenner 35fc3cc3f5SBill Fenner printf( "multicast membership test program; " ); 36fc3cc3f5SBill Fenner printf( "enter ? for list of commands\n" ); 37fc3cc3f5SBill Fenner 38fc3cc3f5SBill Fenner while( fgets( line, 79, stdin ) != NULL ) 39fc3cc3f5SBill Fenner { 40fc3cc3f5SBill Fenner lineptr = line; 41fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 42fc3cc3f5SBill Fenner switch( *lineptr ) 43fc3cc3f5SBill Fenner { 44fc3cc3f5SBill Fenner case '?': 45fc3cc3f5SBill Fenner { 46fc3cc3f5SBill Fenner printf( "%s%s%s%s%s%s%s", 47fc3cc3f5SBill Fenner " j g.g.g.g i.i.i.i - join IP multicast group \n", 48fc3cc3f5SBill Fenner " l g.g.g.g i.i.i.i - leave IP multicast group \n", 49fc3cc3f5SBill Fenner " a ifname e.e.e.e.e.e - add ether multicast address \n", 50fc3cc3f5SBill Fenner " d ifname e.e.e.e.e.e - del ether multicast address \n", 51fc3cc3f5SBill Fenner " m ifname 1/0 - set/clear ether allmulti flag \n", 52fc3cc3f5SBill Fenner " p ifname 1/0 - set/clear ether promisc flag \n", 53fc3cc3f5SBill Fenner " q - quit \n\n" ); 54fc3cc3f5SBill Fenner break; 55fc3cc3f5SBill Fenner } 56fc3cc3f5SBill Fenner 57fc3cc3f5SBill Fenner case 'j': 58fc3cc3f5SBill Fenner { 59fc3cc3f5SBill Fenner ++lineptr; 60fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 61a89409a2SPhilippe Charnier if( (n = sscanf( lineptr, "%u.%u.%u.%u %u.%u.%u.%u", 62fc3cc3f5SBill Fenner &g1, &g2, &g3, &g4, &i1, &i2, &i3, &i4 )) != 8 ) 63fc3cc3f5SBill Fenner { 64fc3cc3f5SBill Fenner printf( "bad args\n" ); 65fc3cc3f5SBill Fenner break; 66fc3cc3f5SBill Fenner } 67fc3cc3f5SBill Fenner imr.imr_multiaddr.s_addr = (g1<<24) | (g2<<16) | (g3<<8) | g4; 68fc3cc3f5SBill Fenner imr.imr_multiaddr.s_addr = htonl(imr.imr_multiaddr.s_addr); 69fc3cc3f5SBill Fenner imr.imr_interface.s_addr = (i1<<24) | (i2<<16) | (i3<<8) | i4; 70fc3cc3f5SBill Fenner imr.imr_interface.s_addr = htonl(imr.imr_interface.s_addr); 71fc3cc3f5SBill Fenner if( setsockopt( so, IPPROTO_IP, IP_ADD_MEMBERSHIP, 72fc3cc3f5SBill Fenner &imr, sizeof(struct ip_mreq) ) == -1 ) 73a89409a2SPhilippe Charnier warn( "can't join group" ); 74fc3cc3f5SBill Fenner else printf( "group joined\n" ); 75fc3cc3f5SBill Fenner break; 76fc3cc3f5SBill Fenner } 77fc3cc3f5SBill Fenner 78fc3cc3f5SBill Fenner case 'l': 79fc3cc3f5SBill Fenner { 80fc3cc3f5SBill Fenner ++lineptr; 81fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 82a89409a2SPhilippe Charnier if( (n = sscanf( lineptr, "%u.%u.%u.%u %u.%u.%u.%u", 83fc3cc3f5SBill Fenner &g1, &g2, &g3, &g4, &i1, &i2, &i3, &i4 )) != 8 ) 84fc3cc3f5SBill Fenner { 85fc3cc3f5SBill Fenner printf( "bad args\n" ); 86fc3cc3f5SBill Fenner break; 87fc3cc3f5SBill Fenner } 88fc3cc3f5SBill Fenner imr.imr_multiaddr.s_addr = (g1<<24) | (g2<<16) | (g3<<8) | g4; 89fc3cc3f5SBill Fenner imr.imr_multiaddr.s_addr = htonl(imr.imr_multiaddr.s_addr); 90fc3cc3f5SBill Fenner imr.imr_interface.s_addr = (i1<<24) | (i2<<16) | (i3<<8) | i4; 91fc3cc3f5SBill Fenner imr.imr_interface.s_addr = htonl(imr.imr_interface.s_addr); 92fc3cc3f5SBill Fenner if( setsockopt( so, IPPROTO_IP, IP_DROP_MEMBERSHIP, 93fc3cc3f5SBill Fenner &imr, sizeof(struct ip_mreq) ) == -1 ) 94a89409a2SPhilippe Charnier warn( "can't leave group" ); 95fc3cc3f5SBill Fenner else printf( "group left\n" ); 96fc3cc3f5SBill Fenner break; 97fc3cc3f5SBill Fenner } 98fc3cc3f5SBill Fenner 99fc3cc3f5SBill Fenner case 'a': 100fc3cc3f5SBill Fenner { 1014a71a2e7SJulian Elischer struct sockaddr_dl *dlp; 1024a71a2e7SJulian Elischer unsigned char *bp; 103fc3cc3f5SBill Fenner ++lineptr; 104fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 105fc3cc3f5SBill Fenner if( (n = sscanf( lineptr, "%s %x.%x.%x.%x.%x.%x", 106fc3cc3f5SBill Fenner ifr.ifr_name, &e1, &e2, &e3, &e4, &e5, &e6 )) != 7 ) 107fc3cc3f5SBill Fenner { 108fc3cc3f5SBill Fenner printf( "bad args\n" ); 109fc3cc3f5SBill Fenner break; 110fc3cc3f5SBill Fenner } 1114a71a2e7SJulian Elischer dlp = (struct sockaddr_dl *)&ifr.ifr_addr; 1124a71a2e7SJulian Elischer dlp->sdl_len = sizeof(struct sockaddr_dl); 1134a71a2e7SJulian Elischer dlp->sdl_family = AF_LINK; 1144a71a2e7SJulian Elischer dlp->sdl_index = 0; 1154a71a2e7SJulian Elischer dlp->sdl_nlen = 0; 1164a71a2e7SJulian Elischer dlp->sdl_alen = 6; 1174a71a2e7SJulian Elischer dlp->sdl_slen = 0; 1184a71a2e7SJulian Elischer bp = LLADDR(dlp); 1194a71a2e7SJulian Elischer bp[0] = e1; 1204a71a2e7SJulian Elischer bp[1] = e2; 1214a71a2e7SJulian Elischer bp[2] = e3; 1224a71a2e7SJulian Elischer bp[3] = e4; 1234a71a2e7SJulian Elischer bp[4] = e5; 1244a71a2e7SJulian Elischer bp[5] = e6; 125fc3cc3f5SBill Fenner if( ioctl( so, SIOCADDMULTI, &ifr ) == -1 ) 126a89409a2SPhilippe Charnier warn( "can't add ether address" ); 127fc3cc3f5SBill Fenner else printf( "ether address added\n" ); 128fc3cc3f5SBill Fenner break; 129fc3cc3f5SBill Fenner } 130fc3cc3f5SBill Fenner 131fc3cc3f5SBill Fenner case 'd': 132fc3cc3f5SBill Fenner { 1334a71a2e7SJulian Elischer struct sockaddr_dl *dlp; 1344a71a2e7SJulian Elischer unsigned char *bp; 135fc3cc3f5SBill Fenner ++lineptr; 136fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 137fc3cc3f5SBill Fenner if( (n = sscanf( lineptr, "%s %x.%x.%x.%x.%x.%x", 138fc3cc3f5SBill Fenner ifr.ifr_name, &e1, &e2, &e3, &e4, &e5, &e6 )) != 7 ) 139fc3cc3f5SBill Fenner { 140fc3cc3f5SBill Fenner printf( "bad args\n" ); 141fc3cc3f5SBill Fenner break; 142fc3cc3f5SBill Fenner } 1434a71a2e7SJulian Elischer dlp = (struct sockaddr_dl *)&ifr.ifr_addr; 1444a71a2e7SJulian Elischer dlp->sdl_len = sizeof(struct sockaddr_dl); 1454a71a2e7SJulian Elischer dlp->sdl_family = AF_LINK; 1464a71a2e7SJulian Elischer dlp->sdl_index = 0; 1474a71a2e7SJulian Elischer dlp->sdl_nlen = 0; 1484a71a2e7SJulian Elischer dlp->sdl_alen = 6; 1494a71a2e7SJulian Elischer dlp->sdl_slen = 0; 1504a71a2e7SJulian Elischer bp = LLADDR(dlp); 1514a71a2e7SJulian Elischer bp[0] = e1; 1524a71a2e7SJulian Elischer bp[1] = e2; 1534a71a2e7SJulian Elischer bp[2] = e3; 1544a71a2e7SJulian Elischer bp[3] = e4; 1554a71a2e7SJulian Elischer bp[4] = e5; 1564a71a2e7SJulian Elischer bp[5] = e6; 157fc3cc3f5SBill Fenner if( ioctl( so, SIOCDELMULTI, &ifr ) == -1 ) 158a89409a2SPhilippe Charnier warn( "can't delete ether address" ); 159fc3cc3f5SBill Fenner else printf( "ether address deleted\n" ); 160fc3cc3f5SBill Fenner break; 161fc3cc3f5SBill Fenner } 162fc3cc3f5SBill Fenner 163fc3cc3f5SBill Fenner case 'm': 164fc3cc3f5SBill Fenner { 165fc3cc3f5SBill Fenner ++lineptr; 166fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 167fc3cc3f5SBill Fenner if( (n = sscanf( lineptr, "%s %u", ifr.ifr_name, &f )) != 2 ) 168fc3cc3f5SBill Fenner { 169fc3cc3f5SBill Fenner printf( "bad args\n" ); 170fc3cc3f5SBill Fenner break; 171fc3cc3f5SBill Fenner } 172fc3cc3f5SBill Fenner if( ioctl( so, SIOCGIFFLAGS, &ifr ) == -1 ) 173fc3cc3f5SBill Fenner { 174a89409a2SPhilippe Charnier warn( "can't get interface flags" ); 175fc3cc3f5SBill Fenner break; 176fc3cc3f5SBill Fenner } 177fc3cc3f5SBill Fenner printf( "interface flags %x, ", ifr.ifr_flags ); 178fc3cc3f5SBill Fenner fflush( stdout ); 179fc3cc3f5SBill Fenner if( f ) ifr.ifr_flags |= IFF_ALLMULTI; 180fc3cc3f5SBill Fenner else ifr.ifr_flags &= ~IFF_ALLMULTI; 181fc3cc3f5SBill Fenner if( ioctl( so, SIOCSIFFLAGS, &ifr ) == -1 ) 182a89409a2SPhilippe Charnier warn( "can't set" ); 183fc3cc3f5SBill Fenner else printf( "changed to %x\n", ifr.ifr_flags ); 184fc3cc3f5SBill Fenner break; 185fc3cc3f5SBill Fenner } 186fc3cc3f5SBill Fenner 187fc3cc3f5SBill Fenner case 'p': 188fc3cc3f5SBill Fenner { 189fc3cc3f5SBill Fenner ++lineptr; 190fc3cc3f5SBill Fenner while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr; 191fc3cc3f5SBill Fenner if( (n = sscanf( lineptr, "%s %u", ifr.ifr_name, &f )) != 2 ) 192fc3cc3f5SBill Fenner { 193fc3cc3f5SBill Fenner printf( "bad args\n" ); 194fc3cc3f5SBill Fenner break; 195fc3cc3f5SBill Fenner } 196fc3cc3f5SBill Fenner if( ioctl( so, SIOCGIFFLAGS, &ifr ) == -1 ) 197fc3cc3f5SBill Fenner { 198a89409a2SPhilippe Charnier warn( "can't get interface flags" ); 199fc3cc3f5SBill Fenner break; 200fc3cc3f5SBill Fenner } 201fc3cc3f5SBill Fenner printf( "interface flags %x, ", ifr.ifr_flags ); 202fc3cc3f5SBill Fenner fflush( stdout ); 203fc3cc3f5SBill Fenner if( f ) ifr.ifr_flags |= IFF_PROMISC; 204fc3cc3f5SBill Fenner else ifr.ifr_flags &= ~IFF_PROMISC; 205fc3cc3f5SBill Fenner if( ioctl( so, SIOCSIFFLAGS, &ifr ) == -1 ) 206a89409a2SPhilippe Charnier warn( "can't set" ); 207fc3cc3f5SBill Fenner else printf( "changed to %x\n", ifr.ifr_flags ); 208fc3cc3f5SBill Fenner break; 209fc3cc3f5SBill Fenner } 210fc3cc3f5SBill Fenner 211fc3cc3f5SBill Fenner case 'q': exit( 0 ); 212fc3cc3f5SBill Fenner 213fc3cc3f5SBill Fenner case 0: 214fc3cc3f5SBill Fenner case '\n': break; 215fc3cc3f5SBill Fenner 216fc3cc3f5SBill Fenner default: 217fc3cc3f5SBill Fenner { 218fc3cc3f5SBill Fenner printf( "bad command\n" ); 219fc3cc3f5SBill Fenner break; 220fc3cc3f5SBill Fenner } 221fc3cc3f5SBill Fenner } 222fc3cc3f5SBill Fenner } 223a89409a2SPhilippe Charnier return(0); 224fc3cc3f5SBill Fenner } 225