diff options
| author | wiz <wiz@NetBSD.org> | 2003-03-05 22:09:46 +0000 |
|---|---|---|
| committer | wiz <wiz@NetBSD.org> | 2003-03-05 22:09:46 +0000 |
| commit | d201ab97524d0dea49ef4e231fb7d075589b4aa9 (patch) | |
| tree | b88119ec6d6986a054b3dd358ae5a69b36b58555 /gnu | |
| parent | 54ad96333df255c3f07add7859d4827eae487197 (diff) | |
Moved back to usr.sbin.
Diffstat (limited to 'gnu')
33 files changed, 0 insertions, 14581 deletions
diff --git a/gnu/dist/map-mbone/map-mbone.8 b/gnu/dist/map-mbone/map-mbone.8 deleted file mode 100644 index 51ced7d0827..00000000000 --- a/gnu/dist/map-mbone/map-mbone.8 +++ /dev/null @@ -1,91 +0,0 @@ -.\" $NetBSD: map-mbone.8,v 1.1 2002/10/01 03:50:08 itojun Exp $ -.\" -.TH MAP-MBONE 8 -.UC 5 -.SH NAME -map-mbone \- Multicast connection mapper -.SH SYNOPSIS -.B /usr/sbin/map-mbone -[ -.B \-d -.I debug_level -] [ -.B \-f -] [ -.B \-g -] [ -.B \-n -] [ -.B \-r -.I retry_count -] [ -.B \-t -.I timeout_count -] [ -.B starting_router -] -.SH DESCRIPTION -.I map-mbone -attempts to display all multicast routers that are reachable from the multicast -.I starting_router. -If not specified on the command line, the default multicast -.I starting_router -is the localhost. -.PP -.I map-mbone -traverses neighboring multicast routers by sending the ASK_NEIGHBORS IGMP -message to the multicast starting_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 recent multicast version -number, then -.I map-mbone -requests additional information such as metrics, thresholds, and flags from the -multicast router. For each new occurrence of neighboring multicast router in -the reply and provided the flooding option has been selected, then -.I map-mbone -asks each of this multicast router for a list of neighbors. This search -for unique routers will continue until no new neighboring multicast routers -are reported. -.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 map-mbone -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 -"\-f" option sets flooding option. Flooding allows the recursive search -of neighboring multicast routers and is enable by default when starting_router -is not used. -.PP -"\-g" option sets graphing in GraphEd format. -.PP -"\-n" option disables the DNS lookup for the multicast routers names. -.PP -"\-r retry_count" sets the neighbor query retry limit. Default is 1 retry. -.PP -"\-t timeout_count" sets the number of seconds to wait for a neighbor query -reply before retrying. Default timeout is 2 seconds. -.PP -.SH IMPORTANT NOTE -.I map-mbone -must be run as root. -.PP -.SH SEE ALSO -.BR mrouted (8) , -.BR mrinfo (8) , -.BR mtrace (8) -.PP -.SH AUTHOR -Pavel Curtis diff --git a/gnu/dist/map-mbone/mapper.c b/gnu/dist/map-mbone/mapper.c deleted file mode 100644 index 124449241dc..00000000000 --- a/gnu/dist/map-mbone/mapper.c +++ /dev/null @@ -1,974 +0,0 @@ -/* $NetBSD: mapper.c,v 1.2 2002/12/06 16:01:14 thorpej Exp $ */ - -/* Mapper for connections between MRouteD multicast routers. - * Written by Pavel Curtis <Pavel@PARC.Xerox.Com> - */ - -/* - * Copyright (c) 1992, 2001 Xerox Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 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. - * - * Neither name of the Xerox, PARC, nor the names of its contributors may be used - * to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 XEROX CORPORATION 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. - */ - -#include <string.h> -#include <netdb.h> -#include <sys/time.h> -#include <poll.h> -#include "defs.h" -#include <arpa/inet.h> -#include <stdarg.h> - -#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_t 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_t addr; /* IP address of the interface in NET order */ - Neighbor *neighbors; /* List of neighbors' IP addresses */ -} Interface; - -typedef struct node { - u_int32_t addr; /* IP address of this entry in NET order */ - u_int32_t 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_t 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(u_int32_t addr, Node **ptr); -Interface * find_interface(u_int32_t addr, Node *node); -Neighbor * find_neighbor(u_int32_t addr, Node *node); -int main(int argc, char *argv[]); -void ask(u_int32_t dst); -void ask2(u_int32_t dst); -int retry_requests(Node *node); -char * inet_name(u_int32_t addr); -void print_map(Node *node); -char * graph_name(u_int32_t addr, char *buf); -void graph_edges(Node *node); -void elide_aliases(Node *node); -void graph_map(void); -int get_number(int *var, int deflt, char ***pargv, - int *pargc); -u_int32_t host_addr(char *name); - -void logit(int severity, int syserr, const char *format, ...) - __attribute__((__format__(__printf__, 3, 4))); - -Node *find_node(u_int32_t 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(u_int32_t 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(u_int32_t 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. - */ -void -logit(int severity, int syserr, const char *format, ...) -{ - va_list ap; - 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); - format = fmt; - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - if (syserr == 0) - fprintf(stderr, "\n"); - else - fprintf(stderr, ": %s\n", strerror(syserr)); - } - - if (severity <= LOG_ERR) - exit(1); -} - - -/* - * Send a neighbors-list request. - */ -void ask(u_int32_t dst) -{ - send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS, - htonl(MROUTED_LEVEL), 0); -} - -void ask2(u_int32_t 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(u_int32_t src, u_int32_t dst, u_int32_t group, int r_type) -{ - logit(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(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ - logit(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(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ - logit(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(u_int32_t src, u_int32_t dst) -{ - if (src != our_addr) - logit(LOG_INFO, 0, - "ignoring spurious DVMRP neighbor request from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - -void accept_neighbor_request2(u_int32_t src, u_int32_t dst) -{ - if (src != our_addr) - logit(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(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ - 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_t)*p++ << 24), a += ((u_int32_t)*p++ << 16),\ - a += ((u_int32_t)*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_t ifc_addr; - u_char metric, threshold, ncount; - Node *ifc_node; - Interface *ifc; - Neighbor *old_neighbors; - - if (datalen < 4 + 3) { - logit(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) - logit(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_t neighbor; - Neighbor *nb; - Node *n_node; - - if (datalen < 4) { - logit(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) - logit(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(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ - 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_t ifc_addr; - u_char metric, threshold, ncount, flags; - Node *ifc_node; - Interface *ifc; - Neighbor *old_neighbors; - - if (datalen < 4 + 4) { - logit(LOG_WARNING, 0, "received truncated interface record from %s", - inet_fmt(src, s1)); - return; - } - - ifc_addr = *(u_int32_t*)p; - p += 4; - metric = *p++; - threshold = *p++; - flags = *p++; - ncount = *p++; - datalen -= 4 + 4; - - if (broken_cisco && ncount == 0) /* dumb Ciscos */ - ncount = 1; - if (broken_cisco && ncount > 15) /* dumb Ciscos */ - ncount = ncount & 0xf; - - /* 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_i->threshold) - logit(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-- && datalen > 0) { - u_int32_t neighbor; - Neighbor *nb; - Node *n_node; - - if (datalen < 4) { - logit(LOG_WARNING, 0, "received truncated neighbor list from %s", - inet_fmt(src, s1)); - return; - } - - neighbor = *(u_int32_t*)p; - p += 4; - datalen -= 4; - if (neighbor == 0) - /* make leaf nets point to themselves */ - neighbor = ifc_addr; - - for (nb = old_neighbors; nb; nb = nb->next) - if (nb->addr == neighbor) { - if (metric != nb->metric || threshold != nb->threshold) - logit(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 = flags | NF_PRESENT; - - 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 check_vif_state(void) -{ - logit(LOG_NOTICE, 0, "network marked down..."); -} - - -int retry_requests(Node *node) -{ - int result; - - if (node) { - result = retry_requests(node->left); - if (node->tries > 0 && node->tries < retries) { - if (node->version) - ask2(node->addr); - else - ask(node->addr); - node->tries++; - result = 1; - } - return retry_requests(node->right) || result; - } else - return 0; -} - - -char *inet_name(u_int32_t addr) -{ - struct hostent *e; - - e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); - - return e ? e->h_name : 0; -} - - -void print_map(Node *node) -{ - if (node) { - char *name, *addr; - - print_map(node->left); - - addr = inet_fmt(node->addr, s1); - if (!target_addr - || (node->tries >= 0 && node->u.interfaces) - || (node->tries == -1 - && node->u.alias->tries >= 0 - && node->u.alias->u.interfaces)) { - if (show_names && (name = inet_name(node->addr))) - printf("%s (%s):", addr, name); - else - printf("%s:", addr); - if (node->tries < 0) - printf(" alias for %s\n\n", inet_fmt(node->u.alias->addr, s1)); - else if (!node->u.interfaces) - printf(" no response to query\n\n"); - else { - Interface *ifc; - - if (node->version) - printf(" <v%d.%d>", node->version & 0xff, - (node->version >> 8) & 0xff); - printf("\n"); - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) { - Neighbor *nb; - char *ifc_name = inet_fmt(ifc->addr, s1); - int ifc_len = strlen(ifc_name); - int count = 0; - - printf(" %s:", ifc_name); - for (nb = ifc->neighbors; nb; nb = nb->next) { - if (count > 0) - printf("%*s", ifc_len + 5, ""); - printf(" %s", inet_fmt(nb->addr, s1)); - if (show_names && (name = inet_name(nb->addr))) - printf(" (%s)", name); - printf(" [%d/%d", nb->metric, nb->threshold); - if (nb->flags) { - u_short flags = nb->flags; - if (flags & DVMRP_NF_TUNNEL) - printf("/tunnel"); - if (flags & DVMRP_NF_SRCRT) - printf("/srcrt"); - if (flags & DVMRP_NF_QUERIER) - printf("/querier"); - if (flags & DVMRP_NF_DISABLED) - printf("/disabled"); - if (flags & DVMRP_NF_DOWN) - printf("/down"); - } - printf("]\n"); - count++; - } - } - printf("\n"); - } - } - print_map(node->right); - } -} - - -char *graph_name(u_int32_t addr, char *buf) -{ - char *name; - - if (show_names && (name = inet_name(addr))) - strcpy(buf, name); - else - inet_fmt(addr, buf); - - return buf; -} - - -void graph_edges(Node *node) -{ - Interface *ifc; - Neighbor *nb; - char name[100]; - - if (node) { - graph_edges(node->left); - if (node->tries >= 0) { - printf(" %d {$ NP %d0 %d0 $} \"%s%s\" \n", - (int) node->addr, - node->addr & 0xFF, (node->addr >> 8) & 0xFF, - graph_name(node->addr, name), - node->u.interfaces ? "" : "*"); - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) - for (nb = ifc->neighbors; nb; nb = nb->next) { - Node *nb_node = find_node(nb->addr, &routers); - Neighbor *nb2; - - if (nb_node->tries < 0) - nb_node = nb_node->u.alias; - - if (node != nb_node && - (!(nb2 = find_neighbor(node->addr, nb_node)) - || node->addr < nb_node->addr)) { - printf(" %d \"%d/%d", - nb_node->addr, nb->metric, nb->threshold); - if (nb2 && (nb2->metric != nb->metric - || nb2->threshold != nb->threshold)) - printf(",%d/%d", nb2->metric, nb2->threshold); - if (nb->flags & NF_PRESENT) - printf("%s%s", - nb->flags & DVMRP_NF_SRCRT ? "" : - nb->flags & DVMRP_NF_TUNNEL ? "E" : "P", - nb->flags & DVMRP_NF_DOWN ? "D" : ""); - printf("\"\n"); - } - } - printf(" ;\n"); - } - graph_edges(node->right); - } -} - -void elide_aliases(Node *node) -{ - if (node) { - elide_aliases(node->left); - if (node->tries >= 0) { - Interface *ifc; - - for (ifc = node->u.interfaces; ifc; ifc = ifc->next) { - Neighbor *nb; - - for (nb = ifc->neighbors; nb; nb = nb->next) { - Node *nb_node = find_node(nb->addr, &routers); - - if (nb_node->tries < 0) - nb->addr = nb_node->u.alias->addr; - } - } - } - elide_aliases(node->right); - } -} - -void graph_map(void) -{ - time_t now = time(0); - char *nowstr = ctime(&now); - - nowstr[24] = '\0'; /* Kill the newline at the end */ - elide_aliases(routers); - printf("GRAPH \"Multicast Router Connectivity: %s\" = UNDIRECTED\n", - nowstr); - graph_edges(routers); - printf("END\n"); -} - - -int get_number(int *var, int deflt, char ***pargv, int *pargc) -{ - 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(char *name) -{ - struct hostent *e = gethostbyname(name); - int addr; - - if (e) - memcpy(&addr, e->h_addr_list[0], e->h_length); - else { - addr = inet_addr(name); - if (addr == -1) - addr = 0; - } - - return addr; -} - - -int main(int argc, char **argv) -{ - int flood = FALSE, graph = FALSE; - struct pollfd set[1]; - - setlinebuf(stderr); - - if (geteuid() != 0) { - fprintf(stderr, "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)) - goto usage; - break; - case 'f': - flood = TRUE; - break; - case 'g': - graph = TRUE; - break; - case 'n': - show_names = FALSE; - break; - case 'r': - if (!get_number(&retries, -1, &argv, &argc)) - goto usage; - break; - case 't': - if (!get_number(&timeout, -1, &argv, &argc)) - goto usage; - break; - default: - goto usage; - } - argv++, argc--; - } - - if (argc > 1) { - usage: - fprintf(stderr, - "Usage: map-mbone [-f] [-g] [-n] [-t timeout] %s\n\n", - "[-r retries] [-d [debug-level]] [router]"); - fprintf(stderr, "\t-f Flood the routing graph with queries\n"); - fprintf(stderr, "\t (True by default unless `router' is given)\n"); - fprintf(stderr, "\t-g Generate output in GraphEd format\n"); - fprintf(stderr, "\t-n Don't look up DNS names for routers\n"); - exit(1); - } else if (argc == 1 && !(target_addr = host_addr(argv[0]))) { - fprintf(stderr, "Unknown host: %s\n", argv[0]); - exit(2); - } - - 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); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = dvmrp_group; - 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; - } - - /* Send initial seed message to all local routers */ - ask(target_addr ? target_addr : allhosts_group); - - if (target_addr) { - Node *n = find_node(target_addr, &routers); - - n->tries = 1; - - if (flood) - target_addr = 0; - } - - /* Main receive loop */ - set[0].fd = igmp_socket; - set[0].events = POLLIN; - for(;;) { - int count, recvlen, dummy = 0; - - count = poll(set, 1, timeout * 1000); - - if (count < 0) { - if (errno != EINTR) - perror("poll"); - continue; - } else if (count == 0) { - logit(LOG_DEBUG, 0, "Timed out receiving neighbor lists"); - if (retry_requests(routers)) - continue; - else - break; - } - - recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, - 0, NULL, &dummy); - if (recvlen >= 0) - accept_igmp(recvlen); - else if (errno != EINTR) - perror("recvfrom"); - } - - printf("\n"); - - if (graph) - graph_map(); - else { - if (!target_addr) - printf("Multicast Router Connectivity:\n\n"); - print_map(routers); - } - - exit(0); -} - -/* dummies */ -void accept_prune(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void accept_graft(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void accept_g_ack(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void add_table_entry(u_int32_t origin, u_int32_t mcastgrp) -{ -} -void accept_leave_message(u_int32_t src, u_int32_t dst, u_int32_t group) -{ -} -void accept_mtrace(u_int32_t src, u_int32_t dst, u_int32_t group, char *data, - u_int no, int datalen) -{ -} -void accept_membership_query(u_int32_t src, u_int32_t dst, u_int32_t group, - int tmo) -{ -} -void accept_info_request(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ -} -void accept_info_reply(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ -} diff --git a/gnu/dist/mrinfo/mrinfo.8 b/gnu/dist/mrinfo/mrinfo.8 deleted file mode 100644 index dd1fb13e986..00000000000 --- a/gnu/dist/mrinfo/mrinfo.8 +++ /dev/null @@ -1,85 +0,0 @@ -.\" $NetBSD: mrinfo.8,v 1.1 2002/10/01 03:50:09 itojun 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 -\*[Gt] 0.0.0.0 (?) [1/1/querier] - 127.148.176.10 -\*[Gt] 127.0.8.4 (mbone2.phony.dom.net) [1/45/tunnel] - 127.148.176.10 -\*[Gt] 105.1.41.9 (momoney.com) [1/32/tunnel/down] - 127.148.176.10 -\*[Gt] 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/gnu/dist/mrinfo/mrinfo.c b/gnu/dist/mrinfo/mrinfo.c deleted file mode 100644 index ae5c5a30484..00000000000 --- a/gnu/dist/mrinfo/mrinfo.c +++ /dev/null @@ -1,600 +0,0 @@ -/* $NetBSD: mrinfo.c,v 1.2 2002/12/06 16:02:20 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) 1992, 2001 Xerox Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 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. - - * Neither name of the Xerox, PARC, nor the names of its contributors may be used - * to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 XEROX CORPORATION 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. - */ - -#include <sys/cdefs.h> -#ifndef lint -#if 0 -static char rcsid[] = - "@(#) Header: mrinfo.c,v 1.6 93/04/08 15:14:16 van Exp (LBL)"; -#else -__RCSID("$NetBSD: mrinfo.c,v 1.2 2002/12/06 16:02:20 thorpej Exp $"); -#endif -#endif - -#include <string.h> -#include <netdb.h> -#include <sys/time.h> -#include <poll.h> -#include "defs.h" -#include <arpa/inet.h> -#include <stdarg.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 = 0; -vifi_t numvifs; /* to keep loader happy */ - /* (see COPY_TABLES macro called in kern.c) */ - -char * inet_name(u_int32_t addr); -void ask(u_int32_t dst); -void ask2(u_int32_t dst); -int get_number(int *var, int deflt, char ***pargv, - int *pargc); -u_int32_t host_addr(char *name); -void usage(void); - -/* to shut up -Wstrict-prototypes */ -int main(int argc, char *argv[]); -/* logit() prototyped in defs.h */ - - -char * -inet_name(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 -logit(int severity, int syserr, const char *format, ...) -{ - va_list ap; - - switch (debug) { - case 0: - if (severity > LOG_WARNING) - return; - case 1: - if (severity > LOG_NOTICE) - return; - case 2: - if (severity > LOG_INFO) - return; - default: - if (severity == LOG_WARNING) - fprintf(stderr, "warning - "); - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - if (syserr == 0) - fprintf(stderr, "\n"); - else - fprintf(stderr, ": %s\n", strerror(syserr)); - } - - if (severity <= LOG_ERR) - exit(1); -} - -/* - * Send a neighbors-list request. - */ -void -ask(u_int32_t dst) -{ - send_igmp(our_addr, dst, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS, - htonl(MROUTED_LEVEL), 0); -} - -void -ask2(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(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ - 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) { - u_int32_t laddr; - u_char metric; - u_char thresh; - int ncount; - - GET_ADDR(laddr); - laddr = htonl(laddr); - metric = *p++; - thresh = *p++; - ncount = *p++; - while (--ncount >= 0) { - 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(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ - u_char *ep = p + datalen; - u_int broken_cisco = ((level & 0xffff) == 0x020a); /* 10.2 */ - /* well, only possibly_broken_cisco, but that's too long to type. */ - - printf("%s (%s) [version %d.%d", inet_fmt(src, s1), inet_name(src), - level & 0xff, (level >> 8) & 0xff); - if ((level >> 16) & NF_LEAF) { printf (",leaf"); } - if ((level >> 16) & NF_PRUNE) { printf (",prune"); } - if ((level >> 16) & NF_GENID) { printf (",genid"); } - if ((level >> 16) & NF_MTRACE) { printf (",mtrace"); } - printf ("]:\n"); - - while (p < ep) { - u_char metric; - u_char thresh; - u_char flags; - int ncount; - 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) { - 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(int *var, int deflt, char ***pargv, int *pargc) -{ - 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; - } - } -} - -void -usage(void) -{ - fprintf(stderr, - "Usage: mrinfo [-n] [-t timeout] [-r retries] [router]\n"); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int tries; - int trynew; - struct timeval et; - struct hostent *hp; - struct hostent bogus; - char *host; - int curaddr; - - if (geteuid() != 0) { - fprintf(stderr, "mrinfo: must be root\n"); - exit(1); - } - init_igmp(); - if (setuid(getuid()) == -1) - logit(LOG_ERR, errno, "setuid"); - - setlinebuf(stderr); - - 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) - host = argv[0]; - else - host = "127.0.0.1"; - - if ((target_addr = inet_addr(host)) != -1) { - hp = &bogus; - hp->h_length = sizeof(target_addr); - hp->h_addr_list = (char **)malloc(2 * sizeof(char *)); - if (hp->h_addr_list == NULL) - logit(LOG_ERR, errno, "malloc"); - hp->h_addr_list[0] = malloc(hp->h_length); - if (hp->h_addr_list[0] == NULL) - logit(LOG_ERR, errno, "malloc"); - memcpy(hp->h_addr_list[0], &target_addr, sizeof(hp->h_addr_list[0])); - hp->h_addr_list[1] = NULL; - } else - hp = gethostbyname(host); - - if (hp == NULL || hp->h_length != sizeof(target_addr)) { - fprintf(stderr, "mrinfo: %s: no such host\n", argv[0]); - exit(1); - } - if (debug) - fprintf(stderr, "Debug level %u\n", debug); - - /* Check all addresses; mrouters often have unreachable interfaces */ - for (curaddr = 0; hp->h_addr_list[curaddr] != NULL; curaddr++) { - memcpy(&target_addr, hp->h_addr_list[curaddr], sizeof(target_addr)); - { /* Find a good local address for us. */ - int udp; - struct sockaddr_in addr; - int addrlen = sizeof(addr); - - memset(&addr, 0, 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; - } - - tries = 0; - trynew = 1; - /* - * New strategy: send 'ask2' for two timeouts, then fall back - * to 'ask', since it's not very likely that we are going to - * find someone who only responds to 'ask' these days - */ - ask2(target_addr); - - gettimeofday(&et, 0); - et.tv_sec += timeout; - - /* Main receive loop */ - for (;;) { - struct pollfd set[1]; - struct timeval tv, now; - int count, recvlen, dummy = 0; - u_int32_t src, dst, group; - struct ip *ip; - struct igmp *igmp; - int ipdatalen, iphdrlen, igmpdatalen; - - set[0].fd = igmp_socket; - set[0].events = POLLIN; - - gettimeofday(&now, 0); - tv.tv_sec = et.tv_sec - now.tv_sec; - tv.tv_usec = et.tv_usec - now.tv_usec; - - if (tv.tv_usec < 0) { - tv.tv_usec += 1000000L; - --tv.tv_sec; - } - if (tv.tv_sec < 0) - tv.tv_sec = tv.tv_usec = 0; - - count = poll(set, 1, tv.tv_sec * 1000 + tv.tv_usec / 1000); - - if (count < 0) { - if (errno != EINTR) - perror("select"); - continue; - } else if (count == 0) { - logit(LOG_DEBUG, 0, "Timed out receiving neighbor lists"); - if (++tries > retries) - break; - /* If we've tried ASK_NEIGHBORS2 twice with - * no response, fall back to ASK_NEIGHBORS - */ - if (tries == 2 && target_level == 0) - trynew = 0; - if (target_level == 0 && trynew == 0) - ask(target_addr); - else - ask2(target_addr); - gettimeofday(&et, 0); - et.tv_sec += timeout; - 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)) { - logit(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) { - logit(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) { - logit(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, (u_char *)(igmp + 1), - igmpdatalen, ntohl(group)); - exit(0); - } - break; - - case DVMRP_NEIGHBORS2: - accept_neighbors2(src, dst, (u_char *)(igmp + 1), - igmpdatalen, ntohl(group)); - exit(0); - } - } - } - exit(1); -} - -/* dummies */ -void accept_probe(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ -} -void accept_group_report(u_int32_t src, u_int32_t dst, u_int32_t group, - int r_type) -{ -} -void accept_neighbor_request2(u_int32_t src, u_int32_t dst) -{ -} -void accept_report(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ -} -void accept_neighbor_request(u_int32_t src, u_int32_t dst) -{ -} -void accept_prune(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void accept_graft(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void accept_g_ack(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void add_table_entry(u_int32_t origin, u_int32_t mcastgrp) -{ -} -void check_vif_state(void) -{ -} -void accept_leave_message(u_int32_t src, u_int32_t dst, u_int32_t group) -{ -} -void accept_mtrace(u_int32_t src, u_int32_t dst, u_int32_t group, char *data, - u_int no, int datalen) -{ -} -void accept_membership_query(u_int32_t src, u_int32_t dst, u_int32_t group, - int tmo) -{ -} -void accept_info_request(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ -} -void accept_info_reply(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ -} diff --git a/gnu/dist/mrouted/LICENSE b/gnu/dist/mrouted/LICENSE deleted file mode 100644 index ef7da470b11..00000000000 --- a/gnu/dist/mrouted/LICENSE +++ /dev/null @@ -1,48 +0,0 @@ - -The mrouted program is covered by the following license. Use of the -mrouted program represents acceptance of these terms and conditions. - -1. STANFORD grants to LICENSEE a nonexclusive and nontransferable license -to use, copy and modify the computer software ``mrouted'' (hereinafter -called the ``Program''), upon the terms and conditions hereinafter set -out and until Licensee discontinues use of the Licensed Program. - -2. LICENSEE acknowledges that the Program is a research tool still in -the development state, that it is being supplied ``as is,'' without any -accompanying services from STANFORD, and that this license is entered -into in order to encourage scientific collaboration aimed at further -development and application of the Program. - -3. LICENSEE may copy the Program and may sublicense others to use object -code copies of the Program or any derivative version of the Program. -All copies must contain all copyright and other proprietary notices found -in the Program as provided by STANFORD. Title to copyright to the -Program remains with STANFORD. - -4. LICENSEE may create derivative versions of the Program. LICENSEE -hereby grants STANFORD a royalty-free license to use, copy, modify, -distribute and sublicense any such derivative works. At the time -LICENSEE provides a copy of a derivative version of the Program to a -third party, LICENSEE shall provide STANFORD with one copy of the source -code of the derivative version at no charge to STANFORD. - -5. STANFORD MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. -By way of example, but not limitation, STANFORD MAKES NO REPRESENTATION -OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR -THAT THE USE OF THE LICENSED PROGRAM WILL NOT INFRINGE ANY PATENTS, -COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. STANFORD shall not be held liable -for any liability nor for any direct, indirect or consequential damages -with respect to any claim by LICENSEE or any third party on account of or -arising from this Agreement or use of the Program. - -6. This agreement shall be construed, interpreted and applied in -accordance with the State of California and any legal action arising -out of this Agreement or use of the Program shall be filed in a court -in the State of California. - -7. Nothing in this Agreement shall be construed as conferring rights to -use in advertising, publicity or otherwise any trademark or the name -of ``Stanford''. - -The mrouted program is COPYRIGHT 1989 by The Board of Trustees of -Leland Stanford Junior University. diff --git a/gnu/dist/mrouted/callout.c b/gnu/dist/mrouted/callout.c deleted file mode 100644 index 4b76d29a8ec..00000000000 --- a/gnu/dist/mrouted/callout.c +++ /dev/null @@ -1,227 +0,0 @@ -/* $NetBSD: callout.c,v 1.2 2002/12/06 16:02:55 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -#include "defs.h" - -/* the code below implements a callout queue */ -static int id = 0; -static struct timeout_q *Q = 0; /* pointer to the beginning of timeout queue */ - -static int in_callout = 0; - -struct timeout_q { - struct timeout_q *next; /* next event */ - int id; - cfunc_t func; /* function to call */ - char *data; /* func's data */ - int time; /* time offset to next event*/ -}; - -#ifdef IGMP_DEBUG -static void print_Q(void); -#else -#define print_Q() -#endif - -int secs_remaining(int); - -void -callout_init(void) -{ - Q = (struct timeout_q *) 0; -} - - -/* - * signal handler for SIGALARM that is called once every second - */ -void -age_callout_queue(void) -{ - struct timeout_q *ptr; - - if (in_callout) - return; - - in_callout = 1; - ptr = Q; - - while (ptr) { - if (!ptr->time) { - /* timeout has happened */ - Q = Q->next; - - in_callout = 0; - if (ptr->func) - ptr->func(ptr->data); - in_callout = 1; - - free(ptr); - ptr = Q; - } - else { - ptr->time --; -#ifdef IGMP_DEBUG - logit(LOG_DEBUG,0,"[callout, age_callout_queue] -- time (%d)", ptr->time); -#endif /* IGMP_DEBUG */ - in_callout = 0; return; - } - } - in_callout = 0; - return; -} - - -/* - * sets the timer - * - * delay: number of units for timeout - * action: function to be called on timeout - * data: what to call the timeout function with - */ -int -timer_setTimer(int delay, cfunc_t action, char *data) -{ - struct timeout_q *ptr, *node, *prev; - - if (in_callout) - return -1; - - in_callout = 1; - - /* create a node */ - node = (struct timeout_q *)malloc(sizeof(struct timeout_q)); - if (node == 0) { - logit(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n"); - in_callout = 0; - return -1; - } - node->func = action; - node->data = data; - node->time = delay; - node->next = 0; - node->id = ++id; - - prev = ptr = Q; - - /* insert node in the queue */ - - /* if the queue is empty, insert the node and return */ - if (!Q) - Q = node; - else { - /* chase the pointer looking for the right place */ - while (ptr) { - - if (delay < ptr->time) { - /* right place */ - - node->next = ptr; - if (ptr == Q) - Q = node; - else - prev->next = node; - ptr->time -= node->time; - print_Q(); - in_callout = 0; - return node->id; - } else { - /* keep moving */ - - delay -= ptr->time; node->time = delay; - prev = ptr; - ptr = ptr->next; - } - } - prev->next = node; - } - print_Q(); - in_callout = 0; - return node->id; -} - - -/* clears the associated timer */ -void -timer_clearTimer(int timer_id) -{ - struct timeout_q *ptr, *prev; - - if (in_callout) - return; - if (!timer_id) - return; - - in_callout = 1; - - prev = ptr = Q; - - /* - * find the right node, delete it. the subsequent node's time - * gets bumped up - */ - - print_Q(); - while (ptr) { - if (ptr->id == timer_id) { - /* got the right node */ - - /* unlink it from the queue */ - if (ptr == Q) - Q = Q->next; - else - prev->next = ptr->next; - - /* increment next node if any */ - if (ptr->next != 0) - (ptr->next)->time += ptr->time; - - free(ptr->data); - free(ptr); - print_Q(); - in_callout = 0; - return; - } - prev = ptr; - ptr = ptr->next; - } - print_Q(); - in_callout = 0; -} - -#ifdef IGMP_DEBUG -/* - * debugging utility - */ -static void -print_Q(void) -{ - struct timeout_q *ptr; - - for(ptr = Q; ptr; ptr = ptr->next) - logit(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time); -} -#endif /* IGMP_DEBUG */ - -int -secs_remaining(int timer_id) -{ - struct timeout_q *ptr; - int left=0; - - for (ptr = Q; ptr && ptr->id != timer_id; ptr = ptr->next) - left += ptr->time; - - if (!ptr) /* not found */ - return 0; - - return left + ptr->time; -} diff --git a/gnu/dist/mrouted/cfparse.y b/gnu/dist/mrouted/cfparse.y deleted file mode 100644 index a9d60476ca7..00000000000 --- a/gnu/dist/mrouted/cfparse.y +++ /dev/null @@ -1,624 +0,0 @@ -%{ -/* $NetBSD: cfparse.y,v 1.2 2002/12/06 16:02:55 thorpej Exp $ */ - -/* - * Configuration file parser for mrouted. - * - * Written by Bill Fenner, NRL, 1994 - * Copyright (c) 1994 - * Naval Research Laboratory (NRL/CCS) - * and the - * Defense Advanced Research Projects Agency (DARPA) - * - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright notice and - * this permission notice appear in all copies of the software, derivative - * works or modified versions, and any portions thereof, and that both notices - * appear in supporting documentation. - * - * NRL AND DARPA ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND - * DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM - * THE USE OF THIS SOFTWARE. - */ -#include <stdio.h> -#include <stdarg.h> -#include "defs.h" -#include <netdb.h> - -/* - * Local function declarations - */ -static void fatal(char *fmt, ...) - __attribute__((__format__(__printf__, 1, 2))); -static void warn(char *fmt, ...) - __attribute__((__format__(__printf__, 1, 2))); -static void yyerror(char *s); -static char * next_word(void); -static int yylex(void); -static u_int32_t valid_if(char *s); -static struct ifreq * ifconfaddr(struct ifconf *ifcp, u_int32_t a); -int yyparse(void); - -static FILE *f __attribute__((__unused__)); /* XXX egcs */ -extern int udp_socket; -char *configfilename = _PATH_MROUTED_CONF; - -extern int cache_lifetime; -extern int max_prune_lifetime; - -static int lineno; -static struct ifreq ifbuf[32]; -static struct ifconf ifc; - -static struct uvif *v; - -static int order; - -struct addrmask { - u_int32_t addr; - int mask; -}; - -struct boundnam { - char *name; - struct addrmask bound; -}; - -#define MAXBOUNDS 20 - -struct boundnam boundlist[MAXBOUNDS]; /* Max. of 20 named boundaries */ -int numbounds = 0; /* Number of named boundaries */ - -%} - -%union -{ - int num; - char *ptr; - struct addrmask addrmask; - u_int32_t addr; -}; - -%token CACHE_LIFETIME PRUNING -%token PHYINT TUNNEL NAME -%token DISABLE IGMPV1 SRCRT -%token METRIC THRESHOLD RATE_LIMIT BOUNDARY NETMASK ALTNET -%token SYSNAM SYSCONTACT SYSVERSION SYSLOCATION -%token <num> BOOLEAN -%token <num> NUMBER -%token <ptr> STRING -%token <addrmask> ADDRMASK -%token <addr> ADDR - -%type <addr> interface addrname -%type <addrmask> bound boundary addrmask - -%start conf - -%% - -conf : stmts - ; - -stmts : /* Empty */ - | stmts stmt - ; - -stmt : error - | PHYINT interface { - - vifi_t vifi; - - if (order) - fatal("phyints must appear before tunnels"); - - for (vifi = 0, v = uvifs; - vifi < numvifs; - ++vifi, ++v) - if (!(v->uv_flags & VIFF_TUNNEL) && - $2 == v->uv_lcl_addr) - break; - - if (vifi == numvifs) - fatal("%s is not a configured interface", - inet_fmt($2,s1)); - - } - ifmods - | TUNNEL interface addrname { - - struct ifreq *ifr; - struct ifreq ffr; - vifi_t vifi; - - order++; - - ifr = ifconfaddr(&ifc, $2); - if (ifr == 0) - fatal("Tunnel local address %s is not mine", - inet_fmt($2, s1)); - - strncpy(ffr.ifr_name, ifr->ifr_name, IFNAMSIZ); - if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ffr)<0) - fatal("ioctl SIOCGIFFLAGS on %s",ffr.ifr_name); - if (ffr.ifr_flags & IFF_LOOPBACK) - fatal("Tunnel local address %s is a loopback interface", - inet_fmt($2, s1)); - - if (ifconfaddr(&ifc, $3) != 0) - fatal("Tunnel remote address %s is one of mine", - inet_fmt($3, s1)); - - for (vifi = 0, v = uvifs; - vifi < numvifs; - ++vifi, ++v) - if (v->uv_flags & VIFF_TUNNEL) { - if ($3 == v->uv_rmt_addr) - fatal("Duplicate tunnel to %s", - inet_fmt($3, s1)); - } else if (!(v->uv_flags & VIFF_DISABLED)) { - if (($3 & v->uv_subnetmask) == v->uv_subnet) - fatal("Unnecessary tunnel to %s", - inet_fmt($3,s1)); - } - - if (numvifs == MAXVIFS) - fatal("too many vifs"); - - v = &uvifs[numvifs]; - v->uv_flags = VIFF_TUNNEL; - v->uv_metric = DEFAULT_METRIC; - v->uv_rate_limit= DEFAULT_TUN_RATE_LIMIT; - v->uv_threshold = DEFAULT_THRESHOLD; - v->uv_lcl_addr = $2; - v->uv_rmt_addr = $3; - v->uv_subnet = 0; - v->uv_subnetmask= 0; - v->uv_subnetbcast= 0; - strncpy(v->uv_name, ffr.ifr_name, IFNAMSIZ); - v->uv_groups = NULL; - v->uv_neighbors = NULL; - v->uv_acl = NULL; - v->uv_addrs = NULL; - - if (!(ffr.ifr_flags & IFF_UP)) { - v->uv_flags |= VIFF_DOWN; - vifs_down = TRUE; - } - } - tunnelmods - { - logit(LOG_INFO, 0, - "installing tunnel from %s to %s as vif #%u - rate=%d", - inet_fmt($2, s1), inet_fmt($3, s2), - numvifs, v->uv_rate_limit); - - ++numvifs; - } - | PRUNING BOOLEAN { pruning = $2; } - | CACHE_LIFETIME NUMBER { cache_lifetime = $2; - max_prune_lifetime = cache_lifetime * 2; - } - | NAME STRING boundary { if (numbounds >= MAXBOUNDS) { - fatal("Too many named boundaries (max %d)", MAXBOUNDS); - } - - boundlist[numbounds].name = malloc(strlen($2) + 1); - strcpy(boundlist[numbounds].name, $2); - boundlist[numbounds++].bound = $3; - } - | SYSNAM STRING { -#ifdef SNMP - set_sysName($2); -#endif /* SNMP */ - } - | SYSCONTACT STRING { -#ifdef SNMP - set_sysContact($2); -#endif /* SNMP */ - } - | SYSVERSION STRING { -#ifdef SNMP - set_sysVersion($2); -#endif /* SNMP */ - } - | SYSLOCATION STRING { -#ifdef SNMP - set_sysLocation($2); -#endif /* SNMP */ - } - ; - -tunnelmods : /* empty */ - | tunnelmods tunnelmod - ; - -tunnelmod : mod - | SRCRT { fatal("Source-route tunnels not supported"); } - ; - -ifmods : /* empty */ - | ifmods ifmod - ; - -ifmod : mod - | DISABLE { v->uv_flags |= VIFF_DISABLED; } - | IGMPV1 { v->uv_flags |= VIFF_IGMPV1; } - | NETMASK addrname { - u_int32_t subnet, mask; - - mask = $2; - subnet = v->uv_lcl_addr & mask; - if (!inet_valid_subnet(subnet, mask)) - fatal("Invalid netmask"); - v->uv_subnet = subnet; - v->uv_subnetmask = mask; - v->uv_subnetbcast = subnet | ~mask; - } - | NETMASK { - - warn("Expected address after netmask keyword, ignored"); - - } - | ALTNET addrmask { - - struct phaddr *ph; - - ph = (struct phaddr *)malloc(sizeof(struct phaddr)); - if (ph == NULL) - fatal("out of memory"); - if ($2.mask) { - VAL_TO_MASK(ph->pa_subnetmask, $2.mask); - } else - ph->pa_subnetmask = v->uv_subnetmask; - ph->pa_subnet = $2.addr & ph->pa_subnetmask; - ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask; - if ($2.addr & ~ph->pa_subnetmask) - warn("Extra subnet %s/%d has host bits set", - inet_fmt($2.addr,s1), $2.mask); - ph->pa_next = v->uv_addrs; - v->uv_addrs = ph; - - } - | ALTNET { - - warn("Expected address after altnet keyword, ignored"); - - } - ; - -mod : THRESHOLD NUMBER { if ($2 < 1 || $2 > 255) - fatal("Invalid threshold %d",$2); - v->uv_threshold = $2; - } - | THRESHOLD { - - warn("Expected number after threshold keyword, ignored"); - - } - | METRIC NUMBER { if ($2 < 1 || $2 > UNREACHABLE) - fatal("Invalid metric %d",$2); - v->uv_metric = $2; - } - | METRIC { - - warn("Expected number after metric keyword, ignored"); - - } - | RATE_LIMIT NUMBER { if ($2 > MAX_RATE_LIMIT) - fatal("Invalid rate_limit %d",$2); - v->uv_rate_limit = $2; - } - | RATE_LIMIT { - - warn("Expected number after rate_limit keyword, ignored"); - - } - | BOUNDARY bound { - - struct vif_acl *v_acl; - - v_acl = (struct vif_acl *)malloc(sizeof(struct vif_acl)); - if (v_acl == NULL) - fatal("out of memory"); - VAL_TO_MASK(v_acl->acl_mask, $2.mask); - v_acl->acl_addr = $2.addr & v_acl->acl_mask; - if ($2.addr & ~v_acl->acl_mask) - warn("Boundary spec %s/%d has host bits set", - inet_fmt($2.addr,s1),$2.mask); - v_acl->acl_next = v->uv_acl; - v->uv_acl = v_acl; - - } - | BOUNDARY { - - warn("Expected boundary spec after boundary keyword, ignored"); - - } - ; - -interface : ADDR { $$ = $1; } - | STRING { - $$ = valid_if($1); - if ($$ == 0) - fatal("Invalid interface name %s",$1); - } - ; - -addrname : ADDR { $$ = $1; } - | STRING { struct hostent *hp; - - if ((hp = gethostbyname($1)) == NULL) - fatal("No such host %s", $1); - - if (hp->h_addr_list[1]) - fatal("Hostname %s does not %s", - $1, "map to a unique address"); - - bcopy(hp->h_addr_list[0], &$$, - hp->h_length); - } - -bound : boundary { $$ = $1; } - | STRING { int i; - - for (i=0; i < numbounds; i++) { - if (!strcmp(boundlist[i].name, $1)) { - $$ = boundlist[i].bound; - break; - } - } - if (i == numbounds) { - fatal("Invalid boundary name %s",$1); - } - } - ; - -boundary : ADDRMASK { - - if ((ntohl($1.addr) & 0xff000000) != 0xef000000) { - fatal("Boundaries must be 239.x.x.x, not %s/%d", - inet_fmt($1.addr, s1), $1.mask); - } - $$ = $1; - - } - ; - -addrmask : ADDRMASK { $$ = $1; } - | ADDR { $$.addr = $1; $$.mask = 0; } - ; -%% -static void -fatal(char *fmt, ...) -{ - va_list ap; - char buf[200]; - - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - va_end(ap); - - logit(LOG_ERR,0,"%s: %s near line %d", configfilename, buf, lineno); -} - -static void -warn(char *fmt, ...) -{ - va_list ap; - char buf[200]; - - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - va_end(ap); - - logit(LOG_WARNING,0,"%s: %s near line %d", configfilename, buf, lineno); -} - -static void -yyerror(s) -char *s; -{ - logit(LOG_ERR, 0, "%s: %s near line %d", configfilename, s, lineno); -} - -static char * -next_word() -{ - static char buf[1024]; - static char *p=NULL; - extern FILE *f; - char *q; - - while (1) { - if (!p || !*p) { - lineno++; - if (fgets(buf, sizeof(buf), f) == NULL) - return NULL; - p = buf; - } - while (*p && (*p == ' ' || *p == '\t')) /* skip whitespace */ - p++; - if (*p == '#') { - p = NULL; /* skip comments */ - continue; - } - q = p; -#ifdef SNMP - if (*p == '"') { - p++; - while (*p && *p != '"' && *p != '\n') - p++; /* find next whitespace */ - if (*p == '"') - p++; - } else -#endif - while (*p && *p != ' ' && *p != '\t' && *p != '\n') - p++; /* find next whitespace */ - *p++ = '\0'; /* null-terminate string */ - - if (!*q) { - p = NULL; - continue; /* if 0-length string, read another line */ - } - - return q; - } -} - -static int -yylex() -{ - int n; - u_int32_t addr; - char *q; - - if ((q = next_word()) == NULL) { - return 0; - } - - if (!strcmp(q,"cache_lifetime")) - return CACHE_LIFETIME; - if (!strcmp(q,"pruning")) - return PRUNING; - if (!strcmp(q,"phyint")) - return PHYINT; - if (!strcmp(q,"tunnel")) - return TUNNEL; - if (!strcmp(q,"disable")) - return DISABLE; - if (!strcmp(q,"metric")) - return METRIC; - if (!strcmp(q,"threshold")) - return THRESHOLD; - if (!strcmp(q,"rate_limit")) - return RATE_LIMIT; - if (!strcmp(q,"srcrt") || !strcmp(q,"sourceroute")) - return SRCRT; - if (!strcmp(q,"boundary")) - return BOUNDARY; - if (!strcmp(q,"netmask")) - return NETMASK; - if (!strcmp(q,"igmpv1")) - return IGMPV1; - if (!strcmp(q,"altnet")) - return ALTNET; - if (!strcmp(q,"name")) - return NAME; - if (!strcmp(q,"on") || !strcmp(q,"yes")) { - yylval.num = 1; - return BOOLEAN; - } - if (!strcmp(q,"off") || !strcmp(q,"no")) { - yylval.num = 0; - return BOOLEAN; - } - if (sscanf(q,"%[.0-9]/%d%c",s1,&n,s2) == 2) { - if ((addr = inet_parse(s1)) != 0xffffffff) { - yylval.addrmask.mask = n; - yylval.addrmask.addr = addr; - return ADDRMASK; - } - /* fall through to returning STRING */ - } - if (sscanf(q,"%[.0-9]%c",s1,s2) == 1) { - if ((addr = inet_parse(s1)) != 0xffffffff && - inet_valid_host(addr)) { - yylval.addr = addr; - return ADDR; - } - } - if (sscanf(q,"0x%8x%c",&n,s1) == 1) { - yylval.addr = n; - return ADDR; - } - if (sscanf(q,"%d%c",&n,s1) == 1) { - yylval.num = n; - return NUMBER; - } -#ifdef SNMP - if (!strcmp(q,"sysName")) - return SYSNAM; - if (!strcmp(q,"sysContact")) - return SYSCONTACT; - if (!strcmp(q,"sysVersion")) - return SYSVERSION; - if (!strcmp(q,"sysLocation")) - return SYSLOCATION; - if (*q=='"') { - if (q[ strlen(q)-1 ]=='"') - q[ strlen(q)-1 ]='\0'; /* trash trailing quote */ - yylval.ptr = q+1; - return STRING; - } -#endif - yylval.ptr = q; - return STRING; -} - -void -config_vifs_from_file() -{ - extern FILE *f; - - order = 0; - numbounds = 0; - lineno = 0; - - if ((f = fopen(configfilename, "r")) == NULL) { - if (errno != ENOENT) - logit(LOG_ERR, errno, "can't open %s", configfilename); - return; - } - - ifc.ifc_buf = (char *)ifbuf; - ifc.ifc_len = sizeof(ifbuf); - if (ioctl(udp_socket, SIOCGIFCONF, (char *)&ifc) < 0) - logit(LOG_ERR, errno, "ioctl SIOCGIFCONF"); - - yyparse(); - - fclose(f); -} - -static u_int32_t -valid_if(s) -char *s; -{ - vifi_t vifi; - struct uvif *v; - - for (vifi=0, v=uvifs; vifi<numvifs; vifi++, v++) - if (!strcmp(v->uv_name, s)) - return v->uv_lcl_addr; - - return 0; -} - -static struct ifreq * -ifconfaddr(ifcp, a) - struct ifconf *ifcp; - u_int32_t a; -{ - int n; - struct ifreq *ifrp = (struct ifreq *)ifcp->ifc_buf; - struct ifreq *ifend = (struct ifreq *)((char *)ifrp + ifcp->ifc_len); - - while (ifrp < ifend) { - if (ifrp->ifr_addr.sa_family == AF_INET && - ((struct sockaddr_in *)&ifrp->ifr_addr)->sin_addr.s_addr == a) - return (ifrp); -#if (defined(BSD) && (BSD >= 199006)) - n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - ++ifrp; - else - ifrp = (struct ifreq *)((char *)ifrp + n); -#else - ++ifrp; -#endif - } - return (0); -} diff --git a/gnu/dist/mrouted/config.c b/gnu/dist/mrouted/config.c deleted file mode 100644 index 6667594ff0f..00000000000 --- a/gnu/dist/mrouted/config.c +++ /dev/null @@ -1,121 +0,0 @@ -/* $NetBSD: config.c,v 1.2 2002/12/06 16:02:55 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -#include "defs.h" -#include <net/if.h> -#include <ifaddrs.h> - - -/* - * Query the kernel to find network interfaces that are multicast-capable - * and install them in the uvifs array. - */ -void -config_vifs_from_kernel(void) -{ - struct ifaddrs *ifa, *ifap; - struct uvif *v; - vifi_t vifi; - u_int32_t addr, mask, subnet; - short flags; - - if (getifaddrs(&ifap) < 0) - logit(LOG_ERR, errno, "getifaddrs"); - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - /* - * Ignore any interface for an address family other than IP. - */ - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - - addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr; - - /* - * Ignore loopback interfaces and interfaces that do not support - * multicast. - */ - flags = ifa->ifa_flags; - if ((flags & (IFF_LOOPBACK|IFF_MULTICAST)) != IFF_MULTICAST) - continue; - - /* - * Ignore any interface whose address and mask do not define a - * valid subnet number, or whose address is of the form {subnet,0} - * or {subnet,-1}. - */ - mask = ((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr.s_addr; - subnet = addr & mask; - if (!inet_valid_subnet(subnet, mask) || - addr == subnet || - addr == (subnet | ~mask)) { - logit(LOG_WARNING, 0, - "ignoring %s, has invalid address (%s) and/or mask (%s)", - ifa->ifa_name, inet_fmt(addr, s1), inet_fmt(mask, s2)); - continue; - } - - /* - * Ignore any interface that is connected to the same subnet as - * one already installed in the uvifs array. - */ - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if ((addr & v->uv_subnetmask) == v->uv_subnet || - (v->uv_subnet & mask) == subnet) { - logit(LOG_WARNING, 0, "ignoring %s, same subnet as %s", - ifa->ifa_name, v->uv_name); - break; - } - } - if (vifi != numvifs) - continue; - - /* - * If there is room in the uvifs array, install this interface. - */ - if (numvifs == MAXVIFS) { - logit(LOG_WARNING, 0, "too many vifs, ignoring %s", ifa->ifa_name); - continue; - } - v = &uvifs[numvifs]; - v->uv_flags = 0; - v->uv_metric = DEFAULT_METRIC; - v->uv_rate_limit = DEFAULT_PHY_RATE_LIMIT; - v->uv_threshold = DEFAULT_THRESHOLD; - v->uv_lcl_addr = addr; - v->uv_rmt_addr = 0; - v->uv_subnet = subnet; - v->uv_subnetmask = mask; - v->uv_subnetbcast = subnet | ~mask; - strlcpy(v->uv_name, ifa->ifa_name, sizeof(v->uv_name)); - v->uv_groups = NULL; - v->uv_neighbors = NULL; - v->uv_acl = NULL; - v->uv_addrs = NULL; - - logit(LOG_INFO,0,"installing %s (%s on subnet %s) as vif #%u - rate=%d", - v->uv_name, inet_fmt(addr, s1), inet_fmts(subnet, mask, s2), - numvifs, v->uv_rate_limit); - - ++numvifs; - - /* - * If the interface is not yet up, set the vifs_down flag to - * remind us to check again later. - */ - if (!(flags & IFF_UP)) { - v->uv_flags |= VIFF_DOWN; - vifs_down = TRUE; - } - } - - freeifaddrs(ifap); -} diff --git a/gnu/dist/mrouted/defs.h b/gnu/dist/mrouted/defs.h deleted file mode 100644 index ce6afe4351c..00000000000 --- a/gnu/dist/mrouted/defs.h +++ /dev/null @@ -1,304 +0,0 @@ -/* $NetBSD: defs.h,v 1.2 2002/12/06 16:02:55 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <syslog.h> -#include <signal.h> -#include <string.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#ifdef SYSV -#include <sys/sockio.h> -#endif -#include <sys/time.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/igmp.h> -#include <netinet/ip_mroute.h> -#ifdef RSRR -#include <sys/un.h> -#endif /* RSRR */ - -typedef void (*cfunc_t)(void *); -typedef void (*ihfunc_t)(int, fd_set *); - -#include "dvmrp.h" -#include "vif.h" -#include "route.h" -#include "prune.h" -#include "pathnames.h" -#ifdef RSRR -#include "rsrr.h" -#include "rsrr_var.h" -#endif /* RSRR */ - -/* - * Miscellaneous constants and macros. - */ -#define FALSE 0 -#define TRUE 1 - -#define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0) - -#define TIMER_INTERVAL ROUTE_MAX_REPORT_DELAY - -#define VENDOR_CODE 1 /* Get a new vendor code if you make significant - * changes to mrouted. */ - -#define PROTOCOL_VERSION 3 /* increment when packet format/content changes */ - -#define MROUTED_VERSION 8 /* increment on local changes or bug fixes, */ - /* reset to 0 whever PROTOCOL_VERSION increments */ - -#define MROUTED_LEVEL ((MROUTED_VERSION << 8) | PROTOCOL_VERSION | \ - ((NF_PRUNE | NF_GENID | NF_MTRACE) << 16) | \ - (VENDOR_CODE << 24)) - /* for IGMP 'group' field of DVMRP messages */ - -#define LEAF_FLAGS (( vifs_with_neighbors == 1 ) ? 0x010000 : 0) - /* more for IGMP 'group' field of DVMRP messages */ -#define DEL_RTE_GROUP 0 -#define DEL_ALL_ROUTES 1 - /* for Deleting kernel table entries */ - -/* obnoxious gcc gives an extraneous warning about this constant... */ -#define JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ - -#ifdef RSRR -#define BIT_ZERO(X) ((X) = 0) -#define BIT_SET(X,n) ((X) |= 1 << (n)) -#define BIT_CLR(X,n) ((X) &= ~(1 << (n))) -#define BIT_TST(X,n) ((X) & 1 << (n)) -#endif /* RSRR */ - -#ifdef SYSV -#define bcopy(a, b, c) memcpy(b, a, c) -#define bzero(s, n) memset((s), 0, (n)) -#define setlinebuf(s) setvbuf(s, NULL, _IOLBF, 0) -#define signal(s,f) sigset(s,f) -#endif - -/* - * External declarations for global variables and functions. - */ -#define RECV_BUF_SIZE 8192 -extern char *recv_buf; -extern char *send_buf; -extern int igmp_socket; -#ifdef RSRR -extern int rsrr_socket; -#endif /* RSRR */ -extern u_int32_t allhosts_group; -extern u_int32_t allrtrs_group; -extern u_int32_t dvmrp_group; -extern u_int32_t dvmrp_genid; - -#define DEFAULT_DEBUG 2 /* default if "-d" given without value */ - -extern int debug; -extern u_char pruning; - -extern int routes_changed; -extern int delay_change_reports; -extern unsigned nroutes; - -extern struct uvif uvifs[MAXVIFS]; -extern vifi_t numvifs; -extern int vifs_down; -extern int udp_socket; -extern int vifs_with_neighbors; - -extern char s1[]; -extern char s2[]; -extern char s3[]; -extern char s4[]; - -#if !(defined(BSD) && (BSD >= 199103)) -extern int errno; -extern int sys_nerr; -extern char * sys_errlist[]; -#endif - -#ifdef OLD_KERNEL -#define MRT_INIT DVMRP_INIT -#define MRT_DONE DVMRP_DONE -#define MRT_ADD_VIF DVMRP_ADD_VIF -#define MRT_DEL_VIF DVMRP_DEL_VIF -#define MRT_ADD_MFC DVMRP_ADD_MFC -#define MRT_DEL_MFC DVMRP_DEL_MFC - -#define IGMP_PIM 0x14 -#endif - -/* main.c */ -extern void logit(int, int, const char *, ...) - __attribute__((__format__(__printf__, 3, 4))); -extern int register_input_handler(int fd, ihfunc_t func); - -/* igmp.c */ -extern void init_igmp(void); -extern void accept_igmp(int recvlen); -extern void send_igmp(u_int32_t src, u_int32_t dst, int type, - int code, u_int32_t group, int datalen); - -/* callout.c */ -extern void callout_init(void); -extern void age_callout_queue(void); -extern int timer_setTimer(int delay, cfunc_t action, char *data); -extern void timer_clearTimer(int timer_id); - -/* route.c */ -extern void init_routes(void); -extern void start_route_updates(void); -extern void update_route(u_int32_t origin, u_int32_t mask, - u_int metric, u_int32_t src, vifi_t vifi); -extern void age_routes(void); -extern void expire_all_routes(void); -extern void free_all_routes(void); -extern void accept_probe(u_int32_t src, u_int32_t dst, - char *p, int datalen, u_int32_t level); -extern void accept_report(u_int32_t src, u_int32_t dst, - char *p, int datalen, u_int32_t level); -extern struct rtentry * determine_route(u_int32_t src); -extern void report(int which_routes, vifi_t vifi, u_int32_t dst); -extern void report_to_all_neighbors(int which_routes); -extern int report_next_chunk(void); -extern void add_vif_to_routes(vifi_t vifi); -extern void delete_vif_from_routes(vifi_t vifi); -extern void delete_neighbor_from_routes(u_int32_t addr, - vifi_t vifi); -extern void dump_routes(FILE *fp); -extern void start_route_updates(void); - -/* vif.c */ -extern void init_vifs(void); -extern void check_vif_state(void); -extern vifi_t find_vif(u_int32_t src, u_int32_t dst); -extern void age_vifs(void); -extern void dump_vifs(FILE *fp); -extern void stop_all_vifs(void); -extern struct listaddr *neighbor_info(vifi_t vifi, u_int32_t addr); -extern void accept_group_report(u_int32_t src, u_int32_t dst, - u_int32_t group, int r_type); -extern void query_groups(void); -extern void probe_for_neighbors(void); -extern int update_neighbor(vifi_t vifi, u_int32_t addr, - int msgtype, char *p, int datalen, - u_int32_t level); -extern void accept_neighbor_request(u_int32_t src, u_int32_t dst); -extern void accept_neighbor_request2(u_int32_t src, u_int32_t dst); -extern void accept_neighbors(u_int32_t src, u_int32_t dst, - u_char *p, int datalen, - u_int32_t level); -extern void accept_neighbors2(u_int32_t src, u_int32_t dst, - u_char *p, int datalen, - u_int32_t level); -extern void accept_leave_message(u_int32_t src, u_int32_t dst, - u_int32_t group); -extern void accept_membership_query(u_int32_t src, u_int32_t dst, - u_int32_t group, int tmo); - -/* config.c */ -extern void config_vifs_from_kernel(void); - -/* cfparse.y */ -extern void config_vifs_from_file(void); - -/* inet.c */ -extern int inet_valid_host(u_int32_t naddr); -extern int inet_valid_mask(u_int32_t mask); -extern int inet_valid_subnet(u_int32_t nsubnet, u_int32_t nmask); -extern char * inet_fmt(u_int32_t addr, char *s); -extern char * inet_fmts(u_int32_t addr, u_int32_t mask, char *s); -extern u_int32_t inet_parse(char *s); -extern int inet_cksum(u_short *addr, u_int len); - -/* prune.c */ -extern unsigned kroutes; -extern void add_table_entry(u_int32_t origin, u_int32_t mcastgrp); -extern void del_table_entry(struct rtentry *r, - u_int32_t mcastgrp, u_int del_flag); -extern void update_table_entry(struct rtentry *r); -extern void init_ktable(void); -extern void accept_prune(u_int32_t src, u_int32_t dst, char *p, - int datalen); -extern void steal_sources(struct rtentry *rt); -extern void reset_neighbor_state(vifi_t vifi, u_int32_t addr); -extern int grplst_mem(vifi_t vifi, u_int32_t mcastgrp); -extern int scoped_addr(vifi_t vifi, u_int32_t addr); -extern void free_all_prunes(void); -extern void age_table_entry(void); -extern void dump_cache(FILE *fp2); -extern void update_lclgrp(vifi_t vifi, u_int32_t mcastgrp); -extern void delete_lclgrp(vifi_t vifi, u_int32_t mcastgrp); -extern void chkgrp_graft(vifi_t vifi, u_int32_t mcastgrp); -extern void accept_graft(u_int32_t src, u_int32_t dst, char *p, - int datalen); -extern void accept_g_ack(u_int32_t src, u_int32_t dst, char *p, - int datalen); -/* u_int is promoted u_char */ -extern void accept_mtrace(u_int32_t src, u_int32_t dst, - u_int32_t group, char *data, u_int no, - int datalen); -extern int find_src_grp(u_int32_t, u_int32_t, u_int32_t); - -/* kern.c */ -extern void k_set_rcvbuf(int bufsize); -extern void k_hdr_include(int bool); -extern void k_set_ttl(int t); -extern void k_set_loop(int l); -extern void k_set_if(u_int32_t ifa); -extern void k_join(u_int32_t grp, u_int32_t ifa); -extern void k_leave(u_int32_t grp, u_int32_t ifa); -extern void k_init_dvmrp(void); -extern void k_stop_dvmrp(void); -extern void k_add_vif(vifi_t vifi, struct uvif *v); -extern void k_del_vif(vifi_t vifi); -extern void k_add_rg(u_int32_t origin, struct gtable *g); -extern int k_del_rg(u_int32_t origin, struct gtable *g); -extern int k_get_version(void); - -#ifdef SNMP -/* prune.c */ -extern struct rtentry * snmp_find_route(); -extern struct gtable * find_grp(); -extern struct stable * find_grp_src(); -#endif - -#ifdef RSRR -/* prune.c */ -extern struct gtable *kernel_table; -extern struct gtable *gtp; -extern int find_src_grp(u_int32_t src, u_int32_t mask, - u_int32_t grp); - -/* rsrr.c */ -extern void rsrr_init(void); -extern void rsrr_read(int f, fd_set *rfd); -extern void rsrr_clean(void); -extern void rsrr_cache_send(struct gtable *gt, int notify); -extern void rsrr_cache_clean(struct gtable *gt); -#endif /* RSRR */ - -/* vif.c */ -extern void accept_info_reply(u_int32_t, u_int32_t, u_char *, int); -extern void accept_info_request(u_int32_t, u_int32_t, - u_char *, int); -extern void init_installvifs(void); diff --git a/gnu/dist/mrouted/dvmrp.h b/gnu/dist/mrouted/dvmrp.h deleted file mode 100644 index a7e71a9bdc3..00000000000 --- a/gnu/dist/mrouted/dvmrp.h +++ /dev/null @@ -1,173 +0,0 @@ -/* $NetBSD: dvmrp.h,v 1.1 2002/10/01 03:31:07 itojun Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -/* - * A DVMRP message consists of an IP header + an IGMP header + (for some types) - * zero or more bytes of data. - * - * For REPORT messages, the data is route information; the route information - * consists of one or more lists of the following form: - * - * (mask, (origin, metric), (origin, metric), ...) - * - * where: - * - * "mask" is the subnet mask for all the origins in the list. - * It is always THREE bytes long, containing the low-order - * three bytes of the mask (the high-order byte is always - * 0xff and therefore need not be transmitted). - * - * "origin" is the number of a subnet from which multicast datagrams - * may originate. It is from one to four bytes long, - * depending on the value of "mask": - * if all bytes of the mask are zero - * the subnet number is one byte long - * else if the low-order two bytes of the mask are zero - * the subnet number is two bytes long - * else if the lowest-order byte of the mask is zero - * the subnet number is three bytes long, - * else - * the subnet number is four bytes long. - * - * "metric" is a one-byte value consisting of two subfields: - * - the high-order bit is a flag which, when set, indicates - * the last (origin, metric) pair of a list. - * - the low-order seven bits contain the routing metric for - * the corresponding origin, relative to the sender of the - * DVMRP report. The metric may have the value of UNREACHABLE - * added to it as a "split horizon" indication (so called - * "poisoned reverse"). - * - * Within a list, the origin subnet numbers must be in ascending order, and - * the lists themselves are in order of increasing mask value. A message may - * not exceed 576 bytes, the default maximum IP reassembly size, including - * the IP and IGMP headers; the route information may be split across more - * than one message if necessary, by terminating a list in one message and - * starting a new list in the next message (repeating the same mask value, - * if necessary). - * - * For NEIGHBORS messages, the data is neighboring-router information - * consisting of one or more lists of the following form: - * - * (local-addr, metric, threshold, ncount, neighbor, neighbor, ...) - * - * where: - * - * "local-addr" is the sending router's address as seen by the neighbors - * in this list; it is always four bytes long. - * "metric" is a one-byte unsigned value, the TTL `cost' of forwarding - * packets to any of the neighbors on this list. - * "threshold" is a one-byte unsigned value, a lower bound on the TTL a - * packet must have to be forwarded to any of the neighbors on - * this list. - * "ncount" is the number of neighbors in this list. - * "neighbor" is the address of a neighboring router, four bytes long. - * - * As with REPORT messages, NEIGHBORS messages should not exceed 576 bytes, - * including the IP and IGMP headers; split longer messages by terminating the - * list in one and continuing in another, repeating the local-addr, etc., if - * necessary. - * - * For NEIGHBORS2 messages, the data is identical to NEIGHBORS except - * there is a flags byte before the neighbor count: - * - * (local-addr, metric, threshold, flags, ncount, neighbor, neighbor, ...) - */ - -/* - * DVMRP message types (carried in the "code" field of an IGMP header) - */ -#define DVMRP_PROBE 1 /* for finding neighbors */ -#define DVMRP_REPORT 2 /* for reporting some or all routes */ -#define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ - /* of this router's neighbors. */ -#define DVMRP_NEIGHBORS 4 /* response to such a request */ -#define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ -#define DVMRP_NEIGHBORS2 6 -#define DVMRP_PRUNE 7 /* prune message */ -#define DVMRP_GRAFT 8 /* graft message */ -#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ -#define DVMRP_INFO_REQUEST 10 /* information request */ -#define DVMRP_INFO_REPLY 11 /* information reply */ - -/* - * 'flags' byte values in DVMRP_NEIGHBORS2 reply. - */ -#define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ -#define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ -#define DVMRP_NF_PIM 0x04 /* neighbor is a PIM neighbor */ -#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ -#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ -#define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ -#define DVMRP_NF_LEAF 0x80 /* Neighbor reports that it is a leaf */ - -/* - * Request/reply types for info queries/replies - */ -#define DVMRP_INFO_VERSION 1 /* version string */ -#define DVMRP_INFO_NEIGHBORS 2 /* neighbors2 data */ - -/* - * Limit on length of route data - */ -#define MAX_IP_PACKET_LEN 576 -#define MIN_IP_HEADER_LEN 20 -#define MAX_IP_HEADER_LEN 60 -#define MAX_DVMRP_DATA_LEN \ - ( MAX_IP_PACKET_LEN - MAX_IP_HEADER_LEN - IGMP_MINLEN ) - -/* - * Various protocol constants (all times in seconds) - */ - /* address for multicast DVMRP msgs */ -#define INADDR_DVMRP_GROUP (u_int32_t)0xe0000004 /* 224.0.0.4 */ -/* - * The IGMPv2 <netinet/in.h> defines INADDR_ALLRTRS_GROUP, but earlier - * ones don't, so we define it conditionally here. - */ -#ifndef INADDR_ALLRTRS_GROUP - /* address for multicast mtrace msg */ -#define INADDR_ALLRTRS_GROUP (u_int32_t)0xe0000002 /* 224.0.0.2 */ -#endif - -#define ROUTE_MAX_REPORT_DELAY 5 /* max delay for reporting changes */ - /* (This is the timer interrupt */ - /* interval; all times must be */ - /* multiples of this value.) */ - -#define ROUTE_REPORT_INTERVAL 60 /* periodic route report interval */ -#define ROUTE_SWITCH_TIME 140 /* time to switch to equivalent gw */ -#define ROUTE_EXPIRE_TIME 200 /* time to mark route invalid */ -#define ROUTE_DISCARD_TIME 340 /* time to garbage collect route */ - -#define LEAF_CONFIRMATION_TIME 200 /* time to consider subnet a leaf */ - -#define NEIGHBOR_PROBE_INTERVAL 10 /* periodic neighbor probe interval */ -#define NEIGHBOR_EXPIRE_TIME 140 /* time to consider neighbor gone */ - -#define GROUP_QUERY_INTERVAL 125 /* periodic group query interval */ -#define GROUP_EXPIRE_TIME 270 /* time to consider group gone */ -#define LEAVE_EXPIRE_TIME 3 /* " " after receiving a leave */ -/* Note: LEAVE_EXPIRE_TIME should ideally be shorter, but the resolution of - * the timer in mrouted doesn't allow us to make it any shorter. */ - -#define UNREACHABLE 32 /* "infinity" metric, must be <= 64 */ -#define DEFAULT_METRIC 1 /* default subnet/tunnel metric */ -#define DEFAULT_THRESHOLD 1 /* default subnet/tunnel threshold */ - -#define MAX_RATE_LIMIT 100000 /* max rate limit */ -#define DEFAULT_PHY_RATE_LIMIT 0 /* default phyint rate limit */ -#define DEFAULT_TUN_RATE_LIMIT 500 /* default tunnel rate limit */ - -#define DEFAULT_CACHE_LIFETIME 300 /* kernel route entry discard time */ -#define GRAFT_TIMEOUT_VAL 5 /* retransmission time for grafts */ - -#define OLD_AGE_THRESHOLD 2 diff --git a/gnu/dist/mrouted/igmp.c b/gnu/dist/mrouted/igmp.c deleted file mode 100644 index 9c2670fe674..00000000000 --- a/gnu/dist/mrouted/igmp.c +++ /dev/null @@ -1,351 +0,0 @@ -/* $NetBSD: igmp.c,v 1.2 2002/12/06 16:02:56 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include "defs.h" - - -/* - * Exported variables. - */ -char *recv_buf; /* input packet buffer */ -char *send_buf; /* output packet buffer */ -int igmp_socket; /* socket for all network I/O */ -u_int32_t allhosts_group; /* All hosts addr in net order */ -u_int32_t allrtrs_group; /* All-Routers " in net order */ -u_int32_t dvmrp_group; /* DVMRP grp addr in net order */ -u_int32_t dvmrp_genid; /* IGMP generation id */ - -/* - * Local function definitions. - */ -/* u_char promoted to u_int */ -static char * packet_kind(u_int type, u_int code); -static int igmp_log_level(u_int type, u_int code); - -/* - * Open and initialize the igmp socket, and fill in the non-changing - * IP header fields in the output packet buffer. - */ -void -init_igmp(void) -{ - struct ip *ip; - - recv_buf = malloc(RECV_BUF_SIZE); - send_buf = malloc(RECV_BUF_SIZE); - - if ((igmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP)) < 0) - logit(LOG_ERR, errno, "IGMP socket"); - - k_hdr_include(TRUE); /* include IP header when sending */ - k_set_rcvbuf(48*1024); /* lots of input buffering */ - k_set_ttl(1); /* restrict multicasts to one hop */ - k_set_loop(FALSE); /* disable multicast loopback */ - - ip = (struct ip *)send_buf; - ip->ip_hl = sizeof(struct ip) >> 2; - ip->ip_v = IPVERSION; - ip->ip_tos = 0; - ip->ip_off = 0; - ip->ip_p = IPPROTO_IGMP; - ip->ip_ttl = MAXTTL; /* applies to unicasts only */ - - allhosts_group = htonl(INADDR_ALLHOSTS_GROUP); - dvmrp_group = htonl(INADDR_DVMRP_GROUP); - allrtrs_group = htonl(INADDR_ALLRTRS_GROUP); -} - -#define PIM_QUERY 0 -#define PIM_REGISTER 1 -#define PIM_REGISTER_STOP 2 -#define PIM_JOIN_PRUNE 3 -#define PIM_RP_REACHABLE 4 -#define PIM_ASSERT 5 -#define PIM_GRAFT 6 -#define PIM_GRAFT_ACK 7 - -static char * -packet_kind(u_int type, u_int code) -{ - switch (type) { - case IGMP_HOST_MEMBERSHIP_QUERY: return "membership query "; - case IGMP_v1_HOST_MEMBERSHIP_REPORT: return "v1 member report "; - case IGMP_v2_HOST_MEMBERSHIP_REPORT: return "v2 member report "; - case IGMP_HOST_LEAVE_MESSAGE: return "leave message "; - case IGMP_DVMRP: - switch (code) { - case DVMRP_PROBE: return "neighbor probe "; - case DVMRP_REPORT: return "route report "; - case DVMRP_ASK_NEIGHBORS: return "neighbor request "; - case DVMRP_NEIGHBORS: return "neighbor list "; - case DVMRP_ASK_NEIGHBORS2: return "neighbor request 2"; - case DVMRP_NEIGHBORS2: return "neighbor list 2 "; - case DVMRP_PRUNE: return "prune message "; - case DVMRP_GRAFT: return "graft message "; - case DVMRP_GRAFT_ACK: return "graft message ack "; - case DVMRP_INFO_REQUEST: return "info request "; - case DVMRP_INFO_REPLY: return "info reply "; - default: return "unknown DVMRP msg "; - } - case IGMP_PIM: - switch (code) { - case PIM_QUERY: return "PIM Router-Query "; - case PIM_REGISTER: return "PIM Register "; - case PIM_REGISTER_STOP: return "PIM Register-Stop "; - case PIM_JOIN_PRUNE: return "PIM Join/Prune "; - case PIM_RP_REACHABLE: return "PIM RP-Reachable "; - case PIM_ASSERT: return "PIM Assert "; - case PIM_GRAFT: return "PIM Graft "; - case PIM_GRAFT_ACK: return "PIM Graft-Ack "; - default: return "unknown PIM msg "; - } - case IGMP_MTRACE_QUERY: return "IGMP trace query "; - case IGMP_MTRACE_REPLY: return "IGMP trace reply "; - default: return "unknown IGMP msg "; - } -} - -/* - * Process a newly received IGMP packet that is sitting in the input - * packet buffer. - */ -void -accept_igmp(int recvlen) -{ - u_int32_t src, dst, group; - struct ip *ip; - struct igmp *igmp; - int ipdatalen, iphdrlen, igmpdatalen; - - if (recvlen < sizeof(struct ip)) { - logit(LOG_WARNING, 0, - "received packet too short (%u bytes) for IP header", recvlen); - return; - } - - ip = (struct ip *)recv_buf; - src = ip->ip_src.s_addr; - dst = ip->ip_dst.s_addr; - - /* - * this is most likely a message from the kernel indicating that - * a new src grp pair message has arrived and so, it would be - * necessary to install a route into the kernel for this. - */ - if (ip->ip_p == 0) { - if (src == 0 || dst == 0) - logit(LOG_WARNING, 0, "kernel request not accurate"); - else - add_table_entry(src, dst); - return; - } - - iphdrlen = ip->ip_hl << 2; - ipdatalen = ip->ip_len; - if (iphdrlen + ipdatalen != recvlen) { - logit(LOG_WARNING, 0, - "received packet from %s shorter (%u bytes) than hdr+data length (%u+%u)", - inet_fmt(src, s1), recvlen, iphdrlen, ipdatalen); - return; - } - - igmp = (struct igmp *)(recv_buf + iphdrlen); - group = igmp->igmp_group.s_addr; - igmpdatalen = ipdatalen - IGMP_MINLEN; - if (igmpdatalen < 0) { - logit(LOG_WARNING, 0, - "received IP data field too short (%u bytes) for IGMP, from %s", - ipdatalen, inet_fmt(src, s1)); - return; - } - - logit(LOG_DEBUG, 0, "RECV %s from %-15s to %s", - packet_kind(igmp->igmp_type, igmp->igmp_code), - inet_fmt(src, s1), inet_fmt(dst, s2)); - - switch (igmp->igmp_type) { - - case IGMP_HOST_MEMBERSHIP_QUERY: - accept_membership_query(src, dst, group, igmp->igmp_code); - return; - - case IGMP_v1_HOST_MEMBERSHIP_REPORT: - case IGMP_v2_HOST_MEMBERSHIP_REPORT: - accept_group_report(src, dst, group, igmp->igmp_type); - return; - - case IGMP_HOST_LEAVE_MESSAGE: - accept_leave_message(src, dst, group); - return; - - case IGMP_DVMRP: - group = ntohl(group); - - switch (igmp->igmp_code) { - case DVMRP_PROBE: - accept_probe(src, dst, - (char *)(igmp+1), igmpdatalen, group); - return; - - case DVMRP_REPORT: - accept_report(src, dst, - (char *)(igmp+1), igmpdatalen, group); - return; - - case DVMRP_ASK_NEIGHBORS: - accept_neighbor_request(src, dst); - return; - - case DVMRP_ASK_NEIGHBORS2: - accept_neighbor_request2(src, dst); - return; - - case DVMRP_NEIGHBORS: - accept_neighbors(src, dst, (u_char *)(igmp+1), igmpdatalen, - group); - return; - - case DVMRP_NEIGHBORS2: - accept_neighbors2(src, dst, (u_char *)(igmp+1), igmpdatalen, - group); - return; - - case DVMRP_PRUNE: - accept_prune(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - case DVMRP_GRAFT: - accept_graft(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - case DVMRP_GRAFT_ACK: - accept_g_ack(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - case DVMRP_INFO_REQUEST: - accept_info_request(src, dst, (char *)(igmp+1), - igmpdatalen); - return; - - case DVMRP_INFO_REPLY: - accept_info_reply(src, dst, (char *)(igmp+1), igmpdatalen); - return; - - default: - logit(LOG_INFO, 0, - "ignoring unknown DVMRP message code %u from %s to %s", - igmp->igmp_code, inet_fmt(src, s1), - inet_fmt(dst, s2)); - return; - } - - case IGMP_PIM: - return; - - case IGMP_MTRACE_REPLY: - return; - - case IGMP_MTRACE_QUERY: - accept_mtrace(src, dst, group, (char *)(igmp+1), - igmp->igmp_code, igmpdatalen); - return; - - default: - logit(LOG_INFO, 0, - "ignoring unknown IGMP message type %x from %s to %s", - igmp->igmp_type, inet_fmt(src, s1), - inet_fmt(dst, s2)); - return; - } -} - -/* - * Some IGMP messages are more important than others. This routine - * determines the logging level at which to log a send error (often - * "No route to host"). This is important when there is asymmetric - * reachability and someone is trying to, i.e., mrinfo me periodically. - */ -static int -igmp_log_level(u_int type, u_int code) -{ - switch (type) { - case IGMP_MTRACE_REPLY: - return LOG_INFO; - - case IGMP_DVMRP: - switch (code) { - case DVMRP_NEIGHBORS: - case DVMRP_NEIGHBORS2: - return LOG_INFO; - } - } - return LOG_WARNING; -} - -/* - * Construct an IGMP message in the output packet buffer. The caller may - * have already placed data in that buffer, of length 'datalen'. Then send - * the message from the interface with IP address 'src' to destination 'dst'. - */ -void -send_igmp(u_int32_t src, u_int32_t dst, int type, int code, u_int32_t group, - int datalen) -{ - struct sockaddr_in sdst; - struct ip *ip; - struct igmp *igmp; - int setloop; - - setloop = 0; - ip = (struct ip *)send_buf; - ip->ip_src.s_addr = src; - ip->ip_dst.s_addr = dst; - ip->ip_len = MIN_IP_HEADER_LEN + IGMP_MINLEN + datalen; - - igmp = (struct igmp *)(send_buf + MIN_IP_HEADER_LEN); - igmp->igmp_type = type; - igmp->igmp_code = code; - igmp->igmp_group.s_addr = group; - igmp->igmp_cksum = 0; - igmp->igmp_cksum = inet_cksum((u_int16_t *)igmp, - IGMP_MINLEN + datalen); - - if (IN_MULTICAST(ntohl(dst))) { - k_set_if(src); - if (type != IGMP_DVMRP) { - setloop = 1; - k_set_loop(TRUE); - } - } - - bzero(&sdst, sizeof(sdst)); - sdst.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - sdst.sin_len = sizeof(sdst); -#endif - sdst.sin_addr.s_addr = dst; - if (sendto(igmp_socket, send_buf, ip->ip_len, 0, - (struct sockaddr *)&sdst, sizeof(sdst)) < 0) { - if (errno == ENETDOWN) - check_vif_state(); - else - logit(igmp_log_level(type, code), errno, - "sendto to %s on %s", - inet_fmt(dst, s1), inet_fmt(src, s2)); - } - - if (setloop) - k_set_loop(FALSE); - - logit(LOG_DEBUG, 0, "SENT %s from %-15s to %s", - packet_kind(type, code), inet_fmt(src, s1), inet_fmt(dst, s2)); -} diff --git a/gnu/dist/mrouted/inet.c b/gnu/dist/mrouted/inet.c deleted file mode 100644 index 725a30adcd5..00000000000 --- a/gnu/dist/mrouted/inet.c +++ /dev/null @@ -1,223 +0,0 @@ -/* $NetBSD: inet.c,v 1.1 2002/10/01 03:31:08 itojun Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include "defs.h" - - -/* - * Exported variables. - */ -char s1[19]; /* buffers to hold the string representations */ -char s2[19]; /* of IP addresses, to be passed to inet_fmt() */ -char s3[19]; /* or inet_fmts(). */ -char s4[19]; - - -/* - * Verify that a given IP address is credible as a host address. - * (Without a mask, cannot detect addresses of the form {subnet,0} or - * {subnet,-1}.) - */ -int -inet_valid_host(u_int32_t naddr) -{ - u_int32_t addr; - - addr = ntohl(naddr); - - return (!(IN_MULTICAST(addr) || - IN_BADCLASS (addr) || - (addr & 0xff000000) == 0)); -} - -/* - * Verify that a given netmask is plausible; - * make sure that it is a series of 1's followed by - * a series of 0's with no discontiguous 1's. - */ -int -inet_valid_mask(u_int32_t mask) -{ - if (~(((mask & -mask) - 1) | mask) != 0) { - /* Mask is not contiguous */ - return (FALSE); - } - - return (TRUE); -} - -/* - * Verify that a given subnet number and mask pair are credible. - * - * With CIDR, almost any subnet and mask are credible. mrouted still - * can't handle aggregated class A's, so we still check that, but - * otherwise the only requirements are that the subnet address is - * within the [ABC] range and that the host bits of the subnet - * are all 0. - */ -int -inet_valid_subnet(u_int32_t nsubnet, u_int32_t nmask) -{ - u_int32_t subnet, mask; - - subnet = ntohl(nsubnet); - mask = ntohl(nmask); - - if ((subnet & mask) != subnet) return (FALSE); - - if (subnet == 0) - return (mask == 0); - - if (IN_CLASSA(subnet)) { - if (mask < 0xff000000 || - (subnet & 0xff000000) == 0x7f000000 || - (subnet & 0xff000000) == 0x00000000) return (FALSE); - } - else if (IN_CLASSD(subnet) || IN_BADCLASS(subnet)) { - /* Above Class C address space */ - return (FALSE); - } - if (subnet & ~mask) { - /* Host bits are set in the subnet */ - return (FALSE); - } - if (!inet_valid_mask(mask)) { - /* Netmask is not contiguous */ - return (FALSE); - } - - return (TRUE); -} - - -/* - * Convert an IP address in u_long (network) format into a printable string. - */ -char * -inet_fmt(u_int32_t addr, char *s) -{ - u_char *a; - - a = (u_char *)&addr; - sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); - return (s); -} - - -/* - * Convert an IP subnet number in u_long (network) format into a printable - * string including the netmask as a number of bits. - */ -char * -inet_fmts(u_int32_t addr, u_int32_t mask, char *s) -{ - u_char *a, *m; - int bits; - - if ((addr == 0) && (mask == 0)) { - sprintf(s, "default"); - return (s); - } - a = (u_char *)&addr; - m = (u_char *)&mask; - bits = 33 - ffs(ntohl(mask)); - - if (m[3] != 0) sprintf(s, "%u.%u.%u.%u/%d", a[0], a[1], a[2], a[3], - bits); - else if (m[2] != 0) sprintf(s, "%u.%u.%u/%d", a[0], a[1], a[2], bits); - else if (m[1] != 0) sprintf(s, "%u.%u/%d", a[0], a[1], bits); - else sprintf(s, "%u/%d", a[0], bits); - - return (s); -} - -/* - * Convert the printable string representation of an IP address into the - * u_long (network) format. Return 0xffffffff on error. (To detect the - * legal address with that value, you must explicitly compare the string - * with "255.255.255.255".) - */ -u_int32_t -inet_parse(char *s) -{ - u_int32_t a = 0; - u_int a0, a1, a2, a3; - char c; - - if (sscanf(s, "%u.%u.%u.%u%c", &a0, &a1, &a2, &a3, &c) != 4 || - a0 > 255 || a1 > 255 || a2 > 255 || a3 > 255) - return (0xffffffff); - - ((u_char *)&a)[0] = a0; - ((u_char *)&a)[1] = a1; - ((u_char *)&a)[2] = a2; - ((u_char *)&a)[3] = a3; - - return (a); -} - - -/* - * inet_cksum extracted from: - * P I N G . C - * - * Author - - * Mike Muuss - * U. S. Army Ballistic Research Laboratory - * December, 1983 - * Modified at Uc Berkeley - * - * (ping.c) Status - - * Public Domain. Distribution Unlimited. - * - * I N _ C K S U M - * - * Checksum routine for Internet Protocol family headers (C Version) - * - */ -int -inet_cksum(u_int16_t *addr, u_int len) -{ - int nleft = (int)len; - u_int16_t *w = addr; - int32_t sum = 0; - union { - u_int16_t w; - u_int8_t b[2]; - } answer; - - /* - * Our algorithm is simple, using a 32 bit accumulator (sum), - * we add sequential 16 bit words to it, and at the end, fold - * back all the carry bits from the top 16 bits into the lower - * 16 bits. - */ - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nleft == 1) { - answer.w = 0; - answer.b[0] = *(u_char *)w ; - sum += answer.w; - } - - /* - * add back carry outs from top 16 bits to low 16 bits - */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer.w = ~sum; /* truncate to 16 bits */ - return (answer.w); -} diff --git a/gnu/dist/mrouted/kern.c b/gnu/dist/mrouted/kern.c deleted file mode 100644 index ca2d20babe8..00000000000 --- a/gnu/dist/mrouted/kern.c +++ /dev/null @@ -1,224 +0,0 @@ -/* $NetBSD: kern.c,v 1.2 2002/12/06 16:02:56 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include "defs.h" - - -void k_set_rcvbuf(int bufsize) -{ - if (setsockopt(igmp_socket, SOL_SOCKET, SO_RCVBUF, - (char *)&bufsize, sizeof(bufsize)) < 0) - logit(LOG_ERR, errno, "setsockopt SO_RCVBUF %u", bufsize); -} - - -void k_hdr_include(int bool) -{ -#ifdef IP_HDRINCL - if (setsockopt(igmp_socket, IPPROTO_IP, IP_HDRINCL, - (char *)&bool, sizeof(bool)) < 0) - logit(LOG_ERR, errno, "setsockopt IP_HDRINCL %u", bool); -#endif -} - - -void k_set_ttl(int t) -{ - u_char ttl; - - ttl = t; - if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_TTL, - (char *)&ttl, sizeof(ttl)) < 0) - logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_TTL %u", ttl); -} - - -void k_set_loop(int l) -{ - u_char loop; - - loop = l; - if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_LOOP, - (char *)&loop, sizeof(loop)) < 0) - logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_LOOP %u", loop); -} - - -void k_set_if(u_int32_t ifa) -{ - struct in_addr adr; - - adr.s_addr = ifa; - if (setsockopt(igmp_socket, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&adr, sizeof(adr)) < 0) - logit(LOG_ERR, errno, "setsockopt IP_MULTICAST_IF %s", - inet_fmt(ifa, s1)); -} - - -void k_join(u_int32_t grp, u_int32_t ifa) -{ - struct ip_mreq mreq; - - mreq.imr_multiaddr.s_addr = grp; - mreq.imr_interface.s_addr = ifa; - - if (setsockopt(igmp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *)&mreq, sizeof(mreq)) < 0) - logit(LOG_WARNING, errno, "can't join group %s on interface %s", - inet_fmt(grp, s1), inet_fmt(ifa, s2)); -} - - -void k_leave(u_int32_t grp, u_int32_t ifa) -{ - struct ip_mreq mreq; - - mreq.imr_multiaddr.s_addr = grp; - mreq.imr_interface.s_addr = ifa; - - if (setsockopt(igmp_socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, - (char *)&mreq, sizeof(mreq)) < 0) - logit(LOG_WARNING, errno, "can't leave group %s on interface %s", - inet_fmt(grp, s1), inet_fmt(ifa, s2)); -} - - -void k_init_dvmrp(void) -{ -#ifdef OLD_KERNEL - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT, - (char *)NULL, 0) < 0) -#else - int v=1; - - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_INIT, - (char *)&v, sizeof(int)) < 0) -#endif - logit(LOG_ERR, errno, "can't enable Multicast routing in kernel"); -} - - -void k_stop_dvmrp(void) -{ - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DONE, - (char *)NULL, 0) < 0) - logit(LOG_WARNING, errno, "can't disable Multicast routing in kernel"); -} - - -void k_add_vif(vifi_t vifi, struct uvif *v) -{ - struct vifctl vc; - - vc.vifc_vifi = vifi; - vc.vifc_flags = v->uv_flags & VIFF_KERNEL_FLAGS; - vc.vifc_threshold = v->uv_threshold; - vc.vifc_rate_limit = v->uv_rate_limit; - vc.vifc_lcl_addr.s_addr = v->uv_lcl_addr; - vc.vifc_rmt_addr.s_addr = v->uv_rmt_addr; - - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_VIF, - (char *)&vc, sizeof(vc)) < 0) - logit(LOG_ERR, errno, "setsockopt MRT_ADD_VIF"); -} - - -void k_del_vif(vifi_t vifi) -{ - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_VIF, - (char *)&vifi, sizeof(vifi)) < 0) - logit(LOG_ERR, errno, "setsockopt MRT_DEL_VIF"); -} - - -/* - * Adds a (source, mcastgrp) entry to the kernel - */ -void k_add_rg(u_int32_t origin, struct gtable *g) -{ - struct mfcctl mc; - vifi_t i; - -#ifdef DEBUG_MFC - md_log(MD_ADD, origin, g->gt_mcastgrp); -#endif - /* copy table values so that setsockopt can process it */ - mc.mfcc_origin.s_addr = origin; -#ifdef OLD_KERNEL - mc.mfcc_originmask.s_addr = 0xffffffff; -#endif - mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp; - mc.mfcc_parent = g->gt_route ? g->gt_route->rt_parent : NO_VIF; - for (i = 0; i < numvifs; i++) - mc.mfcc_ttls[i] = g->gt_ttls[i]; - - /* write to kernel space */ - if (setsockopt(igmp_socket, IPPROTO_IP, MRT_ADD_MFC, - (char *)&mc, sizeof(mc)) < 0) { -#ifdef DEBUG_MFC - md_log(MD_ADD_FAIL, origin, g->gt_mcastgrp); -#endif - logit(LOG_WARNING, errno, "setsockopt MRT_ADD_MFC"); - } -} - - -/* - * Deletes a (source, mcastgrp) entry from the kernel - */ -int k_del_rg(u_int32_t origin, struct gtable *g) -{ - struct mfcctl mc; - int retval; - -#ifdef DEBUG_MFC - md_log(MD_DEL, origin, g->gt_mcastgrp); -#endif - /* copy table values so that setsockopt can process it */ - mc.mfcc_origin.s_addr = origin; -#ifdef OLD_KERNEL - mc.mfcc_originmask.s_addr = 0xffffffff; -#endif - mc.mfcc_mcastgrp.s_addr = g->gt_mcastgrp; - - /* write to kernel space */ - if ((retval = setsockopt(igmp_socket, IPPROTO_IP, MRT_DEL_MFC, - (char *)&mc, sizeof(mc))) < 0) { -#ifdef DEBUG_MFC - md_log(MD_DEL_FAIL, origin, g->gt_mcastgrp); -#endif - logit(LOG_WARNING, errno, "setsockopt MRT_DEL_MFC"); - } - - return retval; -} - -/* - * Get the kernel's idea of what version of mrouted needs to run with it. - */ -int k_get_version(void) -{ -#ifdef OLD_KERNEL - return -1; -#else - int vers; - int len = sizeof(vers); - - if (getsockopt(igmp_socket, IPPROTO_IP, MRT_VERSION, - (char *)&vers, &len) < 0) - logit(LOG_ERR, errno, - "getsockopt MRT_VERSION: perhaps your kernel is too old"); - - return vers; -#endif -} diff --git a/gnu/dist/mrouted/main.c b/gnu/dist/mrouted/main.c deleted file mode 100644 index 48512a39696..00000000000 --- a/gnu/dist/mrouted/main.c +++ /dev/null @@ -1,701 +0,0 @@ -/* $NetBSD: main.c,v 1.2 2002/12/06 16:02:56 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -/* - * Written by Steve Deering, Stanford University, February 1989. - * - * (An earlier version of DVMRP was implemented by David Waitzman of - * BBN STC by extending Berkeley's routed program. Some of Waitzman's - * extensions have been incorporated into mrouted, but none of the - * original routed code has been adopted.) - */ - - -#include "defs.h" -#include <stdarg.h> -#include <fcntl.h> - -#ifdef SNMP -#include "snmp.h" -#endif - -#include <sys/cdefs.h> -#ifndef lint -__RCSID("@(#) $NetBSD: main.c,v 1.2 2002/12/06 16:02:56 thorpej Exp $"); -#endif - -#include <err.h> -#include <util.h> - -extern char *configfilename; -char versionstring[100]; - -static char dumpfilename[] = _PATH_MROUTED_DUMP; -static char cachefilename[] = _PATH_MROUTED_CACHE; -static char genidfilename[] = _PATH_MROUTED_GENID; - -int cache_lifetime = DEFAULT_CACHE_LIFETIME; -int max_prune_lifetime = DEFAULT_CACHE_LIFETIME * 2; - -int debug = 0; -u_char pruning = 1; /* Enable pruning by default */ - -#ifdef SNMP -#define NHANDLERS 34 -#else -#define NHANDLERS 2 -#endif - -static struct ihandler { - int fd; /* File descriptor */ - ihfunc_t func; /* Function to call with &fd_set */ -} ihandlers[NHANDLERS]; -static int nhandlers = 0; - -/* - * Forward declarations. - */ -static void fasttimer(int); -static void done(int); -static void dump(int); -static void fdump(int); -static void cdump(int); -static void restart(int); -static void timer(void); -static void cleanup(void); -static void resetlogging(void *); - -/* To shut up gcc -Wstrict-prototypes */ -int main(int argc, char *argv[]); -void logit(int severity, int syserr, const char *format, ...) - __attribute__((__format__(__printf__, 3, 4))); - -int -register_input_handler(int fd, ihfunc_t func) -{ - if (nhandlers >= NHANDLERS) - return -1; - - ihandlers[nhandlers].fd = fd; - ihandlers[nhandlers++].func = func; - - return 0; -} - -int -main(int argc, char *argv[]) -{ - int recvlen; - int omask; - int dummy; - FILE *fp; - struct timeval tv; - u_int32_t prev_genid; - int vers; - fd_set rfds, readers; - int nfds, n, i; -#ifdef SNMP - struct timeval timeout, *tvp = &timeout; - struct timeval sched, *svp = &sched, now, *nvp = &now; - int index, block; -#endif - - setlinebuf(stderr); - - if (geteuid() != 0) { - fprintf(stderr, "must be root\n"); - exit(1); - } - - argv++, argc--; - while (argc > 0 && *argv[0] == '-') { - if (strcmp(*argv, "-d") == 0) { - if (argc > 1 && isdigit(*(argv + 1)[0])) { - argv++, argc--; - debug = atoi(*argv); - } else - debug = DEFAULT_DEBUG; - } else if (strcmp(*argv, "-c") == 0) { - if (argc > 1) { - argv++, argc--; - configfilename = *argv; - } else - goto usage; - } else if (strcmp(*argv, "-p") == 0) { - pruning = 0; -#ifdef SNMP - } else if (strcmp(*argv, "-P") == 0) { - if (argc > 1 && isdigit(*(argv + 1)[0])) { - argv++, argc--; - dest_port = atoi(*argv); - } else - dest_port = DEFAULT_PORT; -#endif - } else - goto usage; - argv++, argc--; - } - - if (argc > 0) { -usage: fprintf(stderr, - "usage: mrouted [-p] [-c configfile] [-d [debug_level]]\n"); - exit(1); - } - - if (debug == 0) { - /* - * Detach from the terminal - */ - if (daemon(0, 0)) - err(1, "can't fork"); - pidfile(NULL); - } - else - fprintf(stderr, "debug level %u\n", debug); - -#ifdef LOG_DAEMON - (void)openlog("mrouted", LOG_PID, LOG_DAEMON); - (void)setlogmask(LOG_UPTO(LOG_NOTICE)); -#else - (void)openlog("mrouted", LOG_PID); -#endif - sprintf(versionstring, "mrouted version %d.%d", - PROTOCOL_VERSION, MROUTED_VERSION); - - logit(LOG_NOTICE, 0, "%s", versionstring); - -#ifdef SYSV - srand48(time(NULL)); -#else - srandom(gethostid()); -#endif - - /* - * Get generation id - */ - gettimeofday(&tv, 0); - dvmrp_genid = tv.tv_sec; - - fp = fopen(genidfilename, "r"); - if (fp != NULL) { - fscanf(fp, "%d", &prev_genid); - if (prev_genid == dvmrp_genid) - dvmrp_genid++; - (void) fclose(fp); - } - - fp = fopen(genidfilename, "w"); - if (fp != NULL) { - fprintf(fp, "%d", dvmrp_genid); - (void) fclose(fp); - } - - callout_init(); - init_igmp(); - init_routes(); - init_ktable(); - k_init_dvmrp(); /* enable DVMRP routing in kernel */ - -#ifndef OLD_KERNEL - vers = k_get_version(); - /*XXX - * This function must change whenever the kernel version changes - */ - if ((((vers >> 8) & 0xff) != 3) || - ((vers & 0xff) != 5)) - logit(LOG_ERR, 0, "kernel (v%d.%d)/mrouted (v%d.%d) version mismatch", - (vers >> 8) & 0xff, vers & 0xff, - PROTOCOL_VERSION, MROUTED_VERSION); -#endif - -#ifdef SNMP - if (i = snmp_init()) - return i; - - gettimeofday(nvp, 0); - if (nvp->tv_usec < 500000L){ - svp->tv_usec = nvp->tv_usec + 500000L; - svp->tv_sec = nvp->tv_sec; - } else { - svp->tv_usec = nvp->tv_usec - 500000L; - svp->tv_sec = nvp->tv_sec + 1; - } -#endif /* SNMP */ - - init_vifs(); - -#ifdef RSRR - rsrr_init(); -#endif /* RSRR */ - - /* - * Allow cleanup if unexpected exit. Apparently some architectures - * have a kernel bug where closing the socket doesn't do an - * ip_mrouter_done(), so we attempt to do it on exit. - */ - atexit(cleanup); - - if (debug) - fprintf(stderr, "pruning %s\n", pruning ? "on" : "off"); - - (void)signal(SIGALRM, fasttimer); - - (void)signal(SIGHUP, restart); - (void)signal(SIGTERM, done); - (void)signal(SIGINT, done); - (void)signal(SIGUSR1, fdump); - (void)signal(SIGUSR2, cdump); - if (debug != 0) - (void)signal(SIGQUIT, dump); - - FD_ZERO(&readers); - if (igmp_socket >= FD_SETSIZE) - logit(LOG_ERR, 0, "descriptor too big"); - FD_SET(igmp_socket, &readers); - nfds = igmp_socket + 1; - for (i = 0; i < nhandlers; i++) { - if (ihandlers[i].fd >= FD_SETSIZE) - logit(LOG_ERR, 0, "descriptor too big"); - FD_SET(ihandlers[i].fd, &readers); - if (ihandlers[i].fd >= nfds) - nfds = ihandlers[i].fd + 1; - } - - /* - * Install the vifs in the kernel as late as possible in the - * initialization sequence. - */ - init_installvifs(); - - if (debug >= 2) dump(0); - - /* Start up the log rate-limiter */ - resetlogging(NULL); - - (void)alarm(1); /* schedule first timer interrupt */ - - /* - * Main receive loop. - */ - dummy = 0; - for(;;) { -#ifdef SYSV - sigset_t block, oblock; -#endif - bcopy((char *)&readers, (char *)&rfds, sizeof(rfds)); -#ifdef SNMP - gettimeofday(nvp, 0); - if (nvp->tv_sec > svp->tv_sec - || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){ - alarmTimer(nvp); - eventTimer(nvp); - if (nvp->tv_usec < 500000L){ - svp->tv_usec = nvp->tv_usec + 500000L; - svp->tv_sec = nvp->tv_sec; - } else { - svp->tv_usec = nvp->tv_usec - 500000L; - svp->tv_sec = nvp->tv_sec + 1; - } - } - - tvp = &timeout; - tvp->tv_sec = 0; - tvp->tv_usec = 500000L; - - block = 0; - snmp_select_info(&nfds, &rfds, tvp, &block); - if (block == 1) - tvp = NULL; /* block without timeout */ - if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0) -#else - if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0) -#endif - { - if (errno != EINTR) /* SIGALRM is expected */ - logit(LOG_WARNING, errno, "select failed"); - continue; - } - - if (FD_ISSET(igmp_socket, &rfds)) { - recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, - 0, NULL, &dummy); - if (recvlen < 0) { - if (errno != EINTR) logit(LOG_ERR, errno, "recvfrom"); - continue; - } -#ifdef SYSV - (void)sigemptyset(&block); - (void)sigaddset(&block, SIGALRM); - if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0) - logit(LOG_ERR, errno, "sigprocmask"); -#else - omask = sigblock(sigmask(SIGALRM)); -#endif - accept_igmp(recvlen); -#ifdef SYSV - (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL); -#else - (void)sigsetmask(omask); -#endif - } - - for (i = 0; i < nhandlers; i++) { - if (FD_ISSET(ihandlers[i].fd, &rfds)) { - (*ihandlers[i].func)(ihandlers[i].fd, &rfds); - } - } - -#ifdef SNMP - snmp_read(&rfds); - snmp_timeout(); /* poll */ -#endif - } -} - - -/* - * routine invoked every second. Its main goal is to cycle through - * the routing table and send partial updates to all neighbors at a - * rate that will cause the entire table to be sent in ROUTE_REPORT_INTERVAL - * seconds. Also, every TIMER_INTERVAL seconds it calls timer() to - * do all the other time-based processing. - */ -static void -fasttimer(int i) -{ - static unsigned int tlast; - static unsigned int nsent; - unsigned int t = tlast + 1; - int n; - - /* - * if we're in the last second, send everything that's left. - * otherwise send at least the fraction we should have sent by now. - */ - if (t >= ROUTE_REPORT_INTERVAL) { - int nleft = nroutes - nsent; - while (nleft > 0) { - if ((n = report_next_chunk()) <= 0) - break; - nleft -= n; - } - tlast = 0; - nsent = 0; - } else { - unsigned int ncum = nroutes * t / ROUTE_REPORT_INTERVAL; - while (nsent < ncum) { - if ((n = report_next_chunk()) <= 0) - break; - nsent += n; - } - tlast = t; - } - if ((t % TIMER_INTERVAL) == 0) - timer(); - - age_callout_queue();/* Advance the timer for the callout queue - for groups */ - alarm(1); -} - -/* - * The 'virtual_time' variable is initialized to a value that will cause the - * first invocation of timer() to send a probe or route report to all vifs - * and send group membership queries to all subnets for which this router is - * querier. This first invocation occurs approximately TIMER_INTERVAL seconds - * after the router starts up. Note that probes for neighbors and queries - * for group memberships are also sent at start-up time, as part of initial- - * ization. This repetition after a short interval is desirable for quickly - * building up topology and membership information in the presence of possible - * packet loss. - * - * 'virtual_time' advances at a rate that is only a crude approximation of - * real time, because it does not take into account any time spent processing, - * and because the timer intervals are sometimes shrunk by a random amount to - * avoid unwanted synchronization with other routers. - */ - -static u_long virtual_time = 0; - - -/* - * Timer routine. Performs periodic neighbor probing, route reporting, and - * group querying duties, and drives various timers in routing entries and - * virtual interface data structures. - */ -static void -timer(void) -{ - age_routes(); /* Advance the timers in the route entries */ - age_vifs(); /* Advance the timers for neighbors */ - age_table_entry(); /* Advance the timers for the cache entries */ - - if (virtual_time % GROUP_QUERY_INTERVAL == 0) { - /* - * Time to query the local group memberships on all subnets - * for which this router is the elected querier. - */ - query_groups(); - } - - if (virtual_time % NEIGHBOR_PROBE_INTERVAL == 0) { - /* - * Time to send a probe on all vifs from which no neighbors have - * been heard. Also, check if any inoperative interfaces have now - * come up. (If they have, they will also be probed as part of - * their initialization.) - */ - probe_for_neighbors(); - - if (vifs_down) - check_vif_state(); - } - - delay_change_reports = FALSE; - if (routes_changed) { - /* - * Some routes have changed since the last timer interrupt, but - * have not been reported yet. Report the changed routes to all - * neighbors. - */ - report_to_all_neighbors(CHANGED_ROUTES); - } - -#ifdef SNMP - sync_timer(); -#endif - - /* - * Advance virtual time - */ - virtual_time += TIMER_INTERVAL; -} - - -/* - * On termination, let everyone know we're going away. - */ -static void -done(int i) -{ - logit(LOG_NOTICE, 0, "%s exiting", versionstring); - cleanup(); - _exit(1); -} - -static void -cleanup(void) -{ - static int in_cleanup = 0; - - if (!in_cleanup) { - in_cleanup++; -#ifdef RSRR - rsrr_clean(); -#endif /* RSRR */ - expire_all_routes(); - report_to_all_neighbors(ALL_ROUTES); - k_stop_dvmrp(); - } -} - - -/* - * Dump internal data structures to stderr. - */ -static void -dump(int i) -{ - dump_vifs(stderr); - dump_routes(stderr); -} - - -/* - * Dump internal data structures to a file. - */ -static void -fdump(int i) -{ - FILE *fp; - - fp = fopen(dumpfilename, "w"); - if (fp != NULL) { - dump_vifs(fp); - dump_routes(fp); - (void) fclose(fp); - } -} - - -/* - * Dump local cache contents to a file. - */ -static void -cdump(int i) -{ - FILE *fp; - - fp = fopen(cachefilename, "w"); - if (fp != NULL) { - dump_cache(fp); - (void) fclose(fp); - } -} - - -/* - * Restart mrouted - */ -static void -restart(int i) -{ - int omask; -#ifdef SYSV - sigset_t block, oblock; -#endif - - logit(LOG_NOTICE, 0, "%s restart", versionstring); - - /* - * reset all the entries - */ -#ifdef SYSV - (void)sigemptyset(&block); - (void)sigaddset(&block, SIGALRM); - if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0) - logit(LOG_ERR, errno, "sigprocmask"); -#else - omask = sigblock(sigmask(SIGALRM)); -#endif - free_all_prunes(); - free_all_routes(); - stop_all_vifs(); - k_stop_dvmrp(); - close(igmp_socket); - close(udp_socket); - - /* - * start processing again - */ - dvmrp_genid++; - pruning = 1; - - init_igmp(); - init_routes(); - init_ktable(); - init_vifs(); - k_init_dvmrp(); /* enable DVMRP routing in kernel */ - init_installvifs(); - -#ifdef SYSV - (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL); -#else - (void)sigsetmask(omask); -#endif -} - -#define LOG_MAX_MSGS 20 /* if > 20/minute then shut up for a while */ -#define LOG_SHUT_UP 600 /* shut up for 10 minutes */ -static int log_nmsgs = 0; - -static void -resetlogging(void *arg) -{ - int nxttime = 60; - void *narg = NULL; - - if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) { - nxttime = LOG_SHUT_UP; - narg = (void *)&log_nmsgs; /* just need some valid void * */ - syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes", - LOG_SHUT_UP / 60); - } else { - log_nmsgs = 0; - } - - timer_setTimer(nxttime, resetlogging, narg); -} - -/* - * Log errors and other messages to the system log daemon and 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 -logit(int severity, int syserr, const char *format, ...) -{ - va_list ap; - static char fmt[211] = "warning - "; - char *msg; - char tbuf[20]; - struct timeval now; - struct tm *thyme; - time_t t; - - va_start(ap, format); - vsprintf(&fmt[10], format, ap); - va_end(ap); - msg = (severity == LOG_WARNING) ? fmt : &fmt[10]; - - switch (debug) { - case 0: break; - case 1: if (severity > LOG_NOTICE) break; - case 2: if (severity > LOG_INFO ) break; - default: - gettimeofday(&now,NULL); - t = now.tv_sec; - thyme = localtime(&t); - strftime(tbuf, sizeof(tbuf), "%X", thyme); - fprintf(stderr, "%s.%03ld %s", tbuf, (long)now.tv_usec / 1000, - msg); - if (syserr == 0) - fprintf(stderr, "\n"); - else - fprintf(stderr, ": %s\n", strerror(syserr)); - } - - if (severity <= LOG_NOTICE) { - if (log_nmsgs++ < LOG_MAX_MSGS) { - if (syserr != 0) { - errno = syserr; - syslog(severity, "%s: %m", msg); - } else - syslog(severity, "%s", msg); - } - - if (severity <= LOG_ERR) exit(1); - } -} - -#ifdef DEBUG_MFC -void -md_log(int what, u_int32_t origin, u_int32_t mcastgrp) -{ - static FILE *f = NULL; - struct timeval tv; - u_int32_t buf[4]; - - if (!f) { - if ((f = fopen("/tmp/mrouted.clog", "w")) == NULL) { - logit(LOG_ERR, errno, "open /tmp/mrouted.clog"); - } - } - - gettimeofday(&tv, NULL); - buf[0] = tv.tv_sec; - buf[1] = what; - buf[2] = origin; - buf[3] = mcastgrp; - - fwrite(buf, sizeof(u_int32_t), 4, f); -} -#endif diff --git a/gnu/dist/mrouted/mrouted.8 b/gnu/dist/mrouted/mrouted.8 deleted file mode 100644 index 35d13383d38..00000000000 --- a/gnu/dist/mrouted/mrouted.8 +++ /dev/null @@ -1,404 +0,0 @@ -'\" $NetBSD: mrouted.8,v 1.1 2002/10/01 03:31:08 itojun Exp $ -'\"COPYRIGHT 1989 by The Board of Trustees of Leland Stanford Junior University. -.TH MROUTED 8 -.UC 5 -.SH NAME -mrouted \- IP multicast routing daemon -.SH SYNOPSIS -.B mrouted -[ -.B \-p -] [ -.B \-c -.I config_file -] [ -.B \-d -[ -.I debug_level -]] -.SH DESCRIPTION -.I Mrouted -is an implementation of the Distance-Vector Multicast Routing -Protocol (DVMRP), an earlier version of which is specified in RFC-1075. -It maintains topological knowledge via a distance-vector routing protocol -(like RIP, described in RFC-1058), upon which it implements a multicast -datagram forwarding algorithm called Reverse Path Multicasting. -.PP -.I Mrouted -forwards a multicast datagram along a shortest (reverse) path tree -rooted at the subnet on which the datagram originates. The multicast -delivery tree may be thought of as a broadcast delivery tree that has -been pruned back so that it does not extend beyond those subnetworks -that have members of the destination group. Hence, datagrams -are not forwarded along those branches which have no listeners of the -multicast group. The IP time-to-live of a multicast datagram can be -used to limit the range of multicast datagrams. -.PP -In order to support multicasting among subnets that are separated by (unicast) -routers that do not support IP multicasting, -.I mrouted -includes support for -"tunnels", which are virtual point-to-point links between pairs of -.IR mrouted s -located anywhere in an internet. IP multicast packets are encapsulated for -transmission through tunnels, so that they look like normal unicast datagrams -to intervening routers and subnets. The encapsulation -is added on entry to a tunnel, and stripped off -on exit from a tunnel. -By default, the packets are encapsulated using the IP-in-IP protocol -(IP protocol number 4). -Older versions of -.I mrouted -tunnel using IP source routing, which puts a heavy load on some -types of routers. -This version does not support IP source route tunnelling. -.PP -The tunnelling mechanism allows -.I mrouted -to establish a virtual internet, for -the purpose of multicasting only, which is independent of the physical -internet, and which may span multiple Autonomous Systems. This capability -is intended for experimental support of internet multicasting only, pending -widespread support for multicast routing by the regular (unicast) routers. -.I Mrouted -suffers from the well-known scaling problems of any distance-vector -routing protocol, and does not (yet) support hierarchical multicast routing. -.PP -.I Mrouted -handles multicast routing only; there may or may not be unicast routing -software running on the same machine as -.IR mrouted . -With the use of tunnels, it -is not necessary for -.I mrouted -to have access to more than one physical subnet -in order to perform multicast forwarding. -.br -.ne 5 -.SH INVOCATION -.PP -If no "\-d" option is given, or if the debug level is specified as 0, -.I mrouted -detaches from the invoking terminal. Otherwise, it remains attached to the -invoking terminal and responsive to signals from that terminal. If "\-d" is -given with no argument, the debug level defaults to 2. Regardless of the -debug level, -.I mrouted -always writes warning and error messages to the system -log demon. Non-zero debug levels have the following effects: -.IP "level 1" -all syslog'ed messages are also printed to stderr. -.IP "level 2" -all level 1 messages plus notifications of "significant" -events are printed to stderr. -.IP "level 3" -all level 2 messages plus notifications of all packet -arrivals and departures are printed to stderr. -.PP -Upon startup, mrouted writes its pid to the file /var/run/mrouted.pid . -.SH CONFIGURATION -.PP -.I Mrouted -automatically configures itself to forward on all multicast-capable -interfaces, i.e., interfaces that have the IFF_MULTICAST flag set (excluding -the loopback "interface"), and it finds other -.IR mrouted s -directly reachable -via those interfaces. To override the default configuration, or to add -tunnel links to other -.IR mrouted s, -configuration commands may be placed in -/etc/mrouted.conf (or an alternative file, specified by the "\-c" option). -There are four types of configuration commands: -.nf - - phyint \*[Lt]local-addr\*[Gt] [disable] [metric \*[Lt]m\*[Gt]] - [threshold \*[Lt]t\*[Gt]] [rate_limit \*[Lt]b\*[Gt]] - [boundary (\*[Lt]boundary-name\*[Gt]|\*[Lt]scoped-addr\*[Gt]/\*[Lt]mask-len\*[Gt])] - [altnet \*[Lt]network\*[Gt]/\*[Lt]mask-len\*[Gt]] - - tunnel \*[Lt]local-addr\*[Gt] \*[Lt]remote-addr\*[Gt] [metric \*[Lt]m\*[Gt]] - [threshold \*[Lt]t\*[Gt]] [rate_limit \*[Lt]b\*[Gt]] - [boundary (\*[Lt]boundary-name\*[Gt]|\*[Lt]scoped-addr\*[Gt]/\*[Lt]mask-len\*[Gt])] - - cache_lifetime \*[Lt]ct\*[Gt] - - pruning \*[Lt]off/on\*[Gt] - - name \*[Lt]boundary-name\*[Gt] \*[Lt]scoped-addr\*[Gt]/\*[Lt]mask-len\*[Gt] - -.fi -.PP -The file format is free-form; whitespace (including newlines) is not -significant. -The -.I boundary -and -.I altnet -options may be specified as many times as necessary. -.PP -The phyint command can be used to disable multicast routing on the physical -interface identified by local IP address \*[Lt]local-addr\*[Gt], or to associate a -non-default metric or threshold with the specified physical interface. -The local IP address \*[Lt]local-addr\*[Gt] may be replaced by the -interface name (e.g le0). -If a phyint is attached to multiple IP subnets, describe each additional subnet -with the altnet keyword. -Phyint commands must precede tunnel commands. -.PP -The tunnel command can be used to establish a tunnel link between local -IP address \*[Lt]local-addr\*[Gt] and remote IP address \*[Lt]remote-addr\*[Gt], and to associate -a non-default metric or threshold with that tunnel. -The local IP address \*[Lt]local-addr\*[Gt] may be replaced by the -interface name (e.g. le0). The remote IP address \*[Lt]remote-addr\*[Gt] may -be replaced by a host name, if and only if the host name has a single -IP address associated with it. -The tunnel must be set -up in the mrouted.conf files of both routers before it can be used. -'\"For backwards compatibility with older -'\".IR mrouted s, -'\"the srcrt keyword specifies -'\"encapsulation using IP source routing. -.PP -The cache_lifetime is a value that determines the amount of time that a -cached multicast route stays in kernel before timing out. The value of this -entry should lie between 300 (5 min) and 86400 (1 day). It defaults to 300. -.PP -The pruning \*[Lt]off/on\*[Gt] option is provided for -.IR mrouted -to act as a non-pruning router. It is also possible to start -.IR mrouted -in a non-pruning mode using the "-p" option on the command line. It is -expected that a router would be configured in this manner for test -purposes only. The default mode is pruning enabled. -.PP -You may assign names to boundaries to make configuration easier with -the name keyword. The boundary option on phyint or tunnel commands -can accept either a name or a boundary. -.PP -The metric is the "cost" associated with sending a datagram on the given -interface or tunnel; it may be used to influence the choice of routes. -The metric defaults to 1. Metrics should be kept as small as possible, -because -.I mrouted -cannot route along paths with a sum of metrics greater -than 31. -.LP -The threshold is the minimum IP time-to-live required for a multicast datagram -to be forwarded to the given interface or tunnel. It is used to control the -scope of multicast datagrams. (The TTL of forwarded packets is only compared -to the threshold, it is not decremented by the threshold. Every multicast -router decrements the TTL by 1.) The default threshold is 1. -.LP -In general, all -.IR mrouted s -connected to a particular subnet or tunnel should -use the same metric and threshold for that subnet or tunnel. -.PP -The rate_limit option allows the network administrator to specify a -certain bandwidth in Kbits/second which would be allocated to multicast -traffic. It defaults to 500Kbps on tunnels, and 0 (unlimited) on physical -interfaces. -.PP -The boundary option allows an interface -to be configured as an administrative boundary for the specified -scoped address. Packets belonging to this address will not -be forwarded on a scoped interface. The boundary option accepts either -a name or a boundary spec. -.PP -.I Mrouted -will not initiate execution if it has fewer than two enabled vifs, -where a vif (virtual interface) is either a physical multicast-capable -interface or a tunnel. It will log a warning if all of its vifs are -tunnels; such an -.I mrouted -configuration would be better replaced by more -direct tunnels (i.e., eliminate the middle man). -.SH "EXAMPLE CONFIGURATION" -.PP -This is an example configuration for a mythical multicast router at a big -school. -.sp -.nf -# -# mrouted.conf example -# -# Name our boundaries to make it easier -name LOCAL 239.255.0.0/16 -name EE 239.254.0.0/16 -# -# le1 is our gateway to compsci, don't forward our -# local groups to them -phyint le1 boundary EE -# -# le2 is our interface on the classroom net, it has four -# different length subnets on it. -# note that you can use either an ip address or an -# interface name -phyint 172.16.12.38 boundary EE altnet 172.16.15.0/26 - altnet 172.16.15.128/26 altnet 172.16.48.0/24 -# -# atm0 is our ATM interface, which doesn't properly -# support multicasting. -phyint atm0 disable -# -# This is an internal tunnel to another EE subnet -# Remove the default tunnel rate limit, since this -# tunnel is over ethernets -tunnel 192.168.5.4 192.168.55.101 metric 1 threshold 1 - rate_limit 0 -# -# This is our tunnel to the outside world. -# Careful with those boundaries, Eugene. -tunnel 192.168.5.4 10.11.12.13 metric 1 threshold 32 - boundary LOCAL boundary EE -.fi -.SH SIGNALS -.PP -.I Mrouted -responds to the following signals: -.IP HUP -restarts -.I mrouted . -The configuration file is reread every time this signal is evoked. -.IP INT -terminates execution gracefully (i.e., by sending -good-bye messages to all neighboring routers). -.IP TERM -same as INT -.IP USR1 -dumps the internal routing tables to /var/tmp/mrouted.dump. -.IP USR2 -dumps the internal cache tables to /var/tmp/mrouted.cache. -.IP QUIT -dumps the internal routing tables to stderr (only if -.I mrouted -was invoked with a non-zero debug level). -.PP -For convenience in sending signals, -.I mrouted -writes its pid to /var/run/mrouted.pid upon startup. -.bp -.SH EXAMPLE -.PP -The routing tables look like this: -.nf - -Virtual Interface Table - Vif Local-Address Metric Thresh Flags - 0 36.2.0.8 subnet: 36.2 1 1 querier - groups: 224.0.2.1 - 224.0.0.4 - pkts in: 3456 - pkts out: 2322323 - - 1 36.11.0.1 subnet: 36.11 1 1 querier - groups: 224.0.2.1 - 224.0.1.0 - 224.0.0.4 - pkts in: 345 - pkts out: 3456 - - 2 36.2.0.8 tunnel: 36.8.0.77 3 1 - peers: 36.8.0.77 (2.2) - boundaries: 239.0.1 - : 239.1.2 - pkts in: 34545433 - pkts out: 234342 - - 3 36.2.0.8 tunnel: 36.6.8.23 3 16 - -Multicast Routing Table (1136 entries) - Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs - 36.2 1 45 0 1* 2 3* - 36.8 36.8.0.77 4 15 2 0* 1* 3* - 36.11 1 20 1 0* 2 3* - . - . - . - -.fi -In this example, there are four vifs connecting to two subnets and two -tunnels. The vif 3 tunnel is not in use (no peer address). The vif 0 and -vif 1 subnets have some groups present; tunnels never have any groups. This -instance of -.I mrouted -is the one responsible for sending periodic group -membership queries on the vif 0 and vif 1 subnets, as indicated by the -"querier" flags. The list of boundaries indicate the scoped addresses on that -interface. A count of the no. of incoming and outgoing packets is also -shown at each interface. -.PP -Associated with each subnet from which a multicast datagram can originate -is the address of the previous hop router (unless the subnet is directly- -connected), the metric of the path back to the origin, the amount of time -since we last received an update for this subnet, the incoming vif for -multicasts from that origin, and a list of outgoing vifs. "*" means that -the outgoing vif is connected to a leaf of the broadcast tree rooted at the -origin, and a multicast datagram from that origin will be forwarded on that -outgoing vif only if there are members of the destination group on that leaf. -.bp -.PP -.I Mrouted -also maintains a copy of the kernel forwarding cache table. Entries -are created and deleted by -.I mrouted. -.PP -The cache tables look like this: -.nf - -Multicast Routing Cache Table (147 entries) - Origin Mcast-group CTmr Age Ptmr IVif Forwvifs - 13.2.116/22 224.2.127.255 3m 2m - 0 1 -\*[Gt]13.2.116.19 -\*[Gt]13.2.116.196 - 138.96.48/21 224.2.127.255 5m 2m - 0 1 -\*[Gt]138.96.48.108 - 128.9.160/20 224.2.127.255 3m 2m - 0 1 -\*[Gt]128.9.160.45 - 198.106.194/24 224.2.135.190 9m 28s 9m 0P -\*[Gt]198.106.194.22 - -.fi -Each entry is characterized by the origin subnet number and mask and the -destination multicast group. The 'CTmr' field indicates the lifetime -of the entry. The entry is deleted from the cache table -when the timer decrements to zero. The 'Age' field is the time since -this cache entry was originally created. Since cache entries get refreshed -if traffic is flowing, routing entries can grow very old. -The 'Ptmr' field is simply a dash if no prune was sent upstream, or the -amount of time until the upstream prune will time out. -The 'Ivif' field indicates the -incoming vif for multicast packets from that origin. Each router also -maintains a record of the number of prunes received from neighboring -routers for a particular source and group. If there are no members of -a multicast group on any downward link of the multicast tree for a -subnet, a prune message is sent to the upstream router. They are -indicated by a "P" after the vif number. The Forwvifs field shows the -interfaces along which datagrams belonging to the source-group are -forwarded. A "p" indicates that no datagrams are being forwarded along -that interface. An unlisted interface is a leaf subnet with are no -members of the particular group on that subnet. A "b" on an interface -indicates that it is a boundary interface, i.e. traffic will not be -forwarded on the scoped address on that interface. -An additional line with a "\*[Gt]" as the first character is printed for -each source on the subnet. Note that there can be many sources in -one subnet. -.SH FILES -/etc/mrouted.conf -.br -/var/run/mrouted.pid -.br -/var/tmp/mrouted.dump -.br -/var/tmp/mrouted.cache -.SH SEE ALSO -.BR mrinfo (8) , -.BR mtrace (8) , -.BR map-mbone (8) -.sp -DVMRP is described, along with other multicast routing algorithms, in the -paper "Multicast Routing in Internetworks and Extended LANs" by S. Deering, -in the Proceedings of the ACM SIGCOMM '88 Conference. -.SH AUTHORS -Steve Deering, Ajit Thyagarajan, Bill Fenner diff --git a/gnu/dist/mrouted/pathnames.h b/gnu/dist/mrouted/pathnames.h deleted file mode 100644 index 74c49faebee..00000000000 --- a/gnu/dist/mrouted/pathnames.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $NetBSD: pathnames.h,v 1.1 2002/10/01 03:31:09 itojun Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -#define _PATH_MROUTED_CONF "/etc/mrouted.conf" - -#if (defined(BSD) && (BSD >= 199103)) -#define _PATH_MROUTED_GENID "/var/run/mrouted.genid" -#define _PATH_MROUTED_DUMP "/var/tmp/mrouted.dump" -#define _PATH_MROUTED_CACHE "/var/tmp/mrouted.cache" -#else -#define _PATH_MROUTED_GENID "/etc/mrouted.genid" -#define _PATH_MROUTED_DUMP "/usr/tmp/mrouted.dump" -#define _PATH_MROUTED_CACHE "/usr/tmp/mrouted.cache" -#endif diff --git a/gnu/dist/mrouted/prune.c b/gnu/dist/mrouted/prune.c deleted file mode 100644 index 4a1511a1ebd..00000000000 --- a/gnu/dist/mrouted/prune.c +++ /dev/null @@ -1,2234 +0,0 @@ -/* $NetBSD: prune.c,v 1.2 2002/12/06 16:02:56 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include "defs.h" - -extern int cache_lifetime; -extern int max_prune_lifetime; -extern struct rtentry *routing_table; - -extern int phys_vif; - -/* - * dither cache lifetime to obtain a value between x and 2*x - */ -#ifdef SYSV -#define CACHE_LIFETIME(x) ((x) + (lrand48() % (x))) -#else -#define CACHE_LIFETIME(x) ((x) + (random() % (x))) -#endif - -#define CHK_GS(x, y) { \ - switch(x) { \ - case 2: \ - case 4: \ - case 8: \ - case 16: \ - case 32: \ - case 64: \ - case 128: \ - case 256: y = 1; \ - break; \ - default: y = 0; \ - } \ - } - -struct gtable *kernel_table; /* ptr to list of kernel grp entries*/ -static struct gtable *kernel_no_route; /* list of grp entries w/o routes */ -struct gtable *gtp; /* pointer for kernel rt entries */ -unsigned int kroutes; /* current number of cache entries */ - -/**************************************************************************** - Functions that are local to prune.c -****************************************************************************/ -static void prun_add_ttls(struct gtable *gt); -static int pruning_neighbor(vifi_t vifi, u_int32_t addr); -static int can_mtrace(vifi_t vifi, u_int32_t addr); -static struct ptable * find_prune_entry(u_int32_t vr, struct ptable *pt); -static void expire_prune(vifi_t vifi, struct gtable *gt); -static void send_prune(struct gtable *gt); -static void send_graft(struct gtable *gt); -static void send_graft_ack(u_int32_t src, u_int32_t dst, - u_int32_t origin, u_int32_t grp); -static void update_kernel(struct gtable *g); -static char * scaletime(u_long t); - -/* - * Updates the ttl values for each vif. - */ -static void -prun_add_ttls(struct gtable *gt) -{ - struct uvif *v; - vifi_t vifi; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (VIFM_ISSET(vifi, gt->gt_grpmems)) - gt->gt_ttls[vifi] = v->uv_threshold; - else - gt->gt_ttls[vifi] = 0; - } -} - -/* - * checks for scoped multicast addresses - */ -#define GET_SCOPE(gt) { \ - vifi_t _i; \ - if ((ntohl((gt)->gt_mcastgrp) & 0xff000000) == 0xef000000) \ - for (_i = 0; _i < numvifs; _i++) \ - if (scoped_addr(_i, (gt)->gt_mcastgrp)) \ - VIFM_SET(_i, (gt)->gt_scope); \ - } - -int -scoped_addr(vifi_t vifi, u_int32_t addr) -{ - struct vif_acl *acl; - - for (acl = uvifs[vifi].uv_acl; acl; acl = acl->acl_next) - if ((addr & acl->acl_mask) == acl->acl_addr) - return 1; - - return 0; -} - -/* - * Determine if mcastgrp has a listener on vifi - */ -int -grplst_mem(vifi_t vifi, u_int32_t mcastgrp) -{ - struct listaddr *g; - struct uvif *v; - - v = &uvifs[vifi]; - - for (g = v->uv_groups; g != NULL; g = g->al_next) - if (mcastgrp == g->al_addr) - return 1; - - return 0; -} - -/* - * Finds the group entry with the specified source and netmask. - * If netmask is 0, it uses the route's netmask. - * - * Returns TRUE if found a match, and the global variable gtp is left - * pointing to entry before the found entry. - * Returns FALSE if no exact match found, gtp is left pointing to before - * the entry in question belongs, or is NULL if the it belongs at the - * head of the list. - */ -int -find_src_grp(u_int32_t src, u_int32_t mask, u_int32_t grp) -{ - struct gtable *gt; - - gtp = NULL; - gt = kernel_table; - while (gt != NULL) { - if (grp == gt->gt_mcastgrp && - (mask ? (gt->gt_route->rt_origin == src && - gt->gt_route->rt_originmask == mask) : - ((src & gt->gt_route->rt_originmask) == - gt->gt_route->rt_origin))) - return TRUE; - if (ntohl(grp) > ntohl(gt->gt_mcastgrp) || - (grp == gt->gt_mcastgrp && - (ntohl(mask) < ntohl(gt->gt_route->rt_originmask) || - (mask == gt->gt_route->rt_originmask && - (ntohl(src) > ntohl(gt->gt_route->rt_origin)))))) { - gtp = gt; - gt = gt->gt_gnext; - } - else break; - } - return FALSE; -} - -/* - * Check if the neighbor supports pruning - */ -static int -pruning_neighbor(vifi_t vifi, u_int32_t addr) -{ - struct listaddr *n = neighbor_info(vifi, addr); - int vers; - - if (n == NULL) - return 0; - - if (n->al_flags & NF_PRUNE) - return 1; - - /* - * Versions from 3.0 to 3.4 relied on the version number to identify - * that they could handle pruning. - */ - vers = NBR_VERS(n); - return (vers >= 0x0300 && vers <= 0x0304); -} - -/* - * Can the neighbor in question handle multicast traceroute? - */ -static int -can_mtrace(vifi_t vifi, u_int32_t addr) -{ - struct listaddr *n = neighbor_info(vifi, addr); - int vers; - - if (n == NULL) - return 0; - - if (n->al_flags & NF_MTRACE) - return 1; - - /* - * Versions 3.3 and 3.4 relied on the version number to identify - * that they could handle traceroute. - */ - vers = NBR_VERS(n); - return (vers >= 0x0303 && vers <= 0x0304); -} - -/* - * Returns the prune entry of the router, or NULL if none exists - */ -static struct ptable * -find_prune_entry(u_int32_t vr, struct ptable *pt) -{ - while (pt) { - if (pt->pt_router == vr) - return pt; - pt = pt->pt_next; - } - - return NULL; -} - -/* - * Send a prune message to the dominant router for - * this source. - * - * Record an entry that a prune was sent for this group - */ -static void -send_prune(struct gtable *gt) -{ - struct ptable *pt; - char *p; - int i; - int datalen; - u_int32_t src; - u_int32_t dst; - u_int32_t tmp; - - /* Don't process any prunes if router is not pruning */ - if (pruning == 0) - return; - - /* Can't process a prune if we don't have an associated route */ - if (gt->gt_route == NULL) - return; - - /* Don't send a prune to a non-pruning router */ - if (!pruning_neighbor(gt->gt_route->rt_parent, gt->gt_route->rt_gateway)) - return; - - /* - * sends a prune message to the router upstream. - */ - src = uvifs[gt->gt_route->rt_parent].uv_lcl_addr; - dst = gt->gt_route->rt_gateway; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - - /* - * determine prune lifetime - */ - gt->gt_prsent_timer = gt->gt_timer; - for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) - if (pt->pt_timer < gt->gt_prsent_timer) - gt->gt_prsent_timer = pt->pt_timer; - - /* - * If we have a graft pending, cancel graft retransmission - */ - gt->gt_grftsnt = 0; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_route->rt_origin))[i]; - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_mcastgrp))[i]; - tmp = htonl(gt->gt_prsent_timer); - for (i = 0; i < 4; i++) - *p++ = ((char *)&(tmp))[i]; - datalen += 12; - - send_igmp(src, dst, IGMP_DVMRP, DVMRP_PRUNE, - htonl(MROUTED_LEVEL), datalen); - - logit(LOG_DEBUG, 0, "sent prune for (%s %s)/%d on vif %d to %s", - inet_fmts(gt->gt_route->rt_origin, gt->gt_route->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), - gt->gt_prsent_timer, gt->gt_route->rt_parent, - inet_fmt(gt->gt_route->rt_gateway, s3)); -} - -/* - * a prune was sent upstream - * so, a graft has to be sent to annul the prune - * set up a graft timer so that if an ack is not - * heard within that time, another graft request - * is sent out. - */ -static void -send_graft(struct gtable *gt) -{ - char *p; - int i; - int datalen; - u_int32_t src; - u_int32_t dst; - - /* Can't send a graft without an associated route */ - if (gt->gt_route == NULL) - return; - - src = uvifs[gt->gt_route->rt_parent].uv_lcl_addr; - dst = gt->gt_route->rt_gateway; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_route->rt_origin))[i]; - for (i = 0; i < 4; i++) - *p++ = ((char *)&(gt->gt_mcastgrp))[i]; - datalen += 8; - - if (datalen != 0) { - send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT, - htonl(MROUTED_LEVEL), datalen); - } - logit(LOG_DEBUG, 0, "sent graft for (%s %s) to %s on vif %d", - inet_fmts(gt->gt_route->rt_origin, gt->gt_route->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), - inet_fmt(gt->gt_route->rt_gateway, s3), gt->gt_route->rt_parent); -} - -/* - * Send an ack that a graft was received - */ -static void -send_graft_ack(u_int32_t src, u_int32_t dst, u_int32_t origin, u_int32_t grp) -{ - char *p; - int i; - int datalen; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(origin))[i]; - for (i = 0; i < 4; i++) - *p++ = ((char *)&(grp))[i]; - datalen += 8; - - send_igmp(src, dst, IGMP_DVMRP, DVMRP_GRAFT_ACK, - htonl(MROUTED_LEVEL), datalen); - - logit(LOG_DEBUG, 0, "sent graft ack for (%s, %s) to %s", - inet_fmt(origin, s1), inet_fmt(grp, s2), inet_fmt(dst, s3)); -} - -/* - * Update the kernel cache with all the routes hanging off the group entry - */ -static void -update_kernel(struct gtable *g) -{ - struct stable *st; - - for (st = g->gt_srctbl; st; st = st->st_next) - k_add_rg(st->st_origin, g); -} - -/**************************************************************************** - Functions that are used externally -****************************************************************************/ - -#ifdef SNMP -#include <sys/types.h> -#include "snmp.h" - -/* - * Find a specific group entry in the group table - */ -struct gtable * -find_grp(grp) - u_long grp; -{ - struct gtable *gt; - - for (gt = kernel_table; gt; gt = gt->gt_gnext) { - if (ntohl(grp) < ntohl(gt->gt_mcastgrp)) - break; - if (gt->gt_mcastgrp == grp) - return gt; - } - return NULL; -} - -/* - * Given a group entry and source, find the corresponding source table - * entry - */ -struct stable * -find_grp_src(struct gtable *gt, u_long src) -{ - struct stable *st; - u_long grp = gt->gt_mcastgrp; - struct gtable *gtcurr; - - for (gtcurr = gt; gtcurr->gt_mcastgrp == grp; gtcurr = gtcurr->gt_gnext) { - for (st = gtcurr->gt_srctbl; st; st = st->st_next) - if (st->st_origin == src) - return st; - } - return NULL; -} - -/* - * Find next entry > specification - * - * gtpp: ordered by group - * stpp: ordered by source - */ -int -next_grp_src_mask(struct gtable **gtpp, struct stable **stpp, u_long grp, - u_long src, u_long mask) -{ - struct gtable *gt, *gbest = NULL; - struct stable *st, *sbest = NULL; - - /* Find first group entry >= grp spec */ - (*gtpp) = kernel_table; - while ((*gtpp) && ntohl((*gtpp)->gt_mcastgrp) < ntohl(grp)) - (*gtpp)=(*gtpp)->gt_gnext; - if (!(*gtpp)) - return 0; /* no more groups */ - - for (gt = kernel_table; gt; gt=gt->gt_gnext) { - /* Since grps are ordered, we can stop when group changes from gbest */ - if (gbest && gbest->gt_mcastgrp != gt->gt_mcastgrp) - break; - for (st = gt->gt_srctbl; st; st=st->st_next) { - - /* Among those entries > spec, find "lowest" one */ - if (((ntohl(gt->gt_mcastgrp)> ntohl(grp)) - || (ntohl(gt->gt_mcastgrp)==ntohl(grp) - && ntohl(st->st_origin)> ntohl(src)) - || (ntohl(gt->gt_mcastgrp)==ntohl(grp) - && ntohl(st->st_origin)==src && 0xFFFFFFFF>ntohl(mask))) - && (!gbest - || (ntohl(gt->gt_mcastgrp)< ntohl(gbest->gt_mcastgrp)) - || (ntohl(gt->gt_mcastgrp)==ntohl(gbest->gt_mcastgrp) - && ntohl(st->st_origin)< ntohl(sbest->st_origin)))) { - gbest = gt; - sbest = st; - } - } - } - (*gtpp) = gbest; - (*stpp) = sbest; - return (*gtpp)!=0; -} - -/* - * Ensure that sg contains current information for the given group,source. - * This is fetched from the kernel as a unit so that counts for the entry - * are consistent, i.e. packet and byte counts for the same entry are - * read at the same time. - */ -void -refresh_sg(struct sioc_sg_req *sg, struct gtable *gt, struct stable *st) -{ - static int lastq = -1; - - if (quantum != lastq || sg->src.s_addr!=st->st_origin - || sg->grp.s_addr!=gt->gt_mcastgrp) { - lastq = quantum; - sg->src.s_addr = st->st_origin; - sg->grp.s_addr = gt->gt_mcastgrp; - ioctl(igmp_socket, SIOCGETSGCNT, (char *)sg); - } -} - -/* - * Return pointer to a specific route entry. This must be a separate - * function from find_route() which modifies rtp. - */ -struct rtentry * -snmp_find_route(u_long src, u_long mask) -{ - struct rtentry *rt; - - for (rt = routing_table; rt; rt = rt->rt_next) { - if (src == rt->rt_origin && mask == rt->rt_originmask) - return rt; - } - return NULL; -} - -/* - * Find next route entry > specification - */ -int -next_route(struct rtentry **rtpp, u_long src, u_long mask) -{ - struct rtentry *rt, *rbest = NULL; - - /* Among all entries > spec, find "lowest" one in order */ - for (rt = routing_table; rt; rt=rt->rt_next) { - if ((ntohl(rt->rt_origin) > ntohl(src) - || (ntohl(rt->rt_origin) == ntohl(src) - && ntohl(rt->rt_originmask) > ntohl(mask))) - && (!rbest || (ntohl(rt->rt_origin) < ntohl(rbest->rt_origin)) - || (ntohl(rt->rt_origin) == ntohl(rbest->rt_origin) - && ntohl(rt->rt_originmask) < ntohl(rbest->rt_originmask)))) - rbest = rt; - } - (*rtpp) = rbest; - return (*rtpp)!=0; -} - -/* - * Given a routing table entry, and a vifi, find the next vifi/entry - * - * vifi: vifi at which to start looking - */ -int -next_route_child(struct rtentry **rtpp, u_long src, u_long mask, vifi_t *vifi) -{ - struct rtentry *rt; - - /* Get (S,M) entry */ - if (!((*rtpp) = snmp_find_route(src,mask))) - if (!next_route(rtpp, src, mask)) - return 0; - - /* Continue until we get one with a valid next vif */ - do { - for (; (*rtpp)->rt_children && *vifi<numvifs; (*vifi)++) - if (VIFM_ISSET(*vifi, (*rtpp)->rt_children)) - return 1; - *vifi = 0; - } while( next_route(rtpp, (*rtpp)->rt_origin, (*rtpp)->rt_originmask) ); - - return 0; -} - -/* - * Given a routing table entry, and a vifi, find the next entry - * equal to or greater than those - * - * vifi: vifi at which to start looking - */ -int -next_child(struct gtable **gtpp, struct stable **stpp, u_long grp, u_long src, - u_long mask, vifi_t *vifi) -{ - struct stable *st; - - /* Get (G,S,M) entry */ - if (mask!=0xFFFFFFFF - || !((*gtpp) = find_grp(grp)) - || !((*stpp) = find_grp_src((*gtpp),src))) - if (!next_grp_src_mask(gtpp, stpp, grp, src, mask)) - return 0; - - /* Continue until we get one with a valid next vif */ - do { - for (; (*gtpp)->gt_route->rt_children && *vifi<numvifs; (*vifi)++) - if (VIFM_ISSET(*vifi, (*gtpp)->gt_route->rt_children)) - return 1; - *vifi = 0; - } while (next_grp_src_mask(gtpp, stpp, (*gtpp)->gt_mcastgrp, - (*stpp)->st_origin, 0xFFFFFFFF) ); - - return 0; -} -#endif /* SNMP */ - -/* - * Initialize the kernel table structure - */ -void -init_ktable(void) -{ - kernel_table = NULL; - kernel_no_route = NULL; - kroutes = 0; -} - -/* - * Add a new table entry for (origin, mcastgrp) - */ -void -add_table_entry(u_int32_t origin, u_int32_t mcastgrp) -{ - struct rtentry *r; - struct gtable *gt,**gtnp,*prev_gt; - struct stable *st,**stnp; - vifi_t i; - -#ifdef DEBUG_MFC - md_log(MD_MISS, origin, mcastgrp); -#endif - - r = determine_route(origin); - prev_gt = NULL; - if (r == NULL) { - /* - * Look for it on the no_route table; if it is found then - * it will be detected as a duplicate below. - */ - for (gt = kernel_no_route; gt; gt = gt->gt_next) - if (mcastgrp == gt->gt_mcastgrp && - gt->gt_srctbl && gt->gt_srctbl->st_origin == origin) - break; - gtnp = &kernel_no_route; - } else { - gtnp = &r->rt_groups; - while ((gt = *gtnp) != NULL) { - if (gt->gt_mcastgrp >= mcastgrp) - break; - gtnp = >->gt_next; - prev_gt = gt; - } - } - - if (gt == NULL || gt->gt_mcastgrp != mcastgrp) { - gt = (struct gtable *)malloc(sizeof(struct gtable)); - if (gt == NULL) - logit(LOG_ERR, 0, "ran out of memory"); - - gt->gt_mcastgrp = mcastgrp; - gt->gt_timer = CACHE_LIFETIME(cache_lifetime); - time(>->gt_ctime); - gt->gt_grpmems = 0; - gt->gt_scope = 0; - gt->gt_prsent_timer = 0; - gt->gt_grftsnt = 0; - gt->gt_srctbl = NULL; - gt->gt_pruntbl = NULL; - gt->gt_route = r; -#ifdef RSRR - gt->gt_rsrr_cache = NULL; -#endif - - if (r != NULL) { - /* obtain the multicast group membership list */ - for (i = 0; i < numvifs; i++) { - if (VIFM_ISSET(i, r->rt_children) && - !(VIFM_ISSET(i, r->rt_leaves))) - VIFM_SET(i, gt->gt_grpmems); - - if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp)) - VIFM_SET(i, gt->gt_grpmems); - } - GET_SCOPE(gt); - if (VIFM_ISSET(r->rt_parent, gt->gt_scope)) - gt->gt_scope = -1; - gt->gt_grpmems &= ~gt->gt_scope; - } else { - gt->gt_scope = -1; - gt->gt_grpmems = 0; - } - - /* update ttls */ - prun_add_ttls(gt); - - gt->gt_next = *gtnp; - *gtnp = gt; - if (gt->gt_next) - gt->gt_next->gt_prev = gt; - gt->gt_prev = prev_gt; - - if (r) { - if (find_src_grp(r->rt_origin, r->rt_originmask, gt->gt_mcastgrp)) { - struct gtable *g; - - g = gtp ? gtp->gt_gnext : kernel_table; - logit(LOG_WARNING, 0, "Entry for (%s %s) (rt:%p) exists (rt:%p)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), - r, g->gt_route); - } else { - if (gtp) { - gt->gt_gnext = gtp->gt_gnext; - gt->gt_gprev = gtp; - gtp->gt_gnext = gt; - } else { - gt->gt_gnext = kernel_table; - gt->gt_gprev = NULL; - kernel_table = gt; - } - if (gt->gt_gnext) - gt->gt_gnext->gt_gprev = gt; - } - } else { - gt->gt_gnext = gt->gt_gprev = NULL; - } - } - - stnp = >->gt_srctbl; - while ((st = *stnp) != NULL) { - if (ntohl(st->st_origin) >= ntohl(origin)) - break; - stnp = &st->st_next; - } - - if (st == NULL || st->st_origin != origin) { - st = (struct stable *)malloc(sizeof(struct stable)); - if (st == NULL) - logit(LOG_ERR, 0, "ran out of memory"); - - st->st_origin = origin; - st->st_pktcnt = 0; - st->st_next = *stnp; - *stnp = st; - } else { -#ifdef DEBUG_MFC - md_log(MD_DUPE, origin, mcastgrp); -#endif - logit(LOG_WARNING, 0, "kernel entry already exists for (%s %s)", - inet_fmt(origin, s1), inet_fmt(mcastgrp, s2)); - /* XXX Doing this should cause no harm, and may ensure - * kernel<>mrouted synchronization */ - k_add_rg(origin, gt); - return; - } - - kroutes++; - k_add_rg(origin, gt); - - logit(LOG_DEBUG, 0, "add cache entry (%s %s) gm:%x, parent-vif:%d", - inet_fmt(origin, s1), - inet_fmt(mcastgrp, s2), - gt->gt_grpmems, r ? r->rt_parent : -1); - - /* If there are no leaf vifs - * which have this group, then - * mark this src-grp as a prune candidate. - */ - if (!gt->gt_prsent_timer && !gt->gt_grpmems && r && r->rt_gateway) - send_prune(gt); -} - -/* - * An mrouter has gone down and come up on an interface - * Forward on that interface immediately - */ -void -reset_neighbor_state(vifi_t vifi, u_int32_t addr) -{ - struct rtentry *r; - struct gtable *g; - struct ptable *pt, **ptnp; - struct stable *st; - - for (g = kernel_table; g; g = g->gt_gnext) { - r = g->gt_route; - - /* - * If neighbor was the parent, remove the prune sent state - * and all of the source cache info so that prunes get - * regenerated. - */ - if (vifi == r->rt_parent) { - if (addr == r->rt_gateway) { - logit(LOG_DEBUG, 0, "reset_neighbor_state parent reset (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2)); - - g->gt_prsent_timer = 0; - g->gt_grftsnt = 0; - while ((st = g->gt_srctbl) != NULL) { - g->gt_srctbl = st->st_next; - k_del_rg(st->st_origin, g); - kroutes--; - free(st); - } - } - } else { - /* - * Neighbor was not the parent, send grafts to join the groups - */ - if (g->gt_prsent_timer) { - g->gt_grftsnt = 1; - send_graft(g); - g->gt_prsent_timer = 0; - } - - /* - * Remove any prunes that this router has sent us. - */ - ptnp = &g->gt_pruntbl; - while ((pt = *ptnp) != NULL) { - if (pt->pt_vifi == vifi && pt->pt_router == addr) { - *ptnp = pt->pt_next; - free(pt); - } else - ptnp = &pt->pt_next; - } - - /* - * And see if we want to forward again. - */ - if (!VIFM_ISSET(vifi, g->gt_grpmems)) { - if (VIFM_ISSET(vifi, r->rt_children) && - !(VIFM_ISSET(vifi, r->rt_leaves))) - VIFM_SET(vifi, g->gt_grpmems); - - if (VIFM_ISSET(vifi, r->rt_leaves) && - grplst_mem(vifi, g->gt_mcastgrp)) - VIFM_SET(vifi, g->gt_grpmems); - - g->gt_grpmems &= ~g->gt_scope; - prun_add_ttls(g); - - /* Update kernel state */ - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - - logit(LOG_DEBUG, 0, "reset member state (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - } - } - } -} - -/* - * Delete table entry from the kernel - * del_flag determines how many entries to delete - */ -void -del_table_entry(struct rtentry *r, u_int32_t mcastgrp, u_int del_flag) -{ - struct gtable *g, *prev_g; - struct stable *st, *prev_st; - struct ptable *pt, *prev_pt; - - if (del_flag == DEL_ALL_ROUTES) { - g = r->rt_groups; - while (g) { - logit(LOG_DEBUG, 0, "del_table_entry deleting (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2)); - st = g->gt_srctbl; - while (st) { - if (k_del_rg(st->st_origin, g) < 0) { - logit(LOG_WARNING, errno, - "del_table_entry trying to delete (%s, %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(g->gt_mcastgrp, s2)); - } - kroutes--; - prev_st = st; - st = st->st_next; - free(prev_st); - } - g->gt_srctbl = NULL; - - pt = g->gt_pruntbl; - while (pt) { - prev_pt = pt; - pt = pt->pt_next; - free(prev_pt); - } - g->gt_pruntbl = NULL; - - if (g->gt_gnext) - g->gt_gnext->gt_gprev = g->gt_gprev; - if (g->gt_gprev) - g->gt_gprev->gt_gnext = g->gt_gnext; - else - kernel_table = g->gt_gnext; - -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,0); - rsrr_cache_clean(g); -#endif /* RSRR */ - prev_g = g; - g = g->gt_next; - free(prev_g); - } - r->rt_groups = NULL; - } - - /* - * Dummy routine - someday this may be needed, so it is just there - */ - if (del_flag == DEL_RTE_GROUP) { - prev_g = (struct gtable *)&r->rt_groups; - for (g = r->rt_groups; g; g = g->gt_next) { - if (g->gt_mcastgrp == mcastgrp) { - logit(LOG_DEBUG, 0, "del_table_entry deleting (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2)); - st = g->gt_srctbl; - while (st) { - if (k_del_rg(st->st_origin, g) < 0) { - logit(LOG_WARNING, errno, - "del_table_entry trying to delete (%s, %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(g->gt_mcastgrp, s2)); - } - kroutes--; - prev_st = st; - st = st->st_next; - free(prev_st); - } - g->gt_srctbl = NULL; - - pt = g->gt_pruntbl; - while (pt) { - prev_pt = pt; - pt = pt->pt_next; - free(prev_pt); - } - g->gt_pruntbl = NULL; - - if (g->gt_gnext) - g->gt_gnext->gt_gprev = g->gt_gprev; - if (g->gt_gprev) - g->gt_gprev->gt_gnext = g->gt_gnext; - else - kernel_table = g->gt_gnext; - - if (prev_g != (struct gtable *)&r->rt_groups) - g->gt_next->gt_prev = prev_g; - else - g->gt_next->gt_prev = NULL; - prev_g->gt_next = g->gt_next; - -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,0); - rsrr_cache_clean(g); -#endif /* RSRR */ - free(g); - g = prev_g; - } else { - prev_g = g; - } - } - } -} - -/* - * update kernel table entry when a route entry changes - */ -void -update_table_entry(struct rtentry *r) -{ - struct gtable *g; - struct ptable *pt, *prev_pt; - vifi_t i; - - for (g = r->rt_groups; g; g = g->gt_next) { - pt = g->gt_pruntbl; - while (pt) { - prev_pt = pt->pt_next; - free(pt); - pt = prev_pt; - } - g->gt_pruntbl = NULL; - - g->gt_grpmems = 0; - - /* obtain the multicast group membership list */ - for (i = 0; i < numvifs; i++) { - if (VIFM_ISSET(i, r->rt_children) && - !(VIFM_ISSET(i, r->rt_leaves))) - VIFM_SET(i, g->gt_grpmems); - - if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, g->gt_mcastgrp)) - VIFM_SET(i, g->gt_grpmems); - } - if (VIFM_ISSET(r->rt_parent, g->gt_scope)) - g->gt_scope = -1; - g->gt_grpmems &= ~g->gt_scope; - - logit(LOG_DEBUG, 0, "updating cache entries (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), - g->gt_grpmems); - - if (g->gt_grpmems && g->gt_prsent_timer) { - g->gt_grftsnt = 1; - send_graft(g); - g->gt_prsent_timer = 0; - } - - /* update ttls and add entry into kernel */ - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - - /* Check if we want to prune this group */ - if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) { - g->gt_timer = CACHE_LIFETIME(cache_lifetime); - send_prune(g); - } - } -} - -/* - * set the forwarding flag for all mcastgrps on this vifi - */ -void -update_lclgrp(vifi_t vifi, u_int32_t mcastgrp) -{ - struct rtentry *r; - struct gtable *g; - - logit(LOG_DEBUG, 0, "group %s joined on vif %d", - inet_fmt(mcastgrp, s1), vifi); - - for (g = kernel_table; g; g = g->gt_gnext) { - if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp)) - break; - - r = g->gt_route; - if (g->gt_mcastgrp == mcastgrp && - VIFM_ISSET(vifi, r->rt_children)) { - - VIFM_SET(vifi, g->gt_grpmems); - g->gt_grpmems &= ~g->gt_scope; - if (g->gt_grpmems == 0) - continue; - - prun_add_ttls(g); - logit(LOG_DEBUG, 0, "update lclgrp (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - } - } -} - -/* - * reset forwarding flag for all mcastgrps on this vifi - */ -void -delete_lclgrp(vifi_t vifi, u_int32_t mcastgrp) -{ - struct rtentry *r; - struct gtable *g; - - logit(LOG_DEBUG, 0, "group %s left on vif %d", - inet_fmt(mcastgrp, s1), vifi); - - for (g = kernel_table; g; g = g->gt_gnext) { - if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp)) - break; - - if (g->gt_mcastgrp == mcastgrp) { - int stop_sending = 1; - - r = g->gt_route; - /* - * If this is not a leaf, then we have router neighbors on this - * vif. Only turn off forwarding if they have all pruned. - */ - if (!VIFM_ISSET(vifi, r->rt_leaves)) { - struct listaddr *vr; - - for (vr = uvifs[vifi].uv_neighbors; vr; vr = vr->al_next) - if (find_prune_entry(vr->al_addr, g->gt_pruntbl) == NULL) { - stop_sending = 0; - break; - } - } - - if (stop_sending) { - VIFM_CLR(vifi, g->gt_grpmems); - logit(LOG_DEBUG, 0, "delete lclgrp (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - - /* - * If there are no more members of this particular group, - * send prune upstream - */ - if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) - send_prune(g); - } - } - } -} - -/* - * Takes the prune message received and then strips it to - * determine the (src, grp) pair to be pruned. - * - * Adds the router to the (src, grp) entry then. - * - * Determines if further packets have to be sent down that vif - * - * Determines if a corresponding prune message has to be generated - */ -void -accept_prune(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ - u_int32_t prun_src; - u_int32_t prun_grp; - u_int32_t prun_tmr; - vifi_t vifi; - int i; - int stop_sending; - struct rtentry *r; - struct gtable *g; - struct ptable *pt; - struct listaddr *vr; - - /* Don't process any prunes if router is not pruning */ - if (pruning == 0) - return; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - logit(LOG_INFO, 0, - "ignoring prune report from non-neighbor %s", - inet_fmt(src, s1)); - return; - } - - /* Check if enough data is present */ - if (datalen < 12) - { - logit(LOG_WARNING, 0, - "non-decipherable prune from %s", - inet_fmt(src, s1)); - return; - } - - for (i = 0; i< 4; i++) - ((char *)&prun_src)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&prun_grp)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&prun_tmr)[i] = *p++; - prun_tmr = ntohl(prun_tmr); - - logit(LOG_DEBUG, 0, "%s on vif %d prunes (%s %s)/%d", - inet_fmt(src, s1), vifi, - inet_fmt(prun_src, s2), inet_fmt(prun_grp, s3), prun_tmr); - - /* - * Find the subnet for the prune - */ - if (find_src_grp(prun_src, 0, prun_grp)) { - g = gtp ? gtp->gt_gnext : kernel_table; - r = g->gt_route; - - if (!VIFM_ISSET(vifi, r->rt_children)) { - logit(LOG_WARNING, 0, "prune received from non-child %s for (%s %s)", - inet_fmt(src, s1), inet_fmt(prun_src, s2), - inet_fmt(prun_grp, s3)); - return; - } - if (VIFM_ISSET(vifi, g->gt_scope)) { - logit(LOG_WARNING, 0, "prune received from %s on scoped grp (%s %s)", - inet_fmt(src, s1), inet_fmt(prun_src, s2), - inet_fmt(prun_grp, s3)); - return; - } - if ((pt = find_prune_entry(src, g->gt_pruntbl)) != NULL) { - /* - * If it's about to expire, then it's only still around because - * of timer granularity, so don't warn about it. - */ - if (pt->pt_timer > 10) { - logit(LOG_WARNING, 0, "%s %d from %s for (%s %s)/%d %s %d %s %x", - "duplicate prune received on vif", - vifi, inet_fmt(src, s1), inet_fmt(prun_src, s2), - inet_fmt(prun_grp, s3), prun_tmr, - "old timer:", pt->pt_timer, "cur gm:", g->gt_grpmems); - } - pt->pt_timer = prun_tmr; - } else { - /* allocate space for the prune structure */ - pt = (struct ptable *)(malloc(sizeof(struct ptable))); - if (pt == NULL) - logit(LOG_ERR, 0, "pt: ran out of memory"); - - pt->pt_vifi = vifi; - pt->pt_router = src; - pt->pt_timer = prun_tmr; - - pt->pt_next = g->gt_pruntbl; - g->gt_pruntbl = pt; - } - - /* Refresh the group's lifetime */ - g->gt_timer = CACHE_LIFETIME(cache_lifetime); - if (g->gt_timer < prun_tmr) - g->gt_timer = prun_tmr; - - /* - * check if any more packets need to be sent on the - * vif which sent this message - */ - stop_sending = 1; - for (vr = uvifs[vifi].uv_neighbors; vr; vr = vr->al_next) - if (find_prune_entry(vr->al_addr, g->gt_pruntbl) == NULL) { - stop_sending = 0; - break; - } - - if (stop_sending && !grplst_mem(vifi, prun_grp)) { - VIFM_CLR(vifi, g->gt_grpmems); - logit(LOG_DEBUG, 0, "prune (%s %s), stop sending on vif %d, gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), vifi, g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - } - - /* - * check if all the child routers have expressed no interest - * in this group and if this group does not exist in the - * interface - * Send a prune message then upstream - */ - if (!g->gt_prsent_timer && g->gt_grpmems == 0 && r->rt_gateway) { - send_prune(g); - } - } else { - /* - * There is no kernel entry for this group. Therefore, we can - * simply ignore the prune, as we are not forwarding this traffic - * downstream. - */ - logit(LOG_DEBUG, 0, "%s (%s %s)/%d from %s", - "prune message received with no kernel entry for", - inet_fmt(prun_src, s1), inet_fmt(prun_grp, s2), - prun_tmr, inet_fmt(src, s3)); - return; - } -} - -/* - * Checks if this mcastgrp is present in the kernel table - * If so and if a prune was sent, it sends a graft upwards - */ -void -chkgrp_graft(vifi_t vifi, u_int32_t mcastgrp) -{ - struct rtentry *r; - struct gtable *g; - - for (g = kernel_table; g; g = g->gt_gnext) { - if (ntohl(mcastgrp) < ntohl(g->gt_mcastgrp)) - break; - - r = g->gt_route; - if (g->gt_mcastgrp == mcastgrp && VIFM_ISSET(vifi, r->rt_children)) - if (g->gt_prsent_timer) { - VIFM_SET(vifi, g->gt_grpmems); - - /* - * If the vif that was joined was a scoped vif, - * ignore it ; don't graft back - */ - g->gt_grpmems &= ~g->gt_scope; - if (g->gt_grpmems == 0) - continue; - - /* set the flag for graft retransmission */ - g->gt_grftsnt = 1; - - /* send graft upwards */ - send_graft(g); - - /* reset the prune timer and update cache timer*/ - g->gt_prsent_timer = 0; - g->gt_timer = max_prune_lifetime; - - logit(LOG_DEBUG, 0, "chkgrp graft (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - } - } -} - -/* determine the multicast group and src - * - * if it does, then determine if a prune was sent - * upstream. - * if prune sent upstream, send graft upstream and send - * ack downstream. - * - * if no prune sent upstream, change the forwarding bit - * for this interface and send ack downstream. - * - * if no entry exists for this group send ack downstream. - */ -void -accept_graft(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ - vifi_t vifi; - u_int32_t graft_src; - u_int32_t graft_grp; - int i; - struct rtentry *r; - struct gtable *g; - struct ptable *pt, **ptnp; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - logit(LOG_INFO, 0, - "ignoring graft from non-neighbor %s", - inet_fmt(src, s1)); - return; - } - - if (datalen < 8) { - logit(LOG_WARNING, 0, - "received non-decipherable graft from %s", - inet_fmt(src, s1)); - return; - } - - for (i = 0; i< 4; i++) - ((char *)&graft_src)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&graft_grp)[i] = *p++; - - logit(LOG_DEBUG, 0, "%s on vif %d grafts (%s %s)", - inet_fmt(src, s1), vifi, - inet_fmt(graft_src, s2), inet_fmt(graft_grp, s3)); - - /* - * Find the subnet for the graft - */ - if (find_src_grp(graft_src, 0, graft_grp)) { - g = gtp ? gtp->gt_gnext : kernel_table; - r = g->gt_route; - - if (VIFM_ISSET(vifi, g->gt_scope)) { - logit(LOG_WARNING, 0, "graft received from %s on scoped grp (%s %s)", - inet_fmt(src, s1), inet_fmt(graft_src, s2), - inet_fmt(graft_grp, s3)); - return; - } - - ptnp = &g->gt_pruntbl; - while ((pt = *ptnp) != NULL) { - if ((pt->pt_vifi == vifi) && (pt->pt_router == src)) { - *ptnp = pt->pt_next; - free(pt); - - VIFM_SET(vifi, g->gt_grpmems); - logit(LOG_DEBUG, 0, "accept graft (%s %s) gm:%x", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(g->gt_mcastgrp, s2), g->gt_grpmems); - - prun_add_ttls(g); - update_kernel(g); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(g,1); -#endif /* RSRR */ - break; - } else { - ptnp = &pt->pt_next; - } - } - - /* send ack downstream */ - send_graft_ack(dst, src, graft_src, graft_grp); - g->gt_timer = max_prune_lifetime; - - if (g->gt_prsent_timer) { - /* set the flag for graft retransmission */ - g->gt_grftsnt = 1; - - /* send graft upwards */ - send_graft(g); - - /* reset the prune sent timer */ - g->gt_prsent_timer = 0; - } - } else { - /* - * We have no state for the source and group in question. - * We can simply acknowledge the graft, since we know - * that we have no prune state, and grafts are requests - * to remove prune state. - */ - send_graft_ack(dst, src, graft_src, graft_grp); - logit(LOG_DEBUG, 0, "%s (%s %s) from %s", - "graft received with no kernel entry for", - inet_fmt(graft_src, s1), inet_fmt(graft_grp, s2), - inet_fmt(src, s3)); - return; - } -} - -/* - * find out which group is involved first of all - * then determine if a graft was sent. - * if no graft sent, ignore the message - * if graft was sent and the ack is from the right - * source, remove the graft timer so that we don't - * have send a graft again - */ -void -accept_g_ack(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ - struct gtable *g; - vifi_t vifi; - u_int32_t grft_src; - u_int32_t grft_grp; - int i; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - logit(LOG_INFO, 0, - "ignoring graft ack from non-neighbor %s", - inet_fmt(src, s1)); - return; - } - - if (datalen < 0 || datalen > 8) { - logit(LOG_WARNING, 0, - "received non-decipherable graft ack from %s", - inet_fmt(src, s1)); - return; - } - - for (i = 0; i< 4; i++) - ((char *)&grft_src)[i] = *p++; - for (i = 0; i< 4; i++) - ((char *)&grft_grp)[i] = *p++; - - logit(LOG_DEBUG, 0, "%s on vif %d acks graft (%s, %s)", - inet_fmt(src, s1), vifi, - inet_fmt(grft_src, s2), inet_fmt(grft_grp, s3)); - - /* - * Find the subnet for the graft ack - */ - if (find_src_grp(grft_src, 0, grft_grp)) { - g = gtp ? gtp->gt_gnext : kernel_table; - g->gt_grftsnt = 0; - } else { - logit(LOG_WARNING, 0, "%s (%s, %s) from %s", - "rcvd graft ack with no kernel entry for", - inet_fmt(grft_src, s1), inet_fmt(grft_grp, s2), - inet_fmt(src, s3)); - return; - } -} - - -/* - * free all prune entries and kernel routes - * normally, this should inform the kernel that all of its routes - * are going away, but this is only called by restart(), which is - * about to call MRT_DONE which does that anyway. - */ -void -free_all_prunes(void) -{ - struct rtentry *r; - struct gtable *g, *prev_g; - struct stable *s, *prev_s; - struct ptable *p, *prev_p; - - for (r = routing_table; r; r = r->rt_next) { - g = r->rt_groups; - while (g) { - s = g->gt_srctbl; - while (s) { - prev_s = s; - s = s->st_next; - free(prev_s); - } - - p = g->gt_pruntbl; - while (p) { - prev_p = p; - p = p->pt_next; - free(prev_p); - } - - prev_g = g; - g = g->gt_next; - free(prev_g); - } - r->rt_groups = NULL; - } - kernel_table = NULL; - - g = kernel_no_route; - while (g) { - if (g->gt_srctbl) - free(g->gt_srctbl); - - prev_g = g; - g = g->gt_next; - free(prev_g); - } - kernel_no_route = NULL; -} - -/* - * When a new route is created, search - * a) The less-specific part of the routing table - * b) The route-less kernel table - * for sources that the new route might want to handle. - * - * "Inheriting" these sources might be cleanest, but simply deleting - * them is easier, and letting the kernel re-request them. - */ -void -steal_sources(struct rtentry *rt) -{ - struct rtentry *rp; - struct gtable *gt, **gtnp; - struct stable *st, **stnp; - - for (rp = rt->rt_next; rp; rp = rp->rt_next) { - if ((rt->rt_origin & rp->rt_originmask) == rp->rt_origin) { - logit(LOG_DEBUG, 0, "Route for %s stealing sources from %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmts(rp->rt_origin, rp->rt_originmask, s2)); - for (gt = rp->rt_groups; gt; gt = gt->gt_next) { - stnp = >->gt_srctbl; - while ((st = *stnp) != NULL) { - if ((st->st_origin & rt->rt_originmask) == rt->rt_origin) { - logit(LOG_DEBUG, 0, "%s stealing (%s %s) from %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmt(st->st_origin, s3), - inet_fmt(gt->gt_mcastgrp, s4), - inet_fmts(rp->rt_origin, rp->rt_originmask, s2)); - if (k_del_rg(st->st_origin, gt) < 0) { - logit(LOG_WARNING, errno, "%s (%s, %s)", - "steal_sources trying to delete", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - *stnp = st->st_next; - kroutes--; - free(st); - } else { - stnp = &st->st_next; - } - } - } - } - } - - gtnp = &kernel_no_route; - while ((gt = *gtnp) != NULL) { - if (gt->gt_srctbl && ((gt->gt_srctbl->st_origin & rt->rt_originmask) - == rt->rt_origin)) { - logit(LOG_DEBUG, 0, "%s stealing (%s %s) from %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmt(gt->gt_srctbl->st_origin, s3), - inet_fmt(gt->gt_mcastgrp, s4), - "no_route table"); - if (k_del_rg(gt->gt_srctbl->st_origin, gt) < 0) { - logit(LOG_WARNING, errno, "%s (%s %s)", - "steal_sources trying to delete", - inet_fmt(gt->gt_srctbl->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - kroutes--; - free(gt->gt_srctbl); - *gtnp = gt->gt_next; - if (gt->gt_next) - gt->gt_next->gt_prev = gt->gt_prev; - free(gt); - } else { - gtnp = >->gt_next; - } - } -} - -/* - * Advance the timers on all the cache entries. - * If there are any entries whose timers have expired, - * remove these entries from the kernel cache. - */ -void -age_table_entry(void) -{ - struct rtentry *r; - struct gtable *gt, **gtnptr; - struct stable *st, **stnp; - struct ptable *pt, **ptnp; - struct sioc_sg_req sg_req; - - logit(LOG_DEBUG, 0, "ageing entries"); - - gtnptr = &kernel_table; - while ((gt = *gtnptr) != NULL) { - r = gt->gt_route; - - /* advance the timer for the kernel entry */ - gt->gt_timer -= ROUTE_MAX_REPORT_DELAY; - - /* decrement prune timer if need be */ - if (gt->gt_prsent_timer > 0) { - gt->gt_prsent_timer -= ROUTE_MAX_REPORT_DELAY; - if (gt->gt_prsent_timer <= 0) { - logit(LOG_DEBUG, 0, "upstream prune tmo (%s %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - gt->gt_prsent_timer = -1; - } - } - - /* retransmit graft if graft sent flag is still set */ - if (gt->gt_grftsnt) { - int y; - CHK_GS(gt->gt_grftsnt++, y); - if (y) - send_graft(gt); - } - - /* - * Age prunes - * - * If a prune expires, forward again on that vif. - */ - ptnp = >->gt_pruntbl; - while ((pt = *ptnp) != NULL) { - if ((pt->pt_timer -= ROUTE_MAX_REPORT_DELAY) <= 0) { - logit(LOG_DEBUG, 0, "expire prune (%s %s) from %s on vif %d", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), - inet_fmt(pt->pt_router, s3), - pt->pt_vifi); - - expire_prune(pt->pt_vifi, gt); - - /* remove the router's prune entry and await new one */ - *ptnp = pt->pt_next; - free(pt); - } else { - ptnp = &pt->pt_next; - } - } - - /* - * If the cache entry has expired, delete source table entries for - * silent sources. If there are no source entries left, and there - * are no downstream prunes, then the entry is deleted. - * Otherwise, the cache entry's timer is refreshed. - */ - if (gt->gt_timer <= 0) { - /* Check for traffic before deleting source entries */ - sg_req.grp.s_addr = gt->gt_mcastgrp; - stnp = >->gt_srctbl; - while ((st = *stnp) != NULL) { - sg_req.src.s_addr = st->st_origin; - if (ioctl(igmp_socket, SIOCGETSGCNT, (char *)&sg_req) < 0) { - logit(LOG_WARNING, errno, "%s (%s %s)", - "age_table_entry: SIOCGETSGCNT failing for", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - /* Make sure it gets deleted below */ - sg_req.pktcnt = st->st_pktcnt; - } - if (sg_req.pktcnt == st->st_pktcnt) { - *stnp = st->st_next; - logit(LOG_DEBUG, 0, "age_table_entry deleting (%s %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - if (k_del_rg(st->st_origin, gt) < 0) { - logit(LOG_WARNING, errno, - "age_table_entry trying to delete (%s %s)", - inet_fmt(st->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - kroutes--; - free(st); - } else { - st->st_pktcnt = sg_req.pktcnt; - stnp = &st->st_next; - } - } - - /* - * Retain the group entry if we have downstream prunes or if - * there is at least one source in the list that still has - * traffic, or if our upstream prune timer is running. - */ - if (gt->gt_pruntbl != NULL || gt->gt_srctbl != NULL || - gt->gt_prsent_timer > 0) { - gt->gt_timer = CACHE_LIFETIME(cache_lifetime); - if (gt->gt_prsent_timer == -1) { - if (gt->gt_grpmems == 0) - send_prune(gt); - else - gt->gt_prsent_timer = 0; - } - gtnptr = >->gt_gnext; - continue; - } - - logit(LOG_DEBUG, 0, "timeout cache entry (%s, %s)", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - - if (gt->gt_prev) - gt->gt_prev->gt_next = gt->gt_next; - else - gt->gt_route->rt_groups = gt->gt_next; - if (gt->gt_next) - gt->gt_next->gt_prev = gt->gt_prev; - - if (gt->gt_gprev) { - gt->gt_gprev->gt_gnext = gt->gt_gnext; - gtnptr = >->gt_gprev->gt_gnext; - } else { - kernel_table = gt->gt_gnext; - gtnptr = &kernel_table; - } - if (gt->gt_gnext) - gt->gt_gnext->gt_gprev = gt->gt_gprev; - -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(gt,0); - rsrr_cache_clean(gt); -#endif /* RSRR */ - free((char *)gt); - } else { - if (gt->gt_prsent_timer == -1) { - if (gt->gt_grpmems == 0) - send_prune(gt); - else - gt->gt_prsent_timer = 0; - } - gtnptr = >->gt_gnext; - } - } - - /* - * When traversing the no_route table, the decision is much easier. - * Just delete it if it has timed out. - */ - gtnptr = &kernel_no_route; - while ((gt = *gtnptr) != NULL) { - /* advance the timer for the kernel entry */ - gt->gt_timer -= ROUTE_MAX_REPORT_DELAY; - - if (gt->gt_timer < 0) { - if (gt->gt_srctbl) { - if (k_del_rg(gt->gt_srctbl->st_origin, gt) < 0) { - logit(LOG_WARNING, errno, "%s (%s %s)", - "age_table_entry trying to delete no-route", - inet_fmt(gt->gt_srctbl->st_origin, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - } - free(gt->gt_srctbl); - } - *gtnptr = gt->gt_next; - if (gt->gt_next) - gt->gt_next->gt_prev = gt->gt_prev; - - free((char *)gt); - } else { - gtnptr = >->gt_next; - } - } -} - -/* - * Modify the kernel to forward packets when one or multiple prunes that - * were received on the vif given by vifi, for the group given by gt, - * have expired. - */ -static void -expire_prune(vifi_t vifi, struct gtable *gt) -{ - /* - * No need to send a graft, any prunes that we sent - * will expire before any prunes that we have received. - */ - if (gt->gt_prsent_timer > 0) { - logit(LOG_DEBUG, 0, "prune expired with %d left on %s", - gt->gt_prsent_timer, "prsent_timer"); - gt->gt_prsent_timer = 0; - } - - /* modify the kernel entry to forward packets */ - if (!VIFM_ISSET(vifi, gt->gt_grpmems)) { - struct rtentry *rt = gt->gt_route; - VIFM_SET(vifi, gt->gt_grpmems); - logit(LOG_DEBUG, 0, "forw again (%s %s) gm:%x vif:%d", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2), gt->gt_grpmems, vifi); - - prun_add_ttls(gt); - update_kernel(gt); -#ifdef RSRR - /* Send route change notification to reservation protocol. */ - rsrr_cache_send(gt,1); -#endif /* RSRR */ - } -} - - -static char * -scaletime(u_long t) -{ - static char buf1[5]; - static char buf2[5]; - static char *buf=buf1; - char s; - char *p; - - p = buf; - if (buf == buf1) - buf = buf2; - else - buf = buf1; - - if (t < 120) { - s = 's'; - } else if (t < 3600) { - t /= 60; - s = 'm'; - } else if (t < 86400) { - t /= 3600; - s = 'h'; - } else if (t < 864000) { - t /= 86400; - s = 'd'; - } else { - t /= 604800; - s = 'w'; - } - if (t > 999) - return "*** "; - - sprintf(p,"%3d%c", (int)t, s); - - return p; -} - -/* - * Print the contents of the cache table on file 'fp2'. - */ -void -dump_cache(FILE *fp2) -{ - struct rtentry *r; - struct gtable *gt; - struct stable *st; - vifi_t i; - time_t thyme = time(0); - - fprintf(fp2, - "Multicast Routing Cache Table (%d entries)\n%s", kroutes, - " Origin Mcast-group CTmr Age Ptmr IVif Forwvifs\n"); - - for (gt = kernel_no_route; gt; gt = gt->gt_next) { - if (gt->gt_srctbl) { - fprintf(fp2, " %-18s %-15s %-4s %-4s - -1\n", - inet_fmts(gt->gt_srctbl->st_origin, 0xffffffff, s1), - inet_fmt(gt->gt_mcastgrp, s2), scaletime(gt->gt_timer), - scaletime(thyme - gt->gt_ctime)); - fprintf(fp2, ">%s\n", inet_fmt(gt->gt_srctbl->st_origin, s1)); - } - } - - for (gt = kernel_table; gt; gt = gt->gt_gnext) { - r = gt->gt_route; - fprintf(fp2, " %-18s %-15s", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - inet_fmt(gt->gt_mcastgrp, s2)); - - fprintf(fp2, " %-4s", scaletime(gt->gt_timer)); - - fprintf(fp2, " %-4s %-4s ", scaletime(thyme - gt->gt_ctime), - gt->gt_prsent_timer ? scaletime(gt->gt_prsent_timer) : - " -"); - - fprintf(fp2, "%2u%c%c ", r->rt_parent, - gt->gt_prsent_timer ? 'P' : ' ', - VIFM_ISSET(r->rt_parent, gt->gt_scope) ? 'B' : ' '); - - for (i = 0; i < numvifs; ++i) { - if (VIFM_ISSET(i, gt->gt_grpmems)) - fprintf(fp2, " %u ", i); - else if (VIFM_ISSET(i, r->rt_children) && - !VIFM_ISSET(i, r->rt_leaves)) - fprintf(fp2, " %u%c", i, - VIFM_ISSET(i, gt->gt_scope) ? 'b' : 'p'); - } - fprintf(fp2, "\n"); - for (st = gt->gt_srctbl; st; st = st->st_next) { - fprintf(fp2, ">%s\n", inet_fmt(st->st_origin, s1)); - } -#ifdef DEBUG_PRUNES - for (pt = gt->gt_pruntbl; pt; pt = pt->pt_next) { - fprintf(fp2, "<r:%s v:%d t:%d\n", inet_fmt(pt->pt_router, s1), - pt->pt_vifi, pt->pt_timer); - } -#endif - } -} - -/* - * Traceroute function which returns traceroute replies to the requesting - * router. Also forwards the request to downstream routers. - * - * no: promoted u_char - */ -void -accept_mtrace(u_int32_t src, u_int32_t dst, u_int32_t group, char *data, - u_int no, int datalen) -{ - u_char type; - struct rtentry *rt; - struct gtable *gt; - struct tr_query *qry; - struct tr_resp *resp; - int vifi; - char *p; - int rcount; - int errcode = TR_NO_ERR; - int resptype; - struct timeval tp; - struct sioc_vif_req v_req; - struct sioc_sg_req sg_req; - - /* Remember qid across invocations */ - static u_int32_t oqid = 0; - - /* timestamp the request/response */ - gettimeofday(&tp, 0); - - /* - * Check if it is a query or a response - */ - if (datalen == QLEN) { - type = QUERY; - logit(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); - } - else if ((datalen - QLEN) % RLEN == 0) { - type = RESP; - logit(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); - if (IN_MULTICAST(ntohl(dst))) { - logit(LOG_DEBUG, 0, "Dropping multicast response"); - return; - } - } - else { - logit(LOG_WARNING, 0, "%s from %s to %s", - "Non decipherable traceroute request received", - inet_fmt(src, s1), inet_fmt(dst, s2)); - return; - } - - qry = (struct tr_query *)data; - - /* - * if it is a packet with all reports filled, drop it - */ - if ((rcount = (datalen - QLEN)/RLEN) == no) { - logit(LOG_DEBUG, 0, "packet with all reports filled in"); - return; - } - - logit(LOG_DEBUG, 0, "s: %s g: %s d: %s ", inet_fmt(qry->tr_src, s1), - inet_fmt(group, s2), inet_fmt(qry->tr_dst, s3)); - logit(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl, - inet_fmt(qry->tr_raddr, s1)); - logit(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid); - - /* determine the routing table entry for this traceroute */ - rt = determine_route(qry->tr_src); - if (rt) { - logit(LOG_DEBUG, 0, "rt parent vif: %d rtr: %s metric: %d", - rt->rt_parent, inet_fmt(rt->rt_gateway, s1), rt->rt_metric); - logit(LOG_DEBUG, 0, "rt origin %s", - inet_fmts(rt->rt_origin, rt->rt_originmask, s1)); - } else - logit(LOG_DEBUG, 0, "...no route"); - - /* - * Query type packet - check if rte exists - * Check if the query destination is a vif connected to me. - * and if so, whether I should start response back - */ - if (type == QUERY) { - if (oqid == qry->tr_qid) { - /* - * If the multicast router is a member of the group being - * queried, and the query is multicasted, then the router can - * receive multiple copies of the same query. If we have already - * replied to this traceroute, just ignore it this time. - * - * This is not a total solution, but since if this fails you - * only get N copies, N <= the number of interfaces on the router, - * it is not fatal. - */ - logit(LOG_DEBUG, 0, "ignoring duplicate traceroute packet"); - return; - } - - if (rt == NULL) { - logit(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s", - inet_fmt(qry->tr_src, s1)); - if (IN_MULTICAST(ntohl(dst))) - return; - } - vifi = find_vif(qry->tr_dst, 0); - - if (vifi == NO_VIF) { - /* The traceroute destination is not on one of my subnet vifs. */ - logit(LOG_DEBUG, 0, "Destination %s not an interface", - inet_fmt(qry->tr_dst, s1)); - if (IN_MULTICAST(ntohl(dst))) - return; - errcode = TR_WRONG_IF; - } else if (rt != NULL && !VIFM_ISSET(vifi, rt->rt_children)) { - logit(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s", - inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2)); - if (IN_MULTICAST(ntohl(dst))) - return; - errcode = TR_WRONG_IF; - } - } - else { - /* - * determine which interface the packet came in on - * RESP packets travel hop-by-hop so this either traversed - * a tunnel or came from a directly attached mrouter. - */ - if ((vifi = find_vif(src, dst)) == NO_VIF) { - logit(LOG_DEBUG, 0, "Wrong interface for packet"); - errcode = TR_WRONG_IF; - } - } - - /* Now that we've decided to send a response, save the qid */ - oqid = qry->tr_qid; - - logit(LOG_DEBUG, 0, "Sending traceroute response"); - - /* copy the packet to the sending buffer */ - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - - bcopy(data, p, datalen); - - p += datalen; - - /* - * If there is no room to insert our reply, coopt the previous hop - * error indication to relay this fact. - */ - if (p + sizeof(struct tr_resp) > send_buf + RECV_BUF_SIZE) { - resp = (struct tr_resp *)p - 1; - resp->tr_rflags = TR_NO_SPACE; - rt = NULL; - goto sendit; - } - - /* - * fill in initial response fields - */ - resp = (struct tr_resp *)p; - bzero(resp, sizeof(struct tr_resp)); - datalen += RLEN; - - resp->tr_qarr = htonl((tp.tv_sec + JAN_1970) << 16) + - ((tp.tv_usec >> 4) & 0xffff); - - resp->tr_rproto = PROTO_DVMRP; - if (errcode != TR_NO_ERR) { - resp->tr_rflags = errcode; - rt = NULL; /* hack to enforce send straight to requestor */ - goto sendit; - } - resp->tr_outaddr = uvifs[vifi].uv_lcl_addr; - resp->tr_fttl = uvifs[vifi].uv_threshold; - resp->tr_rflags = TR_NO_ERR; - - /* - * obtain # of packets out on interface - */ - v_req.vifi = vifi; - if (ioctl(igmp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0) - resp->tr_vifout = htonl(v_req.ocount); - - /* - * fill in scoping & pruning information - */ - if (rt) - for (gt = rt->rt_groups; gt; gt = gt->gt_next) { - if (gt->gt_mcastgrp >= group) - break; - } - else - gt = NULL; - - if (gt && gt->gt_mcastgrp == group) { - sg_req.src.s_addr = qry->tr_src; - sg_req.grp.s_addr = group; - if (ioctl(igmp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0) - resp->tr_pktcnt = htonl(sg_req.pktcnt); - - if (VIFM_ISSET(vifi, gt->gt_scope)) - resp->tr_rflags = TR_SCOPED; - else if (gt->gt_prsent_timer) - resp->tr_rflags = TR_PRUNED; - else if (!VIFM_ISSET(vifi, gt->gt_grpmems)) { - if (VIFM_ISSET(vifi, rt->rt_children) && - !VIFM_ISSET(vifi, rt->rt_leaves)) - resp->tr_rflags = TR_OPRUNED; - else - resp->tr_rflags = TR_NO_FWD; - } - } else { - if (scoped_addr(vifi, group)) - resp->tr_rflags = TR_SCOPED; - else if (rt && !VIFM_ISSET(vifi, rt->rt_children)) - resp->tr_rflags = TR_NO_FWD; - } - - /* - * if no rte exists, set NO_RTE error - */ - if (rt == NULL) { - src = dst; /* the dst address of resp. pkt */ - resp->tr_inaddr = 0; - resp->tr_rflags = TR_NO_RTE; - resp->tr_rmtaddr = 0; - } else { - /* get # of packets in on interface */ - v_req.vifi = rt->rt_parent; - if (ioctl(igmp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0) - resp->tr_vifin = htonl(v_req.icount); - - MASK_TO_VAL(rt->rt_originmask, resp->tr_smask); - src = uvifs[rt->rt_parent].uv_lcl_addr; - resp->tr_inaddr = src; - resp->tr_rmtaddr = rt->rt_gateway; - if (!VIFM_ISSET(vifi, rt->rt_children)) { - logit(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s", - inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2)); - resp->tr_rflags = TR_WRONG_IF; - } - if (rt->rt_metric >= UNREACHABLE) { - resp->tr_rflags = TR_NO_RTE; - /* Hack to send reply directly */ - rt = NULL; - } - } - -sendit: - /* - * if metric is 1 or no. of reports is 1, send response to requestor - * else send to upstream router. If the upstream router can't handle - * mtrace, set an error code and send to requestor anyway. - */ - logit(LOG_DEBUG, 0, "rcount:%d, no:%d", rcount, no); - - if ((rcount + 1 == no) || (rt == NULL) || (rt->rt_metric == 1)) { - resptype = IGMP_MTRACE_REPLY; - dst = qry->tr_raddr; - } else - if (!can_mtrace(rt->rt_parent, rt->rt_gateway)) { - dst = qry->tr_raddr; - resp->tr_rflags = TR_OLD_ROUTER; - resptype = IGMP_MTRACE_REPLY; - } else { - dst = rt->rt_gateway; - resptype = IGMP_MTRACE_QUERY; - } - - if (IN_MULTICAST(ntohl(dst))) { - /* - * Send the reply on a known multicast capable vif. - * If we don't have one, we can't source any multicasts anyway. - */ - if (phys_vif != -1) { - logit(LOG_DEBUG, 0, "Sending reply to %s from %s", - inet_fmt(dst, s1), inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2)); - k_set_ttl(qry->tr_rttl); - send_igmp(uvifs[phys_vif].uv_lcl_addr, dst, - resptype, no, group, - datalen); - k_set_ttl(1); - } else - logit(LOG_INFO, 0, "No enabled phyints -- %s", - "dropping traceroute reply"); - } else { - logit(LOG_DEBUG, 0, "Sending %s to %s from %s", - resptype == IGMP_MTRACE_REPLY ? "reply" : "request on", - inet_fmt(dst, s1), inet_fmt(src, s2)); - - send_igmp(src, dst, - resptype, no, group, - datalen); - } - return; -} diff --git a/gnu/dist/mrouted/prune.h b/gnu/dist/mrouted/prune.h deleted file mode 100644 index 9f0ad8b8e95..00000000000 --- a/gnu/dist/mrouted/prune.h +++ /dev/null @@ -1,150 +0,0 @@ -/* $NetBSD: prune.h,v 1.1 2002/10/01 03:31:09 itojun Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -/* - * Group table - * - * Each group entry is a member of two doubly-linked lists: - * - * a) A list hanging off of the routing table entry for this source (rt_groups) - * sorted by group address under the routing entry (gt_next, gt_prev) - * b) An independent list pointed to by kernel_table, which is a list of - * active source,group's (gt_gnext, gt_gprev). - * - */ -struct gtable { - struct gtable *gt_next; /* pointer to the next entry */ - struct gtable *gt_prev; /* back pointer for linked list */ - struct gtable *gt_gnext; /* fwd pointer for group list */ - struct gtable *gt_gprev; /* rev pointer for group list */ - u_int32_t gt_mcastgrp; /* multicast group associated */ - vifbitmap_t gt_scope; /* scoped interfaces */ - u_char gt_ttls[MAXVIFS]; /* ttl vector for forwarding */ - vifbitmap_t gt_grpmems; /* forw. vifs for src, grp */ - int gt_prsent_timer; /* prune timer for this group */ - int gt_timer; /* timer for this group entry */ - time_t gt_ctime; /* time of entry creation */ - u_char gt_grftsnt; /* graft sent/retransmit timer */ - struct stable *gt_srctbl; /* source table */ - struct ptable *gt_pruntbl; /* prune table */ - struct rtentry *gt_route; /* parent route */ -#ifdef RSRR - struct rsrr_cache *gt_rsrr_cache; /* RSRR cache */ -#endif /* RSRR */ -}; - -/* - * Source table - * - * When source-based prunes exist, there will be a struct ptable here as well. - */ -struct stable -{ - struct stable *st_next; /* pointer to the next entry */ - u_int32_t st_origin; /* host origin of multicasts */ - u_long st_pktcnt; /* packet count for src-grp entry */ -}; - -/* - * structure to store incoming prunes. Can hang off of either group or source. - */ -struct ptable -{ - struct ptable *pt_next; /* pointer to the next entry */ - u_int32_t pt_router; /* router that sent this prune */ - vifi_t pt_vifi; /* vif prune received on */ - int pt_timer; /* timer for prune */ -}; - -/* - * The packet format for a traceroute request. - */ -struct tr_query { - u_int32_t tr_src; /* traceroute source */ - u_int32_t tr_dst; /* traceroute destination */ - u_int32_t tr_raddr; /* traceroute response address */ -#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) - struct { - u_int qid : 24; /* traceroute query id */ - u_int ttl : 8; /* traceroute response ttl */ - } q; -#else - struct { - u_int ttl : 8; /* traceroute response ttl */ - u_int qid : 24; /* traceroute query id */ - } q; -#endif /* BYTE_ORDER */ -}; - -#define tr_rttl q.ttl -#define tr_qid q.qid - -/* - * Traceroute response format. A traceroute response has a tr_query at the - * beginning, followed by one tr_resp for each hop taken. - */ -struct tr_resp { - u_int32_t tr_qarr; /* query arrival time */ - u_int32_t tr_inaddr; /* incoming interface address */ - u_int32_t tr_outaddr; /* outgoing interface address */ - u_int32_t tr_rmtaddr; /* parent address in source tree */ - u_int32_t tr_vifin; /* input packet count on interface */ - u_int32_t tr_vifout; /* output packet count on interface */ - u_int32_t tr_pktcnt; /* total incoming packets for src-grp */ - u_char tr_rproto; /* routing protocol deployed on router */ - u_char tr_fttl; /* ttl required to forward on outvif */ - u_char tr_smask; /* subnet mask for src addr */ - u_char tr_rflags; /* forwarding error codes */ -}; - -/* defs within mtrace */ -#define QUERY 1 -#define RESP 2 -#define QLEN sizeof(struct tr_query) -#define RLEN sizeof(struct tr_resp) - -/* fields for tr_rflags (forwarding error codes) */ -#define TR_NO_ERR 0 -#define TR_WRONG_IF 1 -#define TR_PRUNED 2 -#define TR_OPRUNED 3 -#define TR_SCOPED 4 -#define TR_NO_RTE 5 -#define TR_NO_FWD 7 -#define TR_RP_OR_CORE 8 -#define TR_RPF_INT 9 -#define TR_NO_MULTICAST 10 -#define TR_NO_SPACE 0x81 -#define TR_OLD_ROUTER 0x82 -#define TR_ADMIN_DENY 0x83 - -/* fields for tr_rproto (routing protocol) */ -#define PROTO_DVMRP 1 -#define PROTO_MOSPF 2 -#define PROTO_PIM 3 -#define PROTO_CBT 4 -#define PROTO_PIM_SPEC 5 -#define PROTO_PIM_STAT 6 -#define PROTO_DVMRP_STAT 7 -#define PROTO_PIM_MBGP 8 - -#define MASK_TO_VAL(x, i) { \ - u_int32_t _x = ntohl(x); \ - (i) = 1; \ - while ((_x) <<= 1) \ - (i)++; \ - }; - -#define VAL_TO_MASK(x, i) { \ - x = htonl(~((1 << (32 - (i))) - 1)); \ - }; - -#define NBR_VERS(n) (((n)->al_pv << 8) + (n)->al_mv) diff --git a/gnu/dist/mrouted/route.c b/gnu/dist/mrouted/route.c deleted file mode 100644 index c33825c26af..00000000000 --- a/gnu/dist/mrouted/route.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* $NetBSD: route.c,v 1.2 2002/12/06 16:02:57 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include "defs.h" - - -/* - * This define statement saves a lot of space later - */ -#define RT_ADDR (struct rtentry *)&routing_table - -/* - * Exported variables. - */ -int routes_changed; /* 1=>some routes have changed */ -int delay_change_reports; /* 1=>postpone change reports */ - - -/* - * The routing table is shared with prune.c , so must not be static. - */ -struct rtentry *routing_table; /* pointer to list of route entries */ - -/* - * Private variables. - */ -static struct rtentry *rtp; /* pointer to a route entry */ -static struct rtentry *rt_end; /* pointer to last route entry */ -unsigned int nroutes; /* current number of route entries */ - -/* - * Private functions. - */ -static int init_children_and_leaves(struct rtentry *r, vifi_t parent); -static int find_route(u_int32_t origin, u_int32_t mask); -static void create_route(u_int32_t origin, u_int32_t mask); -static void discard_route(struct rtentry *prev_r); -static int compare_rts(const void *rt1, const void *rt2); -static int report_chunk(struct rtentry *start_rt, vifi_t vifi, u_int32_t dst); - -/* - * Initialize the routing table and associated variables. - */ -void -init_routes(void) -{ - routing_table = NULL; - rt_end = RT_ADDR; - nroutes = 0; - routes_changed = FALSE; - delay_change_reports = FALSE; -} - - -/* - * Initialize the children and leaf bits for route 'r', along with the - * associated dominant, subordinate, and leaf timing data structures. - * Return TRUE if this changes the value of either the children or - * leaf bitmaps for 'r'. - */ -static int -init_children_and_leaves(struct rtentry *r, vifi_t parent) -{ - vifi_t vifi; - struct uvif *v; - vifbitmap_t old_children, old_leaves; - - VIFM_COPY(r->rt_children, old_children); - VIFM_COPY(r->rt_leaves, old_leaves ); - - VIFM_CLRALL(r->rt_children); - VIFM_CLRALL(r->rt_leaves); - r->rt_flags &= ~RTF_LEAF_TIMING; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - r->rt_dominants [vifi] = 0; - r->rt_subordinates[vifi] = 0; - - if (vifi != parent && !(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { - VIFM_SET(vifi, r->rt_children); - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - } - else { - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - } - else { - r->rt_leaf_timers[vifi] = 0; - } - } - - return (!VIFM_SAME(r->rt_children, old_children) || - !VIFM_SAME(r->rt_leaves, old_leaves)); -} - - -/* - * A new vif has come up -- update the children and leaf bitmaps in all route - * entries to take that into account. - */ -void -add_vif_to_routes(vifi_t vifi) -{ - struct rtentry *r; - struct uvif *v; - - v = &uvifs[vifi]; - for (r = routing_table; r != NULL; r = r->rt_next) { - if (r->rt_metric != UNREACHABLE && - !VIFM_ISSET(vifi, r->rt_children)) { - VIFM_SET(vifi, r->rt_children); - r->rt_dominants [vifi] = 0; - r->rt_subordinates[vifi] = 0; - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - } - else { - VIFM_CLR(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - update_table_entry(r); - } - } -} - - -/* - * A vif has gone down -- expire all routes that have that vif as parent, - * and update the children bitmaps in all other route entries to take into - * account the failed vif. - */ -void -delete_vif_from_routes(vifi_t vifi) -{ - struct rtentry *r; - - for (r = routing_table; r != NULL; r = r->rt_next) { - if (r->rt_metric != UNREACHABLE) { - if (vifi == r->rt_parent) { - del_table_entry(r, 0, DEL_ALL_ROUTES); - r->rt_timer = ROUTE_EXPIRE_TIME; - r->rt_metric = UNREACHABLE; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - else if (VIFM_ISSET(vifi, r->rt_children)) { - VIFM_CLR(vifi, r->rt_children); - VIFM_CLR(vifi, r->rt_leaves); - r->rt_subordinates[vifi] = 0; - r->rt_leaf_timers [vifi] = 0; - update_table_entry(r); - } - else { - r->rt_dominants[vifi] = 0; - } - } - } -} - - -/* - * A neighbor has failed or become unreachable. If that neighbor was - * considered a dominant or subordinate router in any route entries, - * take appropriate action. - */ -void -delete_neighbor_from_routes(u_int32_t addr, vifi_t vifi) -{ - struct rtentry *r; - struct uvif *v; - - v = &uvifs[vifi]; - for (r = routing_table; r != NULL; r = r->rt_next) { - if (r->rt_metric != UNREACHABLE) { - if (r->rt_dominants[vifi] == addr) { - VIFM_SET(vifi, r->rt_children); - r->rt_dominants [vifi] = 0; - r->rt_subordinates[vifi] = 0; - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - } - else { - VIFM_CLR(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - update_table_entry(r); - } - else if (r->rt_subordinates[vifi] == addr) { - r->rt_subordinates[vifi] = 0; - if (v->uv_neighbors == NULL) { - VIFM_SET(vifi, r->rt_leaves); - update_table_entry(r); - } - else { - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - } - else if (v->uv_neighbors == NULL && - r->rt_leaf_timers[vifi] != 0) { - VIFM_SET(vifi, r->rt_leaves); - r->rt_leaf_timers[vifi] = 0; - update_table_entry(r); - } - } - } -} - - -/* - * Prepare for a sequence of ordered route updates by initializing a pointer - * to the start of the routing table. The pointer is used to remember our - * position in the routing table in order to avoid searching from the - * beginning for each update; this relies on having the route reports in - * a single message be in the same order as the route entries in the routing - * table. - */ -void -start_route_updates(void) -{ - rtp = RT_ADDR; -} - - -/* - * Starting at the route entry following the one to which 'rtp' points, - * look for a route entry matching the specified origin and mask. If a - * match is found, return TRUE and leave 'rtp' pointing at the found entry. - * If no match is found, return FALSE and leave 'rtp' pointing to the route - * entry preceding the point at which the new origin should be inserted. - * This code is optimized for the normal case in which the first entry to - * be examined is the matching entry. - */ -static int -find_route(u_int32_t origin, u_int32_t mask) -{ - struct rtentry *r; - - r = rtp->rt_next; - while (r != NULL) { - if (origin == r->rt_origin && mask == r->rt_originmask) { - rtp = r; - return (TRUE); - } - if (ntohl(mask) < ntohl(r->rt_originmask) || - (mask == r->rt_originmask && - ntohl(origin) < ntohl(r->rt_origin))) { - rtp = r; - r = r->rt_next; - } - else break; - } - return (FALSE); -} - -/* - * Create a new routing table entry for the specified origin and link it into - * the routing table. The shared variable 'rtp' is assumed to point to the - * routing entry after which the new one should be inserted. It is left - * pointing to the new entry. - * - * Only the origin, originmask, originwidth and flags fields are initialized - * in the new route entry; the caller is responsible for filling in the rest. - */ -static void -create_route(u_int32_t origin, u_int32_t mask) -{ - struct rtentry *r; - - if ((r = (struct rtentry *) malloc(sizeof(struct rtentry) + - (2 * numvifs * sizeof(u_int32_t)) + - (numvifs * sizeof(u_int)))) == NULL) { - logit(LOG_ERR, 0, "ran out of memory"); /* fatal */ - } - r->rt_origin = origin; - r->rt_originmask = mask; - if (((char *)&mask)[3] != 0) r->rt_originwidth = 4; - else if (((char *)&mask)[2] != 0) r->rt_originwidth = 3; - else if (((char *)&mask)[1] != 0) r->rt_originwidth = 2; - else r->rt_originwidth = 1; - r->rt_flags = 0; - r->rt_dominants = (u_int32_t *)(r + 1); - r->rt_subordinates = (u_int32_t *)(r->rt_dominants + numvifs); - r->rt_leaf_timers = (u_int *)(r->rt_subordinates + numvifs); - r->rt_groups = NULL; - - r->rt_next = rtp->rt_next; - rtp->rt_next = r; - r->rt_prev = rtp; - if (r->rt_next != NULL) - (r->rt_next)->rt_prev = r; - else - rt_end = r; - rtp = r; - ++nroutes; -} - - -/* - * Discard the routing table entry following the one to which 'prev_r' points. - */ -static void -discard_route(struct rtentry *prev_r) -{ - struct rtentry *r; - - r = prev_r->rt_next; - prev_r->rt_next = r->rt_next; - if (prev_r->rt_next != NULL) - (prev_r->rt_next)->rt_prev = prev_r; - else - rt_end = prev_r; - free((char *)r); - --nroutes; -} - - -/* - * Process a route report for a single origin, creating or updating the - * corresponding routing table entry if necessary. 'src' is either the - * address of a neighboring router from which the report arrived, or zero - * to indicate a change of status of one of our own interfaces. - */ -void -update_route(u_int32_t origin, u_int32_t mask, u_int metric, u_int32_t src, - vifi_t vifi) -{ - struct rtentry *r; - u_int adj_metric; - - /* - * Compute an adjusted metric, taking into account the cost of the - * subnet or tunnel over which the report arrived, and normalizing - * all unreachable/poisoned metrics into a single value. - */ - if (src != 0 && (metric < 1 || metric >= 2*UNREACHABLE)) { - logit(LOG_WARNING, 0, - "%s reports out-of-range metric %u for origin %s", - inet_fmt(src, s1), metric, inet_fmts(origin, mask, s2)); - return; - } - adj_metric = metric + uvifs[vifi].uv_metric; - if (adj_metric > UNREACHABLE) adj_metric = UNREACHABLE; - - /* - * Look up the reported origin in the routing table. - */ - if (!find_route(origin, mask)) { - /* - * Not found. - * Don't create a new entry if the report says it's unreachable, - * or if the reported origin and mask are invalid. - */ - if (adj_metric == UNREACHABLE) { - return; - } - if (src != 0 && !inet_valid_subnet(origin, mask)) { - logit(LOG_WARNING, 0, - "%s reports an invalid origin (%s) and/or mask (%08x)", - inet_fmt(src, s1), inet_fmt(origin, s2), ntohl(mask)); - return; - } - - /* - * OK, create the new routing entry. 'rtp' will be left pointing - * to the new entry. - */ - create_route(origin, mask); - - /* - * Now "steal away" any sources that belong under this route - * by deleting any cache entries they might have created - * and allowing the kernel to re-request them. - */ - steal_sources(rtp); - - rtp->rt_metric = UNREACHABLE; /* temporary; updated below */ - } - - /* - * We now have a routing entry for the reported origin. Update it? - */ - r = rtp; - if (r->rt_metric == UNREACHABLE) { - /* - * The routing entry is for a formerly-unreachable or new origin. - * If the report claims reachability, update the entry to use - * the reported route. - */ - if (adj_metric == UNREACHABLE) - return; - - r->rt_parent = vifi; - init_children_and_leaves(r, vifi); - - r->rt_gateway = src; - r->rt_timer = 0; - r->rt_metric = adj_metric; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - update_table_entry(r); - } - else if (src == r->rt_gateway) { - /* - * The report has come either from the interface directly-connected - * to the origin subnet (src and r->rt_gateway both equal zero) or - * from the gateway we have chosen as the best first-hop gateway back - * towards the origin (src and r->rt_gateway not equal zero). Reset - * the route timer and, if the reported metric has changed, update - * our entry accordingly. - */ - r->rt_timer = 0; - if (adj_metric == r->rt_metric) - return; - - if (adj_metric == UNREACHABLE) { - del_table_entry(r, 0, DEL_ALL_ROUTES); - r->rt_timer = ROUTE_EXPIRE_TIME; - } - else if (adj_metric < r->rt_metric) { - if (init_children_and_leaves(r, vifi)) { - update_table_entry(r); - } - } - r->rt_metric = adj_metric; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - else if (src == 0 || - (r->rt_gateway != 0 && - (adj_metric < r->rt_metric || - (adj_metric == r->rt_metric && - (ntohl(src) < ntohl(r->rt_gateway) || - r->rt_timer >= ROUTE_SWITCH_TIME))))) { - /* - * The report is for an origin we consider reachable; the report - * comes either from one of our own interfaces or from a gateway - * other than the one we have chosen as the best first-hop gateway - * back towards the origin. If the source of the update is one of - * our own interfaces, or if the origin is not a directly-connected - * subnet and the reported metric for that origin is better than - * what our routing entry says, update the entry to use the new - * gateway and metric. We also switch gateways if the reported - * metric is the same as the one in the route entry and the gateway - * associated with the route entry has not been heard from recently, - * or if the metric is the same but the reporting gateway has a lower - * IP address than the gateway associated with the route entry. - * Did you get all that? - */ - if (r->rt_parent != vifi || adj_metric < r->rt_metric) { - /* - * XXX Why do we do this if we are just changing the metric? - */ - r->rt_parent = vifi; - if (init_children_and_leaves(r, vifi)) { - update_table_entry(r); - } - } - r->rt_gateway = src; - r->rt_timer = 0; - r->rt_metric = adj_metric; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - else if (vifi != r->rt_parent) { - /* - * The report came from a vif other than the route's parent vif. - * Update the children and leaf info, if necessary. - */ - if (VIFM_ISSET(vifi, r->rt_children)) { - /* - * Vif is a child vif for this route. - */ - if (metric < r->rt_metric || - (metric == r->rt_metric && - ntohl(src) < ntohl(uvifs[vifi].uv_lcl_addr))) { - /* - * Neighbor has lower metric to origin (or has same metric - * and lower IP address) -- it becomes the dominant router, - * and vif is no longer a child for me. - */ - VIFM_CLR(vifi, r->rt_children); - VIFM_CLR(vifi, r->rt_leaves); - r->rt_dominants [vifi] = src; - r->rt_subordinates[vifi] = 0; - r->rt_leaf_timers [vifi] = 0; - update_table_entry(r); - } - else if (metric > UNREACHABLE) { /* "poisoned reverse" */ - /* - * Neighbor considers this vif to be on path to route's - * origin; if no subordinate recorded, record this neighbor - * as subordinate and clear the leaf flag. - */ - if (r->rt_subordinates[vifi] == 0) { - VIFM_CLR(vifi, r->rt_leaves); - r->rt_subordinates[vifi] = src; - r->rt_leaf_timers [vifi] = 0; - update_table_entry(r); - } - } - else if (src == r->rt_subordinates[vifi]) { - /* - * Current subordinate no longer considers this vif to be on - * path to route's origin; it is no longer a subordinate - * router, and we set the leaf confirmation timer to give - * us time to hear from other subordinates. - */ - r->rt_subordinates[vifi] = 0; - if (uvifs[vifi].uv_neighbors == NULL || - uvifs[vifi].uv_neighbors->al_next == NULL) { - VIFM_SET(vifi, r->rt_leaves); - update_table_entry(r); - } - else { - r->rt_leaf_timers [vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - } - - } - else if (src == r->rt_dominants[vifi] && - (metric > r->rt_metric || - (metric == r->rt_metric && - ntohl(src) > ntohl(uvifs[vifi].uv_lcl_addr)))) { - /* - * Current dominant no longer has a lower metric to origin - * (or same metric and lower IP address); we adopt the vif - * as our own child. - */ - VIFM_SET(vifi, r->rt_children); - r->rt_dominants [vifi] = 0; - if (metric > UNREACHABLE) { - r->rt_subordinates[vifi] = src; - } - else if (uvifs[vifi].uv_neighbors == NULL || - uvifs[vifi].uv_neighbors->al_next == NULL) { - VIFM_SET(vifi, r->rt_leaves); - } - else { - r->rt_leaf_timers[vifi] = LEAF_CONFIRMATION_TIME; - r->rt_flags |= RTF_LEAF_TIMING; - } - update_table_entry(r); - } - } -} - - -/* - * On every timer interrupt, advance the timer in each routing entry. - */ -void -age_routes(void) -{ - struct rtentry *r; - struct rtentry *prev_r; - vifi_t vifi; - - for (prev_r = RT_ADDR, r = routing_table; - r != NULL; - prev_r = r, r = r->rt_next) { - - if ((r->rt_timer += TIMER_INTERVAL) < ROUTE_EXPIRE_TIME) { - /* - * Route is still good; see if any leaf timers need to be - * advanced. - */ - if (r->rt_flags & RTF_LEAF_TIMING) { - r->rt_flags &= ~RTF_LEAF_TIMING; - for (vifi = 0; vifi < numvifs; ++vifi) { - if (r->rt_leaf_timers[vifi] != 0) { - /* - * Unlike other timers, leaf timers decrement. - */ - if ((r->rt_leaf_timers[vifi] -= TIMER_INTERVAL) == 0){ -#ifdef NOTYET - /* If the vif is a physical leaf but has neighbors, - * it is not a tree leaf. If I am a leaf, then no - * interface with neighbors is a tree leaf. */ - if (!(((uvifs[vifi].uv_flags & VIFF_LEAF) || - (vifs_with_neighbors == 1)) && - (uvifs[vifi].uv_neighbors != NULL))) { -#endif - VIFM_SET(vifi, r->rt_leaves); - update_table_entry(r); -#ifdef NOTYET - } -#endif - } - else { - r->rt_flags |= RTF_LEAF_TIMING; - } - } - } - } - } - else if (r->rt_timer >= ROUTE_DISCARD_TIME) { - /* - * Time to garbage-collect the route entry. - */ - del_table_entry(r, 0, DEL_ALL_ROUTES); - discard_route(prev_r); - r = prev_r; - } - else if (r->rt_metric != UNREACHABLE) { - /* - * Time to expire the route entry. If the gateway is zero, - * i.e., it is a route to a directly-connected subnet, just - * set the timer back to zero; such routes expire only when - * the interface to the subnet goes down. - */ - if (r->rt_gateway == 0) { - r->rt_timer = 0; - } - else { - del_table_entry(r, 0, DEL_ALL_ROUTES); - r->rt_metric = UNREACHABLE; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } - } - } -} - - -/* - * Mark all routes as unreachable. This function is called only from - * hup() in preparation for informing all neighbors that we are going - * off the air. For consistency, we ought also to delete all reachable - * route entries from the kernel, but since we are about to exit we rely - * on the kernel to do its own cleanup -- no point in making all those - * expensive kernel calls now. - */ -void -expire_all_routes(void) -{ - struct rtentry *r; - - for (r = routing_table; r != NULL; r = r->rt_next) { - r->rt_metric = UNREACHABLE; - r->rt_flags |= RTF_CHANGED; - routes_changed = TRUE; - } -} - - -/* - * Delete all the routes in the routing table. - */ -void -free_all_routes(void) -{ - struct rtentry *r; - - r = RT_ADDR; - - while (r->rt_next) - discard_route(r); -} - - -/* - * Process an incoming neighbor probe message. - */ -void -accept_probe(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ - vifi_t vifi; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - logit(LOG_INFO, 0, - "ignoring probe from non-neighbor %s", inet_fmt(src, s1)); - return; - } - - update_neighbor(vifi, src, DVMRP_PROBE, p, datalen, level); -} - -struct newrt { - u_int32_t mask; - u_int32_t origin; - int metric; - int pad; -}; - -static int -compare_rts(const void *rt1, const void *rt2) -{ - struct newrt *r1 = (struct newrt *)rt1; - struct newrt *r2 = (struct newrt *)rt2; - u_int32_t m1 = ntohl(r1->mask); - u_int32_t m2 = ntohl(r2->mask); - u_int32_t o1, o2; - - if (m1 > m2) - return (-1); - if (m1 < m2) - return (1); - - /* masks are equal */ - o1 = ntohl(r1->origin); - o2 = ntohl(r2->origin); - if (o1 > o2) - return (-1); - if (o1 < o2) - return (1); - return (0); -} - -/* - * Process an incoming route report message. - */ -void -accept_report(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ - vifi_t vifi; - int width, i, nrt = 0; - int metric; - u_int32_t mask; - u_int32_t origin; - struct newrt rt[4096]; - - if ((vifi = find_vif(src, dst)) == NO_VIF) { - logit(LOG_INFO, 0, - "ignoring route report from non-neighbor %s", inet_fmt(src, s1)); - return; - } - - if (!update_neighbor(vifi, src, DVMRP_REPORT, NULL, 0, level)) - return; - - if (datalen > 2*4096) { - logit(LOG_INFO, 0, - "ignoring oversize (%d bytes) route report from %s", - datalen, inet_fmt(src, s1)); - return; - } - - while (datalen > 0) { /* Loop through per-mask lists. */ - - if (datalen < 3) { - logit(LOG_WARNING, 0, - "received truncated route report from %s", - inet_fmt(src, s1)); - return; - } - ((u_char *)&mask)[0] = 0xff; width = 1; - if ((((u_char *)&mask)[1] = *p++) != 0) width = 2; - if ((((u_char *)&mask)[2] = *p++) != 0) width = 3; - if ((((u_char *)&mask)[3] = *p++) != 0) width = 4; - if (!inet_valid_mask(ntohl(mask))) { - logit(LOG_WARNING, 0, - "%s reports bogus netmask 0x%08x (%s)", - inet_fmt(src, s1), ntohl(mask), inet_fmt(mask, s2)); - return; - } - datalen -= 3; - - do { /* Loop through (origin, metric) pairs */ - if (datalen < width + 1) { - logit(LOG_WARNING, 0, - "received truncated route report from %s", - inet_fmt(src, s1)); - return; - } - origin = 0; - for (i = 0; i < width; ++i) - ((char *)&origin)[i] = *p++; - metric = *p++; - datalen -= width + 1; - rt[nrt].mask = mask; - rt[nrt].origin = origin; - rt[nrt].metric = (metric & 0x7f); - ++nrt; - } while (!(metric & 0x80)); - } - - qsort((char*)rt, nrt, sizeof(rt[0]), compare_rts); - start_route_updates(); - /* - * If the last entry is default, change mask from 0xff000000 to 0 - */ - if (rt[nrt-1].origin == 0) - rt[nrt-1].mask = 0; - - logit(LOG_DEBUG, 0, "Updating %d routes from %s to %s", nrt, - inet_fmt(src, s1), inet_fmt(dst, s2)); - for (i = 0; i < nrt; ++i) { - if (i != 0 && rt[i].origin == rt[i-1].origin && - rt[i].mask == rt[i-1].mask) { - logit(LOG_WARNING, 0, "%s reports duplicate route for %s", - inet_fmt(src, s1), inet_fmts(rt[i].origin, rt[i].mask, s2)); - continue; - } - update_route(rt[i].origin, rt[i].mask, rt[i].metric, - src, vifi); - } - - if (routes_changed && !delay_change_reports) - report_to_all_neighbors(CHANGED_ROUTES); -} - - -/* - * Send a route report message to destination 'dst', via virtual interface - * 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. - */ -void -report(int which_routes, vifi_t vifi, u_int32_t dst) -{ - struct rtentry *r; - char *p; - int i; - int datalen = 0; - int width = 0; - u_int32_t mask = 0; - u_int32_t src; - u_int32_t nflags; - - src = uvifs[vifi].uv_lcl_addr; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - -#ifdef NOTYET - /* If I'm not a leaf, but the neighbor is a leaf, only advertise default */ - if ((vifs_with_neighbors != 1) && (uvifs[vifi].uv_flags & VIFF_LEAF)) { - *p++ = 0; /* 0xff000000 mask */ - *p++ = 0; - *p++ = 0; - *p++ = 0; /* class A net 0.0.0.0 == default */ - *p++ = 0x81; /*XXX metric 1, is this safe? */ - datalen += 5; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL), datalen); - return; - } -#endif - - nflags = (uvifs[vifi].uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS; - - for (r = rt_end; r != RT_ADDR; r = r->rt_prev) { - - if (which_routes == CHANGED_ROUTES && !(r->rt_flags & RTF_CHANGED)) - continue; - - /* - * If there is no room for this route in the current message, - * send the message and start a new one. - */ - if (datalen + ((r->rt_originmask == mask) ? - (width + 1) : - (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - datalen = 0; - mask = 0; - } - - if (r->rt_originmask != mask || datalen == 0) { - mask = r->rt_originmask; - width = r->rt_originwidth; - if (datalen != 0) *(p-1) |= 0x80; - *p++ = ((char *)&mask)[1]; - *p++ = ((char *)&mask)[2]; - *p++ = ((char *)&mask)[3]; - datalen += 3; - } - - for (i = 0; i < width; ++i) - *p++ = ((char *)&(r->rt_origin))[i]; - - *p++ = (r->rt_parent == vifi && r->rt_metric != UNREACHABLE) ? - (char)(r->rt_metric + UNREACHABLE) : /* "poisoned reverse" */ - (char)(r->rt_metric); - - datalen += width + 1; - } - - if (datalen != 0) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - } -} - - -/* - * Send a route report message to all neighboring routers. - * 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. - */ -void -report_to_all_neighbors(int which_routes) -{ - vifi_t vifi; - struct uvif *v; - struct rtentry *r; - int routes_changed_before; - - /* - * Remember the state of the global routes_changed flag before - * generating the reports, and clear the flag. - */ - routes_changed_before = routes_changed; - routes_changed = FALSE; - - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (v->uv_neighbors != NULL) { - report(which_routes, vifi, - (v->uv_flags & VIFF_TUNNEL) ? v->uv_rmt_addr - : dvmrp_group); - } - } - - /* - * If there were changed routes before we sent the reports AND - * if no new changes occurred while sending the reports, clear - * the change flags in the individual route entries. If changes - * did occur while sending the reports, new reports will be - * generated at the next timer interrupt. - */ - if (routes_changed_before && !routes_changed) { - for (r = routing_table; r != NULL; r = r->rt_next) { - r->rt_flags &= ~RTF_CHANGED; - } - } - - /* - * Set a flag to inhibit further reports of changed routes until the - * next timer interrupt. This is to alleviate update storms. - */ - delay_change_reports = TRUE; -} - -/* - * Send a route report message to destination 'dst', via virtual interface - * 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. - */ -static int -report_chunk(struct rtentry *start_rt, vifi_t vifi, u_int32_t dst) -{ - struct rtentry *r; - char *p; - int i; - int nrt = 0; - int datalen = 0; - int width = 0; - u_int32_t mask = 0; - u_int32_t src; - u_int32_t nflags; - - src = uvifs[vifi].uv_lcl_addr; - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - - nflags = (uvifs[vifi].uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS; - - for (r = start_rt; r != RT_ADDR; r = r->rt_prev) { - -#ifdef NOTYET - /* Don't send poisoned routes back to parents if I am a leaf */ - if ((vifs_with_neighbors == 1) && (r->rt_parent == vifi) - && (r->rt_metric > 1)) { - ++nrt; - continue; - } -#endif - - /* - * If there is no room for this route in the current message, - * send it & return how many routes we sent. - */ - if (datalen + ((r->rt_originmask == mask) ? - (width + 1) : - (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - return (nrt); - } - if (r->rt_originmask != mask || datalen == 0) { - mask = r->rt_originmask; - width = r->rt_originwidth; - if (datalen != 0) *(p-1) |= 0x80; - *p++ = ((char *)&mask)[1]; - *p++ = ((char *)&mask)[2]; - *p++ = ((char *)&mask)[3]; - datalen += 3; - } - for (i = 0; i < width; ++i) - *p++ = ((char *)&(r->rt_origin))[i]; - - *p++ = (r->rt_parent == vifi && r->rt_metric != UNREACHABLE) ? - (char)(r->rt_metric + UNREACHABLE) : /* "poisoned reverse" */ - (char)(r->rt_metric); - ++nrt; - datalen += width + 1; - } - if (datalen != 0) { - *(p-1) |= 0x80; - send_igmp(src, dst, IGMP_DVMRP, DVMRP_REPORT, - htonl(MROUTED_LEVEL | nflags), datalen); - } - return (nrt); -} - -/* - * send the next chunk of our routing table to all neighbors. - * return the length of the smallest chunk we sent out. - */ -int -report_next_chunk(void) -{ - vifi_t vifi; - struct uvif *v; - struct rtentry *sr; - int i, n = 0, min = 20000; - static int start_rt; - - if (nroutes <= 0) - return (0); - - /* - * find this round's starting route. - */ - for (sr = rt_end, i = start_rt; --i >= 0; ) { - sr = sr->rt_prev; - if (sr == RT_ADDR) - sr = rt_end; - } - - /* - * send one chunk of routes starting at this round's start to - * all our neighbors. - */ - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if ((v->uv_neighbors != NULL) -#ifdef NOTYET - && !(v->uv_flags & VIFF_LEAF) -#endif - ) { - n = report_chunk(sr, vifi, - (v->uv_flags & VIFF_TUNNEL) ? v->uv_rmt_addr - : dvmrp_group); - if (n < min) - min = n; - } - } - if (min == 20000) - min = 0; /* Neighborless router didn't send any routes */ - - n = min; - logit(LOG_INFO, 0, "update %d starting at %d of %d", - n, (nroutes - start_rt), nroutes); - - start_rt = (start_rt + n) % nroutes; - return (n); -} - - -/* - * Print the contents of the routing table on file 'fp'. - */ -void -dump_routes(FILE *fp) -{ - struct rtentry *r; - vifi_t i; - - - fprintf(fp, - "Multicast Routing Table (%u %s)\n%s\n", - nroutes, (nroutes == 1) ? "entry" : "entries", - " Origin-Subnet From-Gateway Metric Tmr In-Vif Out-Vifs"); - - for (r = routing_table; r != NULL; r = r->rt_next) { - - fprintf(fp, " %-18s %-15s ", - inet_fmts(r->rt_origin, r->rt_originmask, s1), - (r->rt_gateway == 0) ? "" : inet_fmt(r->rt_gateway, s2)); - - fprintf(fp, (r->rt_metric == UNREACHABLE) ? " NR " : "%4u ", - r->rt_metric); - - fprintf(fp, " %3u %3u ", r->rt_timer, r->rt_parent); - - for (i = 0; i < numvifs; ++i) { - if (VIFM_ISSET(i, r->rt_children)) { - fprintf(fp, " %u%c", - i, VIFM_ISSET(i, r->rt_leaves) ? '*' : ' '); - } - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); -} - -struct rtentry * -determine_route(u_int32_t src) -{ - struct rtentry *rt; - - for (rt = routing_table; rt != NULL; rt = rt->rt_next) { - if (rt->rt_origin == (src & rt->rt_originmask)) - break; - } - return rt; -} diff --git a/gnu/dist/mrouted/route.h b/gnu/dist/mrouted/route.h deleted file mode 100644 index a81ba2944c1..00000000000 --- a/gnu/dist/mrouted/route.h +++ /dev/null @@ -1,50 +0,0 @@ -/* $NetBSD: route.h,v 1.1 2002/10/01 03:31:10 itojun Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -/* - * Routing Table Entry, one per subnet from which a multicast could originate. - * (Note: all addresses, subnet numbers and masks are kept in NETWORK order.) - * - * The Routing Table is stored as a doubly-linked list of these structures, - * ordered by decreasing value of rt_originmask and, secondarily, by - * decreasing value of rt_origin within each rt_originmask value. - * This data structure is efficient for generating route reports, whether - * full or partial, for processing received full reports, for clearing the - * CHANGED flags, and for periodically advancing the timers in all routes. - * It is not so efficient for updating a small number of routes in response - * to a partial report. In a stable topology, the latter are rare; if they - * turn out to be costing a lot, we can add an auxiliary hash table for - * faster access to arbitrary route entries. - */ -struct rtentry { - struct rtentry *rt_next; /* link to next entry MUST BE FIRST */ - u_int32_t rt_origin; /* subnet origin of multicasts */ - u_int32_t rt_originmask; /* subnet mask for origin */ - short rt_originwidth; /* # bytes of origin subnet number */ - u_char rt_metric; /* cost of route back to origin */ - u_char rt_flags; /* RTF_ flags defined below */ - u_int32_t rt_gateway; /* first-hop gateway back to origin */ - vifi_t rt_parent; /* incoming vif (ie towards origin) */ - vifbitmap_t rt_children; /* outgoing children vifs */ - vifbitmap_t rt_leaves; /* subset of outgoing children vifs */ - u_int32_t *rt_dominants; /* per vif dominant gateways */ - u_int32_t *rt_subordinates; /* per vif subordinate gateways */ - u_int *rt_leaf_timers; /* per vif leaf confirmation timers */ - u_int rt_timer; /* for timing out the route entry */ - struct rtentry *rt_prev; /* link to previous entry */ - struct gtable *rt_groups; /* link to active groups */ -}; - -#define RTF_CHANGED 0x01 /* route changed but not reported */ -#define RTF_LEAF_TIMING 0x02 /* some leaf timers are running */ - -#define ALL_ROUTES 0 /* possible arguments to report() */ -#define CHANGED_ROUTES 1 /* and report_to_all_neighbors() */ diff --git a/gnu/dist/mrouted/rsrr.c b/gnu/dist/mrouted/rsrr.c deleted file mode 100644 index 07d084f2eaf..00000000000 --- a/gnu/dist/mrouted/rsrr.c +++ /dev/null @@ -1,504 +0,0 @@ -/* $NetBSD: rsrr.c,v 1.3 2002/12/06 16:02:57 thorpej Exp $ */ - -/* - * Copyright (c) 1993, 1998-2001. - * The University of Southern California/Information Sciences Institute. - * 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. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - */ - -/* RSRR code written by Daniel Zappala, USC Information Sciences Institute, - * April 1995. - */ - -/* May 1995 -- Added support for Route Change Notification */ - -#ifdef RSRR - -#include "defs.h" -#include <sys/param.h> -#if (defined(BSD) && (BSD >= 199103)) -#include <stddef.h> -#endif - -/* Taken from prune.c */ -/* - * checks for scoped multicast addresses - */ -#define GET_SCOPE(gt) { \ - int _i; \ - if (((gt)->gt_mcastgrp & 0xff000000) == 0xef000000) \ - for (_i = 0; _i < numvifs; _i++) \ - if (scoped_addr(_i, (gt)->gt_mcastgrp)) \ - VIFM_SET(_i, (gt)->gt_scope); \ - } - -/* - * Exported variables. - */ -int rsrr_socket; /* interface to reservation protocol */ - -/* - * Global RSRR variables. - */ -char rsrr_recv_buf[RSRR_MAX_LEN]; /* RSRR receive buffer */ -char rsrr_send_buf[RSRR_MAX_LEN]; /* RSRR send buffer */ - -struct sockaddr_un client_addr; -int client_length = sizeof(client_addr); - - -/* - * Procedure definitions needed internally. - */ -static void rsrr_accept(int recvlen); -static void rsrr_accept_iq(void); -static int rsrr_accept_rq(struct rsrr_rq *route_query, int flags, - struct gtable *gt_notify); -static int rsrr_send(int sendlen); -static void rsrr_cache(struct gtable *gt, struct rsrr_rq *route_query); - -/* Initialize RSRR socket */ -void -rsrr_init() -{ - int servlen; - struct sockaddr_un serv_addr; - - if ((rsrr_socket = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) - logit(LOG_ERR, errno, "Can't create RSRR socket"); - - unlink(RSRR_SERV_PATH); - bzero((char *) &serv_addr, sizeof(serv_addr)); - serv_addr.sun_family = AF_LOCAL; - strcpy(serv_addr.sun_path, RSRR_SERV_PATH); -#if (defined(BSD) && (BSD >= 199103)) - servlen = offsetof(struct sockaddr_un, sun_path) + - strlen(serv_addr.sun_path); - serv_addr.sun_len = servlen; -#else - servlen = sizeof(serv_addr.sun_family) + strlen(serv_addr.sun_path); -#endif - - if (bind(rsrr_socket, (struct sockaddr *) &serv_addr, servlen) < 0) - logit(LOG_ERR, errno, "Can't bind RSRR socket"); - - if (register_input_handler(rsrr_socket,rsrr_read) < 0) - logit(LOG_WARNING, 0, "Couldn't register RSRR as an input handler"); -} - -/* Read a message from the RSRR socket */ -void -rsrr_read(f, rfd) - int f; - fd_set *rfd; -{ - int rsrr_recvlen; - int omask; - - bzero((char *) &client_addr, sizeof(client_addr)); - rsrr_recvlen = recvfrom(rsrr_socket, rsrr_recv_buf, sizeof(rsrr_recv_buf), - 0, (struct sockaddr *)&client_addr, &client_length); - if (rsrr_recvlen < 0) { - if (errno != EINTR) - logit(LOG_ERR, errno, "RSRR recvfrom"); - return; - } - /* Use of omask taken from main() */ - omask = sigblock(sigmask(SIGALRM)); - rsrr_accept(rsrr_recvlen); - (void)sigsetmask(omask); -} - -/* Accept a message from the reservation protocol and take - * appropriate action. - */ -static void -rsrr_accept(recvlen) - int recvlen; -{ - struct rsrr_header *rsrr; - struct rsrr_rq *route_query; - - if (recvlen < RSRR_HEADER_LEN) { - logit(LOG_WARNING, 0, - "Received RSRR packet of %d bytes, which is less than min size", - recvlen); - return; - } - - rsrr = (struct rsrr_header *) rsrr_recv_buf; - - if (rsrr->version > RSRR_MAX_VERSION) { - logit(LOG_WARNING, 0, - "Received RSRR packet version %d, which I don't understand", - rsrr->version); - return; - } - - switch (rsrr->version) { - case 1: - switch (rsrr->type) { - case RSRR_INITIAL_QUERY: - /* Send Initial Reply to client */ - logit(LOG_INFO, 0, "Received Initial Query\n"); - rsrr_accept_iq(); - break; - case RSRR_ROUTE_QUERY: - /* Check size */ - if (recvlen < RSRR_RQ_LEN) { - logit(LOG_WARNING, 0, - "Received Route Query of %d bytes, which is too small", - recvlen); - break; - } - /* Get the query */ - route_query = (struct rsrr_rq *) (rsrr_recv_buf + RSRR_HEADER_LEN); - logit(LOG_INFO, 0, - "Received Route Query for src %s grp %s notification %d", - inet_fmt(route_query->source_addr.s_addr, s1), - inet_fmt(route_query->dest_addr.s_addr,s2), - BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)); - /* Send Route Reply to client */ - rsrr_accept_rq(route_query,rsrr->flags,NULL); - break; - default: - logit(LOG_WARNING, 0, - "Received RSRR packet type %d, which I don't handle", - rsrr->type); - break; - } - break; - - default: - logit(LOG_WARNING, 0, - "Received RSRR packet version %d, which I don't understand", - rsrr->version); - break; - } -} - -/* Send an Initial Reply to the reservation protocol. */ -static void -rsrr_accept_iq() -{ - struct rsrr_header *rsrr; - struct rsrr_vif *vif_list; - struct uvif *v; - int vifi, sendlen; - - /* Check for space. There should be room for plenty of vifs, - * but we should check anyway. - */ - if (numvifs > RSRR_MAX_VIFS) { - logit(LOG_WARNING, 0, - "Can't send RSRR Route Reply because %d is too many vifs %d", - numvifs); - return; - } - - /* Set up message */ - rsrr = (struct rsrr_header *) rsrr_send_buf; - rsrr->version = 1; - rsrr->type = RSRR_INITIAL_REPLY; - rsrr->flags = 0; - rsrr->num = numvifs; - - vif_list = (struct rsrr_vif *) (rsrr_send_buf + RSRR_HEADER_LEN); - - /* Include the vif list. */ - for (vifi=0, v = uvifs; vifi < numvifs; vifi++, v++) { - vif_list[vifi].id = vifi; - vif_list[vifi].status = 0; - if (v->uv_flags & VIFF_DISABLED) - BIT_SET(vif_list[vifi].status,RSRR_DISABLED_BIT); - vif_list[vifi].threshold = v->uv_threshold; - vif_list[vifi].local_addr.s_addr = v->uv_lcl_addr; - } - - /* Get the size. */ - sendlen = RSRR_HEADER_LEN + numvifs*RSRR_VIF_LEN; - - /* Send it. */ - logit(LOG_INFO, 0, "Send RSRR Initial Reply"); - rsrr_send(sendlen); -} - -/* Send a Route Reply to the reservation protocol. The Route Query - * contains the query to which we are responding. The flags contain - * the incoming flags from the query or, for route change - * notification, the flags that should be set for the reply. The - * kernel table entry contains the routing info to use for a route - * change notification. - */ -static int -rsrr_accept_rq(route_query,flags,gt_notify) - struct rsrr_rq *route_query; - int flags; - struct gtable *gt_notify; -{ - struct rsrr_header *rsrr; - struct rsrr_rr *route_reply; - struct gtable *gt,local_g; - struct rtentry *r; - int sendlen,i; - u_long mcastgrp; - - /* Set up message */ - rsrr = (struct rsrr_header *) rsrr_send_buf; - rsrr->version = 1; - rsrr->type = RSRR_ROUTE_REPLY; - rsrr->flags = 0; - rsrr->num = 0; - - route_reply = (struct rsrr_rr *) (rsrr_send_buf + RSRR_HEADER_LEN); - route_reply->dest_addr.s_addr = route_query->dest_addr.s_addr; - route_reply->source_addr.s_addr = route_query->source_addr.s_addr; - route_reply->query_id = route_query->query_id; - - /* Blank routing entry for error. */ - route_reply->in_vif = 0; - route_reply->reserved = 0; - route_reply->out_vif_bm = 0; - - /* Get the size. */ - sendlen = RSRR_RR_LEN; - - /* If kernel table entry is defined, then we are sending a Route Reply - * due to a Route Change Notification event. Use the kernel table entry - * to supply the routing info. - */ - if (gt_notify) { - /* Set flags */ - rsrr->flags = flags; - /* Include the routing entry. */ - route_reply->in_vif = gt_notify->gt_route->rt_parent; - route_reply->out_vif_bm = gt_notify->gt_grpmems; - - } else if (find_src_grp(route_query->source_addr.s_addr, 0, - route_query->dest_addr.s_addr)) { - - /* Found kernel entry. Code taken from add_table_entry() */ - gt = gtp ? gtp->gt_gnext : kernel_table; - - /* Include the routing entry. */ - route_reply->in_vif = gt->gt_route->rt_parent; - route_reply->out_vif_bm = gt->gt_grpmems; - - /* Cache reply if using route change notification. */ - if BIT_TST(flags,RSRR_NOTIFICATION_BIT) { - rsrr_cache(gt,route_query); - BIT_SET(rsrr->flags,RSRR_NOTIFICATION_BIT); - } - - } else { - /* No kernel entry; use routing table. */ - r = determine_route(route_query->source_addr.s_addr); - - if (r != NULL) { - /* We need to mimic what will happen if a data packet - * is forwarded by multicast routing -- the kernel will - * make an upcall and mrouted will install a route in the kernel. - * Our outgoing vif bitmap should reflect what that table - * will look like. Grab code from add_table_entry(). - * This is gross, but it's probably better to be accurate. - */ - - gt = &local_g; - mcastgrp = route_query->dest_addr.s_addr; - - gt->gt_mcastgrp = mcastgrp; - gt->gt_grpmems = 0; - gt->gt_scope = 0; - gt->gt_route = r; - - /* obtain the multicast group membership list */ - for (i = 0; i < numvifs; i++) { - if (VIFM_ISSET(i, r->rt_children) && - !(VIFM_ISSET(i, r->rt_leaves))) - VIFM_SET(i, gt->gt_grpmems); - - if (VIFM_ISSET(i, r->rt_leaves) && grplst_mem(i, mcastgrp)) - VIFM_SET(i, gt->gt_grpmems); - } - - GET_SCOPE(gt); - gt->gt_grpmems &= ~gt->gt_scope; - - /* Include the routing entry. */ - route_reply->in_vif = gt->gt_route->rt_parent; - route_reply->out_vif_bm = gt->gt_grpmems; - - } else { - /* Set error bit. */ - BIT_SET(rsrr->flags,RSRR_ERROR_BIT); - } - } - - if (gt_notify) - logit(LOG_INFO, 0, "Route Change: Send RSRR Route Reply"); - - else - logit(LOG_INFO, 0, "Send RSRR Route Reply"); - - logit(LOG_INFO, 0, "for src %s dst %s in vif %d out vif %d\n", - inet_fmt(route_reply->source_addr.s_addr,s1), - inet_fmt(route_reply->dest_addr.s_addr,s2), - route_reply->in_vif,route_reply->out_vif_bm); - - /* Send it. */ - return rsrr_send(sendlen); -} - -/* Send an RSRR message. */ -static int -rsrr_send(sendlen) - int sendlen; -{ - int error; - - /* Send it. */ - error = sendto(rsrr_socket, rsrr_send_buf, sendlen, 0, - (struct sockaddr *)&client_addr, client_length); - - /* Check for errors. */ - if (error < 0) { - logit(LOG_WARNING, errno, "Failed send on RSRR socket"); - } else if (error != sendlen) { - logit(LOG_WARNING, 0, - "Sent only %d out of %d bytes on RSRR socket\n", error, sendlen); - } - return error; -} - -/* Cache a message being sent to a client. Currently only used for - * caching Route Reply messages for route change notification. - */ -static void -rsrr_cache(gt,route_query) - struct gtable *gt; - struct rsrr_rq *route_query; -{ - struct rsrr_cache *rc, **rcnp; - struct rsrr_header *rsrr; - - rsrr = (struct rsrr_header *) rsrr_send_buf; - - rcnp = >->gt_rsrr_cache; - while ((rc = *rcnp) != NULL) { - if ((rc->route_query.source_addr.s_addr == - route_query->source_addr.s_addr) && - (rc->route_query.dest_addr.s_addr == - route_query->dest_addr.s_addr) && - (!strcmp(rc->client_addr.sun_path,client_addr.sun_path))) { - /* Cache entry already exists. - * Check if route notification bit has been cleared. - */ - if (!BIT_TST(rsrr->flags,RSRR_NOTIFICATION_BIT)) { - /* Delete cache entry. */ - *rcnp = rc->next; - free(rc); - } else { - /* Update */ - rc->route_query.query_id = route_query->query_id; - logit(LOG_DEBUG, 0, - "Update cached query id %ld from client %s\n", - rc->route_query.query_id, rc->client_addr.sun_path); - } - return; - } - rcnp = &rc->next; - } - - /* Cache entry doesn't already exist. Create one and insert at - * front of list. - */ - rc = (struct rsrr_cache *) malloc(sizeof(struct rsrr_cache)); - if (rc == NULL) - logit(LOG_ERR, 0, "ran out of memory"); - rc->route_query.source_addr.s_addr = route_query->source_addr.s_addr; - rc->route_query.dest_addr.s_addr = route_query->dest_addr.s_addr; - rc->route_query.query_id = route_query->query_id; - strcpy(rc->client_addr.sun_path, client_addr.sun_path); - rc->client_length = client_length; - rc->next = gt->gt_rsrr_cache; - gt->gt_rsrr_cache = rc; - logit(LOG_DEBUG, 0, "Cached query id %ld from client %s\n", - rc->route_query.query_id,rc->client_addr.sun_path); -} - -/* Send all the messages in the cache. Currently this is used to send - * all the cached Route Reply messages for route change notification. - */ -void -rsrr_cache_send(gt,notify) - struct gtable *gt; - int notify; -{ - struct rsrr_cache *rc, **rcnp; - int flags = 0; - - if (notify) - BIT_SET(flags,RSRR_NOTIFICATION_BIT); - - rcnp = >->gt_rsrr_cache; - while ((rc = *rcnp) != NULL) { - if (rsrr_accept_rq(&rc->route_query,flags,gt) < 0) { - logit(LOG_DEBUG, 0, "Deleting cached query id %ld from client %s\n", - rc->route_query.query_id,rc->client_addr.sun_path); - /* Delete cache entry. */ - *rcnp = rc->next; - free(rc); - } else { - rcnp = &rc->next; - } - } -} - -/* Clean the cache by deleting all entries. */ -void -rsrr_cache_clean(gt) - struct gtable *gt; -{ - struct rsrr_cache *rc,*rc_next; - - printf("cleaning cache for group %s\n",inet_fmt(gt->gt_mcastgrp, s1)); - rc = gt->gt_rsrr_cache; - while (rc) { - rc_next = rc->next; - free(rc); - rc = rc_next; - } - gt->gt_rsrr_cache = NULL; -} - -void -rsrr_clean() -{ - unlink(RSRR_SERV_PATH); -} - -#endif /* RSRR */ diff --git a/gnu/dist/mrouted/rsrr.h b/gnu/dist/mrouted/rsrr.h deleted file mode 100644 index 6de824c1200..00000000000 --- a/gnu/dist/mrouted/rsrr.h +++ /dev/null @@ -1,144 +0,0 @@ -/* $NetBSD: rsrr.h,v 1.2 2002/10/01 03:41:13 itojun Exp $ */ - -/* - * Copyright (c) 1993, 1998-2001. - * The University of Southern California/Information Sciences Institute. - * 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. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - */ - -#define RSRR_SERV_PATH "/tmp/.rsrr_svr" -/* Note this needs to be 14 chars for 4.3 BSD compatibility */ -#define RSRR_CLI_PATH "/tmp/.rsrr_cli" - -#define RSRR_MAX_LEN 2048 -#define RSRR_HEADER_LEN (sizeof(struct rsrr_header)) -#define RSRR_RQ_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rq)) -#define RSRR_RR_LEN (RSRR_HEADER_LEN + sizeof(struct rsrr_rr)) -#define RSRR_VIF_LEN (sizeof(struct rsrr_vif)) - -/* Current maximum number of vifs. */ -#define RSRR_MAX_VIFS 32 - -/* Maximum acceptable version */ -#define RSRR_MAX_VERSION 1 - -/* RSRR message types */ -#define RSRR_ALL_TYPES 0 -#define RSRR_INITIAL_QUERY 1 -#define RSRR_INITIAL_REPLY 2 -#define RSRR_ROUTE_QUERY 3 -#define RSRR_ROUTE_REPLY 4 - -/* RSRR Initial Reply (Vif) Status bits - * Each definition represents the position of the bit from right to left. - * - * Right-most bit is the disabled bit, set if the vif is administratively - * disabled. - */ -#define RSRR_DISABLED_BIT 0 -/* All other bits are zeroes */ - -/* RSRR Route Query/Reply flag bits - * Each definition represents the position of the bit from right to left. - * - * Right-most bit is the Route Change Notification bit, set if the - * reservation protocol wishes to receive notification of - * a route change for the source-destination pair listed in the query. - * Notification is in the form of an unsolicitied Route Reply. - */ -#define RSRR_NOTIFICATION_BIT 0 -/* Next bit indicates an error returning the Route Reply. */ -#define RSRR_ERROR_BIT 1 -/* All other bits are zeroes */ - -/* Definition of an RSRR message header. - * An Initial Query uses only the header, and an Initial Reply uses - * the header and a list of vifs. - */ -struct rsrr_header { - u_char version; /* RSRR Version, currently 1 */ - u_char type; /* type of message, as defined above */ - u_char flags; /* flags; defined by type */ - u_char num; /* number; defined by type */ -}; - -/* Definition of a vif as seen by the reservation protocol. - * - * Routing gives the reservation protocol a list of vifs in the - * Initial Reply. - * - * We explicitly list the ID because we can't assume that all routing - * protocols will use the same numbering scheme. - * - * The status is a bitmask of status flags, as defined above. It is the - * responsibility of the reservation protocol to perform any status checks - * if it uses the MULTICAST_VIF socket option. - * - * The threshold indicates the ttl an outgoing packet needs in order to - * be forwarded. The reservation protocol must perform this check itself if - * it uses the MULTICAST_VIF socket option. - * - * The local address is the address of the physical interface over which - * packets are sent. - */ -struct rsrr_vif { - u_char id; /* vif id */ - u_char threshold; /* vif threshold ttl */ - u_short status; /* vif status bitmask */ - struct in_addr local_addr; /* vif local address */ -}; - -/* Definition of an RSRR Route Query. - * - * The query asks routing for the forwarding entry for a particular - * source and destination. The query ID uniquely identifies the query - * for the reservation protocol. Thus, the combination of the client's - * address and the query ID forms a unique identifier for routing. - * Flags are defined above. - */ -struct rsrr_rq { - struct in_addr dest_addr; /* destination */ - struct in_addr source_addr; /* source */ - u_long query_id; /* query ID */ -}; - -/* Definition of an RSRR Route Reply. - * - * Routing uses the reply to give the reservation protocol the - * forwarding entry for a source-destination pair. Routing copies the - * query ID from the query and fills in the incoming vif and a bitmask - * of the outgoing vifs. - * Flags are defined above. - */ -struct rsrr_rr { - struct in_addr dest_addr; /* destination */ - struct in_addr source_addr; /* source */ - u_long query_id; /* query ID */ - u_short in_vif; /* incoming vif */ - u_short reserved; /* reserved */ - u_long out_vif_bm; /* outgoing vif bitmask */ -}; diff --git a/gnu/dist/mrouted/rsrr_var.h b/gnu/dist/mrouted/rsrr_var.h deleted file mode 100644 index 692e894a334..00000000000 --- a/gnu/dist/mrouted/rsrr_var.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $NetBSD: rsrr_var.h,v 1.2 2002/10/01 03:41:13 itojun Exp $ */ - -/* - * Copyright (c) 1998-2001. - * The University of Southern California/Information Sciences Institute. - * 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. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - */ - -/* RSRR things that are only needed by mrouted. */ - -/* Cache of Route Query messages, distinguished by source, - * destination, and client addresses. Cache is flushed by RSRR client - * -- it sends notification when an unwanted Route Reply is received. - * Since this only happens during route changes, it is more likely - * that the cache will be flushed when the kernel table entry is - * deleted. */ -struct rsrr_cache { - struct rsrr_rq route_query; /* Cached Route Query */ - struct sockaddr_un client_addr; /* Client address */ - int client_length; /* Length of client */ - struct rsrr_cache *next; /* next cache item */ -}; - diff --git a/gnu/dist/mrouted/snmp.c b/gnu/dist/mrouted/snmp.c deleted file mode 100644 index 2dba206548f..00000000000 --- a/gnu/dist/mrouted/snmp.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* $NetBSD: snmp.c,v 1.1 2002/10/01 03:31:11 itojun Exp $ */ - -#include "defs.h" -#include <netinet/in_var.h> -#include "snmp.h" -#include "snmplib/asn1.h" -#include "snmplib/party.h" -#include "snmplib/snmp_impl.h" -#define MROUTED -#include "snmpd/snmp_vars.h" - - in_port_t dest_port = 0; - int sdlen = 0; - -struct addrCache { - u_long addr; - int status; -#define UNUSED 0 -#define USED 1 -#define OLD 2 -}; - -static struct addrCache addrCache[10]; - -/* - * Initialize the SNMP part of mrouted - */ -int /* returns: 0 on success, true on error */ -snmp_init(dest_port) - in_port_t dest_port; -{ - u_long myaddr; - int ret; - struct partyEntry *pp; - struct sockaddr_in me; - int index, sd, portlist[32]; - - init_snmp(); - /* init_mib(); why was this here? */ - if (read_party_database("/etc/party.conf") > 0){ - fprintf(stderr, "Couldn't read party database from /etc/party.conf\n"); - exit(0); - } - if (read_context_database("/etc/context.conf") > 0){ - fprintf(stderr, "Couldn't read context database from /etc/context.conf\n"); - exit(0); - } - if (read_acl_database("/etc/acl.conf") > 0){ - fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n"); - exit(0); - } - if (read_view_database("/etc/view.conf") > 0){ - fprintf(stderr, "Couldn't read view database from /etc/view.conf\n"); - exit(0); - } - - myaddr = get_myaddr(); - if (ret = agent_party_init(myaddr, ".1.3.6.1")){ - if (ret == 1){ - fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n"); - } else if (ret == -1){ - fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n"); - exit(1); - } else { - fprintf(stderr, "Unknown error, exiting\n"); - exit(2); - } - } - - printf("Opening port(s): "); - fflush(stdout); - party_scanInit(); - for(pp = party_scanNext(); pp; pp = party_scanNext()){ - if ((pp->partyTDomain != DOMAINSNMPUDP) - || bcmp((char *)&myaddr, pp->partyTAddress, 4)) - continue; /* don't listen for non-local parties */ - - dest_port = 0; - bcopy(pp->partyTAddress + 4, &dest_port, 2); - for(index = 0; index < sdlen; index++) - if (dest_port == portlist[index]) - break; - if (index < sdlen) /* found a hit before the end of the list */ - continue; - printf("%u ", dest_port); - fflush(stdout); - /* Set up connections */ - sd = socket(AF_INET, SOCK_DGRAM, 0); - if (sd < 0){ - perror("socket"); - return 1; - } - memset(&me, 0, sizeof(me)); - me.sin_family = AF_INET; - me.sin_addr.s_addr = INADDR_ANY; - /* already in network byte order (I think) */ - me.sin_port = dest_port; - if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ - perror("bind"); - return 2; - } - register_input_handler(sd, snmp_read_packet); - portlist[sdlen] = dest_port; - if (++sdlen == 32){ - printf("No more sockets... ignoring rest of file\n"); - break; - } - } - printf("\n"); - bzero((char *)addrCache, sizeof(addrCache)); -} - -/* - * Place an IP address into an OID starting at element n - */ -void -put_address(name, addr, n) - oid *name; - u_long addr; - int n; -{ - int i; - - for (i=n+3; i>=n+0; i--) { - name[i] = addr & 0xFF; - addr >>= 8; - } -} - -/* Get an IP address from an OID starting at element n */ -int -get_address(name, length, addr, n) - oid *name; - int length; - u_long *addr; - int n; -{ - int i; - int ok = 1; - - (*addr) = 0; - - if (length < n+4) - return 0; - - for (i=n; i<n+4; i++) { - (*addr) <<= 8; - if (i >= length) - ok = 0; - else - (*addr) |= name[i]; - } - return ok; -} - -/* - * Implements scalar objects from DVMRP and Multicast MIBs - */ -u_char * -o_scalar(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - int result; - - *write_method = 0; - result = compare(name, *length, vp->name, (int)vp->namelen); - if ((exact && (result != 0)) || (!exact && (result >= 0))) - return NULL; - - bcopy((char *)vp->name, (char *)name, - (int)vp->namelen * sizeof(oid)); - *length = vp->namelen; - *var_len = sizeof(long); - - switch (vp->magic) { - - case ipMRouteEnable: - long_return = 1; - return (u_char *) &long_return; - - case dvmrpVersion: { - static char buff[15]; - - sprintf(buff, "mrouted%d.%d", PROTOCOL_VERSION, MROUTED_VERSION); - *var_len = strlen(buff); - return (u_char *)buff; - } - - case dvmrpGenerationId: - long_return = dvmrp_genid; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Find if a specific scoped boundary exists on a Vif - */ -struct vif_acl * -find_boundary(vifi, addr, mask) - vifi_t vifi; - u_long addr; - u_long mask; -{ - struct vif_acl *n; - - for (n = uvifs[vifi].uv_acl; n != NULL; n = n->acl_next) { - if (addr == n->acl_addr && mask==n->acl_mask) - return n; - } - return NULL; -} - -/* - * Find the lowest boundary >= (V,A,M) spec - */ -struct vif_acl * -next_boundary(vifi, addr, mask) - vifi_t *vifi; - u_long addr; - u_long mask; -{ - struct vif_acl *bestn, *n; - int i; - - for (i = *vifi; i < numvifs; i++) { - bestn = NULL; - for (n = uvifs[i].uv_acl; n; n=n->acl_next) { - if ((i > *vifi || n->acl_addr > addr - || (n->acl_addr == addr && n->acl_mask >= mask)) - && (!bestn || n->acl_addr < bestn->acl_addr - || (n->acl_addr==bestn->acl_addr && n->acl_mask<bestn->acl_mask))) - bestn = n; - } - if (bestn) { - *vifi = i; - return bestn; - } - } - return NULL; -} - -/* - * Implements the Boundary Table portion of the DVMRP MIB - */ -u_char * -o_dvmrpBoundaryTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - vifi_t vifi; - u_long addr, mask; - struct vif_acl *bound; - oid newname[MAX_NAME_LEN]; - int len; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 9) - return NULL; - - if ((vifi = name[vp->namelen]) >= numvifs) - return NULL; - - if (!get_address(name, *length, &addr, vp->namelen+1) - || !get_address(name, *length, &mask, vp->namelen+5)) - return NULL; - - if (!(bound = find_boundary(vifi, addr, mask))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 9) { /* get first entry */ - - if (len == vp->namelen) { - vifi = addr = mask = 0; - } else { - vifi = name[vp->namelen]; - get_address(name, len, &addr, vp->namelen+1); - get_address(name, len, &mask, vp->namelen+5); - } - - bound = next_boundary(&vifi,addr,mask); - if (!bound) - return NULL; - - newname[vp->namelen] = vifi; - put_address(newname, bound->acl_addr, vp->namelen+1); - put_address(newname, bound->acl_mask, vp->namelen+5); - } else { /* get next entry given previous */ - vifi = name[vp->namelen]; - get_address(name, *length, &addr, vp->namelen+1); - get_address(name, *length, &mask, vp->namelen+5); - - if (!(bound = next_boundary(&vifi,addr,mask+1))) - return NULL; - - newname[vp->namelen] = vifi; - put_address(newname, bound->acl_addr, vp->namelen+1); - put_address(newname, bound->acl_mask, vp->namelen+5); - } - } - - /* Save new OID */ - *length = vp->namelen + 9; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic) { - - case dvmrpBoundaryVifIndex: - long_return = vifi; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Find the lowest neighbor >= (V,A) spec - */ -struct listaddr * -next_neighbor(vifi, addr) - vifi_t *vifi; - u_long addr; -{ - struct listaddr *bestn, *n; - int i; - - for (i = *vifi; i < numvifs; i++) { - bestn = NULL; - for (n = uvifs[i].uv_neighbors; n; n=n->al_next) { - if ((i > *vifi || n->al_addr >= addr) - && (!bestn || n->al_addr < bestn->al_addr)) - bestn = n; - } - if (bestn) { - *vifi = i; - return bestn; - } - } - return NULL; -} - -/* - * Find a neighbor, if it exists off a given Vif - */ -struct listaddr * -find_neighbor(vifi, addr) - vifi_t vifi; - u_long addr; -{ - struct listaddr *n; - - for (n = uvifs[vifi].uv_neighbors; n != NULL; n = n->al_next) { - if (addr == n->al_addr) - return n; - } - return NULL; -} - -u_char * -o_dvmrpNeighborTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - vifi_t vifi; - u_long addr, mask; - struct listaddr *neighbor; - oid newname[MAX_NAME_LEN]; - int len; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 5) - return NULL; - - if ((vifi = name[vp->namelen]) >= numvifs) - return NULL; - - if (!get_address(name, *length, &addr, vp->namelen+1)) - return NULL; - - if (!(neighbor = find_neighbor(vifi, addr))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 5) { /* get first entry */ - - if (len == vp->namelen) { - vifi = addr = 0; - } else { - vifi = name[vp->namelen]; - get_address(name, len, &addr, vp->namelen+1); - } - - neighbor = next_neighbor(&vifi,addr); - if (!neighbor) - return NULL; - - newname[vp->namelen] = vifi; - put_address(newname, neighbor->al_addr, vp->namelen+1); - } else { /* get next entry given previous */ - vifi = name[vp->namelen]; - get_address(name, *length, &addr, vp->namelen+1); - - if (!(neighbor = next_neighbor(&vifi,addr+1))) - return NULL; - - newname[vp->namelen] = vifi; - put_address(newname, neighbor->al_addr, vp->namelen+1); - } - } - - /* Save new OID */ - *length = vp->namelen + 5; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic) { - - case dvmrpNeighborUpTime: { - time_t currtime; - time(&currtime); - long_return = (currtime - neighbor->al_ctime)*100; - return (u_char *) &long_return; - } - - case dvmrpNeighborExpiryTime: - long_return = (NEIGHBOR_EXPIRE_TIME - neighbor->al_timer - + secs_remaining_offset()) * 100; - return (u_char *) &long_return; - - case dvmrpNeighborVersion: { - static char buff[15]; - - sprintf(buff, "%d.%d", neighbor->al_pv, neighbor->al_mv); - *var_len = strlen(buff); - return (u_char *)buff; - } - - case dvmrpNeighborGenerationId: - long_return = neighbor->al_genid; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* Look up ifIndex given uvifs[ifnum].uv_lcl_addr */ -struct in_ifaddr * /* returns: in_ifaddr structure, or null on error */ -ipaddr_to_ifindex(ipaddr, ifIndex) - u_long ipaddr; - int *ifIndex; -{ - int interface; -static struct in_ifaddr in_ifaddr; - - Interface_Scan_Init(); - for (;;) { - if (Interface_Scan_Next(&interface, (char *)0, NULL, &in_ifaddr) == 0) - return NULL; - - if (((struct sockaddr_in *) &(in_ifaddr.ia_addr))->sin_addr.s_addr - == ipaddr) { - *ifIndex = interface; - return &in_ifaddr; - } - } -} - -/* - * Find if a specific scoped boundary exists on a Vif - */ -struct listaddr * -find_cache(grp, vifi) - u_long grp; - vifi_t vifi; -{ - struct listaddr *n; - - for (n = uvifs[vifi].uv_groups; n != NULL; n = n->al_next) { - if (grp == n->al_addr) - return n; - } - return NULL; -} - -/* - * Find the next group cache entry >= (A,V) spec - */ -struct listaddr * -next_cache(addr, vifi) - u_long addr; - vifi_t *vifi; -{ - struct listaddr *bestn=NULL, *n; - int i, besti; - - /* Step through all entries looking for the next one */ - for (i = 0; i < numvifs; i++) { - for (n = uvifs[i].uv_groups; n; n=n->al_next) { - if ((n->al_addr > addr || (n->al_addr == addr && i >= *vifi)) - && (!bestn || n->al_addr < bestn->al_addr - || (n->al_addr == bestn->al_addr && i < besti))) { - bestn = n; - besti = i; - } - } - } - - if (bestn) { - *vifi = besti; - return bestn; - } - return NULL; -} - -/* - * Implements the IGMP Cache Table portion of the IGMP MIB - */ -u_char * -o_igmpCacheTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - vifi_t vifi; - u_long grp; - int ifIndex; - struct listaddr *cache; - oid newname[MAX_NAME_LEN]; - int len; - struct in_ifaddr *in_ifaddr; - struct in_multi in_multi, *inm; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 5) - return NULL; - - if ((vifi = name[vp->namelen+4]) >= numvifs) - return NULL; - - if (!get_address(name, *length, &grp, vp->namelen)) - return NULL; - - if (!(cache = find_cache(grp, vifi))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 5) { /* get first entry */ - - if (len == vp->namelen) { - vifi = grp = 0; - } else { - get_address(name, len, &grp, vp->namelen); - vifi = name[vp->namelen+4]; - } - - cache = next_cache(grp,&vifi); - if (!cache) - return NULL; - - put_address(newname, cache->al_addr, vp->namelen); - newname[vp->namelen+4] = vifi; - } else { /* get next entry given previous */ - get_address(name, *length, &grp, vp->namelen); - vifi = name[vp->namelen+4]+1; - - if (!(cache = next_cache(grp,&vifi))) - return NULL; - - put_address(newname, cache->al_addr, vp->namelen); - newname[vp->namelen+4] = vifi; - } - } - - /* Save new OID */ - *length = vp->namelen + 5; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - /* Look up ifIndex given uvifs[vifi].uv_lcl_addr */ - in_ifaddr = ipaddr_to_ifindex(uvifs[vifi].uv_lcl_addr, &ifIndex); - - switch (vp->magic) { - - case igmpCacheSelf: - inm = in_ifaddr->ia_multiaddrs; - while (inm) { - klookup( (int)inm, (char *)&in_multi, sizeof(in_multi)); - - if (in_multi.inm_addr.s_addr == cache->al_addr) { - long_return = 1; /* true */ - return (u_char *) &long_return; - } - - inm = in_multi.inm_next; - } - long_return = 2; /* false */ - return (u_char *) &long_return; - - case igmpCacheLastReporter: - return (u_char *) &cache->al_genid; - - case igmpCacheUpTime: { - time_t currtime; - time(&currtime); - long_return = (currtime - cache->al_ctime)*100; - return (u_char *) &long_return; - } - - case igmpCacheExpiryTime: - long_return = secs_remaining(cache->al_timerid)*100; - return (u_char *) &long_return; - - case igmpCacheStatus: - long_return = 1; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Implements the IGMP Interface Table portion of the IGMP MIB - */ -u_char * -o_igmpInterfaceTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - oid newname[MAX_NAME_LEN]; - int ifnum; - int result; -static struct sioc_vif_req v_req; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - /* find "next" interface */ - for(ifnum = 0; ifnum < numvifs; ifnum++){ - if (!(uvifs[ifnum].uv_flags & VIFF_QUERIER)) - continue; - newname[vp->namelen] = (oid)ifnum; - result = compare(name, *length, newname, (int)vp->namelen + 1); - if ((exact && (result == 0)) || (!exact && (result < 0))) - break; - } - if (ifnum >= numvifs) - return NULL; - - /* Save new OID */ - bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid)); - *length = vp->namelen + 1; - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic){ - - case igmpInterfaceQueryInterval: - long_return = GROUP_QUERY_INTERVAL; - return (u_char *) &long_return; - - case igmpInterfaceStatus: - long_return = 1; /* active */ - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Given a virtual interface number, make sure we have the current - * kernel information for that Vif. - */ -refresh_vif(v_req, ifnum) - struct sioc_vif_req *v_req; - int ifnum; -{ - static int lastq = -1; - - if (quantum!=lastq || v_req->vifi != ifnum) { - lastq = quantum; - v_req->vifi = ifnum; - if (ioctl(igmp_socket, SIOCGETVIFCNT, (char *)v_req) < 0) - v_req->icount = v_req->ocount = v_req->ibytes = v_req->obytes = 0; - } -} - -/* - * Implements the Multicast Routing Interface Table portion of the Multicast MIB - */ -u_char * -o_ipMRouteInterfaceTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - oid newname[MAX_NAME_LEN]; - int ifnum; - int result; -static struct sioc_vif_req v_req; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - /* find "next" interface */ - for(ifnum = 0; ifnum < numvifs; ifnum++){ - newname[vp->namelen] = (oid)ifnum; - result = compare(name, *length, newname, (int)vp->namelen + 1); - if ((exact && (result == 0)) || (!exact && (result < 0))) - break; - } - if (ifnum >= numvifs) - return NULL; - - /* Save new OID */ - bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid)); - *length = vp->namelen + 1; - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic){ - - case ipMRouteInterfaceTtl: - long_return = uvifs[ifnum].uv_threshold; - return (u_char *) &long_return; - - case dvmrpVInterfaceType: - if (uvifs[ifnum].uv_flags & VIFF_SRCRT) - long_return = 2; - else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL) - long_return = 1; - else if (uvifs[ifnum].uv_flags & VIFF_QUERIER) - long_return = 3; - else /* SUBNET */ - long_return = 4; - return (u_char *) &long_return; - - case dvmrpVInterfaceState: - if (uvifs[ifnum].uv_flags & VIFF_DISABLED) - long_return = 3; - else if ((uvifs[ifnum].uv_flags & VIFF_DOWN) - || ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) && (uvifs[ifnum].uv_neighbors==NULL))) - long_return = 2; - else /* UP */ - long_return = 1; - return (u_char *) &long_return; - - case dvmrpVInterfaceLocalAddress: - return (u_char *) &uvifs[ifnum].uv_lcl_addr; - - case dvmrpVInterfaceRemoteAddress: - return (u_char *) ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) ? - &uvifs[ifnum].uv_rmt_addr : - &uvifs[ifnum].uv_subnet); - - case dvmrpVInterfaceRemoteSubnetMask: - return (u_char *) &uvifs[ifnum].uv_subnetmask; - - case dvmrpVInterfaceMetric: - long_return = uvifs[ifnum].uv_metric; - return (u_char *) &long_return; - - case dvmrpVInterfaceRateLimit: - long_return = uvifs[ifnum].uv_rate_limit; - return (u_char *) &long_return; - - case dvmrpVInterfaceInPkts: - refresh_vif(&v_req, ifnum); - long_return = v_req.icount; - return (u_char *) &long_return; - - case dvmrpVInterfaceOutPkts: - refresh_vif(&v_req, ifnum); - long_return = v_req.ocount; - return (u_char *) &long_return; - - case dvmrpVInterfaceInOctets: - refresh_vif(&v_req, ifnum); - long_return = v_req.ibytes; - return (u_char *) &long_return; - - case dvmrpVInterfaceOutOctets: - refresh_vif(&v_req, ifnum); - long_return = v_req.obytes; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Implements the DVMRP Route Table portion of the DVMRP MIB - */ -u_char * -o_dvmrpRouteTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - u_long src, mask; - oid newname[MAX_NAME_LEN]; - int len; - struct rtentry *rt = NULL; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 8) - return NULL; - - if (!get_address(name, *length, &src, vp->namelen) - || !get_address(name, *length, &mask, vp->namelen+4)) - return NULL; - - if (!(rt = snmp_find_route(src, mask))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 8) { /* get first entry */ - - if (len == vp->namelen) { - src = mask = 0; - } else { - get_address(name, len, &src, vp->namelen); - get_address(name, len, &mask, vp->namelen+4); - } - - if (!next_route(&rt,src,mask)) /* Get first entry */ - return NULL; - - put_address(newname, rt->rt_origin , vp->namelen); - put_address(newname, rt->rt_originmask, vp->namelen+4); - } else { /* get next entry given previous */ - get_address(name, *length, &src, vp->namelen); - get_address(name, *length, &mask, vp->namelen+4); - - if (!next_route(&rt, src,mask)) - return NULL; - - put_address(newname, rt->rt_origin, vp->namelen); - put_address(newname, rt->rt_originmask, vp->namelen+4); - } - } - - /* Save new OID */ - *length = vp->namelen + 8; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic) { - - case dvmrpRouteUpstreamNeighbor: - return (u_char *) &rt->rt_gateway; - - case dvmrpRouteInVifIndex: - long_return = rt->rt_parent; - return (u_char *) &long_return; - - case dvmrpRouteMetric: - long_return = rt->rt_metric; - return (u_char *) &long_return; - - case dvmrpRouteExpiryTime: - long_return = (ROUTE_EXPIRE_TIME - rt->rt_timer - + secs_remaining_offset()) * 100; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB - */ -u_char * -o_dvmrpRouteNextHopTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - u_long src, mask; - vifi_t vifi; - struct rtentry *rt = NULL; - oid newname[MAX_NAME_LEN]; - int len; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 9) - return NULL; - - if (!get_address(name, *length, &src, vp->namelen) - || !get_address(name, *length, &mask, vp->namelen+4) - || (!(rt=snmp_find_route(src,mask)))) - return NULL; - - vifi = name[vp->namelen+8]; - if (!(VIFM_ISSET(vifi, rt->rt_children))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 9) { /* get first entry */ - - get_address(name, len, &src, vp->namelen); - get_address(name, len, &mask, vp->namelen+4); - - /* Find first child vif */ - vifi=0; - if (!next_route_child(&rt, src, mask, &vifi)) - return NULL; - - put_address(newname, rt->rt_origin, vp->namelen); - put_address(newname, rt->rt_originmask, vp->namelen+4); - newname[vp->namelen+8] = vifi; - } else { /* get next entry given previous */ - vifi = name[vp->namelen+8] + 1; - if (!get_address(name, *length, &src, vp->namelen) - || !get_address(name, *length, &mask, vp->namelen+4) - || !next_route_child(&rt, src, mask, &vifi)) - return NULL; - - put_address(newname, rt->rt_origin, vp->namelen); - put_address(newname, rt->rt_originmask, vp->namelen+4); - newname[vp->namelen+8] = vifi; - } - } - - /* Save new OID */ - *length = vp->namelen + 9; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic) { - - case dvmrpRouteNextHopType: - long_return = (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Implements the IP Multicast Route Table portion of the Multicast MIB - */ -u_char * -o_ipMRouteTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - u_long src, grp, mask; - struct gtable *gt = NULL; - struct stable *st = NULL; -static struct sioc_sg_req sg_req; - oid newname[MAX_NAME_LEN]; - int len; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 12) - return NULL; - - if (!get_address(name, *length, &grp, vp->namelen) - || !get_address(name, *length, &src, vp->namelen+4) - || !get_address(name, *length, &mask, vp->namelen+8) - || (mask != 0xFFFFFFFF) /* we keep sources now, not subnets */ - || !(gt = find_grp(grp)) - || !(st = find_grp_src(gt,src))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 12) { /* get first entry */ - - get_address(name, len, &grp, vp->namelen); - get_address(name, len, &src, vp->namelen+4); - get_address(name, len, &mask, vp->namelen+8); - - if (!next_grp_src_mask(>,&st,grp,src,mask)) /* Get first entry */ - return NULL; - - put_address(newname, gt->gt_mcastgrp, vp->namelen); - put_address(newname, st->st_origin, vp->namelen+4); - put_address(newname, 0xFFFFFFFF, vp->namelen+8); - } else { /* get next entry given previous */ - get_address(name, *length, &grp , vp->namelen); - get_address(name, *length, &src , vp->namelen+4); - get_address(name, *length, &mask, vp->namelen+8); - - if (!next_grp_src_mask(>, &st, grp,src,mask)) - return NULL; - - put_address(newname, gt->gt_mcastgrp, vp->namelen); - put_address(newname, st->st_origin, vp->namelen+4); - put_address(newname, 0xFFFFFFFF, vp->namelen+8); - } - } - - /* Save new OID */ - *length = vp->namelen + 12; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic) { - - case ipMRouteUpstreamNeighbor: - return (u_char *) >->gt_route->rt_gateway; - - case ipMRouteInIfIndex: - long_return = gt->gt_route->rt_parent; - return (u_char *) &long_return; - - case ipMRouteUpTime: { - time_t currtime; - time(&currtime); - long_return = (currtime - gt->gt_ctime)*100; - return (u_char *) &long_return; - } - - case ipMRouteExpiryTime: - long_return = 5*((gt->gt_timer+4)/5); /* round up to nearest 5 */ - long_return = (long_return + secs_remaining_offset()) * 100; - return (u_char *) &long_return; - - case ipMRoutePkts: - refresh_sg(&sg_req, gt, st); - long_return = sg_req.pktcnt; - return (u_char *) &long_return; - - case ipMRouteOctets: - refresh_sg(&sg_req, gt, st); - long_return = sg_req.bytecnt; - return (u_char *) &long_return; - - case ipMRouteDifferentInIfIndexes: - refresh_sg(&sg_req, gt, st); - long_return = sg_req.wrong_if; - return (u_char *) &long_return; - - case ipMRouteProtocol: - long_return = 4; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* - * Implements the IP Multicast Routing Next Hop Table portion of the Multicast - * MIB - */ -u_char * -o_ipMRouteNextHopTable(vp, name, length, exact, var_len, write_method) - struct variable *vp; /* IN - pointer to variable entry that points here */ - oid *name; /* IN/OUT - input name requested, output name found */ - int *length; /* IN/OUT - length of input and output oid's */ - int exact; /* IN - TRUE if an exact match was requested. */ - int *var_len; /* OUT - length of variable or 0 if function returned. */ - int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ -{ - u_long src, grp, mask, addr; - vifi_t vifi; - struct gtable *gt; - struct stable *st; - oid newname[MAX_NAME_LEN]; - int len; - - /* Copy name OID to new OID */ - bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - - if (exact) { - if (*length != vp->namelen + 17) - return NULL; - - if (!get_address(name, *length, &grp, vp->namelen) - || !get_address(name, *length, &src, vp->namelen+4) - || !get_address(name, *length, &mask, vp->namelen+8) - || !get_address(name, *length, &addr, vp->namelen+13) - || grp!=addr - || mask!=0xFFFFFFFF - || (!(gt=find_grp(grp))) - || (!(st=find_grp_src(gt,src)))) - return NULL; - - vifi = name[vp->namelen+12]; - if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children))) - return NULL; - - bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); - } else { - len = *length; - if (compare(name, *length, vp->name, vp->namelen) < 0) - len = vp->namelen; - - if (len < vp->namelen + 17) { /* get first entry */ - - get_address(name, len, &grp, vp->namelen); - get_address(name, len, &src, vp->namelen+4); - get_address(name, len, &mask, vp->namelen+8); - - /* Find first child vif */ - vifi=0; - if (!next_child(>, &st, grp, src, mask, &vifi)) - return NULL; - - put_address(newname, gt->gt_mcastgrp, vp->namelen); - put_address(newname, st->st_origin, vp->namelen+4); - put_address(newname, 0xFFFFFFFF, vp->namelen+8); - newname[vp->namelen+12] = vifi; - put_address(newname, gt->gt_mcastgrp, vp->namelen+13); - - } else { /* get next entry given previous */ - vifi = name[vp->namelen+12]+1; - if (!get_address(name, *length, &grp, vp->namelen) - || !get_address(name, *length, &src, vp->namelen+4) - || !get_address(name, *length, &mask, vp->namelen+8) - || !next_child(>, &st, grp, src, mask, &vifi)) - return NULL; - - put_address(newname, gt->gt_mcastgrp, vp->namelen); - put_address(newname, st->st_origin, vp->namelen+4); - put_address(newname, 0xFFFFFFFF, vp->namelen+8); - newname[vp->namelen+12] = vifi; - put_address(newname, gt->gt_mcastgrp, vp->namelen+13); - } - } - - /* Save new OID */ - *length = vp->namelen + 17; - bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); - *write_method = 0; - *var_len = sizeof(long); - - switch (vp->magic) { - - case ipMRouteNextHopState: - long_return = (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1; - return (u_char *) &long_return; - - /* Currently equal to ipMRouteUpTime */ - case ipMRouteNextHopUpTime: { - time_t currtime; - time(&currtime); - long_return = (currtime - gt->gt_ctime)*100; - return (u_char *) &long_return; - } - - case ipMRouteNextHopExpiryTime: - long_return = 5*((gt->gt_prsent_timer+4)/5); /* round up to nearest 5*/ - long_return = (long_return + secs_remaining_offset()) * 100; - return (u_char *) &long_return; - - case ipMRouteNextHopClosestMemberHops: - long_return = 0; - return (u_char *) &long_return; - - case ipMRouteNextHopProtocol: - long_return = 4; - return (u_char *) &long_return; - - default: - ERROR(""); - } - return NULL; -} - -/* sync_timer is called by timer() every TIMER_INTERVAL seconds. - * Its job is to record this time so that we can compute on demand - * the approx # seconds remaining until the next timer() call - */ -static time_t lasttimer; - -void -sync_timer() -{ - time(&lasttimer); -} - -int /* in range [-TIMER_INTERVAL..0] */ -secs_remaining_offset() -{ - time_t tm; - - time(&tm); - return lasttimer-tm; -} diff --git a/gnu/dist/mrouted/snmp.h b/gnu/dist/mrouted/snmp.h deleted file mode 100644 index 8cf99e84e65..00000000000 --- a/gnu/dist/mrouted/snmp.h +++ /dev/null @@ -1,9 +0,0 @@ -/* $NetBSD: snmp.h,v 1.1 2002/10/01 03:31:11 itojun Exp $ */ - -extern int portlist[32], sdlen; -extern in_port_t dest_port; -extern int quantum; - -extern int snmp_read_packet(); - -#define DEFAULT_PORT 161 diff --git a/gnu/dist/mrouted/vif.c b/gnu/dist/mrouted/vif.c deleted file mode 100644 index f9554ace209..00000000000 --- a/gnu/dist/mrouted/vif.c +++ /dev/null @@ -1,1442 +0,0 @@ -/* $NetBSD: vif.c,v 1.2 2002/12/06 16:02:57 thorpej Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - - -#include "defs.h" -#include <fcntl.h> - -/* - * Exported variables. - */ -struct uvif uvifs[MAXVIFS]; /* array of virtual interfaces */ -vifi_t numvifs; /* number of vifs in use */ -int vifs_down; /* 1=>some interfaces are down */ -int phys_vif; /* An enabled vif */ -int udp_socket; /* Since the honkin' kernel doesn't support */ - /* ioctls on raw IP sockets, we need a UDP */ - /* socket as well as our IGMP (raw) socket. */ - /* How dumb. */ -int vifs_with_neighbors; /* == 1 if I am a leaf */ - -typedef struct { - vifi_t vifi; - struct listaddr *g; - int q_time; -} cbk_t; - -/* - * Forward declarations. - */ -static void start_vif(vifi_t vifi); -static void start_vif2(vifi_t vifi); -static void stop_vif(vifi_t vifi); -static void age_old_hosts(void); -static void send_probe_on_vif(struct uvif *v); -static int info_version(char *p); -static void DelVif(void *arg); -static int SetTimer(vifi_t vifi, struct listaddr *g); -static int DeleteTimer(int id); -static void SendQuery(void *arg); -static int SetQueryTimer(struct listaddr *g, vifi_t vifi, int to_expire, - int q_time); - - -/* - * Initialize the virtual interfaces, but do not install - * them in the kernel. Start routing on all vifs that are - * not down or disabled. - */ -void -init_vifs(void) -{ - vifi_t vifi; - struct uvif *v; - int enabled_vifs, enabled_phyints; - extern char *configfilename; - - numvifs = 0; - vifs_with_neighbors = 0; - vifs_down = FALSE; - - /* - * Configure the vifs based on the interface configuration of the - * the kernel and the contents of the configuration file. - * (Open a UDP socket for ioctl use in the config procedures.) - */ - if ((udp_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - logit(LOG_ERR, errno, "UDP socket"); - logit(LOG_INFO,0,"Getting vifs from kernel interfaces"); - config_vifs_from_kernel(); - logit(LOG_INFO,0,"Getting vifs from %s",configfilename); - config_vifs_from_file(); - - /* - * Quit if there are fewer than two enabled vifs. - */ - enabled_vifs = 0; - enabled_phyints = 0; - phys_vif = -1; - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & VIFF_DISABLED)) { - ++enabled_vifs; - if (!(v->uv_flags & VIFF_TUNNEL)) { - if (phys_vif == -1) - phys_vif = vifi; - ++enabled_phyints; - } - } - } - if (enabled_vifs < 2) - logit(LOG_ERR, 0, "can't forward: %s", - enabled_vifs == 0 ? "no enabled vifs" : "only one enabled vif"); - - if (enabled_phyints == 0) - logit(LOG_WARNING, 0, - "no enabled interfaces, forwarding via tunnels only"); - - logit(LOG_INFO, 0, "Installing vifs in mrouted..."); - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & VIFF_DISABLED)) { - if (!(v->uv_flags & VIFF_DOWN)) { - if (v->uv_flags & VIFF_TUNNEL) - logit(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi, - inet_fmt(v->uv_lcl_addr, s1), - inet_fmt(v->uv_rmt_addr, s2)); - else - logit(LOG_INFO, 0, "vif #%d, phyint %s", vifi, - inet_fmt(v->uv_lcl_addr, s1)); - start_vif2(vifi); - } else logit(LOG_INFO, 0, - "%s is not yet up; vif #%u not in service", - v->uv_name, vifi); - } - } -} - -/* - * Start routing on all virtual interfaces that are not down or - * administratively disabled. - */ -void -init_installvifs(void) -{ - vifi_t vifi; - struct uvif *v; - - logit(LOG_INFO, 0, "Installing vifs in kernel..."); - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & VIFF_DISABLED)) { - if (!(v->uv_flags & VIFF_DOWN)) { - if (v->uv_flags & VIFF_TUNNEL) - logit(LOG_INFO, 0, "vif #%d, tunnel %s -> %s", vifi, - inet_fmt(v->uv_lcl_addr, s1), - inet_fmt(v->uv_rmt_addr, s2)); - else - logit(LOG_INFO, 0, "vif #%d, phyint %s", vifi, - inet_fmt(v->uv_lcl_addr, s1)); - k_add_vif(vifi, &uvifs[vifi]); - } else logit(LOG_INFO, 0, - "%s is not yet up; vif #%u not in service", - v->uv_name, vifi); - } - } -} - -/* - * See if any interfaces have changed from up state to down, or vice versa, - * including any non-multicast-capable interfaces that are in use as local - * tunnel end-points. Ignore interfaces that have been administratively - * disabled. - */ -void -check_vif_state(void) -{ - vifi_t vifi; - struct uvif *v; - struct ifreq ifr; - - vifs_down = FALSE; - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - - if (v->uv_flags & VIFF_DISABLED) continue; - - strncpy(ifr.ifr_name, v->uv_name, IFNAMSIZ); - if (ioctl(udp_socket, SIOCGIFFLAGS, (char *)&ifr) < 0) - logit(LOG_ERR, errno, - "ioctl SIOCGIFFLAGS for %s", ifr.ifr_name); - - if (v->uv_flags & VIFF_DOWN) { - if (ifr.ifr_flags & IFF_UP) { - v->uv_flags &= ~VIFF_DOWN; - start_vif(vifi); - logit(LOG_INFO, 0, - "%s has come up; vif #%u now in service", - v->uv_name, vifi); - } - else vifs_down = TRUE; - } - else { - if (!(ifr.ifr_flags & IFF_UP)) { - stop_vif(vifi); - v->uv_flags |= VIFF_DOWN; - logit(LOG_INFO, 0, - "%s has gone down; vif #%u taken out of service", - v->uv_name, vifi); - vifs_down = TRUE; - } - } - } -} - -/* - * Send a probe message on vif v - */ -static void -send_probe_on_vif(struct uvif *v) -{ - char *p; - int datalen = 0; - struct listaddr *nbr; - int i; - - p = send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN; - - for (i = 0; i < 4; i++) - *p++ = ((char *)&(dvmrp_genid))[i]; - datalen += 4; - - /* - * add the neighbor list on the interface to the message - */ - nbr = v->uv_neighbors; - - while (nbr) { - for (i = 0; i < 4; i++) - *p++ = ((char *)&nbr->al_addr)[i]; - datalen +=4; - nbr = nbr->al_next; - } - - send_igmp(v->uv_lcl_addr, - (v->uv_flags & VIFF_TUNNEL) ? v->uv_rmt_addr - : dvmrp_group, - IGMP_DVMRP, DVMRP_PROBE, - htonl(MROUTED_LEVEL | - ((v->uv_flags & VIFF_LEAF) ? 0 : LEAF_FLAGS)), - datalen); -} - -/* - * Add a vifi to the kernel and start routing on it. - */ -static void -start_vif(vifi_t vifi) -{ - /* - * Install the interface in the kernel's vif structure. - */ - k_add_vif(vifi, &uvifs[vifi]); - - start_vif2(vifi); -} - -/* - * Add a vifi to all the user-level data structures but don't add - * it to the kernel yet. - */ -static void -start_vif2(vifi_t vifi) -{ - struct uvif *v; - u_int32_t src; - struct phaddr *p; - - v = &uvifs[vifi]; - src = v->uv_lcl_addr; - - /* - * Update the existing route entries to take into account the new vif. - */ - add_vif_to_routes(vifi); - - if (!(v->uv_flags & VIFF_TUNNEL)) { - /* - * Join the DVMRP multicast group on the interface. - * (This is not strictly necessary, since the kernel promiscuously - * receives IGMP packets addressed to ANY IP multicast group while - * multicast routing is enabled. However, joining the group allows - * this host to receive non-IGMP packets as well, such as 'pings'.) - */ - k_join(dvmrp_group, src); - - /* - * Join the ALL-ROUTERS multicast group on the interface. - * This allows mtrace requests to loop back if they are run - * on the multicast router. - */ - k_join(allrtrs_group, src); - - /* - * Install an entry in the routing table for the subnet to which - * the interface is connected. - */ - start_route_updates(); - update_route(v->uv_subnet, v->uv_subnetmask, 0, 0, vifi); - for (p = v->uv_addrs; p; p = p->pa_next) { - start_route_updates(); - update_route(p->pa_subnet, p->pa_subnetmask, 0, 0, vifi); - } - - /* - * Until neighbors are discovered, assume responsibility for sending - * periodic group membership queries to the subnet. Send the first - * query. - */ - v->uv_flags |= VIFF_QUERIER; - send_igmp(src, allhosts_group, IGMP_HOST_MEMBERSHIP_QUERY, - (v->uv_flags & VIFF_IGMPV1) ? 0 : - IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0); - age_old_hosts(); - } - - v->uv_leaf_timer = LEAF_CONFIRMATION_TIME; - - /* - * Send a probe via the new vif to look for neighbors. - */ - send_probe_on_vif(v); -} - -/* - * Stop routing on the specified virtual interface. - */ -static void -stop_vif(vifi_t vifi) -{ - struct uvif *v; - struct listaddr *a; - struct phaddr *p; - - v = &uvifs[vifi]; - - if (!(v->uv_flags & VIFF_TUNNEL)) { - /* - * Depart from the DVMRP multicast group on the interface. - */ - k_leave(dvmrp_group, v->uv_lcl_addr); - - /* - * Depart from the ALL-ROUTERS multicast group on the interface. - */ - k_leave(allrtrs_group, v->uv_lcl_addr); - - /* - * Update the entry in the routing table for the subnet to which - * the interface is connected, to take into account the interface - * failure. - */ - start_route_updates(); - update_route(v->uv_subnet, v->uv_subnetmask, UNREACHABLE, 0, vifi); - for (p = v->uv_addrs; p; p = p->pa_next) { - start_route_updates(); - update_route(p->pa_subnet, p->pa_subnetmask, UNREACHABLE, 0, vifi); - } - - /* - * Discard all group addresses. (No need to tell kernel; - * the k_del_vif() call, below, will clean up kernel state.) - */ - while (v->uv_groups != NULL) { - a = v->uv_groups; - v->uv_groups = a->al_next; - free((char *)a); - } - - v->uv_flags &= ~VIFF_QUERIER; - } - - /* - * Update the existing route entries to take into account the vif failure. - */ - delete_vif_from_routes(vifi); - - /* - * Delete the interface from the kernel's vif structure. - */ - k_del_vif(vifi); - - /* - * Discard all neighbor addresses. - */ - if (v->uv_neighbors) - vifs_with_neighbors--; - - while (v->uv_neighbors != NULL) { - a = v->uv_neighbors; - v->uv_neighbors = a->al_next; - free((char *)a); - } -} - - -/* - * stop routing on all vifs - */ -void -stop_all_vifs(void) -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *a; - struct vif_acl *acl; - - for (vifi = 0; vifi < numvifs; vifi++) { - v = &uvifs[vifi]; - while (v->uv_groups != NULL) { - a = v->uv_groups; - v->uv_groups = a->al_next; - free((char *)a); - } - while (v->uv_neighbors != NULL) { - a = v->uv_neighbors; - v->uv_neighbors = a->al_next; - free((char *)a); - } - while (v->uv_acl != NULL) { - acl = v->uv_acl; - v->uv_acl = acl->acl_next; - free((char *)acl); - } - } -} - - -/* - * Find the virtual interface from which an incoming packet arrived, - * based on the packet's source and destination IP addresses. - */ -vifi_t -find_vif(u_int32_t src, u_int32_t dst) -{ - vifi_t vifi; - struct uvif *v; - struct phaddr *p; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { - if (!(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { - if (v->uv_flags & VIFF_TUNNEL) { - if (src == v->uv_rmt_addr && dst == v->uv_lcl_addr) - return(vifi); - } - else { - if ((src & v->uv_subnetmask) == v->uv_subnet && - ((v->uv_subnetmask == 0xffffffff) || - (src != v->uv_subnetbcast))) - return(vifi); - for (p=v->uv_addrs; p; p=p->pa_next) { - if ((src & p->pa_subnetmask) == p->pa_subnet && - ((p->pa_subnetmask == 0xffffffff) || - (src != p->pa_subnetbcast))) - return(vifi); - } - } - } - } - return (NO_VIF); -} - -static void -age_old_hosts(void) -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *g; - - /* - * Decrement the old-hosts-present timer for each - * active group on each vif. - */ - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) - for (g = v->uv_groups; g != NULL; g = g->al_next) - if (g->al_old) - g->al_old--; -} - - -/* - * Send group membership queries to all subnets for which I am querier. - */ -void -query_groups(void) -{ - vifi_t vifi; - struct uvif *v; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - if (v->uv_flags & VIFF_QUERIER) { - send_igmp(v->uv_lcl_addr, allhosts_group, - IGMP_HOST_MEMBERSHIP_QUERY, - (v->uv_flags & VIFF_IGMPV1) ? 0 : - IGMP_MAX_HOST_REPORT_DELAY * IGMP_TIMER_SCALE, 0, 0); - } - } - age_old_hosts(); -} - -/* - * Process an incoming host membership query - */ -void -accept_membership_query(u_int32_t src, u_int32_t dst, u_int32_t group, int tmo) -{ - vifi_t vifi; - struct uvif *v; - - if ((vifi = find_vif(src, dst)) == NO_VIF || - (uvifs[vifi].uv_flags & VIFF_TUNNEL)) { - logit(LOG_INFO, 0, - "ignoring group membership query from non-adjacent host %s", - inet_fmt(src, s1)); - return; - } - - v = &uvifs[vifi]; - - /* - * If we consider ourselves the querier for this vif, but hear a - * query from a router with a lower IP address, yield to them. - * - * This is done here as well as in the neighbor discovery in case - * there is a querier that doesn't speak DVMRP. - * - * XXX If this neighbor doesn't speak DVMRP, then we need to create - * some neighbor state for him so that we can time him out! - */ - if ((v->uv_flags & VIFF_QUERIER) && - (ntohl(src) < ntohl(v->uv_lcl_addr))) { - v->uv_flags &= ~VIFF_QUERIER; - - } -} - -/* - * Process an incoming group membership report. - */ -void -accept_group_report(u_int32_t src, u_int32_t dst, u_int32_t group, int r_type) -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *g; - - if ((vifi = find_vif(src, dst)) == NO_VIF || - (uvifs[vifi].uv_flags & VIFF_TUNNEL)) { - logit(LOG_INFO, 0, - "ignoring group membership report from non-adjacent host %s", - inet_fmt(src, s1)); - return; - } - - v = &uvifs[vifi]; - - /* - * Look for the group in our group list; if found, reset its timer. - */ - for (g = v->uv_groups; g != NULL; g = g->al_next) { - if (group == g->al_addr) { - if (r_type == IGMP_v1_HOST_MEMBERSHIP_REPORT) - g->al_old = OLD_AGE_THRESHOLD; -#ifdef SNMP - g->al_genid = src; -#endif /* SNMP */ - - /** delete old timers, set a timer for expiration **/ - g->al_timer = GROUP_EXPIRE_TIME; - if (g->al_query) - g->al_query = DeleteTimer(g->al_query); - if (g->al_timerid) - g->al_timerid = DeleteTimer(g->al_timerid); - g->al_timerid = SetTimer(vifi, g); - break; - } - } - - /* - * If not found, add it to the list and update kernel cache. - */ - if (g == NULL) { - g = (struct listaddr *)malloc(sizeof(struct listaddr)); - if (g == NULL) - logit(LOG_ERR, 0, "ran out of memory"); /* fatal */ - - g->al_addr = group; - if (r_type == IGMP_v2_HOST_MEMBERSHIP_REPORT) - g->al_old = 0; - else - g->al_old = OLD_AGE_THRESHOLD; -#ifdef SNMP - g->al_genid = src; -#endif - - /** set a timer for expiration **/ - g->al_query = 0; - g->al_timer = GROUP_EXPIRE_TIME; - time(&g->al_ctime); - g->al_timerid = SetTimer(vifi, g); - g->al_next = v->uv_groups; - v->uv_groups = g; - - update_lclgrp(vifi, group); - } - - /* - * Check if a graft is necessary for this group - */ - chkgrp_graft(vifi, group); -} - - -void -accept_leave_message(u_int32_t src, u_int32_t dst, u_int32_t group) -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *g; - - if ((vifi = find_vif(src, dst)) == NO_VIF || - (uvifs[vifi].uv_flags & VIFF_TUNNEL)) { - logit(LOG_INFO, 0, - "ignoring group leave report from non-adjacent host %s", - inet_fmt(src, s1)); - return; - } - - v = &uvifs[vifi]; - - if (!(v->uv_flags & VIFF_QUERIER) || (v->uv_flags & VIFF_IGMPV1)) - return; - - /* - * Look for the group in our group list in order to set up a short-timeout - * query. - */ - for (g = v->uv_groups; g != NULL; g = g->al_next) { - if (group == g->al_addr) { - logit(LOG_DEBUG, 0, - "[vif.c, _accept_leave_message] %d %ld\n", - g->al_old, g->al_query); - - /* Ignore the leave message if there are old hosts present */ - if (g->al_old) - return; - - /* still waiting for a reply to a query, ignore the leave */ - if (g->al_query) - return; - - /** delete old timer set a timer for expiration **/ - if (g->al_timerid) - g->al_timerid = DeleteTimer(g->al_timerid); - - /** send a group specific querry **/ - g->al_timer = LEAVE_EXPIRE_TIME; - send_igmp(v->uv_lcl_addr, g->al_addr, - IGMP_HOST_MEMBERSHIP_QUERY, - LEAVE_EXPIRE_TIME / 3 * IGMP_TIMER_SCALE, - g->al_addr, 0); - g->al_query = SetQueryTimer(g, vifi, g->al_timer / 3, - LEAVE_EXPIRE_TIME / 3 * IGMP_TIMER_SCALE); - g->al_timerid = SetTimer(vifi, g); - break; - } - } -} - - -/* - * Send a periodic probe on all vifs. - * Useful to determine one-way interfaces. - * Detect neighbor loss faster. - */ -void -probe_for_neighbors(void) -{ - vifi_t vifi; - struct uvif *v; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - if (!(v->uv_flags & (VIFF_DOWN|VIFF_DISABLED))) { - send_probe_on_vif(v); - } - } -} - - -/* - * Send a list of all of our neighbors to the requestor, `src'. - */ -void -accept_neighbor_request(u_int32_t src, u_int32_t dst) -{ - vifi_t vifi; - struct uvif *v; - u_char *p, *ncount; - struct listaddr *la; - int datalen; - u_int32_t temp_addr, us, them = src; - - /* Determine which of our addresses to use as the source of our response - * to this query. - */ - if (IN_MULTICAST(ntohl(dst))) { /* query sent to a multicast group */ - int udp; /* find best interface to reply on */ - struct sockaddr_in addr; - int addrlen = sizeof(addr); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = dst; - 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) { - logit(LOG_WARNING, errno, "Determining local address"); - close(udp); - return; - } - close(udp); - us = addr.sin_addr.s_addr; - } else /* query sent to us alone */ - us = dst; - -#define PUT_ADDR(a) temp_addr = ntohl(a); \ - *p++ = temp_addr >> 24; \ - *p++ = (temp_addr >> 16) & 0xFF; \ - *p++ = (temp_addr >> 8) & 0xFF; \ - *p++ = temp_addr & 0xFF; - - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - if (v->uv_flags & VIFF_DISABLED) - continue; - - ncount = 0; - - for (la = v->uv_neighbors; la; la = la->al_next) { - - /* Make sure that there's room for this neighbor... */ - if (datalen + (ncount == 0 ? 4 + 3 + 4 : 4) > MAX_DVMRP_DATA_LEN) { - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS, - htonl(MROUTED_LEVEL), datalen); - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - ncount = 0; - } - - /* Put out the header for this neighbor list... */ - if (ncount == 0) { - PUT_ADDR(v->uv_lcl_addr); - *p++ = v->uv_metric; - *p++ = v->uv_threshold; - ncount = p; - *p++ = 0; - datalen += 4 + 3; - } - - PUT_ADDR(la->al_addr); - datalen += 4; - (*ncount)++; - } - } - - if (datalen != 0) - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS, htonl(MROUTED_LEVEL), - datalen); -} - -/* - * Send a list of all of our neighbors to the requestor, `src'. - */ -void -accept_neighbor_request2(u_int32_t src, u_int32_t dst) -{ - vifi_t vifi; - struct uvif *v; - u_char *p, *ncount; - struct listaddr *la; - int datalen; - u_int32_t us, them = src; - - /* Determine which of our addresses to use as the source of our response - * to this query. - */ - if (IN_MULTICAST(ntohl(dst))) { /* query sent to a multicast group */ - int udp; /* find best interface to reply on */ - struct sockaddr_in addr; - int addrlen = sizeof(addr); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - addr.sin_len = sizeof addr; -#endif - addr.sin_addr.s_addr = dst; - 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) { - logit(LOG_WARNING, errno, "Determining local address"); - close(udp); - return; - } - close(udp); - us = addr.sin_addr.s_addr; - } else /* query sent to us alone */ - us = dst; - - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - u_short vflags = v->uv_flags; - u_char rflags = 0; - if (vflags & VIFF_TUNNEL) - rflags |= DVMRP_NF_TUNNEL; - if (vflags & VIFF_SRCRT) - rflags |= DVMRP_NF_SRCRT; - if (vflags & VIFF_DOWN) - rflags |= DVMRP_NF_DOWN; - if (vflags & VIFF_DISABLED) - rflags |= DVMRP_NF_DISABLED; - if (vflags & VIFF_QUERIER) - rflags |= DVMRP_NF_QUERIER; - if (vflags & VIFF_LEAF) - rflags |= DVMRP_NF_LEAF; - ncount = 0; - la = v->uv_neighbors; - if (la == NULL) { - /* - * include down & disabled interfaces and interfaces on - * leaf nets. - */ - if (rflags & DVMRP_NF_TUNNEL) - rflags |= DVMRP_NF_DOWN; - if (datalen > MAX_DVMRP_DATA_LEN - 12) { - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, - htonl(MROUTED_LEVEL), datalen); - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - } - *(u_int*)p = v->uv_lcl_addr; - p += 4; - *p++ = v->uv_metric; - *p++ = v->uv_threshold; - *p++ = rflags; - *p++ = 1; - *(u_int*)p = v->uv_rmt_addr; - p += 4; - datalen += 12; - } else { - for ( ; la; la = la->al_next) { - /* Make sure that there's room for this neighbor... */ - if (datalen + (ncount == 0 ? 4+4+4 : 4) > MAX_DVMRP_DATA_LEN) { - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, - htonl(MROUTED_LEVEL), datalen); - p = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - datalen = 0; - ncount = 0; - } - /* Put out the header for this neighbor list... */ - if (ncount == 0) { - *(u_int*)p = v->uv_lcl_addr; - p += 4; - *p++ = v->uv_metric; - *p++ = v->uv_threshold; - *p++ = rflags; - ncount = p; - *p++ = 0; - datalen += 4 + 4; - } - *(u_int*)p = la->al_addr; - p += 4; - datalen += 4; - (*ncount)++; - } - } - } - if (datalen != 0) - send_igmp(us, them, IGMP_DVMRP, DVMRP_NEIGHBORS2, htonl(MROUTED_LEVEL), - datalen); -} - -void -accept_info_request(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ - u_char *q; - int len; - int outlen = 0; - - q = (u_char *) (send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - - /* To be general, this must deal properly with breaking up over-sized - * packets. That implies passing a length to each function, and - * allowing each function to request to be called again. Right now, - * we're only implementing the one thing we are positive will fit into - * a single packet, so we wimp out. - */ - while (datalen > 0) { - len = 0; - switch (*p) { - case DVMRP_INFO_VERSION: - len = info_version(q); - break; - - case DVMRP_INFO_NEIGHBORS: - default: - logit(LOG_INFO, 0, "ignoring unknown info type %d", *p); - break; - } - *(q+1) = len++; - outlen += len * 4; - q += len * 4; - len = (*(p+1) + 1) * 4; - p += len; - datalen -= len; - } - - if (outlen != 0) - send_igmp(INADDR_ANY, src, IGMP_DVMRP, DVMRP_INFO_REPLY, - htonl(MROUTED_LEVEL), outlen); -} - -/* - * Information response -- return version string - */ -static int -info_version(char *p) -{ - int len; - extern char versionstring[]; - - *p++ = DVMRP_INFO_VERSION; - p++; /* skip over length */ - *p++ = 0; /* zero out */ - *p++ = 0; /* reserved fields */ - strcpy(p, versionstring); /* XXX strncpy!!! */ - - len = strlen(versionstring); - return ((len + 3) / 4); -} - -/* - * Process an incoming neighbor-list message. - */ -void -accept_neighbors(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ - logit(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Process an incoming neighbor-list message. - */ -void -accept_neighbors2(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ - logit(LOG_INFO, 0, "ignoring spurious DVMRP neighbor list2 from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - -/* - * Process an incoming info reply message. - */ -void -accept_info_reply(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ - logit(LOG_INFO, 0, "ignoring spurious DVMRP info reply from %s to %s", - inet_fmt(src, s1), inet_fmt(dst, s2)); -} - - -/* - * Update the neighbor entry for neighbor 'addr' on vif 'vifi'. - * 'msgtype' is the type of DVMRP message received from the neighbor. - * Return TRUE if 'addr' is a valid neighbor, FALSE otherwise. - */ -int -update_neighbor(vifi_t vifi, u_int32_t addr, int msgtype, char *p, int datalen, u_int32_t level) -{ - struct uvif *v; - struct listaddr *n; - u_int32_t genid = 0; - u_int32_t router; - u_int32_t send_tables = 0; - int do_reset = FALSE; - int nflags; - - v = &uvifs[vifi]; - nflags = (level >> 16) & 0xff; - - /* - * Confirm that 'addr' is a valid neighbor address on vif 'vifi'. - * IT IS ASSUMED that this was preceded by a call to find_vif(), which - * checks that 'addr' is either a valid remote tunnel endpoint or a - * non-broadcast address belonging to a directly-connected subnet. - * Therefore, here we check only that 'addr' is not our own address - * (due to an impostor or erroneous loopback) or an address of the form - * {subnet,0} ("the unknown host"). These checks are not performed in - * find_vif() because those types of address are acceptable for some - * types of IGMP message (such as group membership reports). - */ - if (!(v->uv_flags & VIFF_TUNNEL) && - (addr == v->uv_lcl_addr || - addr == v->uv_subnet )) { - logit(LOG_WARNING, 0, - "received DVMRP message from 'the unknown host' or self: %s", - inet_fmt(addr, s1)); - return (FALSE); - } - - /* - * Look for addr in list of neighbors. - */ - for (n = v->uv_neighbors; n != NULL; n = n->al_next) { - if (addr == n->al_addr) { - break; - } - } - - /* - * Found it. Reset its timer, and check for a version change - */ - if (n) { - n->al_timer = 0; - - /* - * update the neighbors version and protocol number - * if changed => router went down and came up, - * so take action immediately. - */ - if ((n->al_pv != (level & 0xff)) || - (n->al_mv != ((level >> 8) & 0xff))) { - - do_reset = TRUE; - logit(LOG_DEBUG, 0, - "version change neighbor %s [old:%d.%d, new:%d.%d]", - inet_fmt(addr, s1), - n->al_pv, n->al_mv, level&0xff, (level >> 8) & 0xff); - - n->al_pv = level & 0xff; - n->al_mv = (level >> 8) & 0xff; - } - } else { - /* - * If not found, add it to the list. If the neighbor has a lower - * IP address than me, yield querier duties to it. - */ - logit(LOG_DEBUG, 0, "New neighbor %s on vif %d v%d.%d nf 0x%02x", - inet_fmt(addr, s1), vifi, level & 0xff, (level >> 8) & 0xff, - (level >> 16) & 0xff); - - n = (struct listaddr *)malloc(sizeof(struct listaddr)); - if (n == NULL) - logit(LOG_ERR, 0, "ran out of memory"); /* fatal */ - - n->al_addr = addr; - n->al_pv = level & 0xff; - n->al_mv = (level >> 8) & 0xff; - n->al_genid = 0; - - time(&n->al_ctime); - n->al_timer = 0; - n->al_next = v->uv_neighbors; - - /* - * If we thought that we had no neighbors on this vif, send a route - * report to the vif. If this is just a new neighbor on the same - * vif, send the route report just to the new neighbor. - */ - if (v->uv_neighbors == NULL) { - send_tables = (v->uv_flags & VIFF_TUNNEL) ? addr : dvmrp_group; - vifs_with_neighbors++; - } else { - send_tables = addr; - } - - v->uv_neighbors = n; - - if (!(v->uv_flags & VIFF_TUNNEL) && - ntohl(addr) < ntohl(v->uv_lcl_addr)) - v->uv_flags &= ~VIFF_QUERIER; - } - - /* - * Check if the router gen-ids are the same. - * Need to reset the prune state of the router if not. - * Also check for one-way interfaces by seeing if we are in our - * neighbor's list of known routers. - */ - if (msgtype == DVMRP_PROBE) { - - /* Check genid neighbor flag. Also check version number; 3.3 and - * 3.4 didn't set this flag. */ - if ((((level >> 16) & 0xff) & NF_GENID) || - (((level & 0xff) == 3) && (((level >> 8) & 0xff) > 2))) { - - int i; - - if (datalen < 4) { - logit(LOG_WARNING, 0, - "received truncated probe message from %s (len %d)", - inet_fmt(addr, s1), datalen); - return (FALSE); - } - - for (i = 0; i < 4; i++) - ((char *)&genid)[i] = *p++; - datalen -= 4; - - if (n->al_genid == 0) - n->al_genid = genid; - else if (n->al_genid != genid) { - logit(LOG_DEBUG, 0, - "new genid neigbor %s on vif %d [old:%x, new:%x]", - inet_fmt(addr, s1), vifi, n->al_genid, genid); - - n->al_genid = genid; - do_reset = TRUE; - } - - /* - * loop through router list and check for one-way ifs. - */ - - v->uv_flags |= VIFF_ONEWAY; - - while (datalen > 0) { - if (datalen < 4) { - logit(LOG_WARNING, 0, - "received truncated probe message from %s (len %d)", - inet_fmt(addr, s1), datalen); - return (FALSE); - } - for (i = 0; i < 4; i++) - ((char *)&router)[i] = *p++; - datalen -= 4; - if (router == v->uv_lcl_addr) { - v->uv_flags &= ~VIFF_ONEWAY; - break; - } - } - } - } - if (n->al_flags != nflags) { - n->al_flags = nflags; - - if (n->al_flags & NF_LEAF) { - /*XXX If we have non-leaf neighbors then we know we shouldn't - * mark this vif as a leaf. For now we just count on other - * probes and/or reports resetting the timer. */ - if (!v->uv_leaf_timer) - v->uv_leaf_timer = LEAF_CONFIRMATION_TIME; - } else { - /* If we get a leaf to non-leaf transition, we *must* update - * the routing table. */ - if (v->uv_flags & VIFF_LEAF && send_tables == 0) - send_tables = addr; - v->uv_flags &= ~VIFF_LEAF; - v->uv_leaf_timer = 0; - } - } - if (do_reset) { - reset_neighbor_state(vifi, addr); - if (!send_tables) - send_tables = addr; - } - if (send_tables) - report(ALL_ROUTES, vifi, send_tables); - - return (TRUE); -} - - -/* - * On every timer interrupt, advance the timer in each neighbor and - * group entry on every vif. - */ -void -age_vifs(void) -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *a, *prev_a, *n; - u_int32_t addr; - - for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v ) { - if (v->uv_leaf_timer && (v->uv_leaf_timer -= TIMER_INTERVAL == 0)) { - v->uv_flags |= VIFF_LEAF; - } - - for (prev_a = (struct listaddr *)&(v->uv_neighbors), - a = v->uv_neighbors; - a != NULL; - prev_a = a, a = a->al_next) { - - if ((a->al_timer += TIMER_INTERVAL) < NEIGHBOR_EXPIRE_TIME) - continue; - - /* - * Neighbor has expired; delete it from the neighbor list, - * delete it from the 'dominants' and 'subordinates arrays of - * any route entries and assume querier duties unless there is - * another neighbor with a lower IP address than mine. - */ - addr = a->al_addr; - prev_a->al_next = a->al_next; - free((char *)a); - a = prev_a; - - delete_neighbor_from_routes(addr, vifi); - - if (v->uv_neighbors == NULL) - vifs_with_neighbors--; - - v->uv_leaf_timer = LEAF_CONFIRMATION_TIME; - - if (!(v->uv_flags & VIFF_TUNNEL)) { - v->uv_flags |= VIFF_QUERIER; - for (n = v->uv_neighbors; n != NULL; n = n->al_next) { - if (ntohl(n->al_addr) < ntohl(v->uv_lcl_addr)) { - v->uv_flags &= ~VIFF_QUERIER; - } - if (!(n->al_flags & NF_LEAF)) { - v->uv_leaf_timer = 0; - } - } - } - } - } -} - -/* - * Returns the neighbor info struct for a given neighbor - */ -struct listaddr * -neighbor_info(vifi_t vifi, u_int32_t addr) -{ - struct listaddr *u; - - for (u = uvifs[vifi].uv_neighbors; u; u = u->al_next) - if (u->al_addr == addr) - return u; - - return NULL; -} - -/* - * Print the contents of the uvifs array on file 'fp'. - */ -void -dump_vifs(FILE *fp) -{ - vifi_t vifi; - struct uvif *v; - struct listaddr *a; - struct phaddr *p; - struct sioc_vif_req v_req; - - fprintf(fp, "vifs_with_neighbors = %d\n", vifs_with_neighbors); - - if (vifs_with_neighbors == 1) - fprintf(fp,"[This host is a leaf]\n\n"); - - fprintf(fp, - "\nVirtual Interface Table\n%s", - "Vif Name Local-Address "); - fprintf(fp, - "M Thr Rate Flags\n"); - - for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) { - - fprintf(fp, "%2u %6s %-15s %6s: %-18s %2u %3u %5u ", - vifi, - v->uv_name, - inet_fmt(v->uv_lcl_addr, s1), - (v->uv_flags & VIFF_TUNNEL) ? - "tunnel": - "subnet", - (v->uv_flags & VIFF_TUNNEL) ? - inet_fmt(v->uv_rmt_addr, s2) : - inet_fmts(v->uv_subnet, v->uv_subnetmask, s3), - v->uv_metric, - v->uv_threshold, - v->uv_rate_limit); - - if (v->uv_flags & VIFF_ONEWAY) fprintf(fp, " one-way"); - if (v->uv_flags & VIFF_DOWN) fprintf(fp, " down"); - if (v->uv_flags & VIFF_DISABLED) fprintf(fp, " disabled"); - if (v->uv_flags & VIFF_QUERIER) fprintf(fp, " querier"); - if (v->uv_flags & VIFF_SRCRT) fprintf(fp, " src-rt"); - if (v->uv_flags & VIFF_LEAF) fprintf(fp, " leaf"); - if (v->uv_flags & VIFF_IGMPV1) fprintf(fp, " IGMPv1"); - fprintf(fp, "\n"); - - if (v->uv_addrs != NULL) { - fprintf(fp, " alternate subnets: %s\n", - inet_fmts(v->uv_addrs->pa_subnet, v->uv_addrs->pa_subnetmask, s1)); - for (p = v->uv_addrs->pa_next; p; p = p->pa_next) { - fprintf(fp, " %s\n", - inet_fmts(p->pa_subnet, p->pa_subnetmask, s1)); - } - } - - if (v->uv_neighbors != NULL) { - fprintf(fp, " peers: %s (%d.%d) (0x%x)\n", - inet_fmt(v->uv_neighbors->al_addr, s1), - v->uv_neighbors->al_pv, v->uv_neighbors->al_mv, - v->uv_neighbors->al_flags); - for (a = v->uv_neighbors->al_next; a != NULL; a = a->al_next) { - fprintf(fp, " %s (%d.%d) (0x%x)\n", - inet_fmt(a->al_addr, s1), a->al_pv, a->al_mv, - a->al_flags); - } - } - - if (v->uv_groups != NULL) { - fprintf(fp, " groups: %-15s\n", - inet_fmt(v->uv_groups->al_addr, s1)); - for (a = v->uv_groups->al_next; a != NULL; a = a->al_next) { - fprintf(fp, " %-15s\n", - inet_fmt(a->al_addr, s1)); - } - } - if (v->uv_acl != NULL) { - struct vif_acl *acl; - - fprintf(fp, " boundaries: %-18s\n", - inet_fmts(v->uv_acl->acl_addr, v->uv_acl->acl_mask, s1)); - for (acl = v->uv_acl->acl_next; acl != NULL; acl = acl->acl_next) { - fprintf(fp, " : %-18s\n", - inet_fmts(acl->acl_addr, acl->acl_mask, s1)); - } - } - v_req.vifi = vifi; - if (ioctl(igmp_socket, SIOCGETVIFCNT, (char *)&v_req) < 0) { - logit(LOG_WARNING, 0, - "SIOCGETVIFCNT fails"); - } - else { - fprintf(fp, " pkts in : %ld\n", - v_req.icount); - fprintf(fp, " pkts out: %ld\n", - v_req.ocount); - } - fprintf(fp, "\n"); - } - fprintf(fp, "\n"); -} - -/* - * Time out record of a group membership on a vif - */ -static void -DelVif(void *arg) -{ - cbk_t *cbk = (cbk_t *)arg; - vifi_t vifi = cbk->vifi; - struct uvif *v = &uvifs[vifi]; - struct listaddr *a, **anp, *g = cbk->g; - - /* - * Group has expired - * delete all kernel cache entries with this group - */ - if (g->al_query) - DeleteTimer(g->al_query); - - delete_lclgrp(vifi, g->al_addr); - - anp = &(v->uv_groups); - while ((a = *anp) != NULL) { - if (a == g) { - *anp = a->al_next; - free((char *)a); - } else { - anp = &a->al_next; - } - } - - free(cbk); -} - -/* - * Set a timer to delete the record of a group membership on a vif. - */ -static int -SetTimer(vifi_t vifi, struct listaddr *g) -{ - cbk_t *cbk; - - cbk = (cbk_t *) malloc(sizeof(cbk_t)); - cbk->g = g; - cbk->vifi = vifi; - return timer_setTimer(g->al_timer, (cfunc_t)DelVif, (void *)cbk); -} - -/* - * Delete a timer that was set above. - */ -static int -DeleteTimer(int id) -{ - timer_clearTimer(id); - return 0; -} - -/* - * Send a group-specific query. - */ -static void -SendQuery(void *arg) -{ - cbk_t *cbk = (cbk_t *)arg; - struct uvif *v = &uvifs[cbk->vifi]; - - send_igmp(v->uv_lcl_addr, cbk->g->al_addr, - IGMP_HOST_MEMBERSHIP_QUERY, - cbk->q_time, cbk->g->al_addr, 0); - cbk->g->al_query = 0; - free(cbk); -} - -/* - * Set a timer to send a group-specific query. - */ -static int -SetQueryTimer(struct listaddr *g, vifi_t vifi, int to_expire, int q_time) -{ - cbk_t *cbk; - - cbk = (cbk_t *) malloc(sizeof(cbk_t)); - cbk->g = g; - cbk->q_time = q_time; - cbk->vifi = vifi; - return timer_setTimer(to_expire, (cfunc_t)SendQuery, (void *)cbk); -} diff --git a/gnu/dist/mrouted/vif.h b/gnu/dist/mrouted/vif.h deleted file mode 100644 index 80bbc99ccb5..00000000000 --- a/gnu/dist/mrouted/vif.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $NetBSD: vif.h,v 1.1 2002/10/01 03:31:12 itojun Exp $ */ - -/* - * The mrouted program is covered by the license in the accompanying file - * named "LICENSE". Use of the mrouted program represents acceptance of - * the terms and conditions listed in that file. - * - * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of - * Leland Stanford Junior University. - */ - -/* - * User level Virtual Interface structure - * - * A "virtual interface" is either a physical, multicast-capable interface - * (called a "phyint") or a virtual point-to-point link (called a "tunnel"). - * (Note: all addresses, subnet numbers and masks are kept in NETWORK order.) - */ -struct uvif { - u_short uv_flags; /* VIFF_ flags defined below */ - u_char uv_metric; /* cost of this vif */ - u_int uv_rate_limit; /* rate limit on this vif */ - u_char uv_threshold; /* min ttl required to forward on vif */ - u_int32_t uv_lcl_addr; /* local address of this vif */ - u_int32_t uv_rmt_addr; /* remote end-point addr (tunnels only) */ - u_int32_t uv_subnet; /* subnet number (phyints only) */ - u_int32_t uv_subnetmask; /* subnet mask (phyints only) */ - u_int32_t uv_subnetbcast;/* subnet broadcast addr (phyints only) */ - char uv_name[IFNAMSIZ]; /* interface name */ - struct listaddr *uv_groups; /* list of local groups (phyints only) */ - struct listaddr *uv_neighbors; /* list of neighboring routers */ - struct vif_acl *uv_acl; /* access control list of groups */ - int uv_leaf_timer; /* time until this vif is considrd leaf */ - struct phaddr *uv_addrs; /* Additional subnets on this vif */ -}; - -#define VIFF_KERNEL_FLAGS (VIFF_TUNNEL|VIFF_SRCRT) -#define VIFF_DOWN 0x0100 /* kernel state of interface */ -#define VIFF_DISABLED 0x0200 /* administratively disabled */ -#define VIFF_QUERIER 0x0400 /* I am the subnet's querier */ -#define VIFF_ONEWAY 0x0800 /* Maybe one way interface */ -#define VIFF_LEAF 0x1000 /* all neighbors are leaves */ -#define VIFF_IGMPV1 0x2000 /* Act as an IGMPv1 Router */ - -struct phaddr { - struct phaddr *pa_next; - u_int32_t pa_subnet; /* extra subnet */ - u_int32_t pa_subnetmask; /* netmask of extra subnet */ - u_int32_t pa_subnetbcast; /* broadcast of extra subnet */ -}; - -struct vif_acl { - struct vif_acl *acl_next; /* next acl member */ - u_int32_t acl_addr; /* Group address */ - u_int32_t acl_mask; /* Group addr. mask */ -}; - -struct listaddr { - struct listaddr *al_next; /* link to next addr, MUST BE FIRST */ - u_int32_t al_addr; /* local group or neighbor address */ - u_long al_timer; /* for timing out group or neighbor */ - time_t al_ctime; /* neighbor creation time */ - u_int32_t al_genid; /* generation id for neighbor */ - u_char al_pv; /* router protocol version */ - u_char al_mv; /* router mrouted version */ - u_long al_timerid; /* returned by set timer */ - u_long al_query; /* second query in case of leave */ - u_short al_old; /* time since heard old report */ - u_char al_flags; /* flags related to this neighbor */ -}; - -#define NF_LEAF 0x01 /* This neighbor is a leaf */ -#define NF_PRUNE 0x02 /* This neighbor understands prunes */ -#define NF_GENID 0x04 /* I supply genid & rtrlist in probe*/ -#define NF_MTRACE 0x08 /* I can understand mtrace requests */ - -#define NO_VIF ((vifi_t)MAXVIFS) /* An invalid vif index */ diff --git a/gnu/dist/mtrace/mtrace.8 b/gnu/dist/mtrace/mtrace.8 deleted file mode 100644 index 08be3632f8e..00000000000 --- a/gnu/dist/mtrace/mtrace.8 +++ /dev/null @@ -1,516 +0,0 @@ -.\" $NetBSD: mtrace.8,v 1.2 2003/02/04 23:07:31 perry Exp $ -.\" -.\" Copyright (c) 1995 by the University of Southern California -.\" All rights reserved. -.\" -.\" Permission to use, copy, modify, and distribute this software and its -.\" documentation in source and binary forms for non-commercial purposes -.\" and without fee is hereby granted, provided that the above copyright -.\" notice appear in all copies and that both the copyright notice and -.\" this permission notice appear in supporting documentation, and that -.\" any documentation, advertising materials, and other materials related -.\" to such distribution and use acknowledge that the software was -.\" developed by the University of Southern California, Information -.\" Sciences Institute. The name of the University may not be used to -.\" endorse or promote products derived from this software without -.\" specific prior written permission. -.\" -.\" THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about -.\" the suitability of this software for any purpose. THIS SOFTWARE IS -.\" PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -.\" -.\" Other copyrights might apply to parts of this software and are so -.\" noted when applicable. -.\" -.\" This manual page (but not the software) was derived from the -.\" manual page for the traceroute program which bears the following -.\" copyright notice: -.\" -.\" Copyright (c) 1988 The Regents of the University of California. -.\" All rights reserved. -.\" -.TH MTRACE 8 "May 8, 1995" -.UC 6 -.SH NAME -mtrace \- print multicast path from a source to a receiver -.SH SYNOPSIS -.B mtrace -[ -.B \-g -.I gateway -] [ -.B \-i -.I if_addr -] [ -.B \-l -] [ -.B \-M -] [ -.B \-m -.I max_hops -] [ -.B \-n -] [ -.B \-p -] [ -.B \-q -.I nqueries -] [ -.B \-r -.I resp_dest -] [ -.B \-s -] [ -.B \-S -.I stat_int -] [ -.B \-t -.I ttl -] [ -.B \-v -] [ -.B \-w -.I waittime -] -.I source -[ -.I receiver -] [ -.I group -] -.SH DESCRIPTION -Assessing problems in the distribution of IP multicast traffic -can be difficult. -.B mtrace -uses a tracing feature implemented in multicast routers -.RB ( mrouted -version 3.3 and later) that is -accessed via an extension to the IGMP protocol. A trace query is -passed hop-by-hop along the reverse path from the -.I receiver -to the -.IR source , -collecting hop addresses, packet counts, and routing error conditions -along the path, and then the response is returned to the requestor. -.PP -The only required parameter is the -.I source -host name or address. The default -.I receiver -is the host running mtrace, and the default -.I group -is "MBone Audio" (224.2.0.1), which is sufficient if packet loss -statistics for a particular multicast group are not needed. These two -optional parameters may be specified to test the path to some other -receiver in a particular group, subject to some constraints as -detailed below. The two parameters can be distinguished because the -.I receiver -is a unicast address and the -.I group -is a multicast address. -.PP -NOTE: For Solaris 2.4/2.5, if the multicast interface is not the default -interface, the -i option must be used to set the local address. -.SH OPTIONS -.TP 8 8 -.BI \-g\ gwy -Send the trace query via unicast directly to the multicast router -.I gwy -rather than multicasting the query. -This must be the last-hop router on the path from the intended -.I source -to the -.IR receiver . -.RS 8 -.TP 12 12 -.I CAUTION!! -Versions 3.3 and 3.5 of -.B mrouted -will crash if a trace query is received via a -unicast packet and -.B mrouted -has no route for the -.I source -address. Therefore, do not use the -.B \-g -option unless the target -.B mrouted -has been verified to be 3.4 or newer than 3.5. -.RE -.TP 8 8 -.BI \-i\ addr -Use -.I addr -as the local interface address (on a multi-homed host) for sending the -trace query and as the default for the -.I receiver -and the response destination. -.TP 8 8 -.B \-l -Loop indefinitely printing packet rate and loss statistics for the -multicast path every 10 seconds (see -.B \-S -.IR stat_int ). -.TP 8 8 -.B \-M -Always send the response using multicast rather than attempting -unicast first. -.TP 8 8 -.BI \-m\ n -Set to -.I n -the maximum number of hops that will be traced from the -.I receiver -back toward the -.IR source . -The default is 32 hops (infinity for the DVMRP routing protocol). -.TP 8 8 -.B \-n -Print hop addresses numerically rather than symbolically and numerically -(saves a nameserver address-to-name lookup for each router found on the -path). -.TP 8 8 -.BI \-q\ n -Set the maximum number of query attempts for any hop to -.IR n . -The default is 3. -.TP 8 8 -.B \-p -Listen passively for multicast responses from traces initiated by -others. This works best when run on a multicast router. -.TP 8 8 -.BI \-r\ host -Send the trace response to -.I host -rather than to the host on which -.B mtrace -is being run, or to a multicast address other than the one registered -for this purpose (224.0.1.32). -.TP 8 8 -.B \-s -Print a short form output including only the multicast path and not -the packet rate and loss statistics. -.TP 8 8 -.BI \-S\ n -Change the interval between statistics gathering traces to -.I n -seconds (default 10 seconds). -.TP 8 8 -.BI \-t\ ttl -Set the -.I ttl -(time-to-live, or number of hops) for multicast trace queries and -responses. The default is 64, except for local queries to the "all -routers" multicast group which use ttl 1. -.TP 8 8 -.B \-v -Verbose mode; show hop times on the initial trace and statistics display. -.TP 8 8 -.BI \-w\ n -Set the time to wait for a trace response to -.I n -seconds (default 3 seconds). -.SH USAGE -.SS How It Works -The technique used by the -.B traceroute -tool to trace unicast network paths will not work for IP multicast -because ICMP responses are specifically forbidden for multicast traffic. -Instead, a tracing feature has been built into the multicast routers. -This technique has the advantage that additional information about -packet rates and losses can be accumulated while the number of packets -sent is minimized. -.PP -Since multicast uses -reverse path forwarding, the trace is run backwards from the -.I receiver -to the -.IR source . -A trace query packet is sent to the last -hop multicast router (the leaf router for the desired -.I receiver -address). The last hop router builds a trace response packet, fills in -a report for its hop, and forwards the trace packet using unicast to -the router it believes is the previous hop for packets originating -from the specified -.IR source . -Each router along the path adds its report and forwards the packet. -When the trace response packet reaches the first hop router (the router -that is directly connected to the source's net), that router sends the -completed response to the response destination address specified in -the trace query. -.PP -If some multicast router along the path does not implement the -multicast traceroute feature or if there is some outage, then no -response will be returned. To solve this problem, the trace query -includes a maximum hop count field to limit the number of hops traced -before the response is returned. That allows a partial path to be -traced. -.PP -The reports inserted by each router contain not only the address of -the hop, but also the ttl required to forward and some flags to indicate -routing errors, plus counts of the total number of packets on the -incoming and outgoing interfaces and those forwarded for the specified -.IR group . -Taking differences in these counts for two traces separated in time -and comparing the output packet counts from one hop with the input -packet counts of the next hop allows the calculation of packet rate -and packet loss statistics for each hop to isolate congestion -problems. -.SS Finding the Last-Hop Router -The trace query must be sent to the multicast router which is the -last hop on the path from the -.I source -to the -.IR receiver . -If the receiver is on the local subnet (as determined using the subnet -mask), then the default method is to multicast the trace query to -all-routers.mcast.net (224.0.0.2) with a ttl of 1. Otherwise, the -trace query is multicast to the -.I group -address since the last hop router will be a member of that group if -the receiver is. Therefore it is necessary to specify a group that -the intended receiver has joined. This multicast is sent with a -default ttl of 64, which may not be sufficient for all cases (changed -with the -.B \-t -option). -If the last hop router is known, it may also be addressed directly -using the -.B \-g -option). Alternatively, if it is desired to trace a group that the -receiver has not joined, but it is known that the last-hop router is a -member of another group, the -.B \-g -option may also be used to specify a different multicast address for the -trace query. -.PP -When tracing from a multihomed host or router, the default receiver -address may not be the desired interface for the path from the source. -In that case, the desired interface should be specified explicitly as -the -.IR receiver . -.SS Directing the Response -By default, -.B mtrace -first attempts to trace the full reverse path, unless the number of -hops to trace is explicitly set with the -.B \-m -option. If there is no response within a 3 second timeout interval -(changed with the -.B \-w -option), a "*" is printed and the probing switches to hop-by-hop mode. -Trace queries are issued starting with a maximum hop count of one and -increasing by one until the full path is traced or no response is -received. At each hop, multiple probes are sent (default is three, -changed with -.B \-q -option). The first half of the attempts (default is one) are made with -the unicast address of the host running -.B mtrace -as the destination for the response. Since the unicast route may be -blocked, the remainder of attempts request that the response be -multicast to mtrace.mcast.net (224.0.1.32) with the ttl set to 32 more -than what's needed to pass the thresholds seen so far along the path -to the receiver. For the last quarter of the attempts (default is -one), the ttl is increased by another 32 each time up to a maximum of -192. Alternatively, the ttl may be set explicitly with the -.B \-t -option and/or the initial unicast attempts can be forced to use -multicast instead with the -.B \-M -option. For each attempt, if no response is received within the -timeout, a "*" is printed. After the specified number of attempts -have failed, -.B mtrace -will try to query the next hop router with a DVMRP_ASK_NEIGHBORS2 -request (as used by the -.B mrinfo -program) to see what kind of router it is. -.SH EXAMPLES -The output of -.B mtrace -is in two sections. The first section is a short listing of the hops -in the order they are queried, that is, in the reverse of the order -from the -.I source -to the -.IR receiver . -For each hop, a line is printed showing the hop number (counted -negatively to indicate that this is the reverse path); the multicast -routing protocol (DVMRP, MOSPF, PIM, etc.); the threshold required to -forward data (to the previous hop in the listing as indicated by the -up-arrow character); and the cumulative delay for the query to reach -that hop (valid only if the clocks are synchronized). This first -section ends with a line showing the round-trip time which measures -the interval from when the query is issued until the response is -received, both derived from the local system clock. A sample use and -output might be: -.PP -.nf -.ft C -oak.isi.edu 80# mtrace -l caraway.lcs.mit.edu 224.2.0.3 -Mtrace from 18.26.0.170 to 128.9.160.100 via group 224.2.0.3 -Querying full reverse path... - 0 oak.isi.edu (128.9.160.100) - -1 cub.isi.edu (128.9.160.153) DVMRP thresh^ 1 3 ms - -2 la.dart.net (140.173.128.1) DVMRP thresh^ 1 14 ms - -3 dc.dart.net (140.173.64.1) DVMRP thresh^ 1 50 ms - -4 bbn.dart.net (140.173.32.1) DVMRP thresh^ 1 63 ms - -5 mit.dart.net (140.173.48.2) DVMRP thresh^ 1 71 ms - -6 caraway.lcs.mit.edu (18.26.0.170) -Round trip time 124 ms -.fi -.PP -The second section provides a pictorial view of the path in the -forward direction with data flow indicated by arrows pointing downward -and the query path indicated by arrows pointing upward. For each hop, -both the entry and exit addresses of the router are shown if -different, along with the initial ttl required on the packet in order -to be forwarded at this hop and the propagation delay across the hop -assuming that the routers at both ends have synchronized clocks. The -right half of this section is composed of several columns of -statistics in two groups. Within each group, the columns are the -number of packets lost, the number of packets sent, the percentage -lost, and the average packet rate at each hop. These statistics are -calculated from differences between traces and from hop to hop as -explained above. The first group shows the statistics for all traffic -flowing out the interface at one hop and in the interface at the next -hop. The second group shows the statistics only for traffic forwarded -from the specified -.I source -to the specified -.IR group . -.PP -These statistics are shown on one or two lines for each hop. Without -any options, this second section of the output is printed only once, -approximately 10 seconds after the initial trace. One line is shown -for each hop showing the statistics over that 10-second period. If -the -.B \-l -option is given, the second section is repeated every 10 seconds and -two lines are shown for each hop. The first line shows the statistics -for the last 10 seconds, and the second line shows the cumulative -statistics over the period since the initial trace, which is 101 -seconds in the example below. The second section of the output is -omitted if the -.B \-s -option is set. -.ie t \{\ -.ft C -. ie \w'i'<>\w'm' \{\" looks like this is not proper Courier font -(If this example is not properly columned with a fixed-width font, get -.B groff -and try again.) -. \} -.\} -.PP -.ft C -.nf -Waiting to accumulate statistics... Results after 101 seconds: - - Source Response Dest Packet Statistics For Only For Traffic -18.26.0.170 128.9.160.100 All Multicast Traffic From 18.26.0.170 - | __/ rtt 125 ms Lost/Sent = Pct Rate To 224.2.0.3 - v / hop 65 ms --------------------- ------------------ -18.26.0.144 -140.173.48.2 mit.dart.net - | ^ ttl 1 0/6 = --% 0 pps 0/2 = --% 0 pps - v | hop 8 ms 1/52 = 2% 0 pps 0/18 = 0% 0 pps -140.173.48.1 -140.173.32.1 bbn.dart.net - | ^ ttl 2 0/6 = --% 0 pps 0/2 = --% 0 pps - v | hop 12 ms 1/52 = 2% 0 pps 0/18 = 0% 0 pps -140.173.32.2 -140.173.64.1 dc.dart.net - | ^ ttl 3 0/271 = 0% 27 pps 0/2 = --% 0 pps - v | hop 34 ms -1/2652 = 0% 26 pps 0/18 = 0% 0 pps -140.173.64.2 -140.173.128.1 la.dart.net - | ^ ttl 4 -2/831 = 0% 83 pps 0/2 = --% 0 pps - v | hop 11 ms -3/8072 = 0% 79 pps 0/18 = 0% 0 pps -140.173.128.2 -128.9.160.153 cub.isi.edu - | \\__ ttl 5 833 83 pps 2 0 pps - v \\ hop -8 ms 8075 79 pps 18 0 pps -128.9.160.100 128.9.160.100 - Receiver Query Source -.fi -.PP -Because the packet counts may be changing as the trace query is -propagating, there may be small errors (off by 1 or 2) in these -statistics. However, those errors should not accumulate, so the -cumulative statistics line should increase in accuracy as a new trace -is run every 10 seconds. There are two sources of larger errors, both -of which show up as negative losses: -.LP -.RS -.PD 0 -.TP 3 -\(bu -If the input to a node is from a multi-access network with more than -one other node attached, then the input count will be (close to) the -sum of the output counts from all the attached nodes, but the output -count from the previous hop on the traced path will be only part of -that. Hence the output count minus the input count will be negative. -.TP 3 -\(bu -In release 3.3 of the DVMRP multicast forwarding software for SunOS -and other systems, a multicast packet generated on a router will be -counted as having come in an interface even though it did not. This -creates the negative loss that can be seen in the example above. -.PD -.RE -.LP -Note that these negative losses may mask positive losses. -.PP -In the example, there is also one negative hop time. This simply -indicates a lack of synchronization between the system clocks across -that hop. This example also illustrates how the percentage loss is -shown as two dashes when the number of packets sent is less than 10 -because the percentage would not be statistically valid. -.PP -A second example shows a trace to a receiver that is not local; the -query is sent to the last-hop router with the -.B \-g -option. In this example, the trace of the full reverse path resulted -in no response because there was a node running an old version of -.B mrouted -that did not implement the multicast traceroute function, so -.B mtrace -switched to hop-by-hop mode. The \*(lqRoute pruned\*(rq error code -indicates that traffic for group 224.2.143.24 would not be forwarded. -.PP -.nf -.ft C -oak.isi.edu 108# mtrace -g 140.173.48.2 204.62.246.73 \\ - butter.lcs.mit.edu 224.2.143.24 -Mtrace from 204.62.246.73 to 18.26.0.151 via group 224.2.143.24 -Querying full reverse path... * switching to hop-by-hop: - 0 butter.lcs.mit.edu (18.26.0.151) - -1 jam.lcs.mit.edu (18.26.0.144) DVMRP thresh^ 1 33 ms Route pruned - -2 bbn.dart.net (140.173.48.1) DVMRP thresh^ 1 36 ms - -3 dc.dart.net (140.173.32.2) DVMRP thresh^ 1 44 ms - -4 darpa.dart.net (140.173.240.2) DVMRP thresh^ 16 47 ms - -5 * * * noc.hpc.org (192.187.8.2) [mrouted 2.2] didn't respond -Round trip time 95 ms -.fi -.SH AUTHOR -Implemented by Steve Casner based on an initial prototype written by -Ajit Thyagarajan. The multicast traceroute mechanism was designed by -Van Jacobson with help from Steve Casner, Steve Deering, Dino -Farinacci, and Deb Agrawal; it was implemented in -.B mrouted -by Ajit Thyagarajan and Bill Fenner. The option syntax and the output -format of -.B mtrace -are modeled after the unicast -.B traceroute -program written by Van Jacobson. -.SH SEE ALSO -.BR mrouted (8) , -.BR mrinfo (8) , -.BR map-mbone (8) , -.BR traceroute (8) diff --git a/gnu/dist/mtrace/mtrace.c b/gnu/dist/mtrace/mtrace.c deleted file mode 100644 index 2c6775f5323..00000000000 --- a/gnu/dist/mtrace/mtrace.c +++ /dev/null @@ -1,1758 +0,0 @@ -/* $NetBSD: mtrace.c,v 1.2 2002/12/06 16:03:41 thorpej Exp $ */ - -/* - * mtrace.c - * - * This tool traces the branch of a multicast tree from a source to a - * receiver for a particular multicast group and gives statistics - * about packet rate and loss for each hop along the path. It can - * usually be invoked just as - * - * mtrace source - * - * to trace the route from that source to the local host for a default - * group when only the route is desired and not group-specific packet - * counts. See the usage line for more complex forms. - * - * - * Released 4 Apr 1995. This program was adapted by Steve Casner - * (USC/ISI) from a prototype written by Ajit Thyagarajan (UDel and - * Xerox PARC). It attempts to parallel in command syntax and output - * format the unicast traceroute program written by Van Jacobson (LBL) - * for the parts where that makes sense. - * - * Copyright (c) 1995 by the University of Southern California - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation in source and binary forms for non-commercial purposes - * and without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both the copyright notice and - * this permission notice appear in supporting documentation, and that - * any documentation, advertising materials, and other materials related - * to such distribution and use acknowledge that the software was - * developed by the University of Southern California, Information - * Sciences Institute. The name of the University may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about - * the suitability of this software for any purpose. THIS SOFTWARE IS - * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Other copyrights might apply to parts of this software and are so - * noted when applicable. - * - * In particular, parts of the prototype version of this program may - * have been derived from mrouted programs sources covered by the - * license in the accompanying file named "LICENSE". - */ - -#include <sys/cdefs.h> -#ifndef lint -__RCSID("$NetBSD: mtrace.c,v 1.2 2002/12/06 16:03:41 thorpej Exp $"); -#endif - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <poll.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <ctype.h> -#include <memory.h> -#include <netdb.h> -#include <string.h> -#include "defs.h" - -#include <stdarg.h> -#ifdef SUNOS5 -#include <sys/systeminfo.h> -#endif - -#define DEFAULT_TIMEOUT 3 /* How long to wait before retrying requests */ -#define DEFAULT_RETRIES 3 /* How many times to try */ -#define MAXHOPS UNREACHABLE /* Don't need more hops than max metric */ -#define UNICAST_TTL 255 /* TTL for unicast response */ -#define MULTICAST_TTL1 64 /* Default TTL for multicast query/response */ -#define MULTICAST_TTL_INC 32 /* TTL increment for increase after timeout */ -#define MULTICAST_TTL_MAX 192 /* Maximum TTL allowed (protect low-BW links */ - -struct resp_buf { - u_long qtime; /* Time query was issued */ - u_long rtime; /* Time response was received */ - int len; /* Number of reports or length of data */ - struct igmp igmp; /* IGMP header */ - union { - struct { - struct tr_query q; /* Query/response header */ - struct tr_resp r[MAXHOPS]; /* Per-hop reports */ - } t; - char d[MAX_DVMRP_DATA_LEN]; /* Neighbor data */ - } u; -} base, incr[2]; - -#define qhdr u.t.q -#define resps u.t.r -#define ndata u.d - -char names[MAXHOPS][40]; -int reset[MAXHOPS]; /* To get around 3.4 bug, ... */ -int swaps[MAXHOPS]; /* To get around 3.6 bug, ... */ - -int timeout = DEFAULT_TIMEOUT; -int nqueries = DEFAULT_RETRIES; -int numeric = FALSE; -int debug = 0; -int passive = FALSE; -int multicast = FALSE; -int statint = 10; -int verbose = 0; - -u_int32_t defgrp; /* Default group if not specified */ -u_int32_t query_cast; /* All routers multicast addr */ -u_int32_t resp_cast; /* Mtrace response multicast addr */ - -u_int32_t lcl_addr = 0; /* This host address, in NET order */ -u_int32_t dst_netmask; /* netmask to go with qdst */ - -/* - * Query/response parameters, all initialized to zero and set later - * to default values or from options. - */ -u_int32_t qsrc = 0; /* Source address in the query */ -u_int32_t qgrp = 0; /* Group address in the query */ -u_int32_t qdst = 0; /* Destination (receiver) address in query */ -u_char qno = 0; /* Max number of hops to query */ -u_int32_t raddr = 0; /* Address where response should be sent */ -int qttl = 0; /* TTL for the query packet */ -u_char rttl = 0; /* TTL for the response packet */ -u_int32_t gwy = 0; /* User-supplied last-hop router address */ -u_int32_t tdst = 0; /* Address where trace is sent (last-hop) */ - -vifi_t numvifs; /* to keep loader happy */ - /* (see kern.c) */ - -u_long byteswap(u_long); -char * inet_name(u_int32_t addr); -u_int32_t host_addr(char *name); -/* u_int is promoted u_char */ -char * proto_type(u_int type); -char * flag_type(u_int type); - -u_int32_t get_netmask(int s, u_int32_t dst); -int get_ttl(struct resp_buf *buf); -int t_diff(u_long a, u_long b); -u_long fixtime(u_long time); -int send_recv(u_int32_t dst, int type, int code, - int tries, struct resp_buf *save); -char * print_host(u_int32_t addr); -char * print_host2(u_int32_t addr1, u_int32_t addr2); -void print_trace(int index, struct resp_buf *buf); -int what_kind(struct resp_buf *buf, char *why); -char * scale(int *hop); -void stat_line(struct tr_resp *r, struct tr_resp *s, - int have_next, int *res); -void fixup_stats(struct resp_buf *base, - struct resp_buf *prev, - struct resp_buf *new); -int print_stats(struct resp_buf *base, - struct resp_buf *prev, - struct resp_buf *new); -void check_vif_state(void); -void passive_mode(void); - -int main(int argc, char *argv[]); -/* logit() prototyped in defs.h */ - - -char * -inet_name(u_int32_t addr) -{ - struct hostent *e; - - e = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); - - return e ? e->h_name : "?"; -} - - -u_int32_t -host_addr(char *name) -{ - struct hostent *e = (struct hostent *)0; - u_int32_t addr; - int i, dots = 3; - char buf[40]; - char *ip = name; - char *op = buf; - - /* - * Undo BSD's favor -- take fewer than 4 octets as net/subnet address - * if the name is all numeric. - */ - for (i = sizeof(buf) - 7; i > 0; --i) { - if (*ip == '.') --dots; - else if (*ip == '\0') break; - else if (!isdigit(*ip)) dots = 0; /* Not numeric, don't add zeroes */ - *op++ = *ip++; - } - for (i = 0; i < dots; ++i) { - *op++ = '.'; - *op++ = '0'; - } - *op = '\0'; - - if (dots <= 0) e = gethostbyname(name); - if (e) memcpy((char *)&addr, e->h_addr_list[0], sizeof(addr)); - else { - addr = inet_addr(buf); - if (addr == -1) { - addr = 0; - printf("Could not parse %s as host name or address\n", name); - } - } - return addr; -} - - -char * -proto_type(u_int type) -{ - static char buf[80]; - - switch (type) { - case PROTO_DVMRP: - return ("DVMRP"); - case PROTO_MOSPF: - return ("MOSPF"); - case PROTO_PIM: - return ("PIM"); - case PROTO_CBT: - return ("CBT"); - case PROTO_PIM_SPEC: - return ("PIM-special"); - case PROTO_PIM_STAT: - return ("PIM-static"); - case PROTO_DVMRP_STAT: - return ("DVMRP-static"); - case PROTO_PIM_MBGP: - return ("PIM/MBGP"); - default: - (void)snprintf(buf, sizeof buf, "Unknown protocol code %d", type); - return (buf); - } -} - - -char * -flag_type(u_int type) -{ - static char buf[80]; - - switch (type) { - case TR_NO_ERR: - return (""); - case TR_WRONG_IF: - return ("Wrong interface"); - case TR_PRUNED: - return ("Prune sent upstream"); - case TR_OPRUNED: - return ("Output pruned"); - case TR_SCOPED: - return ("Hit scope boundary"); - case TR_NO_RTE: - return ("No route"); - case TR_OLD_ROUTER: - return ("Next router no mtrace"); - case TR_NO_FWD: - return ("Not forwarding"); - case TR_NO_SPACE: - return ("No space in packet"); - case TR_RP_OR_CORE: - return ("RP/Core"); - case TR_RPF_INT: - return ("Trace packet on RPT interface"); - case TR_NO_MULTICAST: - return ("Trace packet on non-MC interface"); - case TR_ADMIN_DENY: - return ("Trace admin-denied"); - default: - (void)snprintf(buf, sizeof buf, "Unknown error code %d", type); - return (buf); - } -} - -/* - * If destination is on a local net, get the netmask, else set the - * netmask to all ones. There are two side effects: if the local - * address was not explicitly set, and if the destination is on a - * local net, use that one; in either case, verify that the local - * address is valid. - */ - -u_int32_t -get_netmask(int s, u_int32_t dst) -{ - unsigned int i; - char ifbuf[5000]; - struct ifconf ifc; - struct ifreq *ifr; - u_int32_t if_addr, if_mask; - u_int32_t retval = 0xFFFFFFFF; - int found = FALSE; - - ifc.ifc_buf = ifbuf; - ifc.ifc_len = sizeof(ifbuf); - if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) { - perror("ioctl (SIOCGIFCONF)"); - return (retval); - } - for (i = 0; i < ifc.ifc_len; ) { - ifr = (struct ifreq *)((char *)ifc.ifc_req + i); - i += sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; - if_addr = ((struct sockaddr_in *)&(ifr->ifr_addr))->sin_addr.s_addr; - if (ioctl(s, SIOCGIFNETMASK, (char *)ifr) >= 0) { - if_mask = ((struct sockaddr_in *)&(ifr->ifr_addr))->sin_addr.s_addr; - if ((dst & if_mask) == (if_addr & if_mask)) { - retval = if_mask; - if (lcl_addr == 0) lcl_addr = if_addr; - } - } - if (lcl_addr == if_addr) found = TRUE; - } - if (!found && lcl_addr != 0) { - printf("Interface address is not valid\n"); - exit(1); - } - return (retval); -} - - -int -get_ttl(struct resp_buf *buf) -{ - int rno; - struct tr_resp *b; - u_int ttl; - - if (buf && (rno = buf->len) > 0) { - b = buf->resps + rno - 1; - ttl = b->tr_fttl; - - while (--rno > 0) { - --b; - if (ttl < b->tr_fttl) ttl = b->tr_fttl; - else ++ttl; - } - ttl += MULTICAST_TTL_INC; - if (ttl < MULTICAST_TTL1) ttl = MULTICAST_TTL1; - if (ttl > MULTICAST_TTL_MAX) ttl = MULTICAST_TTL_MAX; - return (ttl); - } else return(MULTICAST_TTL1); -} - -/* - * Calculate the difference between two 32-bit NTP timestamps and return - * the result in milliseconds. - */ -int -t_diff(u_long a, u_long b) -{ - int d = a - b; - - return ((d * 125) >> 13); -} - -/* - * Fixup for incorrect time format in 3.3 mrouted. - * This is possible because (JAN_1970 mod 64K) is quite close to 32K, - * so correct and incorrect times will be far apart. - */ -u_long -fixtime(u_long time) -{ - if (abs((int)(time-base.qtime)) > 0x3FFFFFFF) - time = ((time & 0xFFFF0000) + (JAN_1970 << 16)) + - ((time & 0xFFFF) << 14) / 15625; - return (time); -} - -/* - * Swap bytes for poor little-endian machines that don't byte-swap - */ -u_long -byteswap(u_long v) -{ - return ((v << 24) | ((v & 0xff00) << 8) | - ((v >> 8) & 0xff00) | (v >> 24)); -} - -int -send_recv(u_int32_t dst, int type, int code, int tries, struct resp_buf *save) -{ - struct pollfd set[1]; - struct timeval tq, tr, tv; - struct ip *ip; - struct igmp *igmp; - struct tr_query *query, *rquery; - int ipdatalen, iphdrlen, igmpdatalen; - u_int32_t local, group; - int datalen; - int count, recvlen, dummy = 0; - int len; - int i; - - if (type == IGMP_MTRACE_QUERY) { - group = qgrp; - datalen = sizeof(struct tr_query); - } else { - group = htonl(MROUTED_LEVEL); - datalen = 0; - } - if (IN_MULTICAST(ntohl(dst))) local = lcl_addr; - else local = INADDR_ANY; - - /* - * If the reply address was not explictly specified, start off - * with the unicast address of this host. Then, if there is no - * response after trying half the tries with unicast, switch to - * the standard multicast reply address. If the TTL was also not - * specified, set a multicast TTL and if needed increase it for the - * last quarter of the tries. - */ - query = (struct tr_query *)(send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN); - query->tr_raddr = raddr ? raddr : multicast ? resp_cast : lcl_addr; - query->tr_rttl = rttl ? rttl : - IN_MULTICAST(ntohl(query->tr_raddr)) ? get_ttl(save) : UNICAST_TTL; - query->tr_src = qsrc; - query->tr_dst = qdst; - - for (i = tries ; i > 0; --i) { - if (tries == nqueries && raddr == 0) { - if (i == ((nqueries + 1) >> 1)) { - query->tr_raddr = resp_cast; - if (rttl == 0) query->tr_rttl = get_ttl(save); - } - if (i <= ((nqueries + 3) >> 2) && rttl == 0) { - query->tr_rttl += MULTICAST_TTL_INC; - if (query->tr_rttl > MULTICAST_TTL_MAX) - query->tr_rttl = MULTICAST_TTL_MAX; - } - } - - /* - * Change the qid for each request sent to avoid being confused - * by duplicate responses - */ -#ifdef SYSV - query->tr_qid = ((u_int32_t)lrand48() >> 8); -#else - query->tr_qid = ((u_int32_t)random() >> 8); -#endif - - /* - * Set timer to calculate delays, then send query - */ - gettimeofday(&tq, 0); - send_igmp(local, dst, type, code, group, datalen); - - /* - * Wait for response, discarding false alarms - */ - set[0].fd = igmp_socket; - set[0].events = POLLIN; - while (TRUE) { - gettimeofday(&tv, 0); - tv.tv_sec = tq.tv_sec + timeout - tv.tv_sec; - tv.tv_usec = tq.tv_usec - tv.tv_usec; - if (tv.tv_usec < 0) tv.tv_usec += 1000000L, --tv.tv_sec; - if (tv.tv_sec < 0) tv.tv_sec = tv.tv_usec = 0; - - count = poll(set, 1, tv.tv_sec * 1000 + tv.tv_usec / 1000); - - if (count < 0) { - if (errno != EINTR) perror("select"); - continue; - } else if (count == 0) { - printf("* "); - fflush(stdout); - break; - } - - gettimeofday(&tr, 0); - recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, - 0, (struct sockaddr *)0, &dummy); - - if (recvlen <= 0) { - if (recvlen && errno != EINTR) perror("recvfrom"); - continue; - } - - if (recvlen < sizeof(struct ip)) { - fprintf(stderr, - "packet too short (%u bytes) for IP header", recvlen); - continue; - } - ip = (struct ip *) recv_buf; - if (ip->ip_p == 0) /* ignore cache creation requests */ - continue; - - iphdrlen = ip->ip_hl << 2; - ipdatalen = ip->ip_len; - if (iphdrlen + ipdatalen != recvlen) { - fprintf(stderr, - "packet shorter (%u bytes) than hdr+data len (%u+%u)\n", - recvlen, iphdrlen, ipdatalen); - continue; - } - - igmp = (struct igmp *) (recv_buf + iphdrlen); - igmpdatalen = ipdatalen - IGMP_MINLEN; - if (igmpdatalen < 0) { - fprintf(stderr, - "IP data field too short (%u bytes) for IGMP from %s\n", - ipdatalen, inet_fmt(ip->ip_src.s_addr, s1)); - continue; - } - - switch (igmp->igmp_type) { - - case IGMP_DVMRP: - if (igmp->igmp_code != DVMRP_NEIGHBORS2) continue; - len = igmpdatalen; - /* - * Accept DVMRP_NEIGHBORS2 response if it comes from the - * address queried or if that address is one of the local - * addresses in the response. - */ - if (ip->ip_src.s_addr != dst) { - u_int32_t *p = (u_int32_t *)(igmp + 1); - u_int32_t *ep = p + (len >> 2); - while (p < ep) { - u_int32_t laddr = *p++; - int n = ntohl(*p++) & 0xFF; - if (laddr == dst) { - ep = p + 1; /* ensure p < ep after loop */ - break; - } - p += n; - } - if (p >= ep) continue; - } - break; - - case IGMP_MTRACE_QUERY: /* For backward compatibility with 3.3 */ - case IGMP_MTRACE_REPLY: - if (igmpdatalen <= QLEN) continue; - if ((igmpdatalen - QLEN)%RLEN) { - printf("packet with incorrect datalen\n"); - continue; - } - - /* - * Ignore responses that don't match query. - */ - rquery = (struct tr_query *)(igmp + 1); - if (rquery->tr_qid != query->tr_qid) continue; - if (rquery->tr_src != qsrc) continue; - if (rquery->tr_dst != qdst) continue; - len = (igmpdatalen - QLEN)/RLEN; - - /* - * Ignore trace queries passing through this node when - * mtrace is run on an mrouter that is in the path - * (needed only because IGMP_MTRACE_QUERY is accepted above - * for backward compatibility with multicast release 3.3). - */ - if (igmp->igmp_type == IGMP_MTRACE_QUERY) { - struct tr_resp *r = (struct tr_resp *)(rquery+1) + len - 1; - u_int32_t smask; - - VAL_TO_MASK(smask, r->tr_smask); - if (len < code && (r->tr_inaddr & smask) != (qsrc & smask) - && r->tr_rmtaddr != 0 && !(r->tr_rflags & 0x80)) - continue; - } - - /* - * A match, we'll keep this one. - */ - if (len > code) { - fprintf(stderr, - "Num hops received (%d) exceeds request (%d)\n", - len, code); - } - rquery->tr_raddr = query->tr_raddr; /* Insure these are */ - rquery->tr_rttl = query->tr_rttl; /* as we sent them */ - break; - - default: - continue; - } - - /* - * Most of the sanity checking done at this point. - * Return this packet we have been waiting for. - */ - if (save) { - save->qtime = ((tq.tv_sec + JAN_1970) << 16) + - (tq.tv_usec << 10) / 15625; - save->rtime = ((tr.tv_sec + JAN_1970) << 16) + - (tr.tv_usec << 10) / 15625; - save->len = len; - bcopy((char *)igmp, (char *)&save->igmp, ipdatalen); - } - return (recvlen); - } - } - return (0); -} - -/* - * Most of this code is duplicated elsewhere. I'm not sure if - * the duplication is absolutely required or not. - * - * Ideally, this would keep track of ongoing statistics - * collection and print out statistics. (& keep track - * of h-b-h traces and only print the longest) For now, - * it just snoops on what traces it can. - */ -void -passive_mode(void) -{ - struct timeval tr; - struct ip *ip; - struct igmp *igmp; - struct tr_resp *r; - int ipdatalen, iphdrlen, igmpdatalen; - int len, recvlen, dummy = 0; - u_int32_t smask; - - if (raddr) { - if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, INADDR_ANY); - } else k_join(htonl(0xE0000120), INADDR_ANY); - - while (1) { - recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE, - 0, (struct sockaddr *)0, &dummy); - gettimeofday(&tr,0); - - if (recvlen <= 0) { - if (recvlen && errno != EINTR) perror("recvfrom"); - continue; - } - - if (recvlen < sizeof(struct ip)) { - fprintf(stderr, - "packet too short (%u bytes) for IP header", recvlen); - continue; - } - ip = (struct ip *) recv_buf; - if (ip->ip_p == 0) /* ignore cache creation requests */ - continue; - - iphdrlen = ip->ip_hl << 2; - ipdatalen = ip->ip_len; - if (iphdrlen + ipdatalen != recvlen) { - fprintf(stderr, - "packet shorter (%u bytes) than hdr+data len (%u+%u)\n", - recvlen, iphdrlen, ipdatalen); - continue; - } - - igmp = (struct igmp *) (recv_buf + iphdrlen); - igmpdatalen = ipdatalen - IGMP_MINLEN; - if (igmpdatalen < 0) { - fprintf(stderr, - "IP data field too short (%u bytes) for IGMP from %s\n", - ipdatalen, inet_fmt(ip->ip_src.s_addr, s1)); - continue; - } - - switch (igmp->igmp_type) { - - case IGMP_MTRACE_QUERY: /* For backward compatibility with 3.3 */ - case IGMP_MTRACE_REPLY: - if (igmpdatalen < QLEN) continue; - if ((igmpdatalen - QLEN)%RLEN) { - printf("packet with incorrect datalen\n"); - continue; - } - - len = (igmpdatalen - QLEN)/RLEN; - - break; - - default: - continue; - } - - base.qtime = ((tr.tv_sec + JAN_1970) << 16) + - (tr.tv_usec << 10) / 15625; - base.rtime = ((tr.tv_sec + JAN_1970) << 16) + - (tr.tv_usec << 10) / 15625; - base.len = len; - bcopy((char *)igmp, (char *)&base.igmp, ipdatalen); - /* - * If the user specified which traces to monitor, - * only accept traces that correspond to the - * request - */ - if ((qsrc != 0 && qsrc != base.qhdr.tr_src) || - (qdst != 0 && qdst != base.qhdr.tr_dst) || - (qgrp != 0 && qgrp != igmp->igmp_group.s_addr)) - continue; - - printf("Mtrace from %s to %s via group %s (mxhop=%d)\n", - inet_fmt(base.qhdr.tr_dst, s1), inet_fmt(base.qhdr.tr_src, s2), - inet_fmt(igmp->igmp_group.s_addr, s3), igmp->igmp_code); - if (len == 0) - continue; - printf(" 0 "); - print_host(base.qhdr.tr_dst); - printf("\n"); - print_trace(1, &base); - r = base.resps + base.len - 1; - VAL_TO_MASK(smask, r->tr_smask); - if ((r->tr_inaddr & smask) == (base.qhdr.tr_src & smask)) { - printf("%3d ", -(base.len+1)); - print_host(base.qhdr.tr_src); - printf("\n"); - } else if (r->tr_rmtaddr != 0) { - printf("%3d ", -(base.len+1)); - what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ? - "doesn't support mtrace" - : "is the next hop"); - } - printf("\n"); - } -} - -char * -print_host(u_int32_t addr) -{ - return print_host2(addr, 0); -} - -/* - * On some routers, one interface has a name and the other doesn't. - * We always print the address of the outgoing interface, but can - * sometimes get the name from the incoming interface. This might be - * confusing but should be slightly more helpful than just a "?". - */ -char * -print_host2(u_int32_t addr1, u_int32_t addr2) -{ - char *name; - - if (numeric) { - printf("%s", inet_fmt(addr1, s1)); - return (""); - } - name = inet_name(addr1); - if (*name == '?' && *(name + 1) == '\0' && addr2 != 0) - name = inet_name(addr2); - printf("%s (%s)", name, inet_fmt(addr1, s1)); - return (name); -} - -/* - * Print responses as received (reverse path from dst to src) - */ -void -print_trace(int index, struct resp_buf *buf) -{ - struct tr_resp *r; - char *name; - int i; - int hop; - char *ms, *ft; - - i = abs(index); - r = buf->resps + i - 1; - - for (; i <= buf->len; ++i, ++r) { - if (index > 0) printf("%3d ", -i); - name = print_host2(r->tr_outaddr, r->tr_inaddr); - printf(" %s thresh^ %d", proto_type(r->tr_rproto), r->tr_fttl); - if (verbose) { - hop = t_diff(fixtime(ntohl(r->tr_qarr)), buf->qtime); - ms = scale(&hop); - printf(" %d%s", hop, ms); - } - ft = flag_type(r->tr_rflags); - if (strlen(ft) != 0) - printf(" %s", ft); - printf("\n"); - memcpy(names[i-1], name, sizeof(names[0]) - 1); - names[i-1][sizeof(names[0])-1] = '\0'; - } -} - -/* - * See what kind of router is the next hop - */ -int -what_kind(struct resp_buf *buf, char *why) -{ - u_int32_t smask; - int retval; - int hops = buf->len; - struct tr_resp *r = buf->resps + hops - 1; - u_int32_t next = r->tr_rmtaddr; - - retval = send_recv(next, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0]); - print_host(next); - if (retval) { - u_int32_t version = ntohl(incr[0].igmp.igmp_group.s_addr); - u_int32_t *p = (u_int32_t *)incr[0].ndata; - u_int32_t *ep = p + (incr[0].len >> 2); - char *type = ""; - retval = 0; - switch (version & 0xFF) { - case 1: - type = "proteon/mrouted "; - retval = 1; - break; - - case 2: - case 3: - if (((version >> 8) & 0xFF) < 3) retval = 1; - /* Fall through */ - case 4: - type = "mrouted "; - break; - - case 10: - type = "cisco "; - } - printf(" [%s%d.%d] %s\n", - type, version & 0xFF, (version >> 8) & 0xFF, - why); - VAL_TO_MASK(smask, r->tr_smask); - while (p < ep) { - u_int32_t laddr = *p++; - int flags = (ntohl(*p) & 0xFF00) >> 8; - int n = ntohl(*p++) & 0xFF; - if (!(flags & (DVMRP_NF_DOWN | DVMRP_NF_DISABLED)) && - (laddr & smask) == (qsrc & smask)) { - printf("%3d ", -(hops+2)); - print_host(qsrc); - printf("\n"); - return 1; - } - p += n; - } - return retval; - } - printf(" %s\n", why); - return 0; -} - - -char * -scale(int *hop) -{ - if (*hop > -1000 && *hop < 10000) return (" ms"); - *hop /= 1000; - if (*hop > -1000 && *hop < 10000) return (" s "); - return ("s "); -} - -/* - * Calculate and print one line of packet loss and packet rate statistics. - * Checks for count of all ones from mrouted 2.3 that doesn't have counters. - */ -#define NEITHER 0 -#define INS 1 -#define OUTS 2 -#define BOTH 3 -void -stat_line(struct tr_resp *r, struct tr_resp *s, int have_next, int *rst) -{ - int timediff = (fixtime(ntohl(s->tr_qarr)) - - fixtime(ntohl(r->tr_qarr))) >> 16; - int v_lost, v_pct; - int g_lost, g_pct; - int v_out = ntohl(s->tr_vifout) - ntohl(r->tr_vifout); - int g_out = ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt); - int v_pps, g_pps; - char v_str[8], g_str[8]; - int have = NEITHER; - int res = *rst; - - if (timediff == 0) timediff = 1; - v_pps = v_out / timediff; - g_pps = g_out / timediff; - - if ((v_out && (s->tr_vifout != 0xFFFFFFFF && s->tr_vifout != 0)) || - (r->tr_vifout != 0xFFFFFFFF && r->tr_vifout != 0)) - have |= OUTS; - - if (have_next) { - --r, --s, --rst; - if ((s->tr_vifin != 0xFFFFFFFF && s->tr_vifin != 0) || - (r->tr_vifin != 0xFFFFFFFF && r->tr_vifin != 0)) - have |= INS; - if (*rst) - res = 1; - } - - switch (have) { - case BOTH: - v_lost = v_out - (ntohl(s->tr_vifin) - ntohl(r->tr_vifin)); - if (v_out) v_pct = (v_lost * 100 + (v_out >> 1)) / v_out; - else v_pct = 0; - if (-100 < v_pct && v_pct < 101 && v_out > 10) - (void)snprintf(v_str, sizeof v_str, "%3d", v_pct); - else memcpy(v_str, " --", 4); - - g_lost = g_out - (ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt)); - if (g_out) g_pct = (g_lost * 100 + (g_out >> 1))/ g_out; - else g_pct = 0; - if (-100 < g_pct && g_pct < 101 && g_out > 10) - (void)snprintf(g_str, sizeof g_str, "%3d", g_pct); - else memcpy(g_str, " --", 4); - - printf("%6d/%-5d=%s%%%4d pps", - v_lost, v_out, v_str, v_pps); - if (res) - printf("\n"); - else - printf("%6d/%-5d=%s%%%4d pps\n", - g_lost, g_out, g_str, g_pps); - break; - - case INS: - v_out = ntohl(s->tr_vifin) - ntohl(r->tr_vifin); - v_pps = v_out / timediff; - /* Fall through */ - - case OUTS: - printf(" %-5d %4d pps", - v_out, v_pps); - if (res) - printf("\n"); - else - printf(" %-5d %4d pps\n", - g_out, g_pps); - break; - - case NEITHER: - printf("\n"); - break; - } - - if (debug > 2) { - printf("\t\t\t\tv_in: %ld ", (long)ntohl(s->tr_vifin)); - printf("v_out: %ld ", (long)ntohl(s->tr_vifout)); - printf("pkts: %ld\n", (long)ntohl(s->tr_pktcnt)); - printf("\t\t\t\tv_in: %ld ", (long)ntohl(r->tr_vifin)); - printf("v_out: %ld ", (long)ntohl(r->tr_vifout)); - printf("pkts: %ld\n", (long)ntohl(r->tr_pktcnt)); - printf("\t\t\t\tv_in: %ld ", - (long)ntohl(s->tr_vifin)-ntohl(r->tr_vifin)); - printf("v_out: %ld ", - (long)(ntohl(s->tr_vifout) - ntohl(r->tr_vifout))); - printf("pkts: %ld ", (long)(ntohl(s->tr_pktcnt) - ntohl(r->tr_pktcnt))); - printf("time: %d\n", timediff); - printf("\t\t\t\tres: %d\n", res); - } -} - -/* - * A fixup to check if any pktcnt has been reset, and to fix the - * byteorder bugs in mrouted 3.6 on little-endian machines. - */ -void -fixup_stats(struct resp_buf *base, struct resp_buf *prev, struct resp_buf *new) -{ - int rno = base->len; - struct tr_resp *b = base->resps + rno; - struct tr_resp *p = prev->resps + rno; - struct tr_resp *n = new->resps + rno; - int *r = reset + rno; - int *s = swaps + rno; - int res; - - /* Check for byte-swappers */ - while (--rno >= 0) { - --n; --p; --b; --s; - if (*s || abs(ntohl(n->tr_vifout) - ntohl(p->tr_vifout)) > 100000) { - /* This host sends byteswapped reports; swap 'em */ - if (!*s) { - *s = 1; - b->tr_qarr = byteswap(b->tr_qarr); - b->tr_vifin = byteswap(b->tr_vifin); - b->tr_vifout = byteswap(b->tr_vifout); - b->tr_pktcnt = byteswap(b->tr_pktcnt); - } - - n->tr_qarr = byteswap(n->tr_qarr); - n->tr_vifin = byteswap(n->tr_vifin); - n->tr_vifout = byteswap(n->tr_vifout); - n->tr_pktcnt = byteswap(n->tr_pktcnt); - } - } - - rno = base->len; - b = base->resps + rno; - p = prev->resps + rno; - n = new->resps + rno; - - while (--rno >= 0) { - --n; --p; --b; --r; - res = ((ntohl(n->tr_pktcnt) < ntohl(b->tr_pktcnt)) || - (ntohl(n->tr_pktcnt) < ntohl(p->tr_pktcnt))); - if (debug > 2) - printf("\t\tr=%d, res=%d\n", *r, res); - if (*r) { - if (res || *r > 1) { - /* - * This router appears to be a 3.4 with that nasty ol' - * neighbor version bug, which causes it to constantly - * reset. Just nuke the statistics for this node, and - * don't even bother giving it the benefit of the - * doubt from now on. - */ - p->tr_pktcnt = b->tr_pktcnt = n->tr_pktcnt; - r++; - } else { - /* - * This is simply the situation that the original - * fixup_stats was meant to deal with -- that a - * 3.3 or 3.4 router deleted a cache entry while - * traffic was still active. - */ - *r = 0; - break; - } - } else - *r = res; - } - - if (rno < 0) return; - - rno = base->len; - b = base->resps + rno; - p = prev->resps + rno; - - while (--rno >= 0) (--b)->tr_pktcnt = (--p)->tr_pktcnt; -} - -/* - * Print responses with statistics for forward path (from src to dst) - */ -int -print_stats(struct resp_buf *base, struct resp_buf *prev, struct resp_buf *new) -{ - int rtt, hop; - char *ms; - u_int32_t smask; - int rno = base->len - 1; - struct tr_resp *b = base->resps + rno; - struct tr_resp *p = prev->resps + rno; - struct tr_resp *n = new->resps + rno; - int *r = reset + rno; - u_long resptime = new->rtime; - u_long qarrtime = fixtime(ntohl(n->tr_qarr)); - u_int ttl = n->tr_fttl; - int first = (base == prev); - - VAL_TO_MASK(smask, b->tr_smask); - printf(" Source Response Dest"); - printf(" Packet Statistics For Only For Traffic\n"); - printf("%-15s %-15s All Multicast Traffic From %s\n", - ((b->tr_inaddr & smask) == (qsrc & smask)) ? s1 : " * * * ", - inet_fmt(base->qhdr.tr_raddr, s2), inet_fmt(qsrc, s1)); - rtt = t_diff(resptime, new->qtime); - ms = scale(&rtt); - printf(" %c __/ rtt%5d%s Lost/Sent = Pct Rate To %s\n", - first ? 'v' : '|', rtt, ms, inet_fmt(qgrp, s2)); - if (!first) { - hop = t_diff(resptime, qarrtime); - ms = scale(&hop); - printf(" v / hop%5d%s", hop, ms); - printf(" --------------------- --------------------\n"); - } - if (debug > 2) { - printf("\t\t\t\tv_in: %ld ", (long)ntohl(n->tr_vifin)); - printf("v_out: %ld ", (long)ntohl(n->tr_vifout)); - printf("pkts: %ld\n", (long)ntohl(n->tr_pktcnt)); - printf("\t\t\t\tv_in: %ld ", (long)ntohl(b->tr_vifin)); - printf("v_out: %ld ", (long)ntohl(b->tr_vifout)); - printf("pkts: %ld\n", (long)ntohl(b->tr_pktcnt)); - printf("\t\t\t\tv_in: %ld ", - (long)(ntohl(n->tr_vifin) - ntohl(b->tr_vifin))); - printf("v_out: %ld ", - (long)(ntohl(n->tr_vifout) - ntohl(b->tr_vifout))); - printf("pkts: %ld\n", - (long)(ntohl(n->tr_pktcnt) - ntohl(b->tr_pktcnt))); - printf("\t\t\t\treset: %d\n", *r); - } - - while (TRUE) { - if ((n->tr_inaddr != b->tr_inaddr) || (n->tr_inaddr != b->tr_inaddr)) - return 1; /* Route changed */ - - if ((n->tr_inaddr != n->tr_outaddr)) - printf("%-15s\n", inet_fmt(n->tr_inaddr, s1)); - printf("%-15s %-14s %s\n", inet_fmt(n->tr_outaddr, s1), names[rno], - flag_type(n->tr_rflags)); - - if (rno-- < 1) break; - - printf(" %c ^ ttl%5d ", first ? 'v' : '|', ttl); - stat_line(p, n, TRUE, r); - if (!first) { - resptime = qarrtime; - qarrtime = fixtime(ntohl((n-1)->tr_qarr)); - hop = t_diff(resptime, qarrtime); - ms = scale(&hop); - printf(" v | hop%5d%s", hop, ms); - stat_line(b, n, TRUE, r); - } - - --b, --p, --n, --r; - if (ttl < n->tr_fttl) ttl = n->tr_fttl; - else ++ttl; - } - - printf(" %c \\__ ttl%5d ", first ? 'v' : '|', ttl); - stat_line(p, n, FALSE, r); - if (!first) { - hop = t_diff(qarrtime, new->qtime); - ms = scale(&hop); - printf(" v \\ hop%5d%s", hop, ms); - stat_line(b, n, FALSE, r); - } - printf("%-15s %s\n", inet_fmt(qdst, s1), inet_fmt(lcl_addr, s2)); - printf(" Receiver Query Source\n\n"); - return 0; -} - - -/*************************************************************************** - * main - ***************************************************************************/ - -int -main(int argc, char **argv) -{ - int udp; - struct sockaddr_in addr; - int addrlen = sizeof(addr); - int recvlen; - struct timeval tv; - struct resp_buf *prev, *new; - struct tr_resp *r; - u_int32_t smask; - int rno; - int hops, nexthop, tries; - u_int32_t lastout = 0; - int numstats = 1; - int waittime; - int seed; - - if (geteuid() != 0) { - fprintf(stderr, "mtrace: must be root\n"); - exit(1); - } - init_igmp(); - if (setuid(getuid()) == -1) - logit(LOG_ERR, errno, "setuid"); - - argv++, argc--; - if (argc == 0) goto usage; - - while (argc > 0 && *argv[0] == '-') { - char *p = *argv++; argc--; - p++; - do { - char c = *p++; - char *arg = (char *) 0; - if (isdigit(*p)) { - arg = p; - p = ""; - } else if (argc > 0) arg = argv[0]; - switch (c) { - case 'd': /* Unlisted debug print option */ - if (arg && isdigit(*arg)) { - debug = atoi(arg); - if (debug < 0) debug = 0; - if (debug > 3) debug = 3; - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'M': /* Use multicast for reponse */ - multicast = TRUE; - break; - case 'l': /* Loop updating stats indefinitely */ - numstats = 3153600; - break; - case 'n': /* Don't reverse map host addresses */ - numeric = TRUE; - break; - case 'p': /* Passive listen for traces */ - passive = TRUE; - break; - case 'v': /* Verbosity */ - verbose = TRUE; - break; - case 's': /* Short form, don't wait for stats */ - numstats = 0; - break; - case 'w': /* Time to wait for packet arrival */ - if (arg && isdigit(*arg)) { - timeout = atoi(arg); - if (timeout < 1) timeout = 1; - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'm': /* Max number of hops to trace */ - if (arg && isdigit(*arg)) { - qno = atoi(arg); - if (qno > MAXHOPS) qno = MAXHOPS; - else if (qno < 1) qno = 0; - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'q': /* Number of query retries */ - if (arg && isdigit(*arg)) { - nqueries = atoi(arg); - if (nqueries < 1) nqueries = 1; - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'g': /* Last-hop gateway (dest of query) */ - if (arg && (gwy = host_addr(arg))) { - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 't': /* TTL for query packet */ - if (arg && isdigit(*arg)) { - qttl = atoi(arg); - if (qttl < 1) qttl = 1; - rttl = qttl; - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'r': /* Dest for response packet */ - if (arg && (raddr = host_addr(arg))) { - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'i': /* Local interface address */ - if (arg && (lcl_addr = host_addr(arg))) { - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - case 'S': /* Stat accumulation interval */ - if (arg && isdigit(*arg)) { - statint = atoi(arg); - if (statint < 1) statint = 1; - if (arg == argv[0]) argv++, argc--; - break; - } else - goto usage; - default: - goto usage; - } - } while (*p); - } - - if (argc > 0 && (qsrc = host_addr(argv[0]))) { /* Source of path */ - if (IN_MULTICAST(ntohl(qsrc))) goto usage; - argv++, argc--; - if (argc > 0 && (qdst = host_addr(argv[0]))) { /* Dest of path */ - argv++, argc--; - if (argc > 0 && (qgrp = host_addr(argv[0]))) { /* Path via group */ - argv++, argc--; - } - if (IN_MULTICAST(ntohl(qdst))) { - u_int32_t temp = qdst; - qdst = qgrp; - qgrp = temp; - if (IN_MULTICAST(ntohl(qdst))) goto usage; - } else if (qgrp && !IN_MULTICAST(ntohl(qgrp))) goto usage; - } - } - - if (passive) { - passive_mode(); - return(0); - } - - if (argc > 0 || qsrc == 0) { -usage: printf("\ -Usage: mtrace [-Mlnps] [-w wait] [-m max_hops] [-q nqueries] [-g gateway]\n\ - [-S statint] [-t ttl] [-r resp_dest] [-i if_addr] source [receiver] [group]\n"); - exit(1); - } - - /* - * Set useful defaults for as many parameters as possible. - */ - - defgrp = htonl(0xE0020001); /* MBone Audio (224.2.0.1) */ - query_cast = htonl(0xE0000002); /* All routers multicast addr */ - resp_cast = htonl(0xE0000120); /* Mtrace response multicast addr */ - if (qgrp == 0) qgrp = defgrp; - - /* - * Get default local address for multicasts to use in setting defaults. - */ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; -#if (defined(BSD) && (BSD >= 199103)) - addr.sin_len = sizeof(addr); -#endif - addr.sin_addr.s_addr = qgrp; - addr.sin_port = htons(2000); /* Any port above 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); - } - -#ifdef SUNOS5 - /* - * SunOS 5.X prior to SunOS 2.6, getsockname returns 0 for udp socket. - * This call to sysinfo will return the hostname. - * If the default multicast interfface (set with the route - * for 224.0.0.0) is not the same as the hostname, - * mtrace -i [if_addr] will have to be used. - */ - if (addr.sin_addr.s_addr == 0) { - char myhostname[MAXHOSTNAMELEN]; - struct hostent *hp; - int error; - - error = sysinfo(SI_HOSTNAME, myhostname, sizeof(myhostname)); - if (error == -1) { - perror("Getting my hostname"); - exit(1); - } - - hp = gethostbyname(myhostname); - if (hp == NULL || hp->h_addrtype != AF_INET || - hp->h_length != sizeof(addr.sin_addr)) { - perror("Finding IP address for my hostname"); - exit(1); - } - - memcpy((char *)&addr.sin_addr.s_addr, hp->h_addr, - sizeof(addr.sin_addr.s_addr)); - } -#endif - - /* - * Default destination for path to be queried is the local host. - */ - if (qdst == 0) qdst = lcl_addr ? lcl_addr : addr.sin_addr.s_addr; - dst_netmask = get_netmask(udp, qdst); - close(udp); - if (lcl_addr == 0) lcl_addr = addr.sin_addr.s_addr; - - /* - * Initialize the seed for random query identifiers. - */ - gettimeofday(&tv, 0); - seed = tv.tv_usec ^ lcl_addr; -#ifdef SYSV - srand48(seed); -#else - srandom(seed); -#endif - - /* - * Protect against unicast queries to mrouted versions that might crash. - */ - if (gwy && !IN_MULTICAST(ntohl(gwy))) - if (send_recv(gwy, IGMP_DVMRP, DVMRP_ASK_NEIGHBORS2, 1, &incr[0])) { - int version = ntohl(incr[0].igmp.igmp_group.s_addr) & 0xFFFF; - if (version == 0x0303 || version == 0x0503) { - printf("Don't use -g to address an mrouted 3.%d, it might crash\n", - (version >> 8) & 0xFF); - exit(0); - } - } - - printf("Mtrace from %s to %s via group %s\n", - inet_fmt(qsrc, s1), inet_fmt(qdst, s2), inet_fmt(qgrp, s3)); - - if ((qdst & dst_netmask) == (qsrc & dst_netmask)) { - printf("Source & receiver are directly connected, no path to trace\n"); - exit(0); - } - - /* - * If the response is to be a multicast address, make sure we - * are listening on that multicast address. - */ - if (raddr) { - if (IN_MULTICAST(ntohl(raddr))) k_join(raddr, lcl_addr); - } else k_join(resp_cast, lcl_addr); - - /* - * If the destination is on the local net, the last-hop router can - * be found by multicast to the all-routers multicast group. - * Otherwise, use the group address that is the subject of the - * query since by definition the last-hop router will be a member. - * Set default TTLs for local remote multicasts. - */ - restart: - - if (gwy == 0) - if ((qdst & dst_netmask) == (lcl_addr & dst_netmask)) tdst = query_cast; - else tdst = qgrp; - else tdst = gwy; - - if (IN_MULTICAST(ntohl(tdst))) { - k_set_loop(1); /* If I am running on a router, I need to hear this */ - if (tdst == query_cast) k_set_ttl(qttl ? qttl : 1); - else k_set_ttl(qttl ? qttl : MULTICAST_TTL1); - } - - /* - * Try a query at the requested number of hops or MAXHOPS if unspecified. - */ - if (qno == 0) { - hops = MAXHOPS; - tries = 1; - printf("Querying full reverse path... "); - fflush(stdout); - } else { - hops = qno; - tries = nqueries; - printf("Querying reverse path, maximum %d hops... ", qno); - fflush(stdout); - } - base.rtime = 0; - base.len = 0; - - recvlen = send_recv(tdst, IGMP_MTRACE_QUERY, hops, tries, &base); - - /* - * If the initial query was successful, print it. Otherwise, if - * the query max hop count is the default of zero, loop starting - * from one until there is no response for four hops. The extra - * hops allow getting past an mtrace-capable mrouter that can't - * send multicast packets because all phyints are disabled. - */ - if (recvlen) { - printf("\n 0 "); - print_host(qdst); - printf("\n"); - print_trace(1, &base); - r = base.resps + base.len - 1; - if (r->tr_rflags == TR_OLD_ROUTER || r->tr_rflags == TR_NO_SPACE || - qno != 0) { - printf("%3d ", -(base.len+1)); - what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ? - "doesn't support mtrace" - : "is the next hop"); - } else { - VAL_TO_MASK(smask, r->tr_smask); - if ((r->tr_inaddr & smask) == (qsrc & smask)) { - printf("%3d ", -(base.len+1)); - print_host(qsrc); - printf("\n"); - } - } - } else if (qno == 0) { - printf("switching to hop-by-hop:\n 0 "); - print_host(qdst); - printf("\n"); - - for (hops = 1, nexthop = 1; hops <= MAXHOPS; ++hops) { - printf("%3d ", -hops); - fflush(stdout); - - /* - * After a successful first hop, try switching to the unicast - * address of the last-hop router instead of multicasting the - * trace query. This should be safe for mrouted versions 3.3 - * and 3.5 because there is a long route timeout with metric - * infinity before a route disappears. Switching to unicast - * reduces the amount of multicast traffic and avoids a bug - * with duplicate suppression in mrouted 3.5. - */ - if (hops == 2 && gwy == 0 && - (recvlen = send_recv(lastout, IGMP_MTRACE_QUERY, hops, 1, &base))) - tdst = lastout; - else recvlen = send_recv(tdst, IGMP_MTRACE_QUERY, hops, nqueries, &base); - - if (recvlen == 0) { - if (hops == 1) break; - if (hops == nexthop) { - if (what_kind(&base, "didn't respond")) { - /* the ask_neighbors determined that the - * not-responding router is the first-hop. */ - break; - } - } else if (hops < nexthop + 3) { - printf("\n"); - } else { - printf("...giving up\n"); - break; - } - continue; - } - r = base.resps + base.len - 1; - if (base.len == hops && - (hops == 1 || (base.resps+nexthop-2)->tr_outaddr == lastout)) { - if (hops == nexthop) { - print_trace(-hops, &base); - } else { - printf("\nResuming...\n"); - print_trace(nexthop, &base); - } - } else { - if (base.len < hops) { - /* - * A shorter trace than requested means a fatal error - * occurred along the path, or that the route changed - * to a shorter one. - * - * If the trace is longer than the last one we received, - * then we are resuming from a skipped router (but there - * is still probably a problem). - * - * If the trace is shorter than the last one we - * received, then the route must have changed (and - * there is still probably a problem). - */ - if (nexthop <= base.len) { - printf("\nResuming...\n"); - print_trace(nexthop, &base); - } else if (nexthop > base.len + 1) { - hops = base.len; - printf("\nRoute must have changed...\n"); - print_trace(1, &base); - } - } else { - /* - * The last hop address is not the same as it was; - * the route probably changed underneath us. - */ - hops = base.len; - printf("\nRoute must have changed...\n"); - print_trace(1, &base); - } - } - lastout = r->tr_outaddr; - - if (base.len < hops || - r->tr_rmtaddr == 0 || - (r->tr_rflags & 0x80)) { - VAL_TO_MASK(smask, r->tr_smask); - if (r->tr_rmtaddr) { - if (hops != nexthop) { - printf("\n%3d ", -(base.len+1)); - } - what_kind(&base, r->tr_rflags == TR_OLD_ROUTER ? - "doesn't support mtrace" : - "would be the next hop"); - /* XXX could do segmented trace if TR_NO_SPACE */ - } else if (r->tr_rflags == TR_NO_ERR && - (r->tr_inaddr & smask) == (qsrc & smask)) { - printf("%3d ", -(hops + 1)); - print_host(qsrc); - printf("\n"); - } - break; - } - - nexthop = hops + 1; - } - } - - if (base.rtime == 0) { - printf("Timed out receiving responses\n"); - if (IN_MULTICAST(ntohl(tdst))) { - if (tdst == query_cast) - printf("Perhaps no local router has a route for source %s\n", - inet_fmt(qsrc, s1)); - else - printf("Perhaps receiver %s is not a member of group %s,\n" - "or no router local to it has a route for source %s,\n" - "or multicast at ttl %d doesn't reach its last-hop router" - " for that source\n", - inet_fmt(qdst, s2), inet_fmt(qgrp, s3), inet_fmt(qsrc, s1), - qttl ? qttl : MULTICAST_TTL1); - } - exit(1); - } - - printf("Round trip time %d ms\n\n", t_diff(base.rtime, base.qtime)); - - /* - * Use the saved response which was the longest one received, - * and make additional probes after delay to measure loss. - */ - raddr = base.qhdr.tr_raddr; - rttl = base.qhdr.tr_rttl; - gettimeofday(&tv, 0); - waittime = statint - (((tv.tv_sec + JAN_1970) & 0xFFFF) - (base.qtime >> 16)); - prev = &base; - new = &incr[numstats&1]; - - while (numstats--) { - if (waittime < 1) printf("\n"); - else { - printf("Waiting to accumulate statistics... "); - fflush(stdout); - sleep((unsigned)waittime); - } - rno = base.len; - recvlen = send_recv(tdst, IGMP_MTRACE_QUERY, rno, nqueries, new); - - if (recvlen == 0) { - printf("Timed out.\n"); - exit(1); - } - - if (rno != new->len) { - printf("Trace length doesn't match:\n"); - /* - * XXX Should this trace result be printed, or is that - * too verbose? Perhaps it should just say restarting. - * But if the path is changing quickly, this may be the - * only snapshot of the current path. But, if the path - * is changing that quickly, does the current path really - * matter? - */ - print_trace(1, new); - printf("Restarting.\n\n"); - numstats++; - goto restart; - } - - printf("Results after %d seconds:\n\n", - (int)((new->qtime - base.qtime) >> 16)); - fixup_stats(&base, prev, new); - if (print_stats(&base, prev, new)) { - printf("Route changed:\n"); - print_trace(1, new); - printf("Restarting.\n\n"); - goto restart; - } - prev = new; - new = &incr[numstats&1]; - waittime = statint; - } - - /* - * If the response was multicast back, leave the group - */ - if (raddr) { - if (IN_MULTICAST(ntohl(raddr))) k_leave(raddr, lcl_addr); - } else k_leave(resp_cast, lcl_addr); - - return (0); -} - -void -check_vif_state(void) -{ - logit(LOG_WARNING, errno, "sendto"); -} - -/* - * 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 -logit(int severity, int syserr, const char *format, ...) -{ - va_list ap; - - switch (debug) { - case 0: if (severity > LOG_WARNING) return; - case 1: if (severity > LOG_NOTICE) return; - case 2: if (severity > LOG_INFO ) return; - default: - if (severity == LOG_WARNING) - fprintf(stderr, "warning - "); - va_start(ap, format); - vfprintf(stderr, format, ap); - va_end(ap); - if (syserr == 0) - fprintf(stderr, "\n"); - else - fprintf(stderr, ": %s\n", strerror(syserr)); - } - if (severity <= LOG_ERR) exit(1); -} - -/* dummies */ -void accept_probe(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ -} -void accept_group_report(u_int32_t src, u_int32_t dst, u_int32_t group, - int r_type) -{ -} -void accept_neighbor_request2(u_int32_t src, u_int32_t dst) -{ -} -void accept_report(u_int32_t src, u_int32_t dst, char *p, int datalen, - u_int32_t level) -{ -} -void accept_neighbor_request(u_int32_t src, u_int32_t dst) -{ -} -void accept_prune(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void accept_graft(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void accept_g_ack(u_int32_t src, u_int32_t dst, char *p, int datalen) -{ -} -void add_table_entry(u_int32_t origin, u_int32_t mcastgrp) -{ -} -void accept_leave_message(u_int32_t src, u_int32_t dst, u_int32_t group) -{ -} -void accept_mtrace(u_int32_t src, u_int32_t dst, u_int32_t group, char *data, - u_int no, int datalen) -{ -} -void accept_membership_query(u_int32_t src, u_int32_t dst, u_int32_t group, - int tmo) -{ -} -void accept_neighbors(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ -} -void accept_neighbors2(u_int32_t src, u_int32_t dst, u_char *p, int datalen, - u_int32_t level) -{ -} -void accept_info_request(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ -} -void accept_info_reply(u_int32_t src, u_int32_t dst, u_char *p, int datalen) -{ -} diff --git a/gnu/usr.sbin/map-mbone/Makefile b/gnu/usr.sbin/map-mbone/Makefile deleted file mode 100644 index 7843fe0c844..00000000000 --- a/gnu/usr.sbin/map-mbone/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2002/10/01 03:50:12 itojun Exp $ -# from: Id: Makefile,v 1.5 1993/06/24 05:11:16 deering Exp - -.include <bsd.own.mk> - -.PATH: ${NETBSDSRCDIR}/gnu/dist/map-mbone ${NETBSDSRCDIR}/gnu/dist/mrouted -CPPFLAGS+= -I${NETBSDSRCDIR}/gnu/dist/mrouted - -PROG= map-mbone -SRCS= igmp.c inet.c kern.c mapper.c -MAN= map-mbone.8 - -.include <bsd.prog.mk> diff --git a/gnu/usr.sbin/mrinfo/Makefile b/gnu/usr.sbin/mrinfo/Makefile deleted file mode 100644 index df81c8acb06..00000000000 --- a/gnu/usr.sbin/mrinfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2002/10/01 03:50:12 itojun Exp $ -# from: Id: Makefile,v 1.5 1993/06/24 05:11:16 deering Exp - -.include <bsd.own.mk> - -.PATH: ${NETBSDSRCDIR}/gnu/dist/mrinfo ${NETBSDSRCDIR}/gnu/dist/mrouted -CPPFLAGS+= -I${NETBSDSRCDIR}/gnu/dist/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/gnu/usr.sbin/mrouted/Makefile b/gnu/usr.sbin/mrouted/Makefile deleted file mode 100644 index 28d5d6bbfda..00000000000 --- a/gnu/usr.sbin/mrouted/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $NetBSD: Makefile,v 1.2 2002/10/17 12:50:00 itojun Exp $ -# from: Id: Makefile,v 1.5 1993/06/24 05:11:16 deering Exp - -.include <bsd.own.mk> - -PROG= mrouted -SRCS= callout.c cfparse.y config.c igmp.c inet.c kern.c main.c prune.c \ - route.c vif.c -MAN= mrouted.8 - -LDADD+= -lutil -DPADD+= ${LIBUTIL} -CPPFLAGS+=-I${NETBSDSRCDIR}/gnu/dist/mrouted -I${.CURDIR} - -.PATH: ${NETBSDSRCDIR}/gnu/dist/mrouted - -.include <bsd.prog.mk> diff --git a/gnu/usr.sbin/mtrace/Makefile b/gnu/usr.sbin/mtrace/Makefile deleted file mode 100644 index 047dd680c0f..00000000000 --- a/gnu/usr.sbin/mtrace/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2002/10/01 03:50:12 itojun Exp $ -# from: Id: Makefile,v 1.5 1993/06/24 05:11:16 deering Exp - -.include <bsd.own.mk> - -.PATH: ${NETBSDSRCDIR}/gnu/dist/mrouted ${NETBSDSRCDIR}/gnu/dist/mtrace -CPPFLAGS+= -I${NETBSDSRCDIR}/gnu/dist/mrouted - -PROG= mtrace -SRCS= igmp.c inet.c kern.c mtrace.c -MAN= mtrace.8 - -BINMODE=4555 -BINOWN= root - -.include <bsd.prog.mk> |
