diff options
author | deraadt <deraadt@openbsd.org> | 1995-10-18 08:37:01 +0000 |
---|---|---|
committer | deraadt <deraadt@openbsd.org> | 1995-10-18 08:37:01 +0000 |
commit | df930be708d50e9715f173caa26ffe1b7599b157 (patch) | |
tree | aa317e49e28cb999c9cf3db7f00c20903fe6010a /usr.sbin/mrinfo | |
download | wireguard-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/Makefile | 13 | ||||
-rw-r--r-- | usr.sbin/mrinfo/mrinfo.8 | 85 | ||||
-rw-r--r-- | usr.sbin/mrinfo/mrinfo.c | 532 |
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() +{ +} |