/**************************************************************************** ** File: rip.c ** ** Author: Mike Borella ** ** Comments: Dump RIP header information. ** ** $Id: rip.c,v 1.14 2002/01/03 00:04:01 mborella Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU Library General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** *****************************************************************************/ #include "global.h" #include "rip.h" #define HOLDER_SIZE 64 /* * RIP command map */ strmap_t rip_command_map [] = { { RIP_CMD_RQ, "request" }, { RIP_CMD_RP, "reply" }, { RIP_CMD_POLL, "poll" }, { RIP_CMD_POLL_ENTRY, "poll entry" }, { 0, "" } }; extern struct arg_t * my_args; /*---------------------------------------------------------------------------- ** ** dump_rip() ** ** Parse RIP packet and dump fields ** **---------------------------------------------------------------------------- */ void dump_rip(packet_t *pkt) { ripv1_header_t ripv1; ripv1_route_header_t ripv1_route; ripv2_header_t ripv2; ripv2_route_header_t ripv2_route; ripv2_auth_header_t ripv2_auth; char holder[HOLDER_SIZE]; u_int16_t address_family; int route_count; /* Set the layer */ set_layer(LAYER_APPLICATION); /* * Look at the version to determine whether to use v1 or v2 */ if (look_packet_bytes((u_int8_t *) &ripv1, pkt, sizeof(ripv1_header_t)) == 0) return; if (ripv1.version == 1) { /* RIP v1 processing here */ /* * Get the RIP v1 static header */ if (get_packet_bytes((u_int8_t *) &ripv1, pkt, sizeof(ripv1_header_t)) == 0) return; /* * Dump header */ if (my_args->m) { display_minimal_string("| RIPv1 "); display_minimal_string(map2str(rip_command_map, ripv1.command)); display_minimal_string(" "); } else { /* announcement */ display_header_banner("RIPv1 Header"); snprintf(holder, HOLDER_SIZE, "%d (%s)", ripv1.command, map2str(rip_command_map, ripv1.command)); display_string("Command", holder); display("Version", (u_int8_t *) &ripv1.version, 1, DISP_DEC); display("MBZ", (u_int8_t *) &ripv1.mbz, 2, DISP_DEC); } /* * Do the individual routes. */ route_count = 0; while(1) { if (get_packet_bytes((u_int8_t *) &ripv1_route, pkt, sizeof(ripv1_route_header_t)) == 0) break; /* * Conversions */ ripv1_route.addr_fam = ntohs(ripv1_route.addr_fam); ripv1_route.metric = ntohl(ripv1_route.metric); /* * Dump route header */ if (my_args->m) { /* for minimal mode, we'll just count the routes */ route_count++; } else { display("Address family", (u_int8_t *) &ripv1_route.addr_fam, 2, DISP_DEC); display("MBZ", (u_int8_t *) &ripv1_route.mbz1, 2, DISP_DEC); display_ipv4("IP address", (u_int8_t *) &ripv1_route.ipaddr); display("MBZ", (u_int8_t *) &ripv1_route.mbz2, 8, DISP_HEX); display("Metric", (u_int8_t *) &ripv1_route.metric, 4, DISP_DEC); } } } else { /* RIP v2 processing here */ /* * Get the RIP v2 static header */ if (get_packet_bytes((u_int8_t *) &ripv2, pkt, sizeof(ripv2_header_t)) == 0) return; /* * Conversions */ ripv2.domain = ntohs(ripv2.domain); /* * Dump header */ if (my_args->m) { display_minimal_string("| RIPv2 "); display_minimal_string(map2str(rip_command_map, ripv2.command)); display_minimal_string(" "); } else { /* announcement */ display_header_banner("RIPv2 Header"); snprintf(holder, HOLDER_SIZE, "%d (%s)", ripv2.command, map2str(rip_command_map, ripv2.command)); display_string("Command", holder); display("Version", (u_int8_t *) &ripv2.version, 1, DISP_DEC); display("Domain", (u_int8_t *) &ripv2.domain, 2, DISP_DEC); } /* * Do the individual routes. * First look at the address family to determine the header type. */ route_count = 0; while (1) { if (look_packet_bytes((u_int8_t *) &address_family, pkt, 2) == 0) break;; /* * If its an auth header, deal with it - otherwise its a regular * route header */ if (address_family == 0xffff) { if (get_packet_bytes((u_int8_t *) &ripv2_auth, pkt, sizeof(ripv2_auth_header_t)) == 0) return; /* * Conversions */ ripv2_auth.addr_fam = ntohs(ripv2_auth.addr_fam); ripv2_auth.type = ntohs(ripv2_auth.type); /* * Dump auth header */ if (my_args->m) { /* not sure what to do here... */ } else { display("Address family", (u_int8_t *) &ripv2_auth.addr_fam, 2, DISP_DEC); display("Type", (u_int8_t *) &ripv2_auth.type, 2, DISP_DEC); display_string("Password", ripv2_auth.passwd); } } else { if (get_packet_bytes((u_int8_t *) &ripv2_route, pkt, sizeof(ripv2_route_header_t)) == 0) return; /* * Conversions */ ripv2_route.addr_fam = ntohs(ripv2_route.addr_fam); ripv2_route.route_tag = ntohs(ripv2_route.route_tag); ripv2_route.metric = ntohl(ripv2_route.metric); /* * Dump route header */ if (my_args->m) { /* just count the routes for minimal mode */ route_count++; } else { display("Address family", (u_int8_t *) &ripv2_route.addr_fam, 2, DISP_DEC); display("Route tag", (u_int8_t *) &ripv2_route.route_tag, 2, DISP_DEC); display_ipv4("IP address", (u_int8_t *) &ripv2_route.ipaddr); display_ipv4("Netmask", (u_int8_t *) &ripv2_route.netmask); display_ipv4("Next hop", (u_int8_t *) &ripv2_route.next_hop); display("Metric", (u_int8_t *) &ripv2_route.metric, 4, DISP_DEC); } } } /* while */ } /* display routes for minimal mode */ if (my_args->m) { display_minimal((u_int8_t *) &route_count, 4, DISP_DEC); display_minimal_string(" routes "); } }