/****************************************************************************
** 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 ");
}
}
syntax highlighted by Code2HTML, v. 0.9.1