print-rip.c revision 98524
117680Spst/*
217680Spst * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2017680Spst */
2117680Spst
2217680Spst#ifndef lint
2326180Sfennerstatic const char rcsid[] =
2498524Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.49 2001/05/10 05:30:22 fenner Exp $ (LBL)";
2517680Spst#endif
2617680Spst
2756893Sfenner#ifdef HAVE_CONFIG_H
2856893Sfenner#include "config.h"
2956893Sfenner#endif
3056893Sfenner
3117680Spst#include <sys/param.h>
3217680Spst#include <sys/time.h>
3317680Spst#include <sys/socket.h>
3417680Spst
3517680Spst#include <netinet/in.h>
3617680Spst
3717680Spst#include <stdio.h>
3875115Sfenner#include <ctype.h>
3975115Sfenner#include <string.h>
4017680Spst
4117680Spst#include "interface.h"
4217680Spst#include "addrtoname.h"
4317680Spst#include "extract.h"			/* must come after interface.h */
4417680Spst
4517680Spststruct rip {
4617680Spst	u_char rip_cmd;			/* request/response */
4717680Spst	u_char rip_vers;		/* protocol version # */
4817680Spst	u_short rip_zero2;		/* unused */
4917680Spst};
5017680Spst#define	RIPCMD_REQUEST		1	/* want info */
5117680Spst#define	RIPCMD_RESPONSE		2	/* responding to request */
5217680Spst#define	RIPCMD_TRACEON		3	/* turn tracing on */
5317680Spst#define	RIPCMD_TRACEOFF		4	/* turn it off */
5417680Spst#define	RIPCMD_POLL		5	/* want info from everybody */
5517680Spst#define	RIPCMD_POLLENTRY	6	/* poll for entry */
5617680Spst
5775115Sfenner#define RIP_AUTHLEN 16
5875115Sfenner
5917680Spststruct rip_netinfo {
6017680Spst	u_short rip_family;
6117680Spst	u_short rip_tag;
6217680Spst	u_int32_t rip_dest;
6317680Spst	u_int32_t rip_dest_mask;
6417680Spst	u_int32_t rip_router;
6517680Spst	u_int32_t rip_metric;		/* cost of route */
6617680Spst};
6717680Spst
6817680Spststatic void
6975115Sfennerrip_printblk(const u_char *cp, const u_char *ep)
7017680Spst{
7175115Sfenner	for (; cp < ep; cp += 2)
7275115Sfenner		printf(" %04x", EXTRACT_16BITS(cp));
7375115Sfenner	return;
7475115Sfenner}
7517680Spst
7675115Sfennerstatic void
7775115Sfennerrip_entry_print_v1(register int vers, register const struct rip_netinfo *ni)
7875115Sfenner{
7975115Sfenner	register u_short family;
8017680Spst
8175115Sfenner	/* RFC 1058 */
8275115Sfenner	family = EXTRACT_16BITS(&ni->rip_family);
8375115Sfenner	if (family != AF_INET) {
8475115Sfenner		printf(" [family %d:", family);
8575115Sfenner		rip_printblk((u_char *)&ni->rip_tag,
8675115Sfenner			     (u_char *)&ni->rip_metric +
8775115Sfenner			     sizeof(ni->rip_metric));
8817680Spst		printf("]");
8975115Sfenner		return;
9075115Sfenner	}
9175115Sfenner	if (ni->rip_tag || ni->rip_dest_mask || ni->rip_router) {
9275115Sfenner		/* MBZ fields not zero */
9375115Sfenner		printf(" [");
9475115Sfenner		rip_printblk((u_char *)&ni->rip_family,
9575115Sfenner			     (u_char *)&ni->rip_metric +
9675115Sfenner			     sizeof(ni->rip_metric));
9775115Sfenner		printf("]");
9875115Sfenner		return;
9975115Sfenner	}
10075115Sfenner	printf(" {%s}(%d)", ipaddr_string(&ni->rip_dest),
10175115Sfenner	       EXTRACT_32BITS(&ni->rip_metric));
10275115Sfenner}
10375115Sfenner
10475115Sfennerstatic void
10575115Sfennerrip_entry_print_v2(register int vers, register const struct rip_netinfo *ni)
10675115Sfenner{
10775115Sfenner	register u_char *p;
10875115Sfenner	register u_short family;
10975115Sfenner	u_char buf[RIP_AUTHLEN];
11075115Sfenner
11175115Sfenner	/* RFC 1723 */
11275115Sfenner	family = EXTRACT_16BITS(&ni->rip_family);
11375115Sfenner	if (family == 0xFFFF) {
11475115Sfenner		if (EXTRACT_16BITS(&ni->rip_tag) == 2) {
11575115Sfenner			memcpy(buf, &ni->rip_dest, sizeof(buf));
11675115Sfenner			buf[sizeof(buf)-1] = '\0';
11775115Sfenner			for (p = buf; *p; p++) {
11875115Sfenner				if (!isprint(*p))
11975115Sfenner					break;
12075115Sfenner			}
12175115Sfenner			if (!*p) {
12275115Sfenner				printf(" [password %s]", buf);
12375115Sfenner			} else {
12475115Sfenner				printf(" [password: ");
12575115Sfenner				rip_printblk((u_char *)&ni->rip_dest,
12675115Sfenner					     (u_char *)&ni->rip_metric +
12775115Sfenner					     sizeof(ni->rip_metric));
12875115Sfenner				printf("]");
12975115Sfenner			}
13075115Sfenner		} else {
13175115Sfenner			printf(" [auth %d:",
13275115Sfenner			       EXTRACT_16BITS(&ni->rip_tag));
13375115Sfenner			rip_printblk((u_char *)&ni->rip_dest,
13475115Sfenner				     (u_char *)&ni->rip_metric +
13575115Sfenner				     sizeof(ni->rip_metric));
13675115Sfenner			printf("]");
13775115Sfenner		}
13875115Sfenner	} else if (family != AF_INET) {
13975115Sfenner		printf(" [family %d:", family);
14075115Sfenner		rip_printblk((u_char *)&ni->rip_tag,
14175115Sfenner			     (u_char *)&ni->rip_metric +
14275115Sfenner			     sizeof(ni->rip_metric));
14375115Sfenner		printf("]");
14475115Sfenner		return;
14575115Sfenner	} else { /* AF_INET */
14617680Spst		printf(" {%s", ipaddr_string(&ni->rip_dest));
14717680Spst		if (ni->rip_dest_mask)
14817680Spst			printf("/%s", ipaddr_string(&ni->rip_dest_mask));
14917680Spst		if (ni->rip_router)
15017680Spst			printf("->%s", ipaddr_string(&ni->rip_router));
15117680Spst		if (ni->rip_tag)
15217680Spst			printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag));
15375115Sfenner		printf("}(%d)", EXTRACT_32BITS(&ni->rip_metric));
15417680Spst	}
15517680Spst}
15617680Spst
15717680Spstvoid
15817680Spstrip_print(const u_char *dat, u_int length)
15917680Spst{
16017680Spst	register const struct rip *rp;
16117680Spst	register const struct rip_netinfo *ni;
16217680Spst	register int i, j, trunc;
16317680Spst
16426180Sfenner	i = min(length, snapend - dat) - sizeof(*rp);
16556893Sfenner	if (i < 0) {
16656893Sfenner		printf(" [|rip]");
16717680Spst		return;
16856893Sfenner	}
16917680Spst
17017680Spst	rp = (struct rip *)dat;
17175115Sfenner	switch (rp->rip_vers) {
17275115Sfenner	case 0:
17375115Sfenner		/*
17475115Sfenner		 * RFC 1058.
17575115Sfenner		 *
17675115Sfenner		 * XXX - RFC 1058 says
17775115Sfenner		 *
17875115Sfenner		 * 0  Datagrams whose version number is zero are to be ignored.
17975115Sfenner		 *    These are from a previous version of the protocol, whose
18075115Sfenner		 *    packet format was machine-specific.
18175115Sfenner		 *
18275115Sfenner		 * so perhaps we should just dump the first few words of
18375115Sfenner		 * the packet, in hex.
18498524Sfenner		 */
18575115Sfenner		printf(" RIPv0: ");
18617680Spst		ni = (struct rip_netinfo *)(rp + 1);
18775115Sfenner		rip_printblk((u_char *)&ni->rip_family,
18875115Sfenner			     (u_char *)&ni->rip_metric +
18975115Sfenner			     sizeof(ni->rip_metric));
19017680Spst		break;
19117680Spst	default:
19275115Sfenner		switch (rp->rip_cmd) {
19375115Sfenner		case RIPCMD_REQUEST:
19475115Sfenner			printf(" RIPv%d-req %d", rp->rip_vers, length);
19575115Sfenner			break;
19675115Sfenner		case RIPCMD_RESPONSE:
19775115Sfenner			j = length / sizeof(*ni);
19875115Sfenner			if (j * sizeof(*ni) != length - 4)
19975115Sfenner				printf(" RIPv%d-resp [items %d] [%d]:",
20075115Sfenner				       rp->rip_vers, j, length);
20175115Sfenner			else
20275115Sfenner				printf(" RIPv%d-resp [items %d]:",
20375115Sfenner				       rp->rip_vers, j);
20475115Sfenner			trunc = (i / sizeof(*ni)) != j;
20575115Sfenner			ni = (struct rip_netinfo *)(rp + 1);
20675115Sfenner			for (; (i -= sizeof(*ni)) >= 0; ++ni) {
20775115Sfenner				if (rp->rip_vers == 1)
20875115Sfenner					rip_entry_print_v1(rp->rip_vers, ni);
20975115Sfenner				else
21075115Sfenner					rip_entry_print_v2(rp->rip_vers, ni);
21175115Sfenner			}
21275115Sfenner			if (trunc)
21375115Sfenner				printf("[|rip]");
21475115Sfenner			break;
21575115Sfenner		case RIPCMD_TRACEON:
21675115Sfenner			printf(" RIPv%d-traceon %d: \"", rp->rip_vers, length);
21775115Sfenner			(void)fn_print((const u_char *)(rp + 1), snapend);
21898524Sfenner			fputs("\"", stdout);
21975115Sfenner			break;
22075115Sfenner		case RIPCMD_TRACEOFF:
22175115Sfenner			printf(" RIPv%d-traceoff %d", rp->rip_vers, length);
22275115Sfenner			break;
22375115Sfenner		case RIPCMD_POLL:
22475115Sfenner			printf(" RIPv%d-poll %d", rp->rip_vers, length);
22575115Sfenner			break;
22675115Sfenner		case RIPCMD_POLLENTRY:
22775115Sfenner			printf(" RIPv%d-pollentry %d", rp->rip_vers, length);
22875115Sfenner			break;
22975115Sfenner		default:
23075115Sfenner			printf(" RIPv%d-#%d %d", rp->rip_vers, rp->rip_cmd,
23175115Sfenner			       length);
23275115Sfenner			break;
23375115Sfenner		}
23498524Sfenner	}
23517680Spst}
236