/*
** xipshcut.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 08:26:08 1999 
** Last update Thu Nov 18 04:39:01 1999 
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "xip.h"
#include "xipshcut.h"
#include "xipvar.h"
#include "xipres.h"

extern char		*pcap_dev;
extern char		hard_filter[];
extern int		pcap_snaplen;
extern int		pcap_promisc;
extern int		pcap_to_ms;
extern int		pcap_optimize;

t_xip_shortcut_def	xip_shortcuts_defs[] =
{
  {"",
   "<b>%Timestamp%</b>: %Pat% %ether.shost% %ether.dhost% %ether.Type% %Len%"},
  {"arp[7] = 1 && arp[6] = 0",
   "<b>%Timestamp%</b>: arp who-has %arpethip.Tpa% tell %arpethip.Spa%"},
  {"arp[7] = 2 && arp[6] = 0",
   "<b>%Timestamp%</b>: %arpethip.Spa% tells %arpethip.Tpa% he has %arpethip.sha%"},
  {"ip",
   "<b>%Timestamp%</b>: ip hl=%ip.hl% v=%ip.v% tos=%ip.Tos% len=%ip.len% id=%ip.id% off=%ip.off% ttl=%ip.ttl% p=%ip.P% sum=%ip.sum% src=%ip.Src% dst=%ip.Dst% %data.len%"},
  {"icmp",
   "<b>%Timestamp%</b>: icmp %ip.Src% > %ip.Dst% %icmp.Type% %icmp.Code% %data.len%"},
  {"igmp",
   "<b>%Timestamp%</b>: igmp %ip.Src% > %ip.Dst% %igmp.Type% %data.len%"},
  {"udp",
   "<b>%Timestamp%</b>: udp %ip.Src%.%udp.Sport% > %ip.Dst%.%udp.Dport% %data.len%"},
  {"tcp",
   "<b>%Timestamp%</b>: tcp %ip.Src%.%tcp.Sport% > %ip.Dst%.%tcp.Dport% seq %tcp.seq% ack %tcp.ack% win %tcp.win% [%tcp.Flags%] %data.len%"},
  {NULL,NULL},
};

t_xip_shortcut_def	xip_shortcuts_local_defs[] =
{
  {"ip",
   "<b>%Timestamp%</b>: ip hl=%ip.hl% v=%ip.v% tos=%ip.Tos% len=%ip.len% id=%ip.id% off=%ip.off% ttl=%ip.ttl% p=%ip.P% sum=%ip.sum% src=%ip.Src% dst=%ip.Dst% %data.len%"},
  {"icmp",
   "<b>%Timestamp%</b>: icmp %ip.Src% > %ip.Dst% %icmp.Type% %icmp.Code% %data.len%"},
  {"igmp",
   "<b>%Timestamp%</b>: igmp %ip.Src% > %ip.Dst% %igmp.Type% %data.len%"},
  {"udp",
   "<b>%Timestamp%</b>: udp %ip.Src%.%udp.Sport% > %ip.Dst%.%udp.Dport% %data.len%"},
  {"tcp",
   "<b>%Timestamp%</b>: tcp %ip.Src%.%tcp.Sport% > %ip.Dst%.%tcp.Dport% seq %tcp.seq% ack %tcp.ack% win %tcp.win% [%tcp.Flags%] %data.len%"},
  {NULL,NULL},
};

t_vec			*xip_shortcuts_vec = NULL;

/* destroys shortcuts context */
VOID_FUNC		xip_shortcuts_destroy(VOID_DECL)
{
  vec_ptr_delete(xip_shortcuts_vec);
}

extern pcap_t		*pcap;

/* adds a shortcut to shortcuts.
   It is intended to be used by plugins.
   Returns 0 if OK. ERR_XIP_SUBROUTINE if pcap compilation fails. Might
   return various errors. */
t_status		xip_shortcut_add(xsd)
t_xip_shortcut_def	*xsd;
{
  t_status		status;
  t_xip_shortcut	*xs;
  struct bpf_program	bp;

  if (pcap_compile(pcap,&bp,
		   xsd->bpf_program,
		   pcap_optimize,
		   0) < 0)
    {
      err_print(ERR_XIP_SUBROUTINE,"pcap_compile %s",xsd->bpf_program);
      return (ERR_XIP_SUBROUTINE);
    }
  if ((xs = XIP_ALLOC_PROC(sizeof (t_xip_shortcut),
			   "xip",
			   "xip_shortcut_add:ptr",
			   &status)) == NULL)
    return (status);
  xs->html_format = xsd->html_format;
  FBCOPY(&bp,&xs->bp,sizeof (bp));
  if ((status = vec_add(xip_shortcuts_vec,
			xs)) != 0)
    {
      XIP_FREE_PROC(xs,
		    "xip",
		    "*:ptr");
      return (status);
    }
  return (0);
}

/* initializes shortcuts context.
   Returns 0 if OK. Might return various errors */
t_status		xip_shortcuts_init(VOID_DECL)
{
  t_status		status;
  t_xip_shortcut_def	*xsd;

  if ((xip_shortcuts_vec = XIP_VEC_NEW(VEC_BASE,
				       &status)) == NULL)
    {
      err_print(status,"XIP_VEC_NEW");
      exit(1);
    }
  if (pcap_datalink(pcap) == DLT_NULL)
    xsd = xip_shortcuts_local_defs;
  else
    xsd = xip_shortcuts_defs;
  while (xsd->bpf_program)
    {
      if ((status = xip_shortcut_add(xsd)) != 0)
	return (status);
      xsd++;
    }
  return (0);
}

/* catenates an HTML shortcut to string by matching pcap filters.
   Returns 0 if OK. Might return various errors such as ERR_MG_BO. */
t_status		xip_shortcuts_html_do(pkt,str,max_len)
t_pkt			*pkt;
char			*str;
int			max_len;
{
  t_status		status;
  char			tmpl[STR_BUFSIZ];
  char			htmlize[STR_BUFSIZ];
  
  VEC_FOR_REV(xip_shortcuts_vec,t_xip_shortcut *xs)
    {
      if (bpf_filter(xs->bp.bf_insns,
		     (unsigned char *)(pkt->buf),
		     pkt->netlen,
		     pkt->len))
	{
	  tmpl[0] = 0;
	  if ((status = str_cat_str(tmpl,
				    sizeof (tmpl),
				    xs->html_format)) != 0)
	    break ;
	  str[0] = 0;
	  if ((status = str_cat_str(str,
				    max_len,
				    "<html><body>")) != 0)
	    return (status);
	  if ((status = pkt_format_html(pkt,
					TRUE,
					tmpl,
					NULL,
					xip_extra_vars,
					str,
					max_len,
					htmlize,
					sizeof (htmlize))) != 0)
	    return (status);
	  if ((status = str_cat_str(str,
				    max_len,
				    "</body><html>")) != 0)
	    return (status);
	  break ;
	}
    }
  VEC_ENDFOR;
  return (0);
}
