/*
** pat_ipproto.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:42:43 1999 
** Last update Thu Oct 28 20:19:54 1999 
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "pat.h"
#include "pat_ipproto.h"

/* Unused for now */
t_assoc				ipproto_assocs[] = 
{
  {"ip",			(VOID_PTR)0},
  {"icmp",			(VOID_PTR)1},
  {"igmp",			(VOID_PTR)2},
  {"ggp",			(VOID_PTR)3},
  {"ipip",			(VOID_PTR)4},
  {"tcp",			(VOID_PTR)6},
  {"egp",			(VOID_PTR)8},
  {"pup",			(VOID_PTR)12},
  {"udp",			(VOID_PTR)17},
  {"idp",			(VOID_PTR)22},
  {"tp",			(VOID_PTR)29},
  {"esp",			(VOID_PTR)50},
  {"ah",			(VOID_PTR)51},
  {"eon",			(VOID_PTR)80},
  {"encap",			(VOID_PTR)98},
  {"raw",			(VOID_PTR)255},
  NULL_ASSOC
};
	     
/* converts a string into a protocol number.
   It uses getprotobyname(3) then ipproto_assocs array and reverts to atoi(3) 
   if not found. 
   Returns protocol number */
int			proto_from_str(str,resolve)
char			*str;		/* A protocol name or a number */
t_boolean		resolve;	/*If FALSE,bypasses getprotobyname(3)*/
{
  if (resolve)
    {
      struct protoent	*protoentry;
      t_assoc		*assoc;

      setprotoent(0);
      if (protoentry = getprotobyname(str))
	{
	  int		proto;
	  
	  proto = protoentry->p_proto;
	  endprotoent();
	  return (proto);
	}
      endprotoent();
      if (assoc = assoc_str_ptr_from_left(ipproto_assocs,str))
	return ((int)assoc->right);
    }
  return (atoi(str));
}

/* converts-and-catenates a protocol number to a bridled string.
   It uses getprotobynumber(3) then ipproto_assocs array and reverts to 
   long_to_str(3) if not found.
   Returns 0 if OK, might return various errors */
t_status		proto_to_str(proto,str,max_len,resolve)
int			proto;		/* Protocol number */
char			*str;		/* Valid string */
int			max_len;	/* Maximum-length */	
t_boolean		resolve;     /* If FALSE,bypasses getprotobynumber(3)*/
{
  if (resolve)
    {
      struct protoent	*protoentry;
      t_assoc		*assoc;

      setprotoent(0);
      if (protoentry = getprotobynumber(proto))
	{
	  char		*name;
	  
	  name = protoentry->p_name;
	  endprotoent();
	  return (str_cat_str(str,
			      max_len,
			      name));
	}
      endprotoent();
      if (assoc = assoc_str_int_from_right(ipproto_assocs,proto))
	return (str_cat_str(str,
			    max_len,
			    assoc->left));
    }
  return (long_to_str((signed long)proto,
		      pat_base,
		      str,
		      max_len));
}

int	ipproto_chan;

PAT_NAME_GENERIC(ipproto_pat_name,
		 (VOID_PTR)&ipproto_chan,
		 "ipproto")

PAT_EXTRACT_DECL(ipproto_pat_extract)
{
  t_u8		ipproto;

  if (len < sizeof (ipproto))
    return (ERR_PAT_TRUNC_FIELD);
  FBCOPY(buf,&ipproto,sizeof (ipproto));
  return (proto_to_str(ipproto,
		       str,
		       max_len,
		       pat_resolve));
}
 
PAT_INSERT_DECL(ipproto_pat_insert)
{
  t_u8		ipproto;
  
  if (len < sizeof (ipproto))
    return (ERR_PAT_TRUNC_FIELD);
  ipproto = proto_from_str(value,
			   TRUE);
  FBCOPY(&ipproto,buf,sizeof (ipproto));
  return (0);
}

PAT_GET_CHOICES_DECL(ipproto_pat_get_choices)
{
  struct protoent	*protoentry;
  t_assoc		*assoc;
  t_status		status;

  setprotoent(0);
  while (protoentry = getprotoent())
    {
      if ((status = vec_str_add(vec_str,
				protoentry->p_name)) != 0)
	return (status);
    }
  endprotoent();
  assoc = ipproto_assocs;
  while (assoc->left)
    {
      if (vec_str_index(vec_str,
			assoc->left) < 0)
	{
	  if ((status = vec_str_add(vec_str,
				    assoc->left)) != 0)
	    return (status);
	}
      assoc++;
    }
  return (0);
}

t_pat				ipproto_pat = 
{
  ipproto_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	*/
  ipproto_pat_extract,		/* t_pat_extract_proc		*/
  ipproto_pat_insert,		/* t_pat_insert_proc		*/
  ipproto_pat_get_choices,	/* t_pat_get_choices_proc	*/
};
