/*
** pat_igmp.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:43:04 1999 
** Last update Thu Oct 28 20:19:59 1999 
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "pat_igmp.h"
#include "pat_ip.h"
#include "pat_ether.h"
#include "pat_data.h"
#include "pat_32.h"
#include "pat_16.h"
#include "pat_8.h"
#include "pat_inaddr.h"

t_bit_field	igmp_v_bit_field = 
{
  0,3
};

t_assoc		igmp_type_assocs[] =
{
  {"query",	(VOID_PTR)1},
  {"report",	(VOID_PTR)2},
  {"dvmrp",	(VOID_PTR)3},
  {"pim",	(VOID_PTR)4},
  {"nreport",	(VOID_PTR)6},
  {"leave",	(VOID_PTR)7},
  {"mresp",	(VOID_PTR)0xe},
  {"mtrace",	(VOID_PTR)0xf},
  NULL_ASSOC
};

t_bit_field	igmp_type_bit_field =
{
  4,7
};

t_bit_field_assocs_data	igmp_type_bfad =
{
  &igmp_type_bit_field,
  igmp_type_assocs
};

t_field				igmp_fields[] = 
{
  {"v",		OFFSET(t_igmp *,vtype),	&u8bitfield_pat,&igmp_v_bit_field},
  {"type",    OFFSET(t_igmp *,vtype),&u8bitfield_pat,&igmp_type_bit_field},
  {"Type",    OFFSET(t_igmp *,vtype),&u8bitfieldassoc_pat,&igmp_type_bfad},
  {"unused",	OFFSET(t_igmp *,unused),&u8_pat,		NULL},
  {"cksum",	OFFSET(t_igmp *,cksum),	&nu16_pat,		NULL},
  {"group",	OFFSET(t_igmp *,group),	&inaddr_pat,		NULL},
  {"Group",	OFFSET(t_igmp *,group),	&inaddr_resolved_pat,NULL},
  NULL_FIELD
};

char				*igmp_itmpl = "\n\
<table _name=igmp[%i%] width=100%%%% bgcolor=\"%%igmpColor%%\">\n\
<tr>\n\
<td align=center width=12%%%%>\n\
<a href=\"set(igmp[%i%].v)\">%%igmp[%i%].v%%</a>\n\
</td>\n\
<td align=center width=13%%%%>\n\
<a href=\"set(igmp[%i%].Type)\">%%igmp[%i%].Type%%</a>\n\
(<a href=\"set(igmp[%i%].type)\">%%igmp[%i%].type%%</a>)\n\
</td>\n\
<td align=center width=25%%%%>\n\
<a href=\"set(igmp[%i%].unused)\">%%igmp[%i%].unused%%</a>\n\
</td>\n\
<td align=center width=50%%%%>\n\
<a href=\"set(igmp[%i%].cksum)\">%%igmp[%i%].cksum%%</a>\n\
</td>\n\
</tr>\n\
<tr>\n\
<td align=center width=100%%%%>\n\
<a href=\"set(igmp[%i%].Group)\">%%igmp[%i%].Group%%</a>\n\
(<a href=\"set(igmp[%i%].group)\">%%igmp[%i%].group%%</a>)\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

VOID_FUNC	igmp_compute_sum(ip,igmp)
t_ip		*ip;
t_igmp		*igmp;
{
  int		datalen;
  t_u16		zero;

  zero = 0;
  FBCOPY(&zero,&(igmp->cksum),sizeof (zero)); /* alignment */
  datalen = ip_get_len(ip) - ip_get_hl(ip) * 4;
  safe_htons(in_cksum((t_u16 *)igmp,datalen >> 1),&(igmp->cksum));
}

int	igmp_chan;

PAT_NAME_GENERIC(igmp_pat_name,
		 (VOID_PTR)&igmp_chan,
		 "igmp")

PAT_GET_FIELD_GENERIC(igmp_pat_get_field,
		      igmp_fields)

PAT_SET_FIELD_GENERIC(igmp_pat_set_field,
		      igmp_fields)

PAT_GET_FIELDS_GENERIC(igmp_pat_get_fields,
		       igmp_fields)

PAT_GET_FIELD_PAT_GENERIC(igmp_pat_get_field_pat,
			  igmp_fields)

PAT_GET_TMPL_GENERIC(igmp_pat_get_tmpl,
		     (VOID_PTR)&igmp_chan,
		     igmp_itmpl)

PAT_SUM_DECL(igmp_pat_sum)
{
  t_igmp	*igmp;
  t_ip		*ip;

  PAT_IGMP_CHECK(igmp,buf,len);
  PAT_IP_CHECK(ip,up_buf,up_len);
  if (ip_get_len(ip) != up_len)
    return (ERR_PAT_BAD_LEN);
  if (ip_get_hl(ip) * 4 < IP_MINHLEN)
    return (ERR_PAT_BAD_HEADER);
  igmp_compute_sum(ip,igmp);
  return (0);
}

PAT_OFF_GENERIC(igmp_pat_off,
		IGMP_HLEN)
	
PAT_SUB_GENERIC(igmp_pat_sub,
		&data_pat)

t_pat				igmp_pat = 
{
  igmp_pat_name,		/* t_pat_name_proc		*/
  igmp_pat_off,			/* t_pat_off_proc		*/
  igmp_pat_sub,			/* t_pat_sub_proc		*/
  igmp_pat_sum,			/* t_pat_sum_proc		*/
  igmp_pat_get_field,		/* t_pat_get_field_proc		*/
  igmp_pat_set_field,		/* t_pat_set_field_proc		*/
  igmp_pat_get_fields,		/* t_pat_get_fields_proc	*/
  igmp_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		*/
  igmp_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	*/
};
