/*
 * Copyright (c) 1992 Purdue University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by Purdue University.  The name of the University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/stream.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <net/if.h>
#include "dp_str.h"
#include "dp.h"
#include "dpconf.h"

typedef struct date_req {
    int tod;
    struct dp_req req;
} date_req;

char *argv0;
main(argc, argv)
int argc;
char **argv;
{
    struct date_req req;
    char *tf;
    FILE *rf;

    argv0 = argv[0];

    init_pathconf();
    tf = expand_dir_file("$DPLOG_DIR", TRACE_FILE);
    rf = fopen(tf, "r");

    if (rf == NULL) {
	fprintf(stderr, "%s: can't open trace file \"%s\"\n", argv0, tf);
	exit(1);
    }
    while (get_req(rf, &req))
	print_req(&req);
}

get_req(rf, rp)
FILE *rf;
date_req *rp;
{
    int n;
    if (!fread((char *)&rp->tod, sizeof(rp->tod), 1, rf))
	return 0;
    if (!fread((char *)&rp->req.dr_info, sizeof(rp->req.dr_info), 1, rf))
	return 0;
    n = rp->req.dr_info.dri_hdrlen;
    if (n < DR_MINHDRLEN || n > DR_MAXHDRLEN) {
	fprintf(stderr, "%s: garbled trace file\n", argv0);
	return 0;
    }
    return fread(rp->req.dr_hdr.drh_data, 1, n, rf);
}

print_req(dr)
struct date_req *dr;
{
    struct dp_req *r = &dr->req;
    printf("if: %s%-2d  flag %d ",
	   r->dr_ifname, r->dr_ifunit, r->dr_flag);
    printf("%s", ctime(&dr->tod));
    print_sin(&r->dr_sin);
    print_ip(&r->dr_ip);
    printf("\n");
}

print_ip(ip)
struct ip *ip;
{
    struct udphdr *uh;
    char line1[64], line2[64];
    sprintf(line1, "ip: len:     %2d", ip->ip_len);
    sprintf(line2, "    proto:   %2d", ip->ip_p);
    switch (ip->ip_p) {
     case IPPROTO_TCP:
	{
	    struct tcphdr *th = (struct tcphdr *)(ip+1);
	    printf("%-16s src:  %s.%d\n", line1,
		   inet_ntoa(ip->ip_src), th->th_sport);
	    printf("%-16s dst:  %s.%d\n", line2,
		   inet_ntoa(ip->ip_dst), th->th_dport);
	}
	break;
     case IPPROTO_UDP:
	{
	    struct udphdr *uh = (struct udphdr *)(ip+1);
	    printf("%-16s src:  %s.%d\n", line1,
		   inet_ntoa(ip->ip_src), uh->uh_sport);
	    printf("%-16s dst:  %s.%d\n", line2,
		   inet_ntoa(ip->ip_dst), uh->uh_dport);
	}
	break;
     default:
	printf("%-16s src:  %s\n", line1, inet_ntoa(ip->ip_src));
	printf("%-16s dst:  %s\n", line2, inet_ntoa(ip->ip_dst));
	break;
    }
}

print_sin(sin)
struct sockaddr_in *sin;
{
    printf("dst: family: %2d  ", sin->sin_family);
    printf("addr: %s\n", inet_ntoa(sin->sin_addr));
}

#include <varargs.h>

void
yyerror(va_alist)
va_dcl
{
    va_list ap;
    char *path,
	 *fmt,
	 buff[256];
    extern int linenum;

    va_start(ap);
    path = va_arg(ap, char *);
    fmt = va_arg(ap, char *);
    (void)sprintf(buff, "Error near line %d of\n\t\"%s\":  %s",
	linenum, path, fmt);
    fprintf(stderr, "%s: %s\n", argv0, buff);
    va_end(ap);
}
