diff options
author | Everton Marques <everton.marques@gmail.com> | 2009-09-30 17:10:11 -0300 |
---|---|---|
committer | David Lamparter <equinox@opensourcerouting.org> | 2015-02-04 06:07:51 +0100 |
commit | 40765fe45f39767ad545ca693fb5985fa90ce4ca (patch) | |
tree | 8a21efb5483af7531c396e1cd26c8983d4170e34 | |
parent | 465185300b26042e1813d53f179616a17154d37a (diff) | |
download | quagga-40765fe45f39767ad545ca693fb5985fa90ce4ca.tar.bz2 quagga-40765fe45f39767ad545ca693fb5985fa90ce4ca.tar.xz |
[pim] Command line tool to test IGMPv3 join.
-rw-r--r-- | pimd/Makefile.am | 10 | ||||
-rw-r--r-- | pimd/pim_igmp_join.c | 61 | ||||
-rw-r--r-- | pimd/pim_igmp_join.h | 32 | ||||
-rw-r--r-- | pimd/pim_sock.c | 30 | ||||
-rw-r--r-- | pimd/pim_sock.h | 2 | ||||
-rw-r--r-- | pimd/test_igmpv3_join.c | 149 |
6 files changed, 254 insertions, 30 deletions
diff --git a/pimd/Makefile.am b/pimd/Makefile.am index 80df2e6b..c722b7ec 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -44,6 +44,7 @@ INSTALL_SDATA=@INSTALL@ -m 600 LIBS = @LIBS@ noinst_LIBRARIES = libpim.a sbin_PROGRAMS = pimd +bin_PROGRAMS = test_igmpv3_join libpim_a_SOURCES = \ pimd.c pim_version.c pim_cmd.c pim_signals.c pim_iface.c \ @@ -51,7 +52,8 @@ libpim_a_SOURCES = \ pim_igmpv3.c pim_str.c pim_mroute.c pim_util.c pim_time.c \ pim_oil.c pim_zlookup.c pim_pim.c pim_tlv.c pim_neighbor.c \ pim_hello.c pim_ifchannel.c pim_join.c pim_assert.c \ - pim_msg.c pim_upstream.c pim_rpf.c pim_rand.c pim_macro.c + pim_msg.c pim_upstream.c pim_rpf.c pim_rand.c pim_macro.c \ + pim_igmp_join.c noinst_HEADERS = \ pimd.h pim_version.h pim_cmd.h pim_signals.h pim_iface.h \ @@ -59,11 +61,15 @@ noinst_HEADERS = \ pim_igmpv3.h pim_str.h pim_mroute.h pim_util.h pim_time.h \ pim_oil.h pim_zlookup.h pim_pim.h pim_tlv.h pim_neighbor.h \ pim_hello.h pim_ifchannel.h pim_join.h pim_assert.h \ - pim_msg.h pim_upstream.h pim_rpf.h pim_rand.h pim_macro.h + pim_msg.h pim_upstream.h pim_rpf.h pim_rand.h pim_macro.h \ + pim_igmp_join.h pimd_SOURCES = \ pim_main.c $(libpim_a_SOURCES) +test_igmpv3_join_SOURCES = \ + test_igmpv3_join.c pim_igmp_join.c + pimd_LDADD = ../lib/libzebra.la @LIBCAP@ examplesdir = $(exampledir) diff --git a/pimd/pim_igmp_join.c b/pimd/pim_igmp_join.c new file mode 100644 index 00000000..7183997c --- /dev/null +++ b/pimd/pim_igmp_join.c @@ -0,0 +1,61 @@ +/* + PIM for Quagga + Copyright (C) 2008 Everton da Silva Marques + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING; if not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA + + $QuaggaId: $Format:%an, %ai, %h$ $ +*/ + +#include <string.h> + +#include "pim_igmp_join.h" + +#ifndef MCAST_JOIN_SOURCE_GROUP +#define MCAST_JOIN_SOURCE_GROUP 46 +struct group_source_req +{ + uint32_t gsr_interface; + struct sockaddr_storage gsr_group; + struct sockaddr_storage gsr_source; +}; +#endif + +int pim_igmp_join_source(int fd, int ifindex, + struct in_addr group_addr, + struct in_addr source_addr) +{ + struct group_source_req req; + struct sockaddr_in *group_sa = (struct sockaddr_in *) &req.gsr_group; + struct sockaddr_in *source_sa = (struct sockaddr_in *) &req.gsr_source; + + memset(group_sa, 0, sizeof(*group_sa)); + group_sa->sin_family = AF_INET; + group_sa->sin_addr = group_addr; + group_sa->sin_port = htons(0); + + memset(source_sa, 0, sizeof(*source_sa)); + source_sa->sin_family = AF_INET; + source_sa->sin_addr = source_addr; + source_sa->sin_port = htons(0); + + req.gsr_interface = ifindex; + + return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, + &req, sizeof(req)); + + return 0; +} diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h new file mode 100644 index 00000000..1127af12 --- /dev/null +++ b/pimd/pim_igmp_join.h @@ -0,0 +1,32 @@ +/* + PIM for Quagga + Copyright (C) 2008 Everton da Silva Marques + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING; if not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA + + $QuaggaId: $Format:%an, %ai, %h$ $ +*/ + +#ifndef PIM_IGMP_JOIN_H +#define PIM_IGMP_JOIN_H + +#include <netinet/in.h> + +int pim_igmp_join_source(int fd, int ifindex, + struct in_addr group_addr, + struct in_addr source_addr); + +#endif /* PIM_IGMP_JOIN_H */ diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 00fc8eda..c908e8b8 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -38,20 +38,11 @@ #include "pimd.h" #include "pim_sock.h" #include "pim_str.h" +#include "pim_igmp_join.h" /* GLOBAL VARS */ extern struct zebra_privs_t pimd_privs; -#ifndef MCAST_JOIN_SOURCE_GROUP -#define MCAST_JOIN_SOURCE_GROUP 46 -struct group_source_req -{ - uint32_t gsr_interface; - struct sockaddr_storage gsr_group; - struct sockaddr_storage gsr_source; -}; -#endif - int pim_socket_raw(int protocol) { int fd; @@ -242,24 +233,7 @@ int pim_socket_join_source(int fd, int ifindex, struct in_addr source_addr, const char *ifname) { - struct group_source_req req; - struct sockaddr_in *group_sa = (struct sockaddr_in *) &req.gsr_group; - struct sockaddr_in *source_sa = (struct sockaddr_in *) &req.gsr_source; - - memset(group_sa, 0, sizeof(*group_sa)); - group_sa->sin_family = AF_INET; - group_sa->sin_addr = group_addr; - group_sa->sin_port = htons(0); - - memset(source_sa, 0, sizeof(*source_sa)); - source_sa->sin_family = AF_INET; - source_sa->sin_addr = source_addr; - source_sa->sin_port = htons(0); - - req.gsr_interface = ifindex; - - if (setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, - &req, sizeof(req))) { + if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) { int e = errno; char group_str[100]; char source_str[100]; diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index e9d5476f..d3557809 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -23,6 +23,8 @@ #ifndef PIM_SOCK_H #define PIM_SOCK_H +#include <netinet/in.h> + #define PIM_SOCK_ERR_NONE (0) /* No error */ #define PIM_SOCK_ERR_SOCKET (-1) /* socket() */ #define PIM_SOCK_ERR_RA (-2) /* Router Alert option */ diff --git a/pimd/test_igmpv3_join.c b/pimd/test_igmpv3_join.c new file mode 100644 index 00000000..af93ab60 --- /dev/null +++ b/pimd/test_igmpv3_join.c @@ -0,0 +1,149 @@ +/* + PIM for Quagga + Copyright (C) 2008 Everton da Silva Marques + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING; if not, write to the + Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + MA 02110-1301 USA + + $QuaggaId: $Format:%an, %ai, %h$ $ +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <net/if.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> + +#include "pim_igmp_join.h" + +const char *prog_name = 0; + +static int iface_solve_index(const char *ifname) +{ + struct if_nameindex *ini; + int ifindex = -1; + int i; + + if (!ifname) + return -1; + + ini = if_nameindex(); + if (!ini) { + int err = errno; + fprintf(stderr, + "%s: interface=%s: failure solving index: errno=%d: %s\n", + prog_name, ifname, err, strerror(err)); + errno = err; + return -1; + } + + for (i = 0; ini[i].if_index; ++i) { +#if 0 + fprintf(stderr, + "%s: interface=%s matching against local ifname=%s ifindex=%d\n", + prog_name, ifname, ini[i].if_name, ini[i].if_index); +#endif + if (!strcmp(ini[i].if_name, ifname)) { + ifindex = ini[i].if_index; + break; + } + } + + if_freenameindex(ini); + + return ifindex; +} + +int main(int argc, const char *argv[]) +{ + struct in_addr group_addr; + struct in_addr source_addr; + const char *ifname; + const char *group; + const char *source; + int ifindex; + int result; + int fd; + + prog_name = argv[0]; + + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + fprintf(stderr, + "%s: could not create socket: socket(): errno=%d: %s\n", + prog_name, errno, strerror(errno)); + exit(1); + } + + if (argc != 4) { + fprintf(stderr, + "usage: %s interface group source\n" + "example: %s eth0 232.1.1.1 1.1.1.1\n", + prog_name, prog_name); + exit(1); + } + + ifname = argv[1]; + group = argv[2]; + source = argv[3]; + + ifindex = iface_solve_index(ifname); + if (ifindex < 0) { + fprintf(stderr, "%s: could not find interface: %s\n", + prog_name, ifname); + exit(1); + } + + result = inet_pton(AF_INET, group, &group_addr); + if (result <= 0) { + fprintf(stderr, "%s: bad group address: %s\n", + prog_name, group); + exit(1); + } + + result = inet_pton(AF_INET, source, &source_addr); + if (result <= 0) { + fprintf(stderr, "%s: bad source address: %s\n", + prog_name, source); + exit(1); + } + + result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr); + if (result) { + fprintf(stderr, + "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n", + prog_name, fd, group, source, ifindex, ifname, + errno, strerror(errno)); + exit(1); + } + + printf("%s: joined channel (S,G)=(%s,%s) on interface %s\n", + prog_name, source, group, ifname); + + printf("%s: waiting...\n", prog_name); + + getchar(); + + close(fd); + + printf("%s: left channel (S,G)=(%s,%s) on interface %s\n", + prog_name, source, group, ifname); + + exit(0); +} |