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