/*
** pat_pat.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:42:14 1999 
** Last update Thu Oct 28 20:19:48 1999 
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "pat.h"
#include "pat_pat.h"
#include "pat_16.h"
#include "pat_32.h"
#include "pat_8.h"
#include "pat_arp.h"
#include "pat_boolean.h"
#include "pat_bootp.h"
#include "pat_buf.h"
#include "pat_bytebuf.h"
#include "pat_data.h"
#include "pat_dns.h"
#include "pat_ethaddr.h"
#include "pat_ether.h"
#include "pat_icmp.h"
#include "pat_icmpcode.h"
#include "pat_ieee802.h"
#include "pat_igmp.h"
#include "pat_inaddr.h"
#include "pat_ip.h"
#include "pat_ipproto.h"
#include "pat_mac.h"
#include "pat_null.h"
#include "pat_pad.h"
#include "pat_port.h"
#include "pat_rip.h"
#include "pat_rpc.h"
#include "pat_rpcnum.h"
#include "pat_seqack.h"
#include "pat_shortbuf.h"
#include "pat_subnet.h"
#include "pat_sz.h"
#include "pat_tcp.h"
#include "pat_tftp.h"
#include "pat_time.h"
#include "pat_tr.h"
#include "pat_udp.h"

t_dict			*pat_dict = NULL;

/* adds a pat to the pat dictionary.
   Returns 0 if OK. Might return various errors */
t_status		pat_add(pat)
t_pat			*pat;
{
  char			name[STR_BUFSIZ];
  t_status		status;
  
  assert(pat_dict);
  if (!pat->name_proc)
    return (ERR_PAT_NO_METHOD_NAME);
  name[0] = 0;
  if ((status = pat->name_proc(NULL,
			       NULL,
			       name,
			       sizeof (name))) != 0)
    return (status);
  if ((status = dict_add(pat_dict,
			 name,
			 (VOID_PTR)pat)) != 0)
    return (status);
  return (0);
}

/* initializes the pat dictionary with all the classes provided by libpat.
   Dictionary is small (HASH_SMALL_BASE).
   Returns 0 if OK. Might return various errors */
t_status		pat_dict_init(VOID_DECL)
{
  t_status		status;
  
  if ((pat_dict = PAT_DICT_NEW(HASH_SMALL_BASE,
			       VEC_BASE,
			       &status)) == NULL)
    return (status);
  if (((status = pat_add(&arp_pat)) != 0) ||
      ((status = pat_add(&arpethip_pat)) != 0) ||
      ((status = pat_add(&boolean_pat)) != 0) ||
      ((status = pat_add(&bootp_pat)) != 0) ||
      ((status = pat_add(&buf_pat)) != 0) ||
      ((status = pat_add(&bufstruntil_pat)) != 0) ||
      ((status = pat_add(&bufassoc_pat)) != 0) ||
      ((status = pat_add(&bufuntil_pat)) != 0) ||
      ((status = pat_add(&bytebuf_pat)) != 0) ||
      ((status = pat_add(&bytebuf_string_pat)) != 0) ||
      ((status = pat_add(&ascii_pat)) != 0) ||
      ((status = pat_add(&data_pat)) != 0) ||
      ((status = pat_add(&dataebcdic_pat)) != 0) ||
      ((status = pat_add(&datalen_pat)) != 0) ||
      ((status = pat_add(&dhcpoverload_pat)) != 0) ||
      ((status = pat_add(&dhcpparam_pat)) != 0) ||
      ((status = pat_add(&dhcptype_pat)) != 0) ||
      ((status = pat_add(&dns_pat)) != 0) ||
      ((status = pat_add(&dnsqname_pat)) != 0) ||
      ((status = pat_add(&dnsqtype_pat)) != 0) ||
      ((status = pat_add(&dnsrdata_pat)) != 0) ||
      ((status = pat_add(&dnsrttl_pat)) != 0) ||
      ((status = pat_add(&ether_pat)) != 0) ||
      ((status = pat_add(&etheraddr_pat)) != 0) ||
      ((status = pat_add(&icmp_pat)) != 0) ||
      ((status = pat_add(&icmpcodeagainsttype_pat)) != 0) ||
      ((status = pat_add(&icmpmask_pat)) != 0) ||
      ((status = pat_add(&icmpmbz_pat)) != 0) ||
      ((status = pat_add(&icmpredirect_pat)) != 0) ||
      ((status = pat_add(&icmpts_pat)) != 0) ||
      ((status = pat_add(&igmp_pat)) != 0) ||
      ((status = pat_add(&inaddr_pat)) != 0) ||
      ((status = pat_add(&inaddrmask_pat)) != 0) ||
      ((status = pat_add(&inaddrrouter_pat)) != 0) ||
      ((status = pat_add(&inaddr_resolved_pat)) != 0) ||
      ((status = pat_add(&inaddrtime_pat)) != 0) ||
      ((status = pat_add(&ip_pat)) != 0) ||
      ((status = pat_add(&ipopt_pat)) != 0) ||
      ((status = pat_add(&ipoptdata_pat)) != 0) ||
      ((status = pat_add(&ipproto_pat)) != 0) ||
      ((status = pat_add(&llc_pat)) != 0) ||
      ((status = pat_add(&mac_pat)) != 0) ||
      ((status = pat_add(&netbiostype_pat)) != 0) ||
      ((status = pat_add(&ns16_pat)) != 0) ||
      ((status = pat_add(&ns32_pat)) != 0) ||
      ((status = pat_add(&nu16_pat)) != 0) ||
      ((status = pat_add(&nu16assoc_pat)) != 0) ||
      ((status = pat_add(&nu16bitfield_pat)) != 0) ||
      ((status = pat_add(&u16bitfield_pat)) != 0) ||
      ((status = pat_add(&nu16bitfieldassoc_pat)) != 0) ||
      ((status = pat_add(&nu32_pat)) != 0) ||
      ((status = pat_add(&nu32assoc_pat)) != 0) ||
      ((status = pat_add(&null_pat)) != 0) ||
      ((status = pat_add(&pad_pat)) != 0) ||
      ((status = pat_add(&pat_pat)) != 0) ||
      ((status = pat_add(&port_resolved_pat)) != 0) ||
      ((status = pat_add(&rfc2132opt_pat)) != 0) ||
      ((status = pat_add(&rfc2132optdata_pat)) != 0) ||
      ((status = pat_add(&rip_pat)) != 0) ||
      ((status = pat_add(&ripinfo_pat)) != 0) ||
      ((status = pat_add(&rpc_pat)) != 0) ||
      ((status = pat_add(&rpccall_pat)) != 0) ||
      ((status = pat_add(&rpcnum_resolved_pat)) != 0) ||
      ((status = pat_add(&s8_pat)) != 0) ||
      ((status = pat_add(&seqack_pat)) != 0) ||
      ((status = pat_add(&shortbuf_pat)) != 0) ||
      ((status = pat_add(&snap_pat)) != 0) ||
      ((status = pat_add(&subnet_pat)) != 0) || 
      ((status = pat_add(&sz_pat)) != 0) ||
      ((status = pat_add(&tcp_pat)) != 0) ||
      ((status = pat_add(&tcpopt_pat)) != 0) ||
      ((status = pat_add(&tcpoptdata_pat)) != 0) ||
      ((status = pat_add(&tftp_pat)) != 0) ||
      ((status = pat_add(&tftpbn_pat)) != 0) ||
      ((status = pat_add(&tftperror_pat)) != 0) ||
      ((status = pat_add(&tftpfname_pat)) != 0) ||
      ((status = pat_add(&tftpmode_pat)) != 0) ||
      ((status = pat_add(&time_pat)) != 0) ||
      ((status = pat_add(&tr_pat)) != 0) ||
      ((status = pat_add(&trrif_pat)) != 0) ||
      ((status = pat_add(&u16_pat)) != 0) ||
      ((status = pat_add(&u32_pat)) != 0) ||
      ((status = pat_add(&u32assoc_pat)) != 0) ||
      ((status = pat_add(&u32mask_pat)) != 0) ||
      ((status = pat_add(&u8_pat)) != 0) ||
      ((status = pat_add(&u8assoc_pat)) != 0) ||
      ((status = pat_add(&u8bitfield_pat)) != 0) ||
      ((status = pat_add(&u8bitfieldassoc_pat)) != 0) ||
      ((status = pat_add(&u8mask_pat)) != 0) ||
      ((status = pat_add(&udp_pat)) != 0))
    return (status);
  return (0);
}

/* destroys the pat dictionary */
VOID_FUNC		pat_dict_destroy(VOID_DECL)
{
  assert(pat_dict);
  dict_delete(pat_dict);
}

/* converts-and-catenates a pat to a bridled string.
   Performs a simple PAT_NAME (with optional_id set to NULL).
   Returns 0 if OK. */
t_status		pat_to_str(pat,str,max_len)
t_pat			*pat;		
char			*str;		/* Destination string */
int			max_len;	/* Dest. string length */	
{
  t_status		status;
  
  if (!pat->name_proc)
    return (ERR_PAT_NO_METHOD_NAME);
  return (pat->name_proc(NULL,
			 NULL,
			 str,
			 max_len));
}

/* converts a string to a pat.
   Note that the pat dictionary must be initialized. 
   Returns a pat or NULL if it has failed */
t_pat			*pat_from_str(str,status)
char			*str;		/* E.g "ip" */
t_status		*status;	/* Filled if NULL */
{
  t_hash_elt		*he;

  assert(pat_dict);
  if (he = dict_get(pat_dict,str))
    {
      return ((t_pat *)(he->value));
    }
  else
    {
      (*status) = ERR_PAT_NO_ENT;
      return (NULL);
    }
}

t_status		pat_get_choices_walk(he,vec_str)
t_hash_elt		*he;
t_vec			*vec_str;
{
  return (vec_str_add(vec_str,he->key));
}

/* gets all the pats names in a vector of strings.
   Note that pat dictionary must be initialized.
   Returns 0 if OK. Might return various errors */
t_status		pat_get_choices(vec_str)
t_vec			*vec_str;		/* Vector of strings */
{
  return (dict_walk(pat_dict,
		    (t_dict_walk_proc)pat_get_choices_walk,
		    vec_str));
}

t_status		pat_displayable_get_choices_walk(he,vec_str)
t_hash_elt		*he;
t_vec			*vec_str;
{
  t_pat			*pat;

  pat = (t_pat *)(he->value);
  if (pat->get_tmpl_proc)
    return (vec_str_add(vec_str,he->key));
  else
    return (0);
}

/* gets all the pats names in a vector of strings.
   Note that pat dictionary must be initialized.
   Returns 0 if OK. Might return various errors */
t_status		pat_displayable_get_choices(vec_str)
t_vec			*vec_str;		/* Vector of strings */
{
  return (dict_walk(pat_dict,
		    (t_dict_walk_proc)pat_displayable_get_choices_walk,
		    vec_str));
}

int	pat_chan;

PAT_NAME_GENERIC(pat_pat_name,
		 (VOID_PTR)&pat_chan,
		 "pat")

PAT_EXTRACT_DECL(pat_pat_extract)
{
  t_pat		*pat;

  if (len < sizeof (t_pat *))
    return (ERR_PAT_TRUNC_FIELD);
  FBCOPY(buf,&pat,sizeof (t_pat *));
  return (pat_to_str(pat,
		     str,
		     max_len));
}

PAT_INSERT_DECL(pat_pat_insert)
{
  t_pat		*pat;
  t_status	status;	

  if (len < sizeof (t_pat *))
    return (ERR_PAT_TRUNC_FIELD);
  if ((pat = pat_from_str(value,
			  &status)) == NULL)
    return (status);
  FBCOPY(&pat,buf,sizeof (t_pat *));
  return (0);
}

PAT_GET_CHOICES_DECL(pat_pat_get_choices)
{
  return (pat_get_choices(vec_str));
}

t_pat				pat_pat = 
{
  pat_pat_name,			/* t_pat_name_proc		*/
  NULL,				/* t_pat_off_proc		*/
  NULL,				/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  NULL,				/* t_pat_get_field_proc		*/
  NULL,				/* t_pat_set_field_proc		*/
  NULL,				/* t_pat_get_fields_proc	*/
  NULL,				/* t_pat_get_tmpl_proc		*/
  NULL,				/* t_pat_get_tmpl2_proc		*/
  NULL,				/* t_pat_has_opt_proc		*/
  NULL,				/* t_pat_adapt_len_proc		*/
  NULL,				/* t_pat_get_field_pat_proc	*/
  pat_pat_extract,		/* t_pat_extract_proc		*/
  pat_pat_insert,		/* t_pat_insert_proc		*/
  pat_pat_get_choices,		/* t_pat_get_choices_proc	*/
};
