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

t_u32			pat_inaddr_per_line = 2;

/* is a t_hash_cmp_proc.
   It compares 2 internet addresses. */
int			inaddr_cmp(addr1,addr2)
struct in_addr		*addr1;
struct in_addr		*addr2;
{
  t_u32			saddr1;
  t_u32			saddr2;
  
  saddr1 = (t_u32)(UNSAFE_HTONL(addr1->s_addr));
  saddr2 = (t_u32)(UNSAFE_HTONL(addr2->s_addr));
  return ((int)(saddr1 - saddr2));
}

/* converts a string to an internet address.
   It first tries to do an inet_addr(3) call, if it fails, it uses
   gethostbyname(3).
   Note that mba_inaddr must be aligned!
   Returns 0 if OK. Returns ERR_PAT_MALFORMED if the number of dots
   in str is != 3. Returns ERR_PAT_UNRESOLVABLE if both inet_addr(3)
   and gethostbyname(3) fail. Returns ERR_PAT_BADFAMILY if address family
   is not AF_INET */
t_status		inaddr_from_str(str,mba_inaddr,resolve)
char			*str;		/* A.b.c.d or a host name */
struct in_addr		*mba_inaddr;	/* An aligned in_addr struct pointer */
t_boolean		resolve;	/* If FALSE,bypasses gethostbyname(3)
					   but doesn't return an error if
					   inet_addr(3) has returned -1 */
{
  struct hostent	*hostentry;

  if (!resolve)
    {
      if (indexcount(str,'.') != 3)
	return (ERR_PAT_MALFORMED);
    }
  mba_inaddr->s_addr = inet_addr(str);
  if (mba_inaddr->s_addr == -1)
    {
      if (resolve)
	{
	  if ((hostentry = gethostbyname(str)) == NULL)
	    return (ERR_PAT_UNRESOLVABLE);
	  if (hostentry->h_addrtype != AF_INET)
	    return (ERR_PAT_BAD_FAMILY);
	  FBCOPY(hostentry->h_addr_list[0],mba_inaddr,hostentry->h_length);
	}
    }
  return (0);
}

/* converts-and-catenates an internet address to a bridled string.
   It uses gethostbyaddr(3) and reverts to inet_ntoa(3) if it fails.
   Note that mba_addr must be aligned!
   Returns 0 if OK, might return ERR_A_BO on buffer overflow */
t_status		inaddr_to_str(mba_inaddr,str,max_len,resolve)
struct in_addr		*mba_inaddr;	/* Aligned in_addr struct pointer */
char			*str;		/* Valid string */
int			max_len;	/* Maximum length */
t_boolean		resolve;      /* If FALSE, bypasses gethostbyaddr(3) */
{
  struct hostent	*hostentry;
  
  if (resolve)
    if ((hostentry = gethostbyaddr((char *)mba_inaddr,
				   sizeof (struct in_addr),
				   AF_INET)) != NULL)
      return (str_cat_str(str,max_len,hostentry->h_name));
  return (str_cat_str(str,max_len,inet_ntoa(*mba_inaddr)));
}

char			*inaddr_itmpl = "\n\
<table _name=inaddr[%i%] bgcolor=\"%%inaddrColor%%\" width=100%%%%>\n\
<tr>\n\
<td align=center>\n\
<small>\n\
<a href=\"set(inaddr[%i%].Inaddr)\">%%inaddr[%i%].Inaddr%%</a>(<a href=\"set(inaddr[%i%].inaddr)\">%%inaddr[%i%].inaddr%%</a>)\n\
</small>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

t_field			inaddr_fields[] = 
{
  {"inaddr",    0,      &inaddr_pat,                 NULL},
  {"Inaddr",    0,      &inaddr_resolved_pat,        NULL},
  NULL_FIELD
};

int			inaddr_chan;

PAT_NAME_GENERIC(inaddr_pat_name,
		 (VOID_PTR)&inaddr_chan,
		 "inaddr")

PAT_GET_FIELD_GENERIC(inaddr_pat_get_field,
		      inaddr_fields)

PAT_SET_FIELD_GENERIC(inaddr_pat_set_field,
		      inaddr_fields)

PAT_GET_FIELDS_GENERIC(inaddr_pat_get_fields,
		       inaddr_fields)

PAT_GET_TMPL_GENERIC(inaddr_pat_get_tmpl,
		     (VOID_PTR)&inaddr_chan,
		     inaddr_itmpl)

PAT_GET_FIELD_PAT_GENERIC(inaddr_pat_get_field_pat,
			  inaddr_fields)

PAT_OFF_GENERIC(inaddr_pat_off,
		4)

PAT_SUB_GENERIC(inaddr_pat_sub,
		&inaddr_pat)

PAT_EXTRACT_DECL(inaddr_pat_extract)
{
  struct in_addr	inaddr;
  
  if (len < sizeof (inaddr))
    return (ERR_PAT_TRUNC_FIELD);
  FBCOPY(buf,&inaddr,sizeof (struct in_addr));
  return (inaddr_to_str(&inaddr,
			str,
			max_len,
			FALSE));
}
 
PAT_INSERT_DECL(inaddr_pat_insert)
{
  struct in_addr	inaddr;
  t_status		status;	
  
  if (len < sizeof (inaddr))
    return (ERR_PAT_TRUNC_FIELD);
  if ((status = inaddr_from_str(value,
				&inaddr,
				TRUE)) != 0)
    return (status);
  FBCOPY(&inaddr,buf,sizeof (struct in_addr));
  return (0);
}

t_pat				inaddr_pat = 
{
  inaddr_pat_name,		/* t_pat_name_proc		*/
  inaddr_pat_off,		/* t_pat_off_proc		*/
  inaddr_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  inaddr_pat_get_field,		/* t_pat_get_field_proc		*/
  inaddr_pat_set_field,		/* t_pat_set_field_proc		*/
  inaddr_pat_get_fields,	/* t_pat_get_fields_proc	*/
  inaddr_pat_get_tmpl,		/* t_pat_get_tmpl_proc		*/
  NULL,				/* t_pat_get_tmpl2_proc		*/
  NULL,				/* t_pat_has_opt_proc		*/
  NULL,				/* t_pat_adapt_len_proc		*/
  inaddr_pat_get_field_pat,	/* t_pat_get_field_pat_proc	*/
  inaddr_pat_extract,		/* t_pat_extract_proc		*/
  inaddr_pat_insert,		/* t_pat_insert_proc		*/
  NULL,				/* t_pat_get_choices_proc	*/
};
 
int	inaddr_resolved_chan;

PAT_NAME_GENERIC(inaddr_resolved_pat_name,
		 (VOID_PTR)&inaddr_resolved_chan,
		 "inaddr_resolved")

PAT_EXTRACT_DECL(inaddr_resolved_pat_extract)
{
  struct in_addr	inaddr;
  
  if (len < sizeof (inaddr))
    return (ERR_PAT_TRUNC_FIELD);
  FBCOPY(buf,&inaddr,sizeof (struct in_addr));
  return (inaddr_to_str_alarm(&inaddr,
			      str,
			      max_len,
			      pat_resolve));
}
 
PAT_INSERT_DECL(inaddr_resolved_pat_insert)
{
  struct in_addr	inaddr;
  t_status		status;	
  
  if (len < sizeof (inaddr))
    return (ERR_PAT_TRUNC_FIELD);
  if ((status = inaddr_from_str_alarm(value,
				      &inaddr,
				      TRUE)) != 0)
    return (status);
  FBCOPY(&inaddr,buf,sizeof (struct in_addr));
  return (0);
}

PAT_GET_CHOICES_DECL(inaddr_resolved_pat_get_choices)
{
  return (nbgethost_get_choices(vec_str));
}

t_pat				inaddr_resolved_pat = 
{
  inaddr_resolved_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	*/
  inaddr_resolved_pat_extract,	/* t_pat_extract_proc		*/
  inaddr_resolved_pat_insert,	/* t_pat_insert_proc		*/
  inaddr_resolved_pat_get_choices,/* t_pat_get_choices_proc	*/
};

char			*inaddrmask_itmpl = "\n\
<table _name=inaddrmask[%i%] bgcolor=\"%%inaddrmaskColor%%\" width=100%%%%>\n\
<tr>\n\
<td align=center>\n\
<small>\n\
<a href=\"set(inaddrmask[%i%].Inaddr)\">%%inaddrmask[%i%].Inaddr%%</a>(<a href=\"set(inaddrmask[%i%].inaddr)\">%%inaddrmask[%i%].inaddr%%</a>)\n\
</small>\n\
</td>\n\
</tr>\n\
<tr>\n\
<td align=center>\n\
<small>\n\
<a href=\"set(inaddrmask[%i%].Mask)\">%%inaddrmask[%i%].Mask%%</a>(<a href=\"set(inaddrmask[%i%].mask)\">%%inaddrmask[%i%].mask%%</a>)\n\
</small>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

t_field			inaddrmask_fields[] = 
{
  {"inaddr",    0,      &inaddr_pat,                 NULL},
  {"Inaddr",    0,      &inaddr_resolved_pat,        NULL},
  {"mask",      4,      &inaddr_pat,                 NULL},
  {"Mask",      4,      &inaddr_resolved_pat,        NULL},
  NULL_FIELD
};

int			inaddrmask_chan;

PAT_NAME_GENERIC(inaddrmask_pat_name,
		 (VOID_PTR)&inaddrmask_chan,
		 "inaddrmask")

PAT_GET_FIELD_GENERIC(inaddrmask_pat_get_field,
		      inaddrmask_fields)

PAT_SET_FIELD_GENERIC(inaddrmask_pat_set_field,
		      inaddrmask_fields)

PAT_GET_FIELDS_GENERIC(inaddrmask_pat_get_fields,
		       inaddrmask_fields)

PAT_GET_TMPL_GENERIC(inaddrmask_pat_get_tmpl,
		     (VOID_PTR)&inaddrmask_chan,
		     inaddrmask_itmpl)

PAT_GET_FIELD_PAT_GENERIC(inaddrmask_pat_get_field_pat,
			  inaddrmask_fields)

PAT_OFF_GENERIC(inaddrmask_pat_off,
		8)
     
PAT_SUB_GENERIC(inaddrmask_pat_sub,
		&inaddrmask_pat)

t_pat				inaddrmask_pat = 
{
  inaddrmask_pat_name,		/* t_pat_name_proc		*/
  inaddrmask_pat_off,		/* t_pat_off_proc		*/
  inaddrmask_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  inaddrmask_pat_get_field,	/* t_pat_get_field_proc		*/
  inaddrmask_pat_set_field,	/* t_pat_set_field_proc		*/
  inaddrmask_pat_get_fields,	/* t_pat_get_fields_proc	*/
  inaddrmask_pat_get_tmpl,	/* t_pat_get_tmpl_proc		*/
  NULL,				/* t_pat_get_tmpl2_proc		*/
  NULL,				/* t_pat_has_opt_proc		*/
  NULL,				/* t_pat_adapt_len_proc		*/
  inaddrmask_pat_get_field_pat,	/* t_pat_get_field_pat_proc	*/
  NULL,				/* t_pat_extract_proc		*/
  NULL,				/* t_pat_insert_proc		*/
  NULL,				/* t_pat_get_choices_proc	*/
};

char			*inaddrrouter_itmpl = "\n\
<table _name=inaddrrouter[%i%] bgcolor=\"%%inaddrrouterColor%%\" width=100%%%%>\n\
<tr>\n\
<td align=center>\n\
<small>\n\
<a href=\"set(inaddrrouter[%i%].Inaddr)\">%%inaddrrouter[%i%].Inaddr%%</a>(<a href=\"set(inaddrrouter[%i%].inaddr)\">%%inaddrrouter[%i%].inaddr%%</a>)\n\
</small>\n\
</td>\n\
</tr>\n\
<tr>\n\
<td align=center>\n\
<small>\n\
<a href=\"set(inaddrrouter[%i%].Router)\">%%inaddrrouter[%i%].Router%%</a>(<a href=\"set(inaddrrouter[%i%].router)\">%%inaddrrouter[%i%].router%%</a>)\n\
</small>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

t_field			inaddrrouter_fields[] = 
{
  {"inaddr",    0,      &inaddr_pat,                 NULL},
  {"Inaddr",    0,      &inaddr_resolved_pat,        NULL},
  {"router",    4,      &inaddr_pat,                 NULL},
  {"Router",    4,      &inaddr_resolved_pat,        NULL},
  NULL_FIELD
};

int			inaddrrouter_chan;

PAT_NAME_GENERIC(inaddrrouter_pat_name,
		 (VOID_PTR)&inaddrrouter_chan,
		 "inaddrrouter")

PAT_GET_FIELD_GENERIC(inaddrrouter_pat_get_field,
		      inaddrrouter_fields)

PAT_SET_FIELD_GENERIC(inaddrrouter_pat_set_field,
		      inaddrrouter_fields)

PAT_GET_FIELDS_GENERIC(inaddrrouter_pat_get_fields,
		       inaddrrouter_fields)

PAT_GET_TMPL_GENERIC(inaddrrouter_pat_get_tmpl,
		     (VOID_PTR)&inaddrrouter_chan,
		     inaddrrouter_itmpl)

PAT_GET_FIELD_PAT_GENERIC(inaddrrouter_pat_get_field_pat,
			  inaddrrouter_fields)

PAT_OFF_GENERIC(inaddrrouter_pat_off,
		8)
     
PAT_SUB_GENERIC(inaddrrouter_pat_sub,
		&inaddrrouter_pat)

t_pat				inaddrrouter_pat = 
{
  inaddrrouter_pat_name,	/* t_pat_name_proc		*/
  inaddrrouter_pat_off,		/* t_pat_off_proc		*/
  inaddrrouter_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  inaddrrouter_pat_get_field,	/* t_pat_get_field_proc		*/
  inaddrrouter_pat_set_field,	/* t_pat_set_field_proc		*/
  inaddrrouter_pat_get_fields,	/* t_pat_get_fields_proc	*/
  inaddrrouter_pat_get_tmpl,	/* t_pat_get_tmpl_proc		*/
  NULL,				/* t_pat_get_tmpl2_proc		*/
  NULL,				/* t_pat_has_opt_proc		*/
  NULL,				/* t_pat_adapt_len_proc		*/
  inaddrrouter_pat_get_field_pat,/* t_pat_get_field_pat_proc	*/
  NULL,				/* t_pat_extract_proc		*/
  NULL,				/* t_pat_insert_proc		*/
  NULL,				/* t_pat_get_choices_proc	*/
};
