summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mrinfo
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>1995-10-18 08:37:01 +0000
committerderaadt <deraadt@openbsd.org>1995-10-18 08:37:01 +0000
commitdf930be708d50e9715f173caa26ffe1b7599b157 (patch)
treeaa317e49e28cb999c9cf3db7f00c20903fe6010a /usr.sbin/mrinfo
downloadwireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.tar.xz
wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.zip
initial import of NetBSD tree
Diffstat (limited to 'usr.sbin/mrinfo')
-rw-r--r--usr.sbin/mrinfo/Makefile13
-rw-r--r--usr.sbin/mrinfo/mrinfo.885
-rw-r--r--usr.sbin/mrinfo/mrinfo.c532
3 files changed, 630 insertions, 0 deletions
diff --git a/usr.sbin/mrinfo/Makefile b/usr.sbin/mrinfo/Makefile
new file mode 100644
index 00000000000..fd54edbdb54
--- /dev/null
+++ b/usr.sbin/mrinfo/Makefile
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile,v 1.3 1995/10/03 23:20:30 thorpej Exp $
+# from: Id: Makefile,v 1.5 1993/06/24 05:11:16 deering Exp
+
+.PATH: ${.CURDIR}/../mrouted
+CFLAGS+= -I${.CURDIR}/../mrouted
+
+PROG= mrinfo
+SRCS= igmp.c inet.c kern.c mrinfo.c
+MAN= mrinfo.8
+BINOWN= root
+BINMODE=4555
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/mrinfo/mrinfo.8 b/usr.sbin/mrinfo/mrinfo.8
new file mode 100644
index 00000000000..60174c8686b
--- /dev/null
+++ b/usr.sbin/mrinfo/mrinfo.8
@@ -0,0 +1,85 @@
+.\" $NetBSD: mrinfo.8,v 1.2 1995/10/03 23:20:39 thorpej Exp $
+.\"
+.TH MRINFO 8
+.UC 5
+.SH NAME
+mrinfo \- Displays configuration info from a multicast router
+.SH SYNOPSIS
+.B /usr/sbin/mrinfo
+[
+.B \-d
+.I debug_level
+] [
+.B \-r
+.I retry_count
+] [
+.B \-t
+.I timeout_count
+]
+.B multicast_router
+
+.SH DESCRIPTION
+.I mrinfo
+attempts to display the configuration information from the multicast router
+.I multicast_router.
+.PP
+.I mrinfo
+uses the ASK_NEIGHBORS IGMP message to the specified multicast router. If this
+multicast router responds, the version number and a list of their neighboring
+multicast router addresses is part of that response. If the responding router
+has a recent multicast version number, then
+.I mrinfo
+requests additional information such as metrics, thresholds, and flags from the
+multicast router. Once the specified multicast router responds, the
+configuration is displayed to the standard output.
+.br
+.ne 5
+.SH INVOCATION
+.PP
+"\-d" option sets the debug level. When the debug level is greater than the
+default value of 0, addition debugging messages are printed. Regardless of
+the debug level, an error condition, will always write an error message and will
+cause
+.I mrinfo
+to terminate.
+Non-zero debug levels have the following effects:
+.IP "level 1"
+packet warnings are printed to stderr.
+.IP "level 2"
+all level 1 messages plus notifications down networks are printed to stderr.
+.IP "level 3"
+all level 2 messages plus notifications of all packet
+timeouts are printed to stderr.
+.PP
+"\-r retry_count" sets the neighbor query retry limit. Default is 3 retry.
+.PP
+"\-t timeout_count" sets the number of seconds to wait for a neighbor query
+reply. Default timeout is 4 seconds.
+.PP
+.SH SAMPLE OUTPUT
+.nf
+.I mrinfo mbone.phony.dom.net
+127.148.176.10 (mbone.phony.dom.net) [version 3.3]:
+ 127.148.176.10 -> 0.0.0.0 (?) [1/1/querier]
+ 127.148.176.10 -> 127.0.8.4 (mbone2.phony.dom.net) [1/45/tunnel]
+ 127.148.176.10 -> 105.1.41.9 (momoney.com) [1/32/tunnel/down]
+ 127.148.176.10 -> 143.192.152.119 (mbone.dipu.edu) [1/32/tunnel]
+.fi
+.PP
+For each neighbor of the queried multicast router, the IP of the queried router
+is displayed, followed by the IP and name of the neighbor. In square brackets
+the metric (cost of connection), the treashold (multicast ttl) is displayed. If
+the queried multicast router has a newer version number, the type (tunnel,
+srcrt) and status (disabled, down) of the connection is displayed.
+.PP
+.SH IMPORTANT NOTE
+.I mrinfo
+must be run as root.
+.PP
+.SH SEE ALSO
+.BR mrouted (8) ,
+.BR map-mbone (8) ,
+.BR mtrace (8)
+.PP
+.SH AUTHOR
+Van Jacobson
diff --git a/usr.sbin/mrinfo/mrinfo.c b/usr.sbin/mrinfo/mrinfo.c
new file mode 100644
index 00000000000..20bd54fcf36
--- /dev/null
+++ b/usr.sbin/mrinfo/mrinfo.c
@@ -0,0 +1,532 @@
+/* $NetBSD: mrinfo.c,v 1.3 1995/10/03 23:20:45 thorpej Exp $ */
+
+/*
+ * This tool requests configuration info from a multicast router
+ * and prints the reply (if any). Invoke it as:
+ *
+ * mrinfo router-name-or-address
+ *
+ * Written Wed Mar 24 1993 by Van Jacobson (adapted from the
+ * multicast mapper written by Pavel Curtis).
+ *
+ * The lawyers insist we include the following UC copyright notice.
+ * The mapper from which this is derived contained a Xerox copyright
+ * notice which follows the UC one. Try not to get depressed noting
+ * that the legal gibberish is larger than the program.
+ *
+ * Copyright (c) 1993 Regents of the University of California.
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * ---------------------------------
+ * Copyright (c) Xerox Corporation 1992. All rights reserved.
+ *
+ * License is granted to copy, to use, and to make and to use derivative works
+ * for research and evaluation purposes, provided that Xerox is acknowledged
+ * in all documentation pertaining to any such copy or derivative work. Xerox
+ * grants no other licenses expressed or implied. The Xerox trade name should
+ * not be used in any advertising without its written permission.
+ *
+ * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE FOR
+ * ANY PARTICULAR PURPOSE. The software is provided "as is" without express
+ * or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this software.
+ */
+
+#ifndef lint
+static char rcsid[] =
+ "@(#) $NetBSD: mrinfo.c,v 1.3 1995/10/03 23:20:45 thorpej Exp $";
+/* original rcsid:
+ "@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)";
+*/
+#endif
+
+#include <string.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include "defs.h"
+#include <arpa/inet.h>
+
+#define DEFAULT_TIMEOUT 4 /* How long to wait before retrying requests */
+#define DEFAULT_RETRIES 3 /* How many times to ask each router */
+
+u_int32_t our_addr, target_addr = 0; /* in NET order */
+int debug = 0;
+int nflag = 0;
+int retries = DEFAULT_RETRIES;
+int timeout = DEFAULT_TIMEOUT;
+int target_level;
+vifi_t numvifs; /* to keep loader happy */
+ /* (see COPY_TABLES macro called in kern.c) */
+
+char *
+inet_name(addr)
+ u_int32_t addr;
+{
+ struct hostent *e;
+ struct in_addr in;
+
+ if (addr == 0)
+ return "local";
+
+ if (nflag ||
+ (e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)) == NULL) {
+ in.s_addr = addr;
+ return (inet_ntoa(in));
+ }
+ return (e->h_name);
+}
+
+/*
+ * Log errors and other messages to stderr, according to the severity of the
+ * message and the current debug level. For errors of severity LOG_ERR or
+ * worse, terminate the program.
+ */
+void
+log(severity, syserr, format, a, b, c, d, e)
+ int severity, syserr;
+ char *format;
+ int a, b, c, d, e;
+{
+ char fmt[100];
+
+ switch (debug) {
+ case 0:
+ if (severity > LOG_WARNING)
+ return;
+ case 1:
+ if (severity > LOG_NOTICE)
+ return;
+ case 2:
+ if (severity > LOG_INFO)
+ return;
+ default:
+ fmt[0] = '\0';
+ if (severity == LOG_WARNING)
+ strcat(fmt, "warning - ");
+ strncat(fmt, format, 80);
+ fprintf(stderr, fmt, a, b, c, d, e);
+ if (syserr == 0)
+ fprintf(stderr, "\n");
+ else if (syserr < sys_nerr)
+ fprintf(stderr, ": %s\n", sys_errlist[syserr]);
+ else
+ fprintf(stderr, ": errno %d\n", syserr);
+ }
+
+ if (severity <= LOG_ERR)
+ exit(-1);
+}
+
+/*
+ * Send a neighbors-list request.
+ */
+void
+ask(dst)
+ u_int32_t dst;
+{
+ send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS,
+ htonl(MROUTED_LEVEL), 0);
+}
+
+void
+ask2(dst)
+ u_int32_t dst;
+{
+ send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2,
+ htonl(MROUTED_LEVEL), 0);
+}
+
+/*
+ * Process an incoming neighbor-list message.
+ */
+void
+accept_neighbors(src, dst, p, datalen)
+ u_int32_t src, dst;
+ u_char *p;
+ int datalen;
+{
+ u_char *ep = p + datalen;
+#define GET_ADDR(a) (a = ((u_int32_t)*p++ << 24), a += ((u_int32_t)*p++ << 16),\
+ a += ((u_int32_t)*p++ << 8), a += *p++)
+
+ printf("%s (%s):\n", inet_fmt(src, s1), inet_name(src));
+ while (p < ep) {
+ register u_int32_t laddr;
+ register u_char metric;
+ register u_char thresh;
+ register int ncount;
+
+ GET_ADDR(laddr);
+ laddr = htonl(laddr);
+ metric = *p++;
+ thresh = *p++;
+ ncount = *p++;
+ while (--ncount >= 0) {
+ register u_int32_t neighbor;
+ GET_ADDR(neighbor);
+ neighbor = htonl(neighbor);
+ printf(" %s -> ", inet_fmt(laddr, s1));
+ printf("%s (%s) [%d/%d]\n", inet_fmt(neighbor, s1),
+ inet_name(neighbor), metric, thresh);
+ }
+ }
+}
+
+void
+accept_neighbors2(src, dst, p, datalen)
+ u_int32_t src, dst;
+ u_char *p;
+ int datalen;
+{
+ u_char *ep = p + datalen;
+ u_int broken_cisco = ((target_level & 0xffff) == 0x020a); /* 10.2 */
+ /* well, only possibly_broken_cisco, but that's too long to type. */
+
+ printf("%s (%s) [version %d.%d]:\n", inet_fmt(src, s1), inet_name(src),
+ target_level & 0xff, (target_level >> 8) & 0xff);
+
+ while (p < ep) {
+ register u_char metric;
+ register u_char thresh;
+ register u_char flags;
+ register int ncount;
+ register u_int32_t laddr = *(u_int32_t*)p;
+
+ p += 4;
+ metric = *p++;
+ thresh = *p++;
+ flags = *p++;
+ ncount = *p++;
+ if (broken_cisco && ncount == 0) /* dumb Ciscos */
+ ncount = 1;
+ if (broken_cisco && ncount > 15) /* dumb Ciscos */
+ ncount = ncount & 0xf;
+ while (--ncount >= 0 && p < ep) {
+ register u_int32_t neighbor = *(u_int32_t*)p;
+ p += 4;
+ printf(" %s -> ", inet_fmt(laddr, s1));
+ printf("%s (%s) [%d/%d", inet_fmt(neighbor, s1),
+ inet_name(neighbor), metric, thresh);
+ if (flags & DVMRP_NF_TUNNEL)
+ printf("/tunnel");
+ if (flags & DVMRP_NF_SRCRT)
+ printf("/srcrt");
+ if (flags & DVMRP_NF_PIM)
+ printf("/pim");
+ if (flags & DVMRP_NF_QUERIER)
+ printf("/querier");
+ if (flags & DVMRP_NF_DISABLED)
+ printf("/disabled");
+ if (flags & DVMRP_NF_DOWN)
+ printf("/down");
+ if (flags & DVMRP_NF_LEAF)
+ printf("/leaf");
+ printf("]\n");
+ }
+ }
+}
+
+int
+get_number(var, deflt, pargv, pargc)
+ int *var, *pargc, deflt;
+ char ***pargv;
+{
+ if ((*pargv)[0][2] == '\0') { /* Get the value from the next
+ * argument */
+ if (*pargc > 1 && isdigit((*pargv)[1][0])) {
+ (*pargv)++, (*pargc)--;
+ *var = atoi((*pargv)[0]);
+ return 1;
+ } else if (deflt >= 0) {
+ *var = deflt;
+ return 1;
+ } else
+ return 0;
+ } else { /* Get value from the rest of this argument */
+ if (isdigit((*pargv)[0][2])) {
+ *var = atoi((*pargv)[0] + 2);
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+}
+
+u_int32_t
+host_addr(name)
+ char *name;
+{
+ struct hostent *e;
+ u_int32_t addr;
+
+ addr = inet_addr(name);
+ if ((int)addr == -1) {
+ e = gethostbyname(name);
+ if (e == NULL || e->h_length != sizeof(addr))
+ return (0);
+ memcpy(&addr, e->h_addr_list[0], e->h_length);
+ }
+ return(addr);
+}
+
+void
+usage()
+{
+ fprintf(stderr,
+ "Usage: mrinfo [-n] [-t timeout] [-r retries] [router]\n");
+ exit(1);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ setlinebuf(stderr);
+
+ if (geteuid() != 0) {
+ fprintf(stderr, "mrinfo: must be root\n");
+ exit(1);
+ }
+ argv++, argc--;
+ while (argc > 0 && argv[0][0] == '-') {
+ switch (argv[0][1]) {
+ case 'd':
+ if (!get_number(&debug, DEFAULT_DEBUG, &argv, &argc))
+ usage();
+ break;
+ case 'n':
+ ++nflag;
+ break;
+ case 'r':
+ if (!get_number(&retries, -1, &argv, &argc))
+ usage();
+ break;
+ case 't':
+ if (!get_number(&timeout, -1, &argv, &argc))
+ usage();
+ break;
+ default:
+ usage();
+ }
+ argv++, argc--;
+ }
+ if (argc > 1)
+ usage();
+ if (argc == 1)
+ target_addr = host_addr(argv[0]);
+ else
+ target_addr = host_addr("127.0.0.1");
+
+ if (target_addr == 0) {
+ fprintf(stderr, "mrinfo: %s: no such host\n", argv[0]);
+ exit(1);
+ }
+ if (debug)
+ fprintf(stderr, "Debug level %u\n", debug);
+
+ init_igmp();
+
+ { /* Find a good local address for us. */
+ int udp;
+ struct sockaddr_in addr;
+ int addrlen = sizeof(addr);
+
+ addr.sin_family = AF_INET;
+#if (defined(BSD) && (BSD >= 199103))
+ addr.sin_len = sizeof addr;
+#endif
+ addr.sin_addr.s_addr = target_addr;
+ addr.sin_port = htons(2000); /* any port over 1024 will
+ * do... */
+ if ((udp = socket(AF_INET, SOCK_DGRAM, 0)) < 0
+ || connect(udp, (struct sockaddr *) & addr, sizeof(addr)) < 0
+ || getsockname(udp, (struct sockaddr *) & addr, &addrlen) < 0) {
+ perror("Determining local address");
+ exit(-1);
+ }
+ close(udp);
+ our_addr = addr.sin_addr.s_addr;
+ }
+
+ ask(target_addr);
+
+ /* Main receive loop */
+ for (;;) {
+ fd_set fds;
+ struct timeval tv;
+ int count, recvlen, dummy = 0;
+ register u_int32_t src, dst, group;
+ struct ip *ip;
+ struct igmp *igmp;
+ int ipdatalen, iphdrlen, igmpdatalen;
+
+ FD_ZERO(&fds);
+ FD_SET(igmp_socket, &fds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ count = select(igmp_socket + 1, &fds, 0, 0, &tv);
+
+ if (count < 0) {
+ if (errno != EINTR)
+ perror("select");
+ continue;
+ } else if (count == 0) {
+ log(LOG_DEBUG, 0, "Timed out receiving neighbor lists");
+ if (--retries < 0)
+ exit(1);
+ if (target_level == 0)
+ ask(target_addr);
+ else
+ ask2(target_addr);
+ continue;
+ }
+ recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
+ 0, NULL, &dummy);
+ if (recvlen <= 0) {
+ if (recvlen && errno != EINTR)
+ perror("recvfrom");
+ continue;
+ }
+
+ if (recvlen < sizeof(struct ip)) {
+ log(LOG_WARNING, 0,
+ "packet too short (%u bytes) for IP header",
+ recvlen);
+ continue;
+ }
+ ip = (struct ip *) recv_buf;
+ if (ip->ip_p == 0)
+ continue; /* Request to install cache entry */
+ src = ip->ip_src.s_addr;
+ dst = ip->ip_dst.s_addr;
+ iphdrlen = ip->ip_hl << 2;
+ ipdatalen = ip->ip_len;
+ if (iphdrlen + ipdatalen != recvlen) {
+ log(LOG_WARNING, 0,
+ "packet shorter (%u bytes) than hdr+data length (%u+%u)",
+ recvlen, iphdrlen, ipdatalen);
+ continue;
+ }
+ igmp = (struct igmp *) (recv_buf + iphdrlen);
+ group = igmp->igmp_group.s_addr;
+ igmpdatalen = ipdatalen - IGMP_MINLEN;
+ if (igmpdatalen < 0) {
+ log(LOG_WARNING, 0,
+ "IP data field too short (%u bytes) for IGMP, from %s",
+ ipdatalen, inet_fmt(src, s1));
+ continue;
+ }
+ if (igmp->igmp_type != IGMP_DVMRP)
+ continue;
+
+ switch (igmp->igmp_code) {
+ case DVMRP_NEIGHBORS:
+ case DVMRP_NEIGHBORS2:
+ if (src != target_addr) {
+ fprintf(stderr, "mrinfo: got reply from %s",
+ inet_fmt(src, s1));
+ fprintf(stderr, " instead of %s\n",
+ inet_fmt(target_addr, s1));
+ /*continue;*/
+ }
+ break;
+ default:
+ continue; /* ignore all other DVMRP messages */
+ }
+
+ switch (igmp->igmp_code) {
+
+ case DVMRP_NEIGHBORS:
+ if (group) {
+ /* knows about DVMRP_NEIGHBORS2 msg */
+ if (target_level == 0) {
+ target_level = ntohl(group);
+ ask2(target_addr);
+ }
+ } else {
+ accept_neighbors(src, dst, (char *)(igmp + 1),
+ igmpdatalen);
+ exit(0);
+ }
+ break;
+
+ case DVMRP_NEIGHBORS2:
+ accept_neighbors2(src, dst, (char *)(igmp + 1),
+ igmpdatalen);
+ exit(0);
+ }
+ }
+}
+
+/* dummies */
+void accept_probe()
+{
+}
+void accept_group_report()
+{
+}
+void accept_neighbor_request2()
+{
+}
+void accept_report()
+{
+}
+void accept_neighbor_request()
+{
+}
+void accept_prune()
+{
+}
+void accept_graft()
+{
+}
+void accept_g_ack()
+{
+}
+void add_table_entry()
+{
+}
+void check_vif_state()
+{
+}
+void accept_leave_message()
+{
+}
+void accept_mtrace()
+{
+}
+void accept_membership_query()
+{
+}