diff options
Diffstat (limited to 'contrib/tcpdump/print-rip.c')
-rw-r--r-- | contrib/tcpdump/print-rip.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/contrib/tcpdump/print-rip.c b/contrib/tcpdump/print-rip.c new file mode 100644 index 0000000..27446a6 --- /dev/null +++ b/contrib/tcpdump/print-rip.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996 + * The 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: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.59 2006-03-23 14:58:44 hannes Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <tcpdump-stdinc.h> + +#include <stdio.h> +#include <string.h> + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +#include "af.h" + +struct rip { + u_int8_t rip_cmd; /* request/response */ + u_int8_t rip_vers; /* protocol version # */ + u_int8_t unused[2]; /* unused */ +}; + +#define RIPCMD_REQUEST 1 /* want info */ +#define RIPCMD_RESPONSE 2 /* responding to request */ +#define RIPCMD_TRACEON 3 /* turn tracing on */ +#define RIPCMD_TRACEOFF 4 /* turn it off */ +#define RIPCMD_POLL 5 /* want info from everybody */ +#define RIPCMD_POLLENTRY 6 /* poll for entry */ + +static const struct tok rip_cmd_values[] = { + { RIPCMD_REQUEST, "Request" }, + { RIPCMD_RESPONSE, "Response" }, + { RIPCMD_TRACEON, "Trace on" }, + { RIPCMD_TRACEOFF, "Trace off" }, + { RIPCMD_POLL, "Poll" }, + { RIPCMD_POLLENTRY, "Poll Entry" }, + { 0, NULL} +}; + +#define RIP_AUTHLEN 16 +#define RIP_ROUTELEN 20 + +/* + * rfc 1723 + * + * 0 1 2 3 3 + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Command (1) | Version (1) | unused | + * +---------------+---------------+-------------------------------+ + * | Address Family Identifier (2) | Route Tag (2) | + * +-------------------------------+-------------------------------+ + * | IP Address (4) | + * +---------------------------------------------------------------+ + * | Subnet Mask (4) | + * +---------------------------------------------------------------+ + * | Next Hop (4) | + * +---------------------------------------------------------------+ + * | Metric (4) | + * +---------------------------------------------------------------+ + * + */ + +struct rip_netinfo { + u_int16_t rip_family; + u_int16_t rip_tag; + u_int32_t rip_dest; + u_int32_t rip_dest_mask; + u_int32_t rip_router; + u_int32_t rip_metric; /* cost of route */ +}; + +static void +rip_entry_print_v1(register const struct rip_netinfo *ni) +{ + register u_short family; + + /* RFC 1058 */ + family = EXTRACT_16BITS(&ni->rip_family); + if (family != BSD_AFNUM_INET) { + printf("\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family)); + print_unknown_data((u_int8_t *)&ni->rip_family,"\n\t ",RIP_ROUTELEN); + return; + } + if (EXTRACT_16BITS(&ni->rip_tag) || + EXTRACT_32BITS(&ni->rip_dest_mask) || + EXTRACT_32BITS(&ni->rip_router)) { + /* MBZ fields not zero */ + print_unknown_data((u_int8_t *)&ni->rip_family,"\n\t ",RIP_ROUTELEN); + return; + } /* BSD_AFNUM_INET */ + printf("\n\t %s, metric: %u", + ipaddr_string(&ni->rip_dest), + EXTRACT_32BITS(&ni->rip_metric)); +} + +static void +rip_entry_print_v2(register const struct rip_netinfo *ni) +{ + register u_char *p; + register u_short family; + u_char buf[RIP_AUTHLEN]; + + family = EXTRACT_16BITS(&ni->rip_family); + if (family == 0xFFFF) { /* 16 bytes authentication ? */ + if (EXTRACT_16BITS(&ni->rip_tag) == 2) { /* simple text authentication ? */ + memcpy(buf, &ni->rip_dest, sizeof(buf)); + buf[sizeof(buf)-1] = '\0'; + for (p = buf; *p; p++) { + if (!isprint(*p)) + break; + } + printf("\n\t Simple Text Authentication data: %s", buf); + } else { + printf("\n\t Unknown (%u) Authentication data:", + EXTRACT_16BITS(&ni->rip_tag)); + print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t ",RIP_AUTHLEN); + } + } else if (family != BSD_AFNUM_INET) { + printf("\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family)); + print_unknown_data((u_int8_t *)&ni->rip_tag,"\n\t ",RIP_ROUTELEN-2); + return; + } else { /* BSD_AFNUM_INET */ + printf("\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ", + tok2str(bsd_af_values, "Unknown (%u)", family), + ipaddr_string(&ni->rip_dest), + mask2plen(EXTRACT_32BITS(&ni->rip_dest_mask)), + EXTRACT_16BITS(&ni->rip_tag), + EXTRACT_32BITS(&ni->rip_metric)); + if (EXTRACT_32BITS(&ni->rip_router)) + printf("%s", ipaddr_string(&ni->rip_router)); + else + printf("self"); + } +} + +void +rip_print(const u_char *dat, u_int length) +{ + register const struct rip *rp; + register const struct rip_netinfo *ni; + register u_int i, j; + register int trunc; + + if (snapend < dat) { + printf(" [|rip]"); + return; + } + i = snapend - dat; + if (i > length) + i = length; + if (i < sizeof(*rp)) { + printf(" [|rip]"); + return; + } + i -= sizeof(*rp); + + rp = (struct rip *)dat; + + printf("%sRIPv%u", + (vflag >= 1) ? "\n\t" : "", + rp->rip_vers); + + switch (rp->rip_vers) { + case 0: + /* + * RFC 1058. + * + * XXX - RFC 1058 says + * + * 0 Datagrams whose version number is zero are to be ignored. + * These are from a previous version of the protocol, whose + * packet format was machine-specific. + * + * so perhaps we should just dump the packet, in hex. + */ + print_unknown_data((u_int8_t *)&rp->rip_cmd,"\n\t",length); + break; + default: + /* dump version and lets see if we know the commands name*/ + printf(", %s, length: %u", + tok2str(rip_cmd_values, + "unknown command (%u)", + rp->rip_cmd), + length); + + if (vflag < 1) + return; + + switch (rp->rip_cmd) { + case RIPCMD_RESPONSE: + j = length / sizeof(*ni); + printf(", routes: %u",j); + trunc = (i / sizeof(*ni)) != j; + ni = (struct rip_netinfo *)(rp + 1); + for (; i >= sizeof(*ni); ++ni) { + if (rp->rip_vers == 1) + rip_entry_print_v1(ni); + else if (rp->rip_vers == 2) + rip_entry_print_v2(ni); + else + break; + i -= sizeof(*ni); + } + if (trunc) + printf("[|rip]"); + break; + + case RIPCMD_REQUEST: + case RIPCMD_TRACEOFF: + case RIPCMD_POLL: + case RIPCMD_POLLENTRY: + break; + + case RIPCMD_TRACEON: + /* fall through */ + default: + if (vflag <= 1) { + if(!print_unknown_data((u_int8_t *)rp,"\n\t",length)) + return; + } + break; + } + /* do we want to see an additionally hexdump ? */ + if (vflag> 1) { + if(!print_unknown_data((u_int8_t *)rp,"\n\t",length)) + return; + } + } +} + + |