Commit c5293750 authored by Kevin Bracey's avatar Kevin Bracey
Browse files

Added RISC OS versions of the multicast diagnostic utilities map-mbone and mtrace.

parent e8e17902
......@@ -55,6 +55,8 @@ FILES=\
${RDIR}.bin.Host\
${SDIR}.ifconfig.IfConfig\
${SDIR}.inetstat.InetStat\
${SDIR}.map-mbone.Map-MBone\
${SDIR}.mtrace.MTrace\
${SDIR}.ping.Ping\
${SDIR}.pong.Pong\
${SDIR}.utils.utl.RMFind\
......@@ -78,6 +80,8 @@ NETUTILS = \
${SDIR}.arp.ARP \
${SDIR}.ifconfig.IfConfig \
${SDIR}.inetstat.InetStat \
${SDIR}.map-mbone.Map-MBone \
${SDIR}.mtrace.MTrace \
${SDIR}.ping.Ping \
${SDIR}.pong.Pong \
${SDIR}.utils.utl.RMFind \
......@@ -112,6 +116,8 @@ install: ${FILES}
${CP} ${SDIR}.arp.ARP ${INSTDIR}.bin.ARP ${CPFLAGS}
${CP} ${SDIR}.ifconfig.IfConfig ${INSTDIR}.bin.IfConfig ${CPFLAGS}
${CP} ${SDIR}.inetstat.InetStat ${INSTDIR}.bin.InetStat ${CPFLAGS}
${CP} ${SDIR}.map-mbone.Map-MBone ${INSTDIR}.bin.Map-MBone ${CPFLAGS}
${CP} ${SDIR}.mtrace.MTrace ${INSTDIR}.bin.MTrace ${CPFLAGS}
${CP} ${SDIR}.ping.Ping ${INSTDIR}.bin.Ping ${CPFLAGS}
${CP} ${SDIR}.pong.Pong ${INSTDIR}.bin.Pong ${CPFLAGS}
${CP} ${SDIR}.utils.utl.RMFind ${INSTDIR}.bin.RMFind ${CPFLAGS}
......@@ -148,6 +154,8 @@ resources-NetUtils: ${NETUTILS}
${CP} ${SDIR}.arp.ARP ${RESD}.bin.ARP ${CPFLAGS}
${CP} ${SDIR}.ifconfig.IfConfig ${RESD}.bin.IfConfig ${CPFLAGS}
${CP} ${SDIR}.inetstat.InetStat ${RESD}.bin.InetStat ${CPFLAGS}
${CP} ${SDIR}.map-mbone.Map-MBone ${RESD}.bin.Map-MBone ${CPFLAGS}
${CP} ${SDIR}.mtrace.MTrace ${RESD}.bin.MTrace ${CPFLAGS}
${CP} ${SDIR}.ping.Ping ${RESD}.bin.Ping ${CPFLAGS}
${CP} ${SDIR}.pong.Pong ${RESD}.bin.Pong ${CPFLAGS}
${CP} ${SDIR}.utils.utl.RMFind ${RESD}.bin.RMFind ${CPFLAGS}
......@@ -188,6 +196,21 @@ ${SDIR}.inetstat.InetStat: ${SDIR}.inetstat.c.main \
@up
@up
${SDIR}.map-mbone.Map-MBone: ${SDIR}.map-mbone.c.Map-MBone \
${SDIR}.map-mbone.c.igmp \
${SDIR}.map-mbone.c.inet \
${SDIR}.map-mbone.c.kern
dir ${SDIR}.map-mbone
@amu_machine
@up
@up
${SDIR}.mtrace.MTrace: ${SDIR}.mtrace.c.MTrace
dir ${SDIR}.mtrace
@amu_machine
@up
@up
${SDIR}.ping.Ping: ${SDIR}.ping.c.Ping
dir ${SDIR}.ping
@amu_machine
......
......@@ -24,7 +24,7 @@
| end
|
If "%*0" = "" Then Error Do not run me with no parameters
If "%1" = "" Then Obey !MkMods %0 arp ifconfig ifrconfig inetstat newfiler ping pong route showstat sysctl traceroute utils
If "%1" = "" Then Obey !MkMods %0 arp ifconfig ifrconfig inetstat map-mbone mtrace newfiler ping pong route showstat sysctl traceroute utils
If "%1" = "" Then Obey
dir %1
......
# Copyright 1999 Pace Micro Technology plc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
TARGET= Map-MBone
INCLUDES= C:,TCPIPLibs:
CC= cc
RM= remove
WFLAGS= fr~c~v
WIPE= -wipe
CFLAGS= -Wp -I$(INCLUDES) -c ${THROWBACK} -depend !Depend
OBJS= o.${TARGET} o.igmp o.inet o.kern
LIBS= C:o.Stubs TCPIPLibs:o.Unixlib TCPIPLibs:o.Inetlib \
TCPIPLibs:o.Socklib5
.SUFFIXES: .c .o
.c.o:; $(CC) $(CFLAGS) -o $@ $<
${TARGET}: $(OBJS) $(LIBS)
Link -o $@ $(OBJS) $(LIBS)
Squeeze $@
clean:; ${RM} ${TARGET}
${WIPE} o.* ${WFLAGS}
# Dynamic dependencies:
/* Copyright 1999 Pace Micro Technology plc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Mapper for connections between MRouteD multicast routers.
* Written by Pavel Curtis <Pavel@PARC.Xerox.Com>
*
* mapper.c,v 3.8.4.3 1998/01/06 01:57:47 fenner Exp
*/
/*
* 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 const char rcsid[] =
"$Id$";
#endif /* not lint */
#include <err.h>
#include <string.h>
#include <netdb.h>
#include <sys/time.h>
#include "defs.h"
#include <arpa/inet.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#ifdef __riscos
char *__progname = "Map-MBone";
static void closesockets(void)
{
if (igmp_socket >= 0) close(igmp_socket);
}
#endif
#define DEFAULT_TIMEOUT 2 /* How long to wait before retrying requests */
#define DEFAULT_RETRIES 1 /* How many times to ask each router */
/* All IP addresses are stored in the data structure in NET order. */
typedef struct neighbor {
struct neighbor *next;
u_int32 addr; /* IP address in NET order */
u_char metric; /* TTL cost of forwarding */
u_char threshold; /* TTL threshold to forward */
u_short flags; /* flags on connection */
#define NF_PRESENT 0x8000 /* True if flags are meaningful */
} Neighbor;
typedef struct interface {
struct interface *next;
u_int32 addr; /* IP address of the interface in NET order */
Neighbor *neighbors; /* List of neighbors' IP addresses */
} Interface;
typedef struct node {
u_int32 addr; /* IP address of this entry in NET order */
u_int32 version; /* which mrouted version is running */
int tries; /* How many requests sent? -1 for aliases */
union {
struct node *alias; /* If alias, to what? */
struct interface *interfaces; /* Else, neighbor data */
} u;
struct node *left, *right;
} Node;
Node *routers = 0;
u_int32 our_addr, target_addr = 0; /* in NET order */
int debug = 0;
int retries = DEFAULT_RETRIES;
int timeout = DEFAULT_TIMEOUT;
int show_names = TRUE;
vifi_t numvifs; /* to keep loader happy */
/* (see COPY_TABLES macro called in kern.c) */
Node * find_node __P((u_int32 addr, Node **ptr));
Interface * find_interface __P((u_int32 addr, Node *node));
Neighbor * find_neighbor __P((u_int32 addr, Node *node));
int main __P((int argc, char *argv[]));
void ask __P((u_int32 dst));
void ask2 __P((u_int32 dst));
int retry_requests __P((Node *node));
char * inet_name __P((u_int32 addr));
void print_map __P((Node *node));
char * graph_name __P((u_int32 addr, char *buf, int len));
void graph_edges __P((Node *node));
void elide_aliases __P((Node *node));
void graph_map __P((void));
int get_number __P((int *var, int deflt, char ***pargv,
int *pargc));
u_int32 host_addr __P((char *name));
static void usage __P((void));
Node *find_node(addr, ptr)
u_int32 addr;
Node **ptr;
{
Node *n = *ptr;
if (!n) {
*ptr = n = (Node *) malloc(sizeof(Node));
n->addr = addr;
n->version = 0;
n->tries = 0;
n->u.interfaces = 0;
n->left = n->right = 0;
return n;
} else if (addr == n->addr)
return n;
else if (addr < n->addr)
return find_node(addr, &(n->left));
else
return find_node(addr, &(n->right));
}
Interface *find_interface(addr, node)
u_int32 addr;
Node *node;
{
Interface *ifc;
for (ifc = node->u.interfaces; ifc; ifc = ifc->next)
if (ifc->addr == addr)
return ifc;
ifc = (Interface *) malloc(sizeof(Interface));
ifc->addr = addr;
ifc->next = node->u.interfaces;
node->u.interfaces = ifc;
ifc->neighbors = 0;
return ifc;
}
Neighbor *find_neighbor(addr, node)
u_int32 addr;
Node *node;
{
Interface *ifc;
for (ifc = node->u.interfaces; ifc; ifc = ifc->next) {
Neighbor *nb;
for (nb = ifc->neighbors; nb; nb = nb->next)
if (nb->addr == addr)
return nb;
}
return 0;
}
/*
* 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.
*/
#ifdef __STDC__
void
log(int severity, int syserr, char *format, ...)
{
va_list ap;
char fmt[100];
va_start(ap, format);
#else
/*VARARGS3*/
void
log(severity, syserr, format, va_alist)
int severity, syserr;
char *format;
va_dcl
{
va_list ap;
char fmt[100];
va_start(ap);
#endif
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)
strcpy(fmt, "warning - ");
strncat(fmt, format, sizeof(fmt)-strlen(fmt));
fmt[sizeof(fmt)-1]='\0';
vfprintf(stderr, fmt, ap);
if (syserr == 0)
fprintf(stderr, "\n");
#ifdef __riscos
else if (syserr == errno)
fprintf(stderr, ": %s\n", _inet_err());
#else
else if (syserr < sys_nerr)
fprintf(stderr, ": %s\n", sys_errlist[syserr]);
#endif
else
fprintf(stderr, ": errno %d\n", syserr);
}
if (severity <= LOG_ERR)
exit(1);
}
/*
* Send a neighbors-list request.
*/
void ask(dst)
u_int32 dst;
{
send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS,
htonl(MROUTED_LEVEL), 0);
}
void ask2(dst)
u_int32 dst;
{
send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2,
htonl(MROUTED_LEVEL), 0);
}
/*
* Process an incoming group membership report.
*/
void accept_group_report(src, dst, group, r_type)
u_int32 src, dst, group;
int r_type;
{
log(LOG_INFO, 0, "ignoring IGMP group membership report from %s to %s",
inet_fmt(src, s1), inet_fmt(dst, s2));
}
/*
* Process an incoming neighbor probe message.
*/
void accept_probe(src, dst, p, datalen, level)
u_int32 src, dst, level;
char *p;
int datalen;
{
log(LOG_INFO, 0, "ignoring DVMRP probe from %s to %s",
inet_fmt(src, s1), inet_fmt(dst, s2));
}
/*
* Process an incoming route report message.
*/
void accept_report(src, dst, p, datalen, level)
u_int32 src, dst, level;
char *p;
int datalen;
{
log(LOG_INFO, 0, "ignoring DVMRP routing report from %s to %s",
inet_fmt(src, s1), inet_fmt(dst, s2));
}
/*
* Process an incoming neighbor-list request message.
*/
void accept_neighbor_request(src, dst)
u_int32 src, dst;
{
if (src != our_addr)
log(LOG_INFO, 0,
"ignoring spurious DVMRP neighbor request from %s to %s",
inet_fmt(src, s1), inet_fmt(dst, s2));
}
void accept_neighbor_request2(src, dst)
u_int32 src, dst;
{
if (src != our_addr)
log(LOG_INFO, 0,
"ignoring spurious DVMRP neighbor request2 from %s to %s",
inet_fmt(src, s1), inet_fmt(dst, s2));
}
/*
* Process an incoming neighbor-list message.
*/
void accept_neighbors(src, dst, p, datalen, level)
u_int32 src, dst, level;
u_char *p;
int datalen;
{
Node *node = find_node(src, &routers);
if (node->tries == 0) /* Never heard of 'em; must have hit them at */
node->tries = 1; /* least once, though...*/
else if (node->tries == -1) /* follow alias link */
node = node->u.alias;
#define GET_ADDR(a) (a = ((u_int32)*p++ << 24), a += ((u_int32)*p++ << 16),\
a += ((u_int32)*p++ << 8), a += *p++)
/* if node is running a recent mrouted, ask for additional info */
if (level != 0) {
node->version = level;
node->tries = 1;
ask2(src);
return;
}
if (debug > 3) {
int i;
fprintf(stderr, " datalen = %d\n", datalen);
for (i = 0; i < datalen; i++) {
if ((i & 0xF) == 0)
fprintf(stderr, " ");
fprintf(stderr, " %02x", p[i]);
if ((i & 0xF) == 0xF)
fprintf(stderr, "\n");
}
if ((datalen & 0xF) != 0xF)
fprintf(stderr, "\n");
}
while (datalen > 0) { /* loop through interfaces */
u_int32 ifc_addr;
u_char metric, threshold, ncount;
Node *ifc_node;
Interface *ifc;
Neighbor *old_neighbors;
if (datalen < 4 + 3) {
log(LOG_WARNING, 0, "received truncated interface record from %s",
inet_fmt(src, s1));
return;
}
GET_ADDR(ifc_addr);
ifc_addr = htonl(ifc_addr);
metric = *p++;
threshold = *p++;
ncount = *p++;
datalen -= 4 + 3;
/* Fix up any alias information */
ifc_node = find_node(ifc_addr, &routers);
if (ifc_node->tries == 0) { /* new node */
ifc_node->tries = -1;
ifc_node->u.alias = node;
} else if (ifc_node != node
&& (ifc_node->tries > 0 || ifc_node->u.alias != node)) {
/* must merge two hosts' nodes */
Interface *ifc_i, *next_ifc_i;
if (ifc_node->tries == -1) {
Node *tmp = ifc_node->u.alias;
ifc_node->u.alias = node;
ifc_node = tmp;
}
/* Merge ifc_node (foo_i) into node (foo_n) */
if (ifc_node->tries > node->tries)
node->tries = ifc_node->tries;
for (ifc_i = ifc_node->u.interfaces; ifc_i; ifc_i = next_ifc_i) {
Neighbor *nb_i, *next_nb_i, *nb_n;
Interface *ifc_n = find_interface(ifc_i->addr, node);
old_neighbors = ifc_n->neighbors;
for (nb_i = ifc_i->neighbors; nb_i; nb_i = next_nb_i) {
next_nb_i = nb_i->next;
for (nb_n = old_neighbors; nb_n; nb_n = nb_n->next)
if (nb_i->addr == nb_n->addr) {
if (nb_i->metric != nb_n->metric
|| nb_i->threshold != nb_n->threshold)
log(LOG_WARNING, 0,
"inconsistent %s for neighbor %s of %s",
"metric/threshold",
inet_fmt(nb_i->addr, s1),
inet_fmt(node->addr, s2));
free(nb_i);
break;
}
if (!nb_n) { /* no match for this neighbor yet */
nb_i->next = ifc_n->neighbors;
ifc_n->neighbors = nb_i;
}
}
next_ifc_i = ifc_i->next;
free(ifc_i);
}
ifc_node->tries = -1;
ifc_node->u.alias = node;
}
ifc = find_interface(ifc_addr, node);
old_neighbors = ifc->neighbors;
/* Add the neighbors for this interface */
while (ncount--) {
u_int32 neighbor;
Neighbor *nb;
Node *n_node;
if (datalen < 4) {
log(LOG_WARNING, 0, "received truncated neighbor list from %s",
inet_fmt(src, s1));
return;
}
GET_ADDR(neighbor);
neighbor = htonl(neighbor);
datalen -= 4;
for (nb = old_neighbors; nb; nb = nb->next)
if (nb->addr == neighbor) {
if (metric != nb->metric || threshold != nb->threshold)
log(LOG_WARNING, 0,
"inconsistent %s for neighbor %s of %s",
"metric/threshold",
inet_fmt(nb->addr, s1), inet_fmt(node->addr, s2));
goto next_neighbor;
}
nb = (Neighbor *) malloc(sizeof(Neighbor));
nb->next = ifc->neighbors;
ifc->neighbors = nb;
nb->addr = neighbor;
nb->metric = metric;
nb->threshold = threshold;
nb->flags = 0;
n_node = find_node(neighbor, &routers);
if (n_node->tries == 0 && !target_addr) { /* it's a new router */
ask(neighbor);
n_node->tries = 1;
}
next_neighbor: ;
}
}
}
void accept_neighbors2(src, dst, p, datalen, level)
u_int32 src, dst, level;
u_char *p;
int datalen;
{
Node *node = find_node(src, &routers);
u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */
/* well, only possibly_broken_cisco, but that's too long to type. */
if (node->tries == 0) /* Never heard of 'em; must have hit them at */
node->tries = 1; /* least once, though...*/
else if (node->tries == -1) /* follow alias link */
node = node->u.alias;
while (datalen > 0) { /* loop through interfaces */
u_int32 ifc_addr;
u_char metric, threshold, ncount, flags;
Node *ifc_node;
Interface *ifc;
Neighbor *old_neighbors;
if (datalen < 4 + 4) {
log(LOG_WARNING, 0, "received truncated interface record from %s",
inet_fmt(src, s1));