#include <stdio.h>
#include <libnd.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <netinet/ip.h>

int char_limit = 100;

void
proto_cb(LND_Packet *packet, LND_ProtoData *pd, void *user_data)
{
  guchar *ptr = pd->data;
  int limit = 0;

  if (pd->inst.proto != libnd_raw_proto_get())
    {
      printf("[%s]", pd->inst.proto->name);
      return;
    }

  printf("[");

  while (ptr != pd->data_end && limit < char_limit)
    {
      char c = *ptr++;
      printf("%c", (c >= 32 && c <= 126 ? c : '.'));
      limit++;
    }
      
  printf("]");

}

void
usage(void)
{
  printf("USAGE: lnd-headerwalk [-l <num>] <trace file>\n"
	 "lnd-headerwalk reads a tcpdump trace file and prints for each packet\n"
	 "the sequence of protocols it finds in the packet, plus any raw payload\n"
	 "that remains uninterpreted. -l, if given, can be used to limit the\n"
	 "number of bytes of raw output shown. Default is 100.\n");
  exit(0);	     
}

int
main(int argc, char **argv)
{
  LND_Trace          *trace;
  LND_PacketIterator  pit;
  int count = 1;
  int c;

  libnd_init();

  opterr = 0;

  while ( (c = getopt (argc, argv, "l:")) != -1)
    switch (c)
      {
      case 'l':
	char_limit = atoi(optarg);
	break;
	
      default:
	usage();
      }

  if (optind >= argc)
    usage();

  if (char_limit < 0)
    char_limit = INT_MAX;

  /* Open a tracefile: */
  if (! (trace = libnd_trace_new(argv[optind])))
    {
      printf("Could not open %s\n", argv[optind]);
      exit(-1);
    }
        
  for (libnd_pit_init(&pit, trace); libnd_pit_get(&pit); libnd_pit_next(&pit))
    {
      printf("%i: ", count++);
      libnd_packet_foreach_proto(libnd_pit_get(&pit), proto_cb, NULL);
      printf("\n");
    }

  return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1