/*
 * Copyright (c) 1988-1990 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 char rcsid[] =
    "@(#) $Header: /usr/staff/martinh/tcpview/RCS/detail-rip.c,v 1.1 1993/04/22 20:17:03 martinh Exp $ (UW)";
#endif

#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <protocols/routed.h>

#include <errno.h>

#include "tcpview.h"
#include "interface.h"
#include "addrtoname.h"

#ifdef __STDC__
static void do_version(register struct rip *rp);
#else
static void do_version();
#endif

static void rip_entry_print(ni,metric)
     register struct netinfo *ni;
     int metric;
{
  char *str1, *str2;

  if (ntohs(ni->rip_dst.sa_family) != AF_INET) {
    register int i;
    
    printf(" [family %d:", ntohs(ni->rip_dst.sa_family));
    for (i = 0; i < 14; i += 2)
      printf(" %02x%02x", ni->rip_dst.sa_data[i],
	     ni->rip_dst.sa_data[i+1]);
    printf("] ");
  } else {
    register struct sockaddr_in *sin = (struct sockaddr_in *)&ni->rip_dst;
    str1 = ipaddr_str(&sin->sin_addr,ADDR_NUMERICAL);
    str2 = ipaddr_str(&sin->sin_addr,0);
    if( strcmp(str1,str2) ) 
      printf("%s [%s] ", str2, str1); 
    else
      printf("%-16s ",str2); 
    if (sin->sin_port)
      printf("[port %d] ", sin->sin_port);
  }
  if( metric ) 
    printf("\t%d\n", ntohl(ni->rip_metric));
  else
    printf("\n");
  hex(0,19);
  Offset += 20;
}

/* dat points to beginning of rip message */
/* amt = Phdr->caplen - Offset is number of bytes left to process */
/* length is number of bytes in message (may not be all captured) */

void detail_rip(dat, length)
     u_char *dat;
     int length;
{
  register struct rip *rp = (struct rip *)dat;
  register struct netinfo *ni;
  register int amt = Phdr->caplen - Offset;
  register int i = min(length, amt) -
    (sizeof(struct rip) - sizeof(struct netinfo));

  int j;
  int trunc;
  
  if (i < 0) /* no nets to print */
    return;

  j = length / sizeof(*ni);  /* number of nets in message */
  trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); /* truncated net? */

  printf("----- RIP Header -----\n\n");
  hex(0, 1);
  hex(-1,-1);

  switch (rp->rip_cmd) {    
  case RIPCMD_REQUEST:
    printf("REQUEST (%d nets)\n",j);
    hex(0,0);
    do_version(rp);
    Offset += 4; /* skip over RIP header */
    for (ni = rp->rip_nets; (i -= sizeof(*ni)) >= 0; ++ni) {
      rip_entry_print(ni,0);  
    }
    if (trunc) {
      printf("-truncated-\n");
      hex(-1,-1);
    }
    break;
  case RIPCMD_RESPONSE:
    printf("RESPONSE (%d nets)\n",j);
    hex(0,0);
    do_version(rp);
    Offset += 4; /* skip over RIP header */
    for (ni = rp->rip_nets; (i -= sizeof(*ni)) >= 0; ++ni) {
      rip_entry_print(ni,1);  
    }
    if (trunc) {
      printf("-truncated-\n");
      hex(-1,-1);
    }
    break;
  case RIPCMD_TRACEON:
    printf("TRACEON  (This is an obsolete command)\n");
    do_version(rp);
    hex(0,0);
    break;
  case RIPCMD_TRACEOFF:
    printf("TRACEOFF  (This is an obsolete command)\n");
    do_version(rp);
    hex(0,0);
    break;
  case RIPCMD_POLL:
    printf("POLL\n");
    do_version(rp);
    hex(0,0);
    break;
  case RIPCMD_POLLENTRY:
    printf("POLLENTRY\n");
    do_version(rp);
    hex(0,0);
    break;
  default:
    printf("unknown command %d\n", rp->rip_cmd);
    do_version(rp);
    hex(0,0);
    break;
  }
}

static void do_version(rp)
     register struct rip *rp;
{
  if( rp->rip_vers == 1 )
    printf("VERSION: 1\n");
  else 
    printf("VERSION: %d ( WARNING: should be 1 )\n",rp->rip_vers);
  hex(1,1);
}


syntax highlighted by Code2HTML, v. 0.9.1