/*
** pat_tftp.c for  in 
** 
** Made by 
** Login   <vianney@epita.fr>
** 
** Started on  Wed Sep  1 06:40:57 1999 
** Last update Thu Oct 28 20:19:29 1999 
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> 
#include <arpa/tftp.h>
#include "pat_tftp.h"
#include "pat_ip.h"
#include "pat_ether.h"
#include "pat_data.h"
#include "pat_16.h"
#include "pat_8.h"
#include "pat_sz.h"

t_field				tftpmode_fields[] = 
{
  {"mode",	0,		&sz_pat,		NULL},
  NULL_FIELD
};

char				*tftpmode_itmpl = "\n\
<table _name=tftpmode[%i%] width=100%%%% bgcolor=\"%%tftpmodeColor%%\">\n\
<tr>\n\
<td align=center width=50%%%%>\n\
<a href=\"set(tftpmode[%i%].mode)\">%%tftpmode[%i%].mode%%</a>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

int	tftpmode_chan;

PAT_NAME_GENERIC(tftpmode_pat_name,
		 (VOID_PTR)&tftpmode_chan,
		 "tftpmode")

PAT_GET_FIELD_GENERIC(tftpmode_pat_get_field,
		      tftpmode_fields)

PAT_SET_FIELD_GENERIC(tftpmode_pat_set_field,
		      tftpmode_fields)

PAT_GET_FIELDS_GENERIC(tftpmode_pat_get_fields,
		       tftpmode_fields)

PAT_GET_FIELD_PAT_GENERIC(tftpmode_pat_get_field_pat,
			  tftpmode_fields)

PAT_GET_TMPL_GENERIC(tftpmode_pat_get_tmpl,
		     (VOID_PTR)&tftpmode_chan,
		     tftpmode_itmpl)

PAT_SUB_GENERIC(tftpmode_pat_sub,
		&data_pat)

t_pat				tftpmode_pat = 
{
  tftpmode_pat_name,		/* t_pat_name_proc		*/
  sz_pat_off,			/* t_pat_off_proc		*/
  tftpmode_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  tftpmode_pat_get_field,	/* t_pat_get_field_proc		*/
  tftpmode_pat_set_field,	/* t_pat_set_field_proc		*/
  tftpmode_pat_get_fields,	/* t_pat_get_fields_proc	*/
  tftpmode_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		*/
  tftpmode_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	*/
};


t_field				tftpfname_fields[] = 
{
  {"name",	0,		&sz_pat,		NULL},
  NULL_FIELD
};

char				*tftpfname_itmpl = "\n\
<table _name=tftpfname[%i%] width=100%%%% bgcolor=\"%%tftpfnameColor%%\">\n\
<tr>\n\
<td align=center width=50%%%%>\n\
<a href=\"set(tftpfname[%i%].name)\">%%tftpfname[%i%].name%%</a>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

int	tftpfname_chan;

PAT_NAME_GENERIC(tftpfname_pat_name,
		 (VOID_PTR)&tftpfname_chan,
		 "tftpfname")

PAT_GET_FIELD_GENERIC(tftpfname_pat_get_field,
		      tftpfname_fields)

PAT_SET_FIELD_GENERIC(tftpfname_pat_set_field,
		      tftpfname_fields)

PAT_GET_FIELDS_GENERIC(tftpfname_pat_get_fields,
		       tftpfname_fields)

PAT_GET_FIELD_PAT_GENERIC(tftpfname_pat_get_field_pat,
			  tftpfname_fields)

PAT_GET_TMPL_GENERIC(tftpfname_pat_get_tmpl,
		     (VOID_PTR)&tftpfname_chan,
		     tftpfname_itmpl)

PAT_SUB_GENERIC(tftpfname_pat_sub,
		&tftpmode_pat)
		    
t_pat				tftpfname_pat = 
{
  tftpfname_pat_name,		/* t_pat_name_proc		*/
  sz_pat_off,			/* t_pat_off_proc		*/
  tftpfname_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  tftpfname_pat_get_field,	/* t_pat_get_field_proc		*/
  tftpfname_pat_set_field,	/* t_pat_set_field_proc		*/
  tftpfname_pat_get_fields,	/* t_pat_get_fields_proc	*/
  tftpfname_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		*/
  tftpfname_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	*/
};

t_assoc			tftpen_assocs[] =
{
  {"undef",		(VOID_PTR)EUNDEF},
  {"notfound",		(VOID_PTR)ENOTFOUND},
  {"access",		(VOID_PTR)EACCESS},
  {"nospace",		(VOID_PTR)ENOSPACE},
  {"badop",		(VOID_PTR)EBADOP},
  {"badid",		(VOID_PTR)EBADID},
  {"exists",		(VOID_PTR)EEXISTS},
  {"nouser",		(VOID_PTR)ENOUSER},
  {NULL,		NULL}
};

t_field				tftperror_fields[] = 
{
  {"en",	0,		&nu16_pat,		NULL},
  {"En",	0,		&nu16assoc_pat,	tftpen_assocs},
  {"msg",	2,		&sz_pat,		NULL},
  NULL_FIELD
};

char				*tftperror_itmpl = "\n\
<table _name=tftperror[%i%] width=100%%%% bgcolor=\"%%tftperrorColor%%\">\n\
<tr>\n\
<td align=center width=100%%%%>\n\
<a href=\"set(tftperror[%i%].En)\">%%tftperror[%i%].En%%</a>\n\
(<a href=\"set(tftperror[%i%].en)\">%%tftperror[%i%].en%%</a>)\n\
</td>\n\
</tr>\n\
<tr>\n\
<td align=center width=100%%%%>\n\
<a href=\"set(tftperror[%i%].msg)\">%%tftperror[%i%].msg%%</a>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

int	tftperror_chan;

PAT_NAME_GENERIC(tftperror_pat_name,
		 (VOID_PTR)&tftperror_chan,
		 "tftperror")

PAT_GET_FIELD_GENERIC(tftperror_pat_get_field,
		      tftperror_fields)

PAT_SET_FIELD_GENERIC(tftperror_pat_set_field,
		      tftperror_fields)

PAT_GET_FIELDS_GENERIC(tftperror_pat_get_fields,
		       tftperror_fields)

PAT_GET_FIELD_PAT_GENERIC(tftperror_pat_get_field_pat,
			  tftperror_fields)

PAT_GET_TMPL_GENERIC(tftperror_pat_get_tmpl,
		     (VOID_PTR)&tftperror_chan,
		     tftperror_itmpl)

PAT_OFF_DECL(tftperror_pat_off)
{
  t_off			off_return2;
  char			*buf2;
  int			len2;
  t_status		status;	

  if (len < 2)
    return (ERR_PAT_TRUNC_PAT);
  buf2 = buf + 2;
  len2 = len - 2;
  assert(sz_pat.off_proc);
  if ((status = sz_pat.off_proc(NULL,
				buf2,
				len2,
				&off_return2)) != 0)
    return (status);
  (*off_return) = off_return2 + 2;
  return (0);
}

PAT_SUB_GENERIC(tftperror_pat_sub,
		&data_pat)

t_pat				tftperror_pat = 
{
  tftperror_pat_name,		/* t_pat_name_proc		*/
  tftperror_pat_off,		/* t_pat_off_proc		*/
  tftperror_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  tftperror_pat_get_field,	/* t_pat_get_field_proc		*/
  tftperror_pat_set_field,	/* t_pat_set_field_proc		*/
  tftperror_pat_get_fields,	/* t_pat_get_fields_proc	*/
  tftperror_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		*/
  tftperror_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	*/
};

t_field				tftpbn_fields[] = 
{
  {"bn",	0,		&nu16_pat,		NULL},
  NULL_FIELD
};

char				*tftpbn_itmpl = "\n\
<table _name=tftpbn[%i%] width=100%%%% bgcolor=\"%%tftpbnColor%%\">\n\
<tr>\n\
<td align=center width=100%%%%>\n\
<a href=\"set(tftpbn[%i%].bn)\">%%tftpbn[%i%].bn%%</a>\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

int	tftpbn_chan;

PAT_NAME_GENERIC(tftpbn_pat_name,
		 (VOID_PTR)&tftpbn_chan,
		 "tftpbn")

PAT_GET_FIELD_GENERIC(tftpbn_pat_get_field,
		      tftpbn_fields)

PAT_SET_FIELD_GENERIC(tftpbn_pat_set_field,
		      tftpbn_fields)

PAT_GET_FIELDS_GENERIC(tftpbn_pat_get_fields,
		       tftpbn_fields)

PAT_GET_FIELD_PAT_GENERIC(tftpbn_pat_get_field_pat,
			  tftpbn_fields)

PAT_GET_TMPL_GENERIC(tftpbn_pat_get_tmpl,
		     (VOID_PTR)&tftpbn_chan,
		     tftpbn_itmpl)

PAT_OFF_GENERIC(tftpbn_pat_off,
		2)

PAT_SUB_GENERIC(tftpbn_pat_sub,
		&data_pat)

t_pat				tftpbn_pat = 
{
  tftpbn_pat_name,		/* t_pat_name_proc		*/
  tftpbn_pat_off,		/* t_pat_off_proc		*/
  tftpbn_pat_sub,		/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  tftpbn_pat_get_field,		/* t_pat_get_field_proc		*/
  tftpbn_pat_set_field,		/* t_pat_set_field_proc		*/
  tftpbn_pat_get_fields,	/* t_pat_get_fields_proc	*/
  tftpbn_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		*/
  tftpbn_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	*/
};

t_assoc		tftpopcode_assocs[] = 
{
  {"rrq",	(VOID_PTR)TFTPOP_RRQ},
  {"wrq",	(VOID_PTR)TFTPOP_WRQ},
  {"data",	(VOID_PTR)TFTPOP_DATA},
  {"ack",	(VOID_PTR)TFTPOP_ACK},
  {"error",	(VOID_PTR)TFTPOP_ERROR},
  {NULL,	0},
};

int		tftp_get_opcode(tftp)
t_tftp		*tftp;
{
  return (safe_ntohs(&tftp->opcode));
}

t_field				tftp_fields[] = 
{
  {"opcode",	0,		&nu16_pat,		NULL},
  {"Opcode",	0,		&nu16assoc_pat,	tftpopcode_assocs},
  NULL_FIELD
};

char				*tftp_itmpl = "\n\
<table _name=tftp[%i%] width=100%%%% bgcolor=\"%%tftpColor%%\">\n\
<tr>\n\
<td align=center width=100%%%%>\n\
<a href=\"set(tftp[%i%].Opcode)\">%%tftp[%i%].Opcode%%</a>\n\
(<a href=\"set(tftp[%i%].opcode)\">%%tftp[%i%].opcode%%</a>)\n\
</td>\n\
</tr>\n\
</table>\n\
<br>\n\
";

int	tftp_chan;

PAT_NAME_GENERIC(tftp_pat_name,
		 (VOID_PTR)&tftp_chan,
		 "tftp")

PAT_GET_FIELD_GENERIC(tftp_pat_get_field,
		      tftp_fields)

PAT_SET_FIELD_GENERIC(tftp_pat_set_field,
		      tftp_fields)

PAT_GET_FIELDS_GENERIC(tftp_pat_get_fields,
		       tftp_fields)

PAT_GET_FIELD_PAT_GENERIC(tftp_pat_get_field_pat,
			  tftp_fields)

PAT_GET_TMPL_GENERIC(tftp_pat_get_tmpl,
		     (VOID_PTR)&tftp_chan,
		     tftp_itmpl)

PAT_OFF_GENERIC(tftp_pat_off,
		2)

PAT_SUB_DECL(tftp_pat_sub)
{
  t_tftp	*tftp;

  PAT_TFTP_CHECK(tftp,buf,len);
  switch (tftp_get_opcode(tftp))
    {
    case TFTPOP_RRQ:
    case TFTPOP_WRQ:
      (*pat_return) = &tftpfname_pat;
      return (0);
    case TFTPOP_DATA:
    case TFTPOP_ACK:
      (*pat_return) = &tftpbn_pat;
      return (0);
    case TFTPOP_ERROR:
      (*pat_return) = &tftperror_pat;
      return (0);
    }
  (*pat_return) = &data_pat;
  return (0);
}

t_pat				tftp_pat = 
{
  tftp_pat_name,		/* t_pat_name_proc		*/
  tftp_pat_off,			/* t_pat_off_proc		*/
  tftp_pat_sub,			/* t_pat_sub_proc		*/
  NULL,				/* t_pat_sum_proc		*/
  tftp_pat_get_field,		/* t_pat_get_field_proc		*/
  tftp_pat_set_field,		/* t_pat_set_field_proc		*/
  tftp_pat_get_fields,		/* t_pat_get_fields_proc	*/
  tftp_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		*/
  tftp_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	*/
};
