MFC:
Merge a slightly cleaner and SSM capable mtest(8).
This commit is contained in:
parent
4054f36633
commit
1f9332241a
@ -2,7 +2,7 @@
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.\" The following requests are required for all man pages.
|
||||
.Dd December 15, 1996
|
||||
.Dd March 8, 2007
|
||||
.Os
|
||||
.Dt MTEST 8
|
||||
.Sh NAME
|
||||
@ -46,13 +46,74 @@ Set or reset ALLMULTI mode on interface
|
||||
.It Ic p Ar ifname Ar 1/0
|
||||
Set or reset promiscuous mode on interface
|
||||
.Ar ifname .
|
||||
.\"
|
||||
.It Ic i Ar g.g.g.g Ar i.i.i.i Ar n Ar x.x.x.x ...
|
||||
Set the socket with group membership of
|
||||
.Ar g.g.g.g
|
||||
on IPv4 address
|
||||
.Ar i.i.i.i
|
||||
to include filter mode, and add
|
||||
.Ar n
|
||||
sources beginning with
|
||||
.Ar x.x.x.x
|
||||
to the inclusion filter list.
|
||||
.\"
|
||||
.It Ic e Ar g.g.g.g Ar i.i.i.i Ar n Ar x.x.x.x ...
|
||||
Set the socket with group membership of
|
||||
.Ar g.g.g.g
|
||||
on IPv4 address
|
||||
.Ar i.i.i.i
|
||||
to exclude filter mode, and add
|
||||
.Ar n
|
||||
sources beginning with
|
||||
.Ar x.x.x.x
|
||||
to the exclusion filter list.
|
||||
.\"
|
||||
.It Ic t Ar g.g.g.g Ar i.i.i.i Ar s.s.s.s
|
||||
Set the socket with group membership of
|
||||
.Ar g.g.g.g
|
||||
on IPv4 address
|
||||
.Ar i.i.i.i
|
||||
to block traffic from source
|
||||
.Ar s.s.s.s .
|
||||
.\"
|
||||
.It Ic b Ar g.g.g.g Ar i.i.i.i Ar s.s.s.s
|
||||
Set the socket with group membership of
|
||||
.Ar g.g.g.g
|
||||
on IPv4 address
|
||||
.Ar i.i.i.i
|
||||
to allow traffic from source
|
||||
.Ar s.s.s.s .
|
||||
.\"
|
||||
.It Ic g Ar g.g.g.g Ar i.i.i.i Ar n
|
||||
Print
|
||||
.Ar n
|
||||
source filter entries for group
|
||||
.An g.g.g.g
|
||||
on IPv4 address
|
||||
.An i.i.i.i .
|
||||
.\"
|
||||
.It Ic f Ar filename
|
||||
Read commands from the file
|
||||
.Ar filename .
|
||||
.It Ic s Ar n
|
||||
Sleep for
|
||||
.Ar n
|
||||
seconds.
|
||||
.It Ic ?\&
|
||||
List legal commands.
|
||||
.It Ic q
|
||||
Quit the program.
|
||||
.El
|
||||
.\" .Sh SEE ALSO
|
||||
.Sh SEE ALSO
|
||||
.Rs
|
||||
.%A D. Thaler
|
||||
.%A B. Fenner
|
||||
.%A B. Quinn
|
||||
.%T "Socket Interface Extensions for Multicast Filters"
|
||||
.%O RFC 3678
|
||||
.Re
|
||||
.Sh AUTHORS
|
||||
.An Steve Deering
|
||||
.Sh BUGS
|
||||
The command parser is not very flexible.
|
||||
.An -split
|
||||
.An "Steve Deering"
|
||||
.An "Wilbert De Graaf"
|
||||
|
@ -1,228 +1,411 @@
|
||||
/*
|
||||
* Program to test new [sg]etsockopts and ioctls for manipulating IP and
|
||||
* Ethernet multicast address filters.
|
||||
/*-
|
||||
* Copyright (c) 2007 Bruce M. Simpson.
|
||||
* Copyright (c) 2000 Wilbert De Graaf.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Steve Deering, Stanford University, February 1989.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Diagnostic and test utility for IPv4 multicast sockets.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void process_file(char *, int);
|
||||
static void process_cmd(char*, int, FILE *fp);
|
||||
static void usage(void);
|
||||
#ifdef WITH_IGMPV3
|
||||
static int inaddr_cmp(const void *a, const void *b);
|
||||
#endif
|
||||
|
||||
#define MAX_ADDRS 20
|
||||
#define STR_SIZE 20
|
||||
#define LINE_LENGTH 80
|
||||
|
||||
int
|
||||
main( argc, argv )
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int so;
|
||||
char line[80];
|
||||
char *lineptr;
|
||||
struct ip_mreq imr;
|
||||
struct ifreq ifr;
|
||||
int n, f;
|
||||
unsigned i1, i2, i3, i4, g1, g2, g3, g4;
|
||||
unsigned e1, e2, e3, e4, e5, e6;
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char line[LINE_LENGTH];
|
||||
char *p;
|
||||
int i, s;
|
||||
|
||||
if( (so = socket( AF_INET, SOCK_DGRAM, 0 )) == -1)
|
||||
err( 1, "can't open socket" );
|
||||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (s == -1)
|
||||
err(1, "can't open socket");
|
||||
|
||||
printf( "multicast membership test program; " );
|
||||
printf( "enter ? for list of commands\n" );
|
||||
if (argc < 2) {
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
printf("multicast membership test program; "
|
||||
"enter ? for list of commands\n");
|
||||
}
|
||||
do {
|
||||
if (fgets(line, sizeof(line), stdin) != NULL) {
|
||||
if (line[0] != 'f')
|
||||
process_cmd(line, s, stdin);
|
||||
else {
|
||||
/* Get the filename */
|
||||
for (i = 1; isblank(line[i]); i++);
|
||||
if ((p = (char*)strchr(line, '\n'))
|
||||
!= NULL)
|
||||
*p = '\0';
|
||||
process_file(&line[i], s);
|
||||
}
|
||||
}
|
||||
} while (!feof(stdin));
|
||||
} else {
|
||||
for (i = 1; i < argc; i++) {
|
||||
process_file(argv[i], s);
|
||||
}
|
||||
}
|
||||
|
||||
while( fgets( line, 79, stdin ) != NULL )
|
||||
{
|
||||
lineptr = line;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
switch( *lineptr )
|
||||
{
|
||||
case '?':
|
||||
{
|
||||
printf( "%s%s%s%s%s%s%s",
|
||||
" j g.g.g.g i.i.i.i - join IP multicast group \n",
|
||||
" l g.g.g.g i.i.i.i - leave IP multicast group \n",
|
||||
" a ifname e.e.e.e.e.e - add ether multicast address \n",
|
||||
" d ifname e.e.e.e.e.e - del ether multicast address \n",
|
||||
" m ifname 1/0 - set/clear ether allmulti flag \n",
|
||||
" p ifname 1/0 - set/clear ether promisc flag \n",
|
||||
" q - quit \n\n" );
|
||||
exit (0);
|
||||
}
|
||||
|
||||
static void
|
||||
process_file(char *fname, int s)
|
||||
{
|
||||
char line[80];
|
||||
FILE *fp;
|
||||
char *lineptr;
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
if (fp == NULL) {
|
||||
warn("fopen");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip comments and empty lines. */
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
lineptr = line;
|
||||
while (isblank(*lineptr))
|
||||
lineptr++;
|
||||
if (*lineptr != '#' && *lineptr != '\n')
|
||||
process_cmd(lineptr, s, fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void
|
||||
process_cmd(char *cmd, int s, FILE *fp __unused)
|
||||
{
|
||||
char str1[STR_SIZE];
|
||||
char str2[STR_SIZE];
|
||||
#ifdef WITH_IGMPV3
|
||||
char str3[STR_SIZE];
|
||||
char filtbuf[IP_MSFILTER_SIZE(MAX_ADDRS)];
|
||||
#endif
|
||||
struct ifreq ifr;
|
||||
struct ip_mreq imr;
|
||||
#ifdef WITH_IGMPV3
|
||||
struct ip_mreq_source imrs;
|
||||
struct ip_msfilter *imsfp;
|
||||
#endif
|
||||
char *line;
|
||||
int n, opt, f, flags;
|
||||
|
||||
line = cmd;
|
||||
while (isblank(*++line))
|
||||
; /* Skip whitespace. */
|
||||
|
||||
switch (*cmd) {
|
||||
case '?':
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'j':
|
||||
{
|
||||
++lineptr;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
if( (n = sscanf( lineptr, "%u.%u.%u.%u %u.%u.%u.%u",
|
||||
&g1, &g2, &g3, &g4, &i1, &i2, &i3, &i4 )) != 8 )
|
||||
{
|
||||
printf( "bad args\n" );
|
||||
break;
|
||||
}
|
||||
imr.imr_multiaddr.s_addr = (g1<<24) | (g2<<16) | (g3<<8) | g4;
|
||||
imr.imr_multiaddr.s_addr = htonl(imr.imr_multiaddr.s_addr);
|
||||
imr.imr_interface.s_addr = (i1<<24) | (i2<<16) | (i3<<8) | i4;
|
||||
imr.imr_interface.s_addr = htonl(imr.imr_interface.s_addr);
|
||||
if( setsockopt( so, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&imr, sizeof(struct ip_mreq) ) == -1 )
|
||||
warn( "can't join group" );
|
||||
else printf( "group joined\n" );
|
||||
case 'q':
|
||||
close(s);
|
||||
exit(0);
|
||||
|
||||
case 's':
|
||||
if ((sscanf(line, "%d", &n) != 1) || (n < 1)) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
sleep(n);
|
||||
printf("ok\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
++lineptr;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
if( (n = sscanf( lineptr, "%u.%u.%u.%u %u.%u.%u.%u",
|
||||
&g1, &g2, &g3, &g4, &i1, &i2, &i3, &i4 )) != 8 )
|
||||
{
|
||||
printf( "bad args\n" );
|
||||
break;
|
||||
}
|
||||
imr.imr_multiaddr.s_addr = (g1<<24) | (g2<<16) | (g3<<8) | g4;
|
||||
imr.imr_multiaddr.s_addr = htonl(imr.imr_multiaddr.s_addr);
|
||||
imr.imr_interface.s_addr = (i1<<24) | (i2<<16) | (i3<<8) | i4;
|
||||
imr.imr_interface.s_addr = htonl(imr.imr_interface.s_addr);
|
||||
if( setsockopt( so, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
||||
&imr, sizeof(struct ip_mreq) ) == -1 )
|
||||
warn( "can't leave group" );
|
||||
else printf( "group left\n" );
|
||||
case 'j':
|
||||
case 'l':
|
||||
sscanf(line, "%s %s", str1, str2);
|
||||
if (((imr.imr_multiaddr.s_addr = inet_addr(str1)) ==
|
||||
INADDR_NONE) ||
|
||||
((imr.imr_interface.s_addr = inet_addr(str2)) ==
|
||||
INADDR_NONE)) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
opt = (*cmd == 'j') ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
|
||||
if (setsockopt( s, IPPROTO_IP, opt, &imr,
|
||||
sizeof(imr)) != 0)
|
||||
warn("setsockopt IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP");
|
||||
else
|
||||
printf("ok\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a':
|
||||
{
|
||||
struct sockaddr_dl *dlp;
|
||||
unsigned char *bp;
|
||||
++lineptr;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
if( (n = sscanf( lineptr, "%s %x.%x.%x.%x.%x.%x",
|
||||
ifr.ifr_name, &e1, &e2, &e3, &e4, &e5, &e6 )) != 7 )
|
||||
{
|
||||
printf( "bad args\n" );
|
||||
break;
|
||||
}
|
||||
case 'a':
|
||||
case 'd': {
|
||||
struct sockaddr_dl *dlp;
|
||||
struct ether_addr *ep;
|
||||
|
||||
memset(&ifr, 0, sizeof(struct ifreq));
|
||||
dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
|
||||
dlp->sdl_len = sizeof(struct sockaddr_dl);
|
||||
dlp->sdl_family = AF_LINK;
|
||||
dlp->sdl_index = 0;
|
||||
dlp->sdl_nlen = 0;
|
||||
dlp->sdl_alen = 6;
|
||||
dlp->sdl_alen = ETHER_ADDR_LEN;
|
||||
dlp->sdl_slen = 0;
|
||||
bp = LLADDR(dlp);
|
||||
bp[0] = e1;
|
||||
bp[1] = e2;
|
||||
bp[2] = e3;
|
||||
bp[3] = e4;
|
||||
bp[4] = e5;
|
||||
bp[5] = e6;
|
||||
if( ioctl( so, SIOCADDMULTI, &ifr ) == -1 )
|
||||
warn( "can't add ether address" );
|
||||
else printf( "ether address added\n" );
|
||||
if (sscanf(line, "%s %s", str1, str2) != 2) {
|
||||
warnc(EINVAL, "sscanf");
|
||||
break;
|
||||
}
|
||||
ep = ether_aton(str2);
|
||||
if (ep == NULL) {
|
||||
warnc(EINVAL, "ether_aton");
|
||||
break;
|
||||
}
|
||||
strlcpy(ifr.ifr_name, str1, IF_NAMESIZE);
|
||||
memcpy(LLADDR(dlp), ep, ETHER_ADDR_LEN);
|
||||
if (ioctl(s, (*cmd == 'a') ? SIOCADDMULTI : SIOCDELMULTI,
|
||||
&ifr) == -1)
|
||||
warn("ioctl SIOCADDMULTI/SIOCDELMULTI");
|
||||
else
|
||||
printf("ok\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case 'd':
|
||||
{
|
||||
struct sockaddr_dl *dlp;
|
||||
unsigned char *bp;
|
||||
++lineptr;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
if( (n = sscanf( lineptr, "%s %x.%x.%x.%x.%x.%x",
|
||||
ifr.ifr_name, &e1, &e2, &e3, &e4, &e5, &e6 )) != 7 )
|
||||
{
|
||||
printf( "bad args\n" );
|
||||
break;
|
||||
}
|
||||
dlp = (struct sockaddr_dl *)&ifr.ifr_addr;
|
||||
dlp->sdl_len = sizeof(struct sockaddr_dl);
|
||||
dlp->sdl_family = AF_LINK;
|
||||
dlp->sdl_index = 0;
|
||||
dlp->sdl_nlen = 0;
|
||||
dlp->sdl_alen = 6;
|
||||
dlp->sdl_slen = 0;
|
||||
bp = LLADDR(dlp);
|
||||
bp[0] = e1;
|
||||
bp[1] = e2;
|
||||
bp[2] = e3;
|
||||
bp[3] = e4;
|
||||
bp[4] = e5;
|
||||
bp[5] = e6;
|
||||
if( ioctl( so, SIOCDELMULTI, &ifr ) == -1 )
|
||||
warn( "can't delete ether address" );
|
||||
else printf( "ether address deleted\n" );
|
||||
case 'm':
|
||||
printf("warning: IFF_ALLMULTI cannot be set from userland "
|
||||
"in FreeBSD; command ignored.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm':
|
||||
{
|
||||
++lineptr;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
if( (n = sscanf( lineptr, "%s %u", ifr.ifr_name, &f )) != 2 )
|
||||
{
|
||||
printf( "bad args\n" );
|
||||
break;
|
||||
}
|
||||
if( ioctl( so, SIOCGIFFLAGS, &ifr ) == -1 )
|
||||
{
|
||||
warn( "can't get interface flags" );
|
||||
break;
|
||||
}
|
||||
printf( "interface flags %x, ", ifr.ifr_flags );
|
||||
fflush( stdout );
|
||||
if( f ) ifr.ifr_flags |= IFF_ALLMULTI;
|
||||
else ifr.ifr_flags &= ~IFF_ALLMULTI;
|
||||
if( ioctl( so, SIOCSIFFLAGS, &ifr ) == -1 )
|
||||
warn( "can't set" );
|
||||
else printf( "changed to %x\n", ifr.ifr_flags );
|
||||
case 'p':
|
||||
if (sscanf(line, "%s %u", ifr.ifr_name, &f) != 2) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
|
||||
warn("ioctl SIOCGIFFLAGS");
|
||||
break;
|
||||
}
|
||||
flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
|
||||
opt = IFF_PPROMISC;
|
||||
if (f == 0) {
|
||||
flags &= ~opt;
|
||||
} else {
|
||||
flags |= opt;
|
||||
}
|
||||
ifr.ifr_flags = flags & 0xffff;
|
||||
ifr.ifr_flagshigh = flags >> 16;
|
||||
if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1)
|
||||
warn("ioctl SIOCGIFFLAGS");
|
||||
else
|
||||
printf( "changed to 0x%08x\n", flags );
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
{
|
||||
++lineptr;
|
||||
while( *lineptr == ' ' || *lineptr == '\t' ) ++lineptr;
|
||||
if( (n = sscanf( lineptr, "%s %u", ifr.ifr_name, &f )) != 2 )
|
||||
{
|
||||
printf( "bad args\n" );
|
||||
break;
|
||||
}
|
||||
if( ioctl( so, SIOCGIFFLAGS, &ifr ) == -1 )
|
||||
{
|
||||
warn( "can't get interface flags" );
|
||||
break;
|
||||
}
|
||||
printf( "interface flags %x, ", ifr.ifr_flags );
|
||||
fflush( stdout );
|
||||
if( f ) ifr.ifr_flags |= IFF_PROMISC;
|
||||
else ifr.ifr_flags &= ~IFF_PROMISC;
|
||||
if( ioctl( so, SIOCSIFFLAGS, &ifr ) == -1 )
|
||||
warn( "can't set" );
|
||||
else printf( "changed to %x\n", ifr.ifr_flags );
|
||||
#ifdef WITH_IGMPV3
|
||||
/*
|
||||
* Set the socket to include or exclude filter mode, and
|
||||
* add some sources to the filterlist, using the full-state,
|
||||
* or advanced api.
|
||||
*/
|
||||
case 'i':
|
||||
case 'e':
|
||||
if ((sscanf(line, "%s %s %d", str1, str2, &n)) != 3) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
imsfp = (struct ip_msfilter *)filtbuf;
|
||||
if (((imsfp->imsf_multiaddr.s_addr = inet_addr(str1)) ==
|
||||
INADDR_NONE) ||
|
||||
((imsfp->imsf_interface.s_addr = inet_addr(str2)) ==
|
||||
INADDR_NONE) || (n > MAX_ADDRS)) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
imsfp->imsf_fmode = (*cmd == 'i') ? MCAST_INCLUDE :
|
||||
MCAST_EXCLUDE;
|
||||
imsfp->imsf_numsrc = n;
|
||||
for (i = 0; i < n; i++) {
|
||||
fgets(str1, sizeof(str1), fp);
|
||||
if ((imsfp->imsf_slist[i].s_addr = inet_addr(str1)) ==
|
||||
INADDR_NONE) {
|
||||
printf("-1\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ioctl(s, SIOCSIPMSFILTER, imsfp) != 0)
|
||||
warn("setsockopt SIOCSIPMSFILTER");
|
||||
else
|
||||
printf("ok\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case 'q': exit( 0 );
|
||||
/*
|
||||
* Allow or block traffic from a source, using the
|
||||
* delta based api.
|
||||
*/
|
||||
case 't':
|
||||
case 'b':
|
||||
sscanf(line, "%s %s %s", str1, str2, str3);
|
||||
if (((imrs.imr_multiaddr.s_addr = inet_addr(str1)) ==
|
||||
INADDR_NONE) ||
|
||||
((imrs.imr_interface.s_addr = inet_addr(str2)) ==
|
||||
INADDR_NONE) ||
|
||||
((imrs.imr_sourceaddr.s_addr = inet_addr(str3)) ==
|
||||
INADDR_NONE)) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
case '\n': break;
|
||||
|
||||
default:
|
||||
{
|
||||
printf( "bad command\n" );
|
||||
/* First determine out current filter mode. */
|
||||
imsfp = (struct ip_msfilter *)filtbuf;
|
||||
imsfp->imsf_multiaddr.s_addr = imrs.imr_multiaddr.s_addr;
|
||||
imsfp->imsf_interface.s_addr = imrs.imr_interface.s_addr;
|
||||
imsfp->imsf_numsrc = 5;
|
||||
if (ioctl(s, SIOCSIPMSFILTER, imsfp) != 0) {
|
||||
/* It's only okay for 't' to fail */
|
||||
if (*cmd != 't') {
|
||||
warn("ioctl SIOCSIPMSFILTER");
|
||||
break;
|
||||
} else {
|
||||
imsfp->imsf_fmode = MCAST_INCLUDE;
|
||||
}
|
||||
}
|
||||
if (imsfp->imsf_fmode == MCAST_EXCLUDE) {
|
||||
/* Any source */
|
||||
opt = (*cmd == 't') ? IP_UNBLOCK_SOURCE :
|
||||
IP_BLOCK_SOURCE;
|
||||
} else {
|
||||
/* Controlled source */
|
||||
opt = (*cmd == 't') ? IP_ADD_SOURCE_MEMBERSHIP :
|
||||
IP_DROP_SOURCE_MEMBERSHIP;
|
||||
}
|
||||
if (setsockopt(s, IPPROTO_IP, opt, &imrs, sizeof(imrs)) == -1)
|
||||
warn("ioctl IP_ADD_SOURCE_MEMBERSHIP/IP_DROP_SOURCE_MEMBERSHIP/IP_UNBLOCK_SOURCE/IP_BLOCK_SOURCE");
|
||||
else
|
||||
printf("ok\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
case 'g':
|
||||
if ((sscanf(line, "%s %s %d", str1, str2, &n)) != 3) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
imsfp = (struct ip_msfilter *)filtbuf;
|
||||
if (((imsfp->imsf_multiaddr.s_addr = inet_addr(str1)) ==
|
||||
INADDR_NONE) ||
|
||||
((imsfp->imsf_interface.s_addr = inet_addr(str2)) ==
|
||||
INADDR_NONE) || (n < 0 || n > MAX_ADDRS)) {
|
||||
printf("-1\n");
|
||||
break;
|
||||
}
|
||||
imsfp->imsf_numsrc = n;
|
||||
if (ioctl(s, SIOCSIPMSFILTER, imsfp) != 0) {
|
||||
warn("setsockopt SIOCSIPMSFILTER");
|
||||
break;
|
||||
}
|
||||
printf("%s\n", (imsfp->imsf_fmode == MCAST_INCLUDE) ?
|
||||
"include" : "exclude");
|
||||
printf("%d\n", imsfp->imsf_numsrc);
|
||||
if (n >= imsfp->imsf_numsrc) {
|
||||
n = imsfp->imsf_numsrc;
|
||||
qsort(imsfp->imsf_slist, n, sizeof(struct in_addr),
|
||||
&inaddr_cmp);
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%s\n", inet_ntoa(imsfp->imsf_slist[i]));
|
||||
}
|
||||
break;
|
||||
#else /* !WITH_IGMPV3 */
|
||||
case 'i':
|
||||
case 'e':
|
||||
case 't':
|
||||
case 'b':
|
||||
case 'g':
|
||||
printf("warning: IGMPv3 is not supported by this version "
|
||||
"of FreeBSD; command ignored.\n");
|
||||
break;
|
||||
#endif /* WITH_IGMPV3 */
|
||||
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
printf("invalid command\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
printf("j g.g.g.g i.i.i.i - join IP multicast group\n");
|
||||
printf("l g.g.g.g i.i.i.i - leave IP multicast group\n");
|
||||
printf("a ifname e.e.e.e.e.e - add ether multicast address\n");
|
||||
printf("d ifname e.e.e.e.e.e - delete ether multicast address\n");
|
||||
printf("m ifname 1/0 - set/clear ether allmulti flag\n");
|
||||
printf("p ifname 1/0 - set/clear ether promisc flag\n");
|
||||
#ifdef WITH_IGMPV3
|
||||
printf("i g.g.g.g i.i.i.i n - set n include mode src filter\n");
|
||||
printf("e g.g.g.g i.i.i.i n - set n exclude mode src filter\n");
|
||||
printf("t g.g.g.g i.i.i.i s.s.s.s - allow traffic from src\n");
|
||||
printf("b g.g.g.g i.i.i.i s.s.s.s - block traffic from src\n");
|
||||
printf("g g.g.g.g i.i.i.i n - get and show n src filters\n");
|
||||
#endif
|
||||
printf("f filename - read command(s) from file\n");
|
||||
printf("s seconds - sleep for some time\n");
|
||||
printf("q - quit\n");
|
||||
}
|
||||
|
||||
#ifdef WITH_IGMPV3
|
||||
static int
|
||||
inaddr_cmp(const void *a, const void *b)
|
||||
{
|
||||
return((int)((const struct in_addr *)a)->s_addr -
|
||||
((const struct in_addr *)b)->s_addr);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user