/* * 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[] = "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.47 2000-10-03 04:19:07 itojun Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ struct rip { u_char rip_cmd; /* request/response */ u_char rip_vers; /* protocol version # */ u_short rip_zero2; /* 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 */ #define RIP_AUTHLEN 16 struct rip_netinfo { u_short rip_family; u_short 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_printblk(const u_char *cp, const u_char *ep) { for (; cp < ep; cp += 2) printf(" %04x", EXTRACT_16BITS(cp)); return; } static void rip_entry_print_v1(register int vers, register const struct rip_netinfo *ni) { register u_short family; /* RFC 1058 */ family = EXTRACT_16BITS(&ni->rip_family); if (family != AF_INET) { printf(" [family %d:", family); rip_printblk((u_char *)&ni->rip_tag, (u_char *)&ni->rip_metric + sizeof(ni->rip_metric)); printf("]"); return; } if (ni->rip_tag || ni->rip_dest_mask || ni->rip_router) { /* MBZ fields not zero */ printf(" ["); rip_printblk((u_char *)&ni->rip_family, (u_char *)&ni->rip_metric + sizeof(ni->rip_metric)); printf("]"); return; } printf(" {%s}(%d)", ipaddr_string(&ni->rip_dest), EXTRACT_32BITS(&ni->rip_metric)); } static void rip_entry_print_v2(register int vers, register const struct rip_netinfo *ni) { register u_char *p; register u_short family; u_char buf[RIP_AUTHLEN]; /* RFC 1723 */ family = EXTRACT_16BITS(&ni->rip_family); if (family == 0xFFFF) { if (EXTRACT_16BITS(&ni->rip_tag) == 2) { memcpy(buf, &ni->rip_dest, sizeof(buf)); buf[sizeof(buf)-1] = '\0'; for (p = buf; *p; p++) { if (!isprint(*p)) break; } if (!*p) { printf(" [password %s]", buf); } else { printf(" [password: "); rip_printblk((u_char *)&ni->rip_dest, (u_char *)&ni->rip_metric + sizeof(ni->rip_metric)); printf("]"); } } else { printf(" [auth %d:", EXTRACT_16BITS(&ni->rip_tag)); rip_printblk((u_char *)&ni->rip_dest, (u_char *)&ni->rip_metric + sizeof(ni->rip_metric)); printf("]"); } } else if (family != AF_INET) { printf(" [family %d:", family); rip_printblk((u_char *)&ni->rip_tag, (u_char *)&ni->rip_metric + sizeof(ni->rip_metric)); printf("]"); return; } else { /* AF_INET */ printf(" {%s", ipaddr_string(&ni->rip_dest)); if (ni->rip_dest_mask) printf("/%s", ipaddr_string(&ni->rip_dest_mask)); if (ni->rip_router) printf("->%s", ipaddr_string(&ni->rip_router)); if (ni->rip_tag) printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag)); printf("}(%d)", EXTRACT_32BITS(&ni->rip_metric)); } } void rip_print(const u_char *dat, u_int length) { register const struct rip *rp; register const struct rip_netinfo *ni; register int i, j, trunc; i = min(length, snapend - dat) - sizeof(*rp); if (i < 0) { printf(" [|rip]"); return; } rp = (struct rip *)dat; 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 first few words of * the packet, in hex. */ printf(" RIPv0: "); ni = (struct rip_netinfo *)(rp + 1); rip_printblk((u_char *)&ni->rip_family, (u_char *)&ni->rip_metric + sizeof(ni->rip_metric)); break; default: switch (rp->rip_cmd) { case RIPCMD_REQUEST: printf(" RIPv%d-req %d", rp->rip_vers, length); break; case RIPCMD_RESPONSE: j = length / sizeof(*ni); if (j * sizeof(*ni) != length - 4) printf(" RIPv%d-resp [items %d] [%d]:", rp->rip_vers, j, length); else printf(" RIPv%d-resp [items %d]:", rp->rip_vers, j); trunc = (i / sizeof(*ni)) != j; ni = (struct rip_netinfo *)(rp + 1); for (; (i -= sizeof(*ni)) >= 0; ++ni) { if (rp->rip_vers == 1) rip_entry_print_v1(rp->rip_vers, ni); else rip_entry_print_v2(rp->rip_vers, ni); } if (trunc) printf("[|rip]"); break; case RIPCMD_TRACEON: printf(" RIPv%d-traceon %d: \"", rp->rip_vers, length); (void)fn_print((const u_char *)(rp + 1), snapend); fputs("\"\n", stdout); break; case RIPCMD_TRACEOFF: printf(" RIPv%d-traceoff %d", rp->rip_vers, length); break; case RIPCMD_POLL: printf(" RIPv%d-poll %d", rp->rip_vers, length); break; case RIPCMD_POLLENTRY: printf(" RIPv%d-pollentry %d", rp->rip_vers, length); break; default: printf(" RIPv%d-#%d %d", rp->rip_vers, rp->rip_cmd, length); break; } } }