/*
** pat_icmpcode.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:43:19 1999 
** Last update Thu Oct 28 20:20:02 1999 
*/
#include "pat.h"
#include "pat_icmpcode.h"

t_assoc			icmp_unreachable_assocs[] = 
{
  {"net_unreachable",		(VOID_PTR)0},
  {"host_unreachable",		(VOID_PTR)1},
  {"prot_unreachable",		(VOID_PTR)2},
  {"port_unreachable",		(VOID_PTR)3},
  {"frag_needed_but_no_df",	(VOID_PTR)4},
  {"src_route_failed",		(VOID_PTR)5},
  {"dst_net_unknown",		(VOID_PTR)6},
  {"dst_host_unknown",		(VOID_PTR)7},
  {"src_host_isolated",		(VOID_PTR)8},
  {"dst_net_prohibited",	(VOID_PTR)9},
  {"dst_host_prohibited",	(VOID_PTR)10},
  {"net_unreachable_for_tos",	(VOID_PTR)11},
  {"host_unreachable_for_tos",	(VOID_PTR)12},
  {"comm_prohibited_by_filtering",(VOID_PTR)13},
  {"host_precedence_violation",	(VOID_PTR)14},
  {"precedence_cutoff_in_effect",(VOID_PTR)15},
  {NULL,			NULL},
};

t_assoc			icmp_redirect_assocs[] = 
{
  {"for_net",			(VOID_PTR)0},
  {"for_host",			(VOID_PTR)1},
  {"for_tos_and_net",		(VOID_PTR)2},
  {"for_tos_and_host",		(VOID_PTR)3},
  {NULL,			NULL},
};

t_assoc			icmp_timex_assocs[] =
{
  {"during_transit",	(VOID_PTR)0},
  {"during_reassembly",	(VOID_PTR)1},
  {NULL,		NULL},
};

t_assoc			icmp_paramprob_assocs[] = 
{
  {"ip_header_bad",	(VOID_PTR)0},
  {"required_opt_missing",(VOID_PTR)1},
  {NULL,		NULL},
};

t_assoc			icmpcode_assocs[] =
{
  {(VOID_PTR)3,		icmp_unreachable_assocs},
  {(VOID_PTR)5,		icmp_redirect_assocs},
  {(VOID_PTR)11,	icmp_timex_assocs},
  {(VOID_PTR)12,	icmp_paramprob_assocs}
};

t_assoc			*icmpcode_get_assocs_from_type(type)
int			type;
{
  int			i;

  i = 0;
  while (i < ARRAY_COUNT(icmpcode_assocs))
    {
      if ((int)(icmpcode_assocs[i].left) == type)
	return ((t_assoc *)(icmpcode_assocs[i].right));
      i++;
    }
  return (NULL);
}

t_status		icmpcode_to_str(buf,len,str,max_len)
char			*buf;
int			len;
char			*str;
int			max_len;
{
  t_assoc		*assocs;

  if (len < 2)
    return (ERR_PAT_TRUNC_FIELD);
  if ((assocs = icmpcode_get_assocs_from_type((t_u32)(t_u8)(buf[0]))) == NULL)
    return (ulong_to_str((unsigned long)(t_u8)(buf[1]),
			 pat_base,
			 str,
			 max_len));
  else
    {
      t_assoc		*assoc;

      if ((assoc = assoc_str_int_from_right(assocs,
					    (t_u32)(t_u8)buf[1])) == NULL)
	return (ulong_to_str((unsigned long)(t_u8)(buf[1]),
			     pat_base,
			     str,
			     max_len));
      else
	return (str_cat_str(str,
			    max_len,
			    assoc->left));
    }
}

t_status		icmpcode_from_str(buf,len,str)
char			*buf;
int			len;
char			*str;
{
  t_assoc		*assocs;

  if (len < 2)
    return (ERR_PAT_TRUNC_FIELD);
  if ((assocs = icmpcode_get_assocs_from_type((t_u32)(t_u8)(buf[0]))) == NULL)
    return (ERR_PAT_UNRESOLVABLE);
  else
    {
      t_assoc		*assoc;

      if ((assoc = assoc_str_ptr_from_left(assocs,str)) == NULL)
	return (ERR_PAT_UNRESOLVABLE);
      else
	{
	  buf[1] = (t_u8)(t_u32)(assoc->right);
	  return (0);
	}
    }
}

t_status		icmpcode_get_choices(buf,len,vec_str)
char			*buf;
int			len;
t_vec			*vec_str;
{
  t_assoc		*assocs;

  if (len < 2)
    return (ERR_PAT_TRUNC_FIELD);
  if ((assocs = icmpcode_get_assocs_from_type((t_u32)(t_u8)(buf[0]))) == NULL)
    return (ERR_PAT_NO_CHOICE);
  else
    {
      t_assoc		*assoc;

      assoc = assocs;
      while (assoc->left)
	{
	  t_status	status;

	  if ((status = vec_str_add(vec_str,
				    assoc->left)) != 0)
	    return (status);
	  assoc++;
	}
      return (0);
    }
}

int	icmpcodeagainsttype_chan;

PAT_NAME_GENERIC(icmpcodeagainsttype_pat_name,
		 (VOID_PTR)&icmpcodeagainsttype_chan,
		 "icmpcodeagainsttype")

PAT_EXTRACT_DECL(icmpcodeagainsttype_pat_extract)
{
  return (icmpcode_to_str(buf,
			  len,
			  str,
			  max_len));
}
 
PAT_INSERT_DECL(icmpcodeagainsttype_pat_insert)
{
  return (icmpcode_from_str(buf,
			    len,
			    value));
}
 
PAT_GET_CHOICES_DECL(icmpcodeagainsttype_pat_get_choices)
{
  return (icmpcode_get_choices(buf,
			       len,
			       vec_str));
}

t_pat				icmpcodeagainsttype_pat = 
{
  icmpcodeagainsttype_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	*/
  icmpcodeagainsttype_pat_extract,/* t_pat_extract_proc		*/
  icmpcodeagainsttype_pat_insert,/* t_pat_insert_proc		*/
  icmpcodeagainsttype_pat_get_choices,/* t_pat_get_choices_proc	*/
};
