diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/tools/mctest/Makefile | 4 | ||||
-rw-r--r-- | tools/tools/mctest/mcgrab.1 | 78 | ||||
-rw-r--r-- | tools/tools/mctest/mcgrab.cc | 189 |
3 files changed, 270 insertions, 1 deletions
diff --git a/tools/tools/mctest/Makefile b/tools/tools/mctest/Makefile index 03bd022..4de93c3 100644 --- a/tools/tools/mctest/Makefile +++ b/tools/tools/mctest/Makefile @@ -3,7 +3,9 @@ # # A Makefile that builds both the mctest program and its manual page. -PROG_CXX= mctest +PROG_CXX= mctest +PROG_CXX= mcgrab + LDADD+= -lpthread .include <bsd.prog.mk> diff --git a/tools/tools/mctest/mcgrab.1 b/tools/tools/mctest/mcgrab.1 new file mode 100644 index 0000000..f2b8b34 --- /dev/null +++ b/tools/tools/mctest/mcgrab.1 @@ -0,0 +1,78 @@ +.\" Copyright (c) 2008 George V. Neville-Neil +.\" All rights reserved. +.\" +.\" 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 +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd July 9, 2008 +.Dt mcgrab 1 +.Os +.Sh NAME +.Nm mcgrab +.Nd "multicast filter overload test" +.Sh SYNOPSIS +.Nm +.Op Fl i Ar interface +.Op Fl g Ar group +.Op Fl n Ar number +.Sh DESCRIPTION +The +.Nm +command implements a multicast test which grabs and holds +N multicast addresses. The purpose of the test is to see what +happens when a network interface is no longer able to filter +multicasts in hardware and has to switch to promiscious or +multicast promiscious mode. A successful test does not have any +result, but an unsuccessful test will have deleterious side effects. +Packet size in bytes. +The options are as follows: +.Bl -tag -width ".Fl d Ar argument" +.It Fl i Ar interface +Network interface, which can be found with ifconfig(1). +.It Fl i Ar group +Multicast group +.It Fl n Ar number +Number of groups to join. +.Sh EXAMPLES +The following is an example of a typical usage +of the +.Nm +command: +.Pp +.Dl "mcgrab -i em0 -g 239.255.255.1 -n 1024" +.Sh SEE ALSO +.Xr mctest 1 , +.Xr ifconfig 8 , +.Xr netstat 1 , +.Xr nanosleep 2 . +.Sh HISTORY +The +.Nm +program first appeared in +.Fx 7.0 . +.Sh AUTHORS +This +manual page was written by +.An George V. Neville-Neil Aq gnn@FreeBSD.org . +.Sh BUGS +Should be reported to the author or to net@freebsd.org. diff --git a/tools/tools/mctest/mcgrab.cc b/tools/tools/mctest/mcgrab.cc new file mode 100644 index 0000000..5522f30 --- /dev/null +++ b/tools/tools/mctest/mcgrab.cc @@ -0,0 +1,189 @@ +// +// Copyright (c) 2008, Neville-Neil Consulting +// All rights reserved. +// +// 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 +// SUCH DAMAGE. +// +// This test simply grabs N multicast addresses starting +// from a base address. The purpose is to make sure that switching a device +// from using a multicast filtering table or function to promiscuous +// multicast listening mode does not cause deleterious side effects. +// + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +// C++ STL and other related includes +#include <stdlib.h> +#include <limits.h> +#include <iostream> +#include <string.h> +#include <string> + +// Operating System and other C based includes +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <net/if.h> +#include <arpa/inet.h> + +// Private include files +#include "mctest.h" + +using namespace std; + +// +// usage - just the program's usage line +// +// +void usage() +{ + cout << "mcgrab -i interface -g multicast group -n number of groups\n"; + exit(-1); +} + +// +// usage - print out the usage with a possible message and exit +// +// \param message optional string +// +// +void usage(string message) +{ + + cerr << message << endl; + usage(); +} + + +// +// grab a set of addresses +// +// @param interface ///< text name of the interface (em0 etc.) +// @param group ///< multicast group +// @param number ///< number of addresses to grab +// +// @return 0 for 0K, -1 for error, sets errno +// +void grab(char *interface, struct in_addr *group, int number) { + + + int sock; + struct ip_mreq mreq; + struct ifreq ifreq; + struct in_addr lgroup; + + if (group == NULL) { + group = &lgroup; + if (inet_pton(AF_INET, DEFAULT_GROUP, group) < 1) + return; + } + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("failed to open datagram socket"); + return; + } + + for (int i = 0; i < number; i++) { + bzero((struct ip_mreq *)&mreq, sizeof(mreq)); + bzero((struct ifreq *)&ifreq, sizeof(ifreq)); + + strncpy(ifreq.ifr_name, interface, IFNAMSIZ); + if (ioctl(sock, SIOCGIFADDR, &ifreq) < 0) { + perror("no such interface"); + return; + } + + memcpy(&mreq.imr_interface, + &((struct sockaddr_in*) &ifreq.ifr_addr)->sin_addr, + sizeof(struct in_addr)); + + mreq.imr_multiaddr.s_addr = group->s_addr; + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, + sizeof(mreq)) < 0) { + + perror("failed to add membership"); + return; + } + + if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, + &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, + sizeof(struct in_addr)) < 0) { + perror("failed to bind interface"); + return; + } + + group->s_addr = htonl(ntohl(group->s_addr) + 1); + } + printf("Press Control-C to exit.\n"); + sleep(INT_MAX); + +} + + +// +// main - the main program +// +// \param -g multicast group address which we will hold +// \param -i interface on which we're holding the address +// +// +int main(int argc, char**argv) +{ + + char ch; ///< character from getopt() + extern char* optarg; ///< option argument + + char* interface = 0; ///< Name of the interface + struct in_addr *group = NULL; ///< the multicast group address + int number = 0; ///< Number of addresses to grab + + if (argc != 7) + usage(); + + while ((ch = getopt(argc, argv, "g:i:n:h")) != -1) { + switch (ch) { + case 'g': + group = new (struct in_addr ); + if (inet_pton(AF_INET, optarg, group) < 1) + usage(argv[0] + string(" Error: invalid multicast group") + + optarg); + break; + case 'i': + interface = optarg; + break; + case 'n': + number = atoi(optarg); + break; + case 'h': + usage(string("Help\n")); + break; + } + } + + grab(interface, group, number); + +} |