2 // Copyright (c) 2008, Neville-Neil Consulting
3 // All rights reserved.
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
8 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
14 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 // This test simply grabs N multicast addresses starting
27 // from a base address. The purpose is to make sure that switching a device
28 // from using a multicast filtering table or function to promiscuous
29 // multicast listening mode does not cause deleterious side effects.
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 // C++ STL and other related includes
42 // Operating System and other C based includes
45 #include <sys/types.h>
47 #include <sys/socket.h>
48 #include <sys/ioctl.h>
49 #include <netinet/in.h>
51 #include <arpa/inet.h>
53 // Private include files
59 // usage - just the program's usage line
64 cout << "mcgrab -i interface -g multicast group -n number of groups\n";
69 // usage - print out the usage with a possible message and exit
71 // \param message optional string
74 void usage(string message)
77 cerr << message << endl;
83 // grab a set of addresses
85 // @param interface ///< text name of the interface (em0 etc.)
86 // @param group ///< multicast group
87 // @param number ///< number of addresses to grab
89 // @return 0 for 0K, -1 for error, sets errno
91 void grab(char *interface, struct in_addr *group, int number) {
97 struct in_addr lgroup;
101 if (inet_pton(AF_INET, DEFAULT_GROUP, group) < 1)
105 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
106 perror("failed to open datagram socket");
110 for (int i = 0; i < number; i++) {
111 bzero((struct ip_mreq *)&mreq, sizeof(mreq));
112 bzero((struct ifreq *)&ifreq, sizeof(ifreq));
114 strncpy(ifreq.ifr_name, interface, IFNAMSIZ);
115 if (ioctl(sock, SIOCGIFADDR, &ifreq) < 0) {
116 perror("no such interface");
120 memcpy(&mreq.imr_interface,
121 &((struct sockaddr_in*) &ifreq.ifr_addr)->sin_addr,
122 sizeof(struct in_addr));
124 mreq.imr_multiaddr.s_addr = group->s_addr;
125 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
128 perror("failed to add membership");
132 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
133 &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr,
134 sizeof(struct in_addr)) < 0) {
135 perror("failed to bind interface");
139 group->s_addr = htonl(ntohl(group->s_addr) + 1);
141 printf("Press Control-C to exit.\n");
148 // main - the main program
150 // \param -g multicast group address which we will hold
151 // \param -i interface on which we're holding the address
154 int main(int argc, char**argv)
157 char ch; ///< character from getopt()
158 extern char* optarg; ///< option argument
160 char* interface = 0; ///< Name of the interface
161 struct in_addr *group = NULL; ///< the multicast group address
162 int number = 0; ///< Number of addresses to grab
167 while ((ch = getopt(argc, argv, "g:i:n:h")) != -1) {
170 group = new (struct in_addr );
171 if (inet_pton(AF_INET, optarg, group) < 1)
172 usage(argv[0] + string(" Error: invalid multicast group") +
179 number = atoi(optarg);
182 usage(string("Help\n"));
187 grab(interface, group, number);