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
23127668Sbmsstatic const char rcsid[] _U_ =
24190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.59 2006-03-23 14:58:44 hannes Exp $ (LBL)";
2517680Spst#endif
2617680Spst
2756893Sfenner#ifdef HAVE_CONFIG_H
2856893Sfenner#include "config.h"
2956893Sfenner#endif
3056893Sfenner
31127668Sbms#include <tcpdump-stdinc.h>
3217680Spst
3317680Spst#include <stdio.h>
3475115Sfenner#include <string.h>
3517680Spst
3617680Spst#include "interface.h"
3717680Spst#include "addrtoname.h"
3817680Spst#include "extract.h"			/* must come after interface.h */
3917680Spst
40190207Srpaulo#include "af.h"
41190207Srpaulo
4217680Spststruct rip {
43127668Sbms	u_int8_t rip_cmd;		/* request/response */
44127668Sbms	u_int8_t rip_vers;		/* protocol version # */
45127668Sbms	u_int8_t unused[2];		/* unused */
4617680Spst};
47127668Sbms
4817680Spst#define	RIPCMD_REQUEST		1	/* want info */
4917680Spst#define	RIPCMD_RESPONSE		2	/* responding to request */
5017680Spst#define	RIPCMD_TRACEON		3	/* turn tracing on */
5117680Spst#define	RIPCMD_TRACEOFF		4	/* turn it off */
5217680Spst#define	RIPCMD_POLL		5	/* want info from everybody */
5317680Spst#define	RIPCMD_POLLENTRY	6	/* poll for entry */
5417680Spst
55127668Sbmsstatic const struct tok rip_cmd_values[] = {
56127668Sbms    { RIPCMD_REQUEST,	        "Request" },
57127668Sbms    { RIPCMD_RESPONSE,	        "Response" },
58127668Sbms    { RIPCMD_TRACEON,	        "Trace on" },
59127668Sbms    { RIPCMD_TRACEOFF,	        "Trace off" },
60127668Sbms    { RIPCMD_POLL,	        "Poll" },
61127668Sbms    { RIPCMD_POLLENTRY,	        "Poll Entry" },
62127668Sbms    { 0, NULL}
63127668Sbms};
6475115Sfenner
65127668Sbms#define RIP_AUTHLEN  16
66127668Sbms#define RIP_ROUTELEN 20
67127668Sbms
68127668Sbms/*
69127668Sbms * rfc 1723
70127668Sbms *
71127668Sbms *  0                   1                   2                   3 3
72127668Sbms *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
73127668Sbms * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74127668Sbms * | Command (1)   | Version (1)   |           unused              |
75127668Sbms * +---------------+---------------+-------------------------------+
76127668Sbms * | Address Family Identifier (2) |        Route Tag (2)          |
77127668Sbms * +-------------------------------+-------------------------------+
78127668Sbms * |                         IP Address (4)                        |
79127668Sbms * +---------------------------------------------------------------+
80127668Sbms * |                         Subnet Mask (4)                       |
81127668Sbms * +---------------------------------------------------------------+
82127668Sbms * |                         Next Hop (4)                          |
83127668Sbms * +---------------------------------------------------------------+
84127668Sbms * |                         Metric (4)                            |
85127668Sbms * +---------------------------------------------------------------+
86127668Sbms *
87127668Sbms */
88127668Sbms
8917680Spststruct rip_netinfo {
90127668Sbms	u_int16_t rip_family;
91127668Sbms	u_int16_t rip_tag;
9217680Spst	u_int32_t rip_dest;
9317680Spst	u_int32_t rip_dest_mask;
9417680Spst	u_int32_t rip_router;
9517680Spst	u_int32_t rip_metric;		/* cost of route */
9617680Spst};
9717680Spst
9817680Spststatic void
99127668Sbmsrip_entry_print_v1(register const struct rip_netinfo *ni)
10017680Spst{
10175115Sfenner	register u_short family;
10217680Spst
10375115Sfenner	/* RFC 1058 */
10475115Sfenner	family = EXTRACT_16BITS(&ni->rip_family);
105251158Sdelphij	if (family != BSD_AFNUM_INET && family != 0) {
106190207Srpaulo		printf("\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family));
107127668Sbms                print_unknown_data((u_int8_t *)&ni->rip_family,"\n\t  ",RIP_ROUTELEN);
10875115Sfenner		return;
10975115Sfenner	}
110127668Sbms	if (EXTRACT_16BITS(&ni->rip_tag) ||
111127668Sbms	    EXTRACT_32BITS(&ni->rip_dest_mask) ||
112127668Sbms	    EXTRACT_32BITS(&ni->rip_router)) {
11375115Sfenner		/* MBZ fields not zero */
114127668Sbms                print_unknown_data((u_int8_t *)&ni->rip_family,"\n\t  ",RIP_ROUTELEN);
11575115Sfenner		return;
116251158Sdelphij	}
117251158Sdelphij	if (family == 0) {
118251158Sdelphij		printf("\n\t  AFI 0, %s, metric: %u",
119251158Sdelphij			ipaddr_string(&ni->rip_dest),
120251158Sdelphij			EXTRACT_32BITS(&ni->rip_metric));
121251158Sdelphij		return;
122190207Srpaulo	} /* BSD_AFNUM_INET */
123127668Sbms	printf("\n\t  %s, metric: %u",
124127668Sbms               ipaddr_string(&ni->rip_dest),
12575115Sfenner	       EXTRACT_32BITS(&ni->rip_metric));
12675115Sfenner}
12775115Sfenner
128251158Sdelphijstatic unsigned
129251158Sdelphijrip_entry_print_v2(register const struct rip_netinfo *ni, const unsigned remaining)
13075115Sfenner{
13175115Sfenner	register u_short family;
13275115Sfenner
13375115Sfenner	family = EXTRACT_16BITS(&ni->rip_family);
134251158Sdelphij	if (family == 0xFFFF) { /* variable-sized authentication structures */
135251158Sdelphij		u_int16_t auth_type = EXTRACT_16BITS(&ni->rip_tag);
136251158Sdelphij		if (auth_type == 2) {
137251158Sdelphij			register u_char *p = (u_char *)&ni->rip_dest;
138251158Sdelphij			u_int i = 0;
139251158Sdelphij			printf("\n\t  Simple Text Authentication data: ");
140251158Sdelphij			for (; i < RIP_AUTHLEN; p++, i++)
141251158Sdelphij				putchar (isprint(*p) ? *p : '.');
142251158Sdelphij		} else if (auth_type == 3) {
143251158Sdelphij			printf("\n\t  Auth header:");
144251210Sdelphij			printf(" Packet Len %u,", EXTRACT_16BITS((u_int8_t *)ni + 4));
145251158Sdelphij			printf(" Key-ID %u,", *((u_int8_t *)ni + 6));
146251158Sdelphij			printf(" Auth Data Len %u,", *((u_int8_t *)ni + 7));
147251158Sdelphij			printf(" SeqNo %u,", EXTRACT_32BITS(&ni->rip_dest_mask));
148251158Sdelphij			printf(" MBZ %u,", EXTRACT_32BITS(&ni->rip_router));
149251158Sdelphij			printf(" MBZ %u", EXTRACT_32BITS(&ni->rip_metric));
150251158Sdelphij		} else if (auth_type == 1) {
151251158Sdelphij			printf("\n\t  Auth trailer:");
152251158Sdelphij			print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t  ",remaining);
153251158Sdelphij			return remaining; /* AT spans till the packet end */
154127668Sbms                } else {
155127668Sbms			printf("\n\t  Unknown (%u) Authentication data:",
15675115Sfenner			       EXTRACT_16BITS(&ni->rip_tag));
157251158Sdelphij			print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t  ",remaining);
15875115Sfenner		}
159251158Sdelphij	} else if (family != BSD_AFNUM_INET && family != 0) {
160190207Srpaulo		printf("\n\t  AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family));
161127668Sbms                print_unknown_data((u_int8_t *)&ni->rip_tag,"\n\t  ",RIP_ROUTELEN-2);
162251158Sdelphij	} else { /* BSD_AFNUM_INET or AFI 0 */
163190207Srpaulo		printf("\n\t  AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ",
164251158Sdelphij                       tok2str(bsd_af_values, "%u", family),
165127668Sbms                       ipaddr_string(&ni->rip_dest),
166127668Sbms		       mask2plen(EXTRACT_32BITS(&ni->rip_dest_mask)),
167127668Sbms                       EXTRACT_16BITS(&ni->rip_tag),
168127668Sbms                       EXTRACT_32BITS(&ni->rip_metric));
169127668Sbms		if (EXTRACT_32BITS(&ni->rip_router))
170127668Sbms			printf("%s", ipaddr_string(&ni->rip_router));
171127668Sbms                else
172127668Sbms                    printf("self");
17317680Spst	}
174251158Sdelphij	return sizeof (*ni);
17517680Spst}
17617680Spst
17717680Spstvoid
17817680Spstrip_print(const u_char *dat, u_int length)
17917680Spst{
18017680Spst	register const struct rip *rp;
18117680Spst	register const struct rip_netinfo *ni;
182127668Sbms	register u_int i, j;
18317680Spst
184127668Sbms	if (snapend < dat) {
18556893Sfenner		printf(" [|rip]");
18617680Spst		return;
18756893Sfenner	}
188127668Sbms	i = snapend - dat;
189127668Sbms	if (i > length)
190127668Sbms		i = length;
191127668Sbms	if (i < sizeof(*rp)) {
192127668Sbms		printf(" [|rip]");
193127668Sbms		return;
194127668Sbms	}
195127668Sbms	i -= sizeof(*rp);
19617680Spst
19717680Spst	rp = (struct rip *)dat;
198127668Sbms
199127668Sbms        printf("%sRIPv%u",
200127668Sbms               (vflag >= 1) ? "\n\t" : "",
201127668Sbms               rp->rip_vers);
202127668Sbms
20375115Sfenner	switch (rp->rip_vers) {
20475115Sfenner	case 0:
20575115Sfenner		/*
20675115Sfenner		 * RFC 1058.
20775115Sfenner		 *
20875115Sfenner		 * XXX - RFC 1058 says
20975115Sfenner		 *
21075115Sfenner		 * 0  Datagrams whose version number is zero are to be ignored.
21175115Sfenner		 *    These are from a previous version of the protocol, whose
21275115Sfenner		 *    packet format was machine-specific.
21375115Sfenner		 *
214127668Sbms		 * so perhaps we should just dump the packet, in hex.
21598524Sfenner		 */
216127668Sbms                print_unknown_data((u_int8_t *)&rp->rip_cmd,"\n\t",length);
21717680Spst		break;
21817680Spst	default:
219127668Sbms                /* dump version and lets see if we know the commands name*/
220127668Sbms                printf(", %s, length: %u",
221127668Sbms                       tok2str(rip_cmd_values,
222127668Sbms                               "unknown command (%u)",
223127668Sbms                               rp->rip_cmd),
224127668Sbms                       length);
225127668Sbms
226127668Sbms                if (vflag < 1)
227127668Sbms                    return;
228127668Sbms
22975115Sfenner		switch (rp->rip_cmd) {
230251158Sdelphij		case RIPCMD_REQUEST:
23175115Sfenner		case RIPCMD_RESPONSE:
23275115Sfenner			j = length / sizeof(*ni);
233251158Sdelphij                        printf(", routes: %u%s", j, rp->rip_vers == 2 ? " or less" : "");
23475115Sfenner			ni = (struct rip_netinfo *)(rp + 1);
235127668Sbms			for (; i >= sizeof(*ni); ++ni) {
23675115Sfenner				if (rp->rip_vers == 1)
237251158Sdelphij				{
238127668Sbms					rip_entry_print_v1(ni);
239251158Sdelphij					i -= sizeof(*ni);
240251158Sdelphij				}
241127668Sbms				else if (rp->rip_vers == 2)
242251158Sdelphij					i -= rip_entry_print_v2(ni, i);
243127668Sbms                                else
244127668Sbms                                    break;
24575115Sfenner			}
246251158Sdelphij			if (i)
24775115Sfenner				printf("[|rip]");
24875115Sfenner			break;
249127668Sbms
25075115Sfenner		case RIPCMD_TRACEOFF:
25175115Sfenner		case RIPCMD_POLL:
25275115Sfenner		case RIPCMD_POLLENTRY:
25375115Sfenner			break;
254127668Sbms
255127668Sbms		case RIPCMD_TRACEON:
256127668Sbms                    /* fall through */
257127668Sbms	        default:
258127668Sbms                    if (vflag <= 1) {
259127668Sbms                        if(!print_unknown_data((u_int8_t *)rp,"\n\t",length))
260127668Sbms                            return;
261127668Sbms                    }
262127668Sbms                    break;
263127668Sbms                }
264127668Sbms                /* do we want to see an additionally hexdump ? */
265127668Sbms                if (vflag> 1) {
266127668Sbms                    if(!print_unknown_data((u_int8_t *)rp,"\n\t",length))
267127668Sbms                        return;
268127668Sbms                }
269127668Sbms        }
27017680Spst}
271127668Sbms
272127668Sbms
273