/*  -*- Mode: C;  -*- */

/******************************************************************************
*                                                                             *
*   Copyright 2005 University of Cambridge Computer Laboratory.               *
*                                                                             *
*   This file is part of Nprobe.                                              *
*                                                                             *
*   Nprobe 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.                                       *
*                                                                             *
*   Nprobe 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 General Public License for more details.                              *
*                                                                             *
*   You should have received a copy of the GNU General Public License         *
*   along with Nprobe; if not, write to the Free Software                     *
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
*                                                                             *
******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <asm/page.h>
#ifdef __alpha__
#include <sys/mbuf.h>
#endif
#include <net/route.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>

#ifdef __linux__
#define __USE_BSD
#endif
#include <netinet/ip.h>


#include <netinet/tcp.h>
#ifdef __alpha__
#include <net/if_llc.h>
#endif
#include <netinet/if_fddi.h>
#include <netinet/if_ether.h>

#ifdef __linux__
#include "if_llc.h"
#endif

#include <linux/limits.h>

#include <unistd.h>
#include <assert.h>

#include "list.h"
#include "pkt.h"
#include "interface.h"
#include "tcpdump_patch.h"
#include "flows.h"
#include "service.h"
#include "http.h"
#include "tcp.h"
#include "udp.h"
#include "udp_ns.h"
#include "print_util.h"
#include "report.h"
#include "output.h"
#include "if_nprobe.h"
#include "tcpdump_patch.h"
#include "writer.h"
#include "content_t.h"

#include "cprintf.h"

#ifndef _alpha_
#define MIN(x, y) ((x) > (y) ? (y) : (x))
#endif


void 
error(char *msg, char *pmsg)
{
  /* is writer running? - kill it off */
  if (writer_pid != 0)
    {
      int wait_ret;
      output_finished++;
      wait_ret = waitpid(writer_pid, NULL, 0);
      fprintf(stderr, "(error - writer terminated (wait returned %d))\n",
	  wait_ret);
    }
    
#ifdef PRINT_OUT
  fprintf(stderr, "%s: FATAL ERROR %s: \n", prog, msg);
  if (pmsg && errno)
    perror(pmsg);
  exit (1);
#else
  fprintf(stderr, "FATAL ERROR %s: %s %s\n", msg, pmsg, 
	  errno ? strerror(errno) : "");
  exit (1);
#endif
}

  

void 
http_error(tcp_conn_t *tconnp, prec_t *pp, int err, int way, char *data)
{
  int got_trans = (int)
    (way == CLIENT ? tconnp->su.http.reqtrans : tconnp->su.http.reptrans);
  unsigned int atmdata = 
    (way == CLIENT ? tconnp->flow_common.inner.src_atmdata 
     : tconnp->flow_common.inner.dst_atmdata);

  BUMP_CTR(http_errs[-err]); // err is < 0

  TCP_STATE |= (way == SERVER ? TCP_SERV_SERV_ERR : TCP_CLI_SERV_ERR);

#if defined PRINT_OUT

  CPRINT_ERR(F_RED, "HTTP ERROR %s:%u>", 
	  inet_ntoa(*((struct in_addr *)&(((host_flow_t *)(tconnp->hconnp))->srcaddr))), 
	  ntohs(tconnp->srcport));
  
  CPRINT_ERR(F_RED, "%s:%u %s\n", 
	  inet_ntoa(*((struct in_addr *)&(((host_flow_t *)(tconnp->hconnp))->dstaddr))), 
	  ntohs(tconnp->dstport), http_err_string(err));
#else


  dump_pkt(pp, err, data, atmdata);

#endif
  
  /* if a current transaction mark it */
  if (got_trans)
    {
      if (way == SERVER)
	{
	  HTTP_REP_ERR = err & 0xff;
	  HTTP_REP_TRANS_STATUS |= TRANS_ERR;
	  HTTP_LASTREP_SEEN = TCP_SSOLID_TM;
	}
      else
	{
	  HTTP_REQ_ERR = err & 0xff;
	  HTTP_REQ_TRANS_STATUS |= TRANS_ERR;
	  HTTP_LASTREQ_SEEN = TCP_CSOLID_TM;
	}
      //pp->buf += pp->len;
      //pp->len = 0;
    }

  /* get a dummy trans to collect rest of the flow */
  new_http_trans(tconnp, way);
  HTTP_NTRANS_DUM++;	 
  if (way == SERVER)
    {
      //HTTP_REP_RECD_LEN += pp->len;
      HTTP_REP_TRANS_STATUS |= TRANS_DUMMY_ERR;
      HTTP_REP_CONTENT_T = CT_POST_ERR;
      HTTP_FIRSTREP_SEEN = TCP_SSOLID_TM;
      HTTP_LASTREP_SEEN = TCP_SSOLID_TM;
      HTTP_LASTDATA_SEEN = TCP_SSOLID_TM;
    }
  else
    {
      //HTTP_REQ_RECD_LEN += pp->len;
      HTTP_REQ_TRANS_STATUS |= TRANS_DUMMY_ERR;
      HTTP_REQ_CONTENT_T = CT_POST_ERR;
      HTTP_FIRSTREQ_SEEN = TCP_SSOLID_TM;
      HTTP_LASTREQ_SEEN = TCP_SSOLID_TM;
    }
  
}


void 
udp_error(udp_conn_t *uconnp, prec_t *pp, int err, int way)
{
  unsigned int atmdata = 
    (way == CLIENT ? uconnp->flow_common.inner.src_atmdata 
     : uconnp->flow_common.inner.dst_atmdata);

  BUMP_CTR(http_errs[-err]); // err is < 0

  UDP_STATE |= (way == SERVER ? UDP_SERV_SERV_ERR : UDP_CLI_SERV_ERR);

#if defined PRINT_OUT

  CPRINT_ERR(F_RED, "UD ERROR %s:%u>", 
	  inet_ntoa(*((struct in_addr *)&(((host_flow_t *)(uconnp->hconnp))->srcaddr))), 
	  ntohs(uconnp->srcport));
  
  CPRINT_ERR(F_RED, "%s:%u %s\n", 
	  inet_ntoa(*((struct in_addr *)&(((host_flow_t *)(uconnp->hconnp))->dstaddr))), 
	  ntohs(uconnp->dstport), http_err_string(err));
#else

  dump_pkt(pp, err, NULL, atmdata);

#endif
  
  fprintf(stderr, "XXXX NS ERROR\n");
}

void 
inform(char *col, char *emsg)
{
#ifdef PRINT_OUT
  CPRINT_ERR(col, "INFORM %s\n", emsg);
#else
  //PRINT_ERR("INFORM %s\n", emsg);
#endif
  return;
}


/*
 * end error.c 
 */
