/*
		                  LCRZO
                             Network library
             Copyright(c) 1999,2000,2001,2002 Laurent Constantin
                                  -----

  Main server    : http://www.laurentconstantin.com/
  Backup servers : http://go.to/laurentconstantin/
                   http://laurentconstantin.est-la.com/
                   http://laurentconstantin.free.fr/
                   http://lauconstantin.multimania.com/
  [my current email address is on the web servers]

                                  -----
  This file is part of Lcrzo.

  Lcrzo is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  Lcrzo is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details (http://www.gnu.org).

------------------------------------------------------------------------
*/

/* -- Note about comments and variable names --
   In versions 1.00 up to 2.08, lcrzo was only written in French (my
   mother tongue). Since version 3.00, lcrzo is written in English, but
   most of comments and variable names are still in French.
   In future versions, I'll try to translate everything into English,
   but as you may guess, that's a quite big work...
   So, for the moment, here are some word translation, if you want to
   be able to understand what's going on in the functions :
     afficher - print     ;  ajouter - add         ;  copie - copy
     dernier - last       ;  donnee - data         ;  ecrire - write
     entete - header      ;  envoye - sent         ;  ferme - close
     fichier - file       ;  lire - read           ;  masque - mask 
     nboct - byte number  ;  ouvre, ouvrir - open  ;  paq, paquet - packet
     plage - range        ;  premier - first       ;  recu - received
     reseau - network     ;  retour - return       ;  taille - size
     tunnel - pipe

*/

#include "lcrzo_incl.h"

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmpdestunreach(lcrzo_uint8 code,
				       lcrzo_constdata ippacket, 
				       lcrzo_uint16 ippacketsize,
				       lcrzo_data *pdataout,
				       lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_hdrlicmp hdricmp;
  lcrzo_uint16 ippacketsizetouse;
  int ret;

  /* parameters verification */
  if (ippacket==NULL && ippacketsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=LCRZO_ICMPTYPE_DESTUNREACH;
  hdricmp.code=code;

  /* we use at most 64 bits of ippacketsize */
  ippacketsizetouse=ippacketsize;
  if (ippacketsizetouse>8) ippacketsizetouse=8;

  /* create icmpdata */
  lcrzo_er(lcrzo_data_initm_char('\0', 4, &data, &datasize));
  lcrzo_er(lcrzo_data_appendm_data(ippacket, ippacketsizetouse,
				   datasize, &data, &datasize));

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, (lcrzo_uint16)datasize,
				  pdataout, pdataoutsize);
  lcrzo_er(lcrzo_data_free(data));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmpdestunreach(lcrzo_hdrlip hdrlip,
					    const lcrzo_ipopt ipopt,
					    lcrzo_uint8 ipoptsize,
					    lcrzo_uint8 code,
					    lcrzo_constdata ippacket, 
					    lcrzo_uint16 ippacketsize,
					    lcrzo_data *pdataout,
					    lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpdestunreach(code, ippacket, ippacketsize,
					      &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmpdestunreach(lcrzo_hdrleth hdrleth,
					       lcrzo_hdrlip hdrlip,
					       const lcrzo_ipopt ipopt,
					       lcrzo_uint8 ipoptsize,
					       lcrzo_uint8 code,
					       lcrzo_constdata ippacket, 
					       lcrzo_uint16 ippacketsize,
				               lcrzo_data *pdataout,
					       lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpdestunreach(code, ippacket, ippacketsize,
					      &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmptimeexceed(lcrzo_uint8 code,
				      lcrzo_constdata ippacket, 
				      lcrzo_uint16 ippacketsize,
				      lcrzo_data *pdataout,
				      lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_hdrlicmp hdricmp;
  lcrzo_uint16 ippacketsizetouse;
  int ret;

  /* parameters verification */
  if (ippacket==NULL && ippacketsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=LCRZO_ICMPTYPE_TIMEEXCEED;
  hdricmp.code=code;

  /* we use at most 64 bits of ippacketsize */
  ippacketsizetouse=ippacketsize;
  if (ippacketsizetouse>8) ippacketsizetouse=8;

  /* create icmpdata */
  lcrzo_er(lcrzo_data_initm_char('\0', 4, &data, &datasize));
  lcrzo_er(lcrzo_data_appendm_data(ippacket, ippacketsizetouse,
				   datasize, &data, &datasize));

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, (lcrzo_uint16)datasize,
				  pdataout, pdataoutsize);
  lcrzo_er(lcrzo_data_free(data));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmptimeexceed(lcrzo_hdrlip hdrlip,
					   const lcrzo_ipopt ipopt,
					   lcrzo_uint8 ipoptsize,
					   lcrzo_uint8 code,
					   lcrzo_constdata ippacket, 
					   lcrzo_uint16 ippacketsize,
					   lcrzo_data *pdataout,
					   lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmptimeexceed(code, ippacket, ippacketsize,
					     &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmptimeexceed(lcrzo_hdrleth hdrleth,
					      lcrzo_hdrlip hdrlip,
					      const lcrzo_ipopt ipopt,
					      lcrzo_uint8 ipoptsize,
					      lcrzo_uint8 code,
					      lcrzo_constdata ippacket, 
					      lcrzo_uint16 ippacketsize,
					      lcrzo_data *pdataout,
					      lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmptimeexceed(code, ippacket, ippacketsize,
					     &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmpparaprob(lcrzo_uint8 code,
				    lcrzo_uint8 pointer,
				    lcrzo_constdata ippacket, 
				    lcrzo_uint16 ippacketsize,
				    lcrzo_data *pdataout,
				    lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_hdrlicmp hdricmp;
  lcrzo_uint16 ippacketsizetouse;
  int ret;

  /* parameters verification */
  if (ippacket==NULL && ippacketsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=LCRZO_ICMPTYPE_PARAPROB;
  hdricmp.code=code;

  /* we use at most 64 bits of ippacketsize */
  ippacketsizetouse=ippacketsize;
  if (ippacketsizetouse>8) ippacketsizetouse=8;

  /* create icmpdata */
  lcrzo_er(lcrzo_data_initm_char('\0', 4, &data, &datasize));
  data[0]=pointer;
  lcrzo_er(lcrzo_data_appendm_data(ippacket, ippacketsizetouse,
				   datasize, &data, &datasize));

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, (lcrzo_uint16)datasize,
				  pdataout, pdataoutsize);
  lcrzo_er(lcrzo_data_free(data));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmpparaprob(lcrzo_hdrlip hdrlip,
					 const lcrzo_ipopt ipopt,
					 lcrzo_uint8 ipoptsize,
					 lcrzo_uint8 code,
					 lcrzo_uint8 pointer,
					 lcrzo_constdata ippacket, 
					 lcrzo_uint16 ippacketsize,
					 lcrzo_data *pdataout,
					 lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpparaprob(code, pointer, 
					   ippacket, ippacketsize,
					   &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmpparaprob(lcrzo_hdrleth hdrleth,
					    lcrzo_hdrlip hdrlip,
					    const lcrzo_ipopt ipopt,
					    lcrzo_uint8 ipoptsize,
					    lcrzo_uint8 code,
					    lcrzo_uint8 pointer,
					    lcrzo_constdata ippacket, 
					    lcrzo_uint16 ippacketsize,
					    lcrzo_data *pdataout,
					    lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpparaprob(code, pointer, 
					   ippacket, ippacketsize,
					   &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmpsrcquench(lcrzo_constdata ippacket, 
				     lcrzo_uint16 ippacketsize,
				     lcrzo_data *pdataout,
				     lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_hdrlicmp hdricmp;
  lcrzo_uint16 ippacketsizetouse;
  int ret;

  /* parameters verification */
  if (ippacket==NULL && ippacketsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=LCRZO_ICMPTYPE_SRCQUENCH;
  hdricmp.code=0;

  /* we use at most 64 bits of ippacketsize */
  ippacketsizetouse=ippacketsize;
  if (ippacketsizetouse>8) ippacketsizetouse=8;

  /* create icmpdata */
  lcrzo_er(lcrzo_data_initm_char('\0', 4, &data, &datasize));
  lcrzo_er(lcrzo_data_appendm_data(ippacket, ippacketsizetouse,
				   datasize, &data, &datasize));

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, (lcrzo_uint16)datasize,
				  pdataout, pdataoutsize);
  lcrzo_er(lcrzo_data_free(data));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmpsrcquench(lcrzo_hdrlip hdrlip,
					  const lcrzo_ipopt ipopt,
					  lcrzo_uint8 ipoptsize,
					  lcrzo_constdata ippacket, 
					  lcrzo_uint16 ippacketsize,
					  lcrzo_data *pdataout,
					  lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpsrcquench(ippacket, ippacketsize,
					    &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmpsrcquench(lcrzo_hdrleth hdrleth,
					     lcrzo_hdrlip hdrlip,
					     const lcrzo_ipopt ipopt,
					     lcrzo_uint8 ipoptsize,
					     lcrzo_constdata ippacket, 
					     lcrzo_uint16 ippacketsize,
					     lcrzo_data *pdataout,
					     lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpsrcquench(ippacket, ippacketsize,
					    &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmpredirect(lcrzo_uint8 code,
				    lcrzo_ipl gw,
				    lcrzo_constdata ippacket, 
				    lcrzo_uint16 ippacketsize,
				    lcrzo_data *pdataout,
				    lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_hdrlicmp hdricmp;
  lcrzo_uint16 ippacketsizetouse;
  lcrzo_ipa ipa;
  int ret;

  /* parameters verification */
  if (ippacket==NULL && ippacketsize) return(LCRZO_ERR_PANULLPTRSIZE);

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=LCRZO_ICMPTYPE_REDIRECT;
  hdricmp.code=code;

  /* we use at most 64 bits of ippacketsize */
  ippacketsizetouse=ippacketsize;
  if (ippacketsizetouse>8) ippacketsizetouse=8;

  /* create icmpdata */
  lcrzo_er(lcrzo_data_initm_char('\0', 4, &data, &datasize));
  lcrzo_er(lcrzo_ipa_init_ipl(gw, ipa));
  data[0]=ipa[0];
  data[1]=ipa[1];
  data[2]=ipa[2];
  data[3]=ipa[3];
  lcrzo_er(lcrzo_data_appendm_data(ippacket, ippacketsizetouse,
				   datasize, &data, &datasize));

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, (lcrzo_uint16)datasize,
				  pdataout, pdataoutsize);
  lcrzo_er(lcrzo_data_free(data));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmpredirect(lcrzo_hdrlip hdrlip,
					 const lcrzo_ipopt ipopt,
					 lcrzo_uint8 ipoptsize,
					 lcrzo_uint8 code,
					 lcrzo_ipl gw,
					 lcrzo_constdata ippacket, 
					 lcrzo_uint16 ippacketsize,
					 lcrzo_data *pdataout,
					 lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpredirect(code, gw, ippacket, ippacketsize,
					   &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmpredirect(lcrzo_hdrleth hdrleth,
					    lcrzo_hdrlip hdrlip,
					    const lcrzo_ipopt ipopt,
					    lcrzo_uint8 ipoptsize,
					    lcrzo_uint8 code,
					    lcrzo_ipl gw,
					    lcrzo_constdata ippacket, 
					    lcrzo_uint16 ippacketsize,
					    lcrzo_data *pdataout,
					    lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpredirect(code, gw, ippacket, ippacketsize,
					   &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmpecho(lcrzo_uint8 type,
				lcrzo_uint16 id,
				lcrzo_uint16 seqnum,
			        lcrzo_constdata echodata, 
				lcrzo_uint16 echodatasize,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_hdrlicmp hdricmp;
  int ret;

  /* parameters verification */
  if ( echodata==NULL && echodatasize ) return(LCRZO_ERR_PANULLPTRSIZE);

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=type;
  hdricmp.code=0;

  /* create icmpdata */
  lcrzo_er(lcrzo_data_initm_char('\0', 4, &data, &datasize));
  data[0]=(lcrzo_uint8)(id>>8);
  data[1]=(lcrzo_uint8)(id&0xFF);
  data[2]=(lcrzo_uint8)(seqnum>>8);
  data[3]=(lcrzo_uint8)(seqnum&0xFF);
  lcrzo_er(lcrzo_data_appendm_data(echodata, echodatasize,
				   datasize, &data, &datasize));

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, (lcrzo_uint16)datasize,
				  pdataout, pdataoutsize);
  lcrzo_er(lcrzo_data_free(data));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmpecho(lcrzo_hdrlip hdrlip,
				     const lcrzo_ipopt ipopt,
				     lcrzo_uint8 ipoptsize,
				     lcrzo_uint8 type,
				     lcrzo_uint16 id,
				     lcrzo_uint16 seqnum,
				     lcrzo_constdata echodata, 
				     lcrzo_uint16 echodatasize,
				     lcrzo_data *pdataout,
				     lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpecho(type, id, seqnum,
				       echodata, echodatasize,
				       &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmpecho(lcrzo_hdrleth hdrleth,
					lcrzo_hdrlip hdrlip,
					const lcrzo_ipopt ipopt,
					lcrzo_uint8 ipoptsize,
					lcrzo_uint8 type,
					lcrzo_uint16 id,
					lcrzo_uint16 seqnum,
					lcrzo_constdata echodata, 
					lcrzo_uint16 echodatasize,
					lcrzo_data *pdataout,
					lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpecho(type, id, seqnum,
				       echodata, echodatasize,
				       &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmptimestamp(lcrzo_uint8 type,
				     lcrzo_uint16 id,
				     lcrzo_uint16 seqnum,
				     lcrzo_uint32 originatetimestamp,
				     lcrzo_uint32 receivetimestamp,
				     lcrzo_uint32 transmittimestamp,
				     lcrzo_data *pdataout,
				     lcrzo_int32 *pdataoutsize)
{ lcrzo_uint8 data[16];
  lcrzo_hdrlicmp hdricmp;
  int ret;

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=type;
  hdricmp.code=0;

  /* create icmpdata */
  data[0]=(lcrzo_uint8)(id>>8);
  data[1]=(lcrzo_uint8)(id&0xFF);
  data[2]=(lcrzo_uint8)(seqnum>>8);
  data[3]=(lcrzo_uint8)(seqnum&0xFF);
  data[4]=(lcrzo_uint8)(originatetimestamp>>24);
  data[5]=(lcrzo_uint8)((originatetimestamp>>16)&0xFF);
  data[6]=(lcrzo_uint8)((originatetimestamp>>8)&0xFF);
  data[7]=(lcrzo_uint8)(originatetimestamp&0xFF);
  data[8]=(lcrzo_uint8)(receivetimestamp>>24);
  data[9]=(lcrzo_uint8)((receivetimestamp>>16)&0xFF);
  data[10]=(lcrzo_uint8)((receivetimestamp>>8)&0xFF);
  data[11]=(lcrzo_uint8)(receivetimestamp&0xFF);
  data[12]=(lcrzo_uint8)(transmittimestamp>>24);
  data[13]=(lcrzo_uint8)((transmittimestamp>>16)&0xFF);
  data[14]=(lcrzo_uint8)((transmittimestamp>>8)&0xFF);
  data[15]=(lcrzo_uint8)(transmittimestamp&0xFF);

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, 16, pdataout, pdataoutsize);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmptimestamp(lcrzo_hdrlip hdrlip,
					  const lcrzo_ipopt ipopt,
					  lcrzo_uint8 ipoptsize,
					  lcrzo_uint8 type,
					  lcrzo_uint16 id,
					  lcrzo_uint16 seqnum,
					  lcrzo_uint32 originatetimestamp,
					  lcrzo_uint32 receivetimestamp,
					  lcrzo_uint32 transmittimestamp,
					  lcrzo_data *pdataout,
					  lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmptimestamp(type, id, seqnum,
					    originatetimestamp,
					    receivetimestamp,
					    transmittimestamp,
					    &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmptimestamp(lcrzo_hdrleth hdrleth,
					     lcrzo_hdrlip hdrlip,
					     const lcrzo_ipopt ipopt,
					     lcrzo_uint8 ipoptsize,
					     lcrzo_uint8 type,
					     lcrzo_uint16 id,
					     lcrzo_uint16 seqnum,
					     lcrzo_uint32 originatetimestamp,
					     lcrzo_uint32 receivetimestamp,
					     lcrzo_uint32 transmittimestamp,
					     lcrzo_data *pdataout,
					     lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmptimestamp(type, id, seqnum,
					    originatetimestamp,
					    receivetimestamp,
					    transmittimestamp,
					    &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_icmpinfo(lcrzo_uint8 type,
				lcrzo_uint16 id,
				lcrzo_uint16 seqnum,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_uint8 data[4];
  lcrzo_hdrlicmp hdricmp;
  int ret;

  /* init icmp header */
  lcrzo_er(lcrzo_hdrlicmp_initdefault(&hdricmp));
  hdricmp.type=type;
  hdricmp.code=0;

  /* create icmpdata */
  data[0]=(lcrzo_uint8)(id>>8);
  data[1]=(lcrzo_uint8)(id&0xFF);
  data[2]=(lcrzo_uint8)(seqnum>>8);
  data[3]=(lcrzo_uint8)(seqnum&0xFF);

  /* create packet */
  ret=lcrzo_packet_initm_icmpdata(hdricmp, data, 4, pdataout, pdataoutsize);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ipopticmpinfo(lcrzo_hdrlip hdrlip,
				     const lcrzo_ipopt ipopt,
				     lcrzo_uint8 ipoptsize,
				     lcrzo_uint8 type,
				     lcrzo_uint16 id,
				     lcrzo_uint16 seqnum,
				     lcrzo_data *pdataout,
				     lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpinfo(type, id, seqnum,
				       &data, &datasize));
  ret=lcrzo_packet_initm_ipoptdata(hdrlip, ipopt, ipoptsize,
				   data, (lcrzo_uint16)datasize,
				   pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_initm_ethipopticmpinfo(lcrzo_hdrleth hdrleth,
					lcrzo_hdrlip hdrlip,
					const lcrzo_ipopt ipopt,
					lcrzo_uint8 ipoptsize,
					lcrzo_uint8 type,
					lcrzo_uint16 id,
					lcrzo_uint16 seqnum,
					lcrzo_data *pdataout,
					lcrzo_int32 *pdataoutsize)
{ lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_bool hdr_compfields, hdr_compfield_ipprotocol;
  int ret;

  /* eventually update IP protocol */
  lcrzo_er(lcrzo_global_get_hdr_compfields(&hdr_compfields));
  lcrzo_er(lcrzo_global_get_hdr_cf_ipprotocol(&hdr_compfield_ipprotocol));
  if ( hdrlip.protocol==LCRZO_HDRLIP_PROTOCOL_DEFVAL &&
       hdr_compfields &&
       hdr_compfield_ipprotocol )
  { hdrlip.protocol=LCRZO_HDRLIP_PROTOCOL_ICMP;
  }

  /* compose packet */
  lcrzo_er(lcrzo_packet_initm_icmpinfo(type, id, seqnum,
				       &data, &datasize));
  ret=lcrzo_packet_initm_ethipoptdata(hdrleth, hdrlip, ipopt, ipoptsize,
				      data, (lcrzo_uint16)datasize,
				      pdataout, pdataoutsize);
  lcrzo_data_free(data);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmpdestunreach(lcrzo_constdata icmppacket,
					 lcrzo_int32 icmppacketsize,
					 lcrzo_uint8 *pcode,
					 lcrzo_data *pbadpacket, 
					 lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_DESTUNREACH )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if (pcode!=NULL) *pcode=hdrlicmp.code;
  lcrzo_er(lcrzo_priv_data_u16_initm_data(icmppacket+8, (lcrzo_uint16)(icmppacketsize-8), 
					  pbadpacket, pbadpacketsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmpdestunreach(lcrzo_constdata ippacket,
					      lcrzo_int32 ippacketsize,
					      lcrzo_hdrlip *phdrlip,
					      lcrzo_ipopt ipopt,
					      lcrzo_uint8 *pipoptsize,
					      lcrzo_uint8 *pcode,
					      lcrzo_data *pbadpacket, 
					      lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpdestunreach(ipdata, ipdatasize,
					   pcode, pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmpdestunreach(lcrzo_constdata ethpacket,
						 lcrzo_int32 ethpacketsize,
						 lcrzo_hdrleth *phdrleth,
						 lcrzo_hdrlip *phdrlip,
						 lcrzo_ipopt ipopt,
						 lcrzo_uint8 *pipoptsize,
						 lcrzo_uint8 *pcode,
						 lcrzo_data *pbadpacket, 
						 lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpdestunreach(ipdata, ipdatasize,
					   pcode, pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmptimeexceed(lcrzo_constdata icmppacket,
					lcrzo_int32 icmppacketsize,
					lcrzo_uint8 *pcode,
					lcrzo_data *pbadpacket, 
					lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_TIMEEXCEED )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if (pcode!=NULL) *pcode=hdrlicmp.code;
  lcrzo_er(lcrzo_priv_data_u16_initm_data(icmppacket+8, (lcrzo_uint16)(icmppacketsize-8), 
					  pbadpacket, pbadpacketsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmptimeexceed(lcrzo_constdata ippacket,
					     lcrzo_int32 ippacketsize,
					     lcrzo_hdrlip *phdrlip,
					     lcrzo_ipopt ipopt,
					     lcrzo_uint8 *pipoptsize,
					     lcrzo_uint8 *pcode,
					     lcrzo_data *pbadpacket, 
					     lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmptimeexceed(ipdata, ipdatasize,
					  pcode, pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmptimeexceed(lcrzo_constdata ethpacket,
						 lcrzo_int32 ethpacketsize,
						 lcrzo_hdrleth *phdrleth,
						 lcrzo_hdrlip *phdrlip,
						 lcrzo_ipopt ipopt,
						 lcrzo_uint8 *pipoptsize,
						 lcrzo_uint8 *pcode,
						 lcrzo_data *pbadpacket, 
						 lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmptimeexceed(ipdata, ipdatasize,
					  pcode, pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmpparaprob(lcrzo_constdata icmppacket,
				      lcrzo_int32 icmppacketsize,
				      lcrzo_uint8 *pcode,
				      lcrzo_uint8 *ppointer,
				      lcrzo_data *pbadpacket, 
				      lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_PARAPROB )
    return(LCRZO_ERR_OKNOTDECODED);
  if (pcode!=NULL) *pcode=hdrlicmp.code;

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if (ppointer!=NULL) *ppointer=icmppacket[4];
  lcrzo_er(lcrzo_priv_data_u16_initm_data(icmppacket+8, (lcrzo_uint16)(icmppacketsize-8), 
					  pbadpacket, pbadpacketsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmpparaprob(lcrzo_constdata ippacket,
					   lcrzo_int32 ippacketsize,
					   lcrzo_hdrlip *phdrlip,
					   lcrzo_ipopt ipopt,
					   lcrzo_uint8 *pipoptsize,
					   lcrzo_uint8 *pcode,
					   lcrzo_uint8 *ppointer,
					   lcrzo_data *pbadpacket, 
					   lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpparaprob(ipdata, ipdatasize,
					pcode, ppointer,
					pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmpparaprob(lcrzo_constdata ethpacket,
					      lcrzo_int32 ethpacketsize,
					      lcrzo_hdrleth *phdrleth,
					      lcrzo_hdrlip *phdrlip,
					      lcrzo_ipopt ipopt,
					      lcrzo_uint8 *pipoptsize,
					      lcrzo_uint8 *pcode,
					      lcrzo_uint8 *ppointer,
					      lcrzo_data *pbadpacket, 
					      lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpparaprob(ipdata, ipdatasize,
					pcode, ppointer, 
					pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmpsrcquench(lcrzo_constdata icmppacket,
				       lcrzo_int32 icmppacketsize,
				       lcrzo_data *pbadpacket, 
				       lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_SRCQUENCH )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  lcrzo_er(lcrzo_priv_data_u16_initm_data(icmppacket+8, (lcrzo_uint16)(icmppacketsize-8), 
					  pbadpacket, pbadpacketsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmpsrcquench(lcrzo_constdata ippacket,
					    lcrzo_int32 ippacketsize,
					    lcrzo_hdrlip *phdrlip,
					    lcrzo_ipopt ipopt,
					    lcrzo_uint8 *pipoptsize,
					    lcrzo_data *pbadpacket, 
					    lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpsrcquench(ipdata, ipdatasize,
					 pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmpsrcquench(lcrzo_constdata ethpacket,
					       lcrzo_int32 ethpacketsize,
					       lcrzo_hdrleth *phdrleth,
					       lcrzo_hdrlip *phdrlip,
					       lcrzo_ipopt ipopt,
					       lcrzo_uint8 *pipoptsize,
					       lcrzo_data *pbadpacket, 
					       lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpsrcquench(ipdata, ipdatasize,
					 pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmpredirect(lcrzo_constdata icmppacket,
				      lcrzo_int32 icmppacketsize,
				      lcrzo_uint8 *pcode,
				      lcrzo_ipl *pgw,
				      lcrzo_data *pbadpacket, 
				      lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_REDIRECT )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if (pcode!=NULL) *pcode=hdrlicmp.code;
  if ( pgw!=NULL )
  { *pgw=(icmppacket[4]<<24) | (icmppacket[5]<<16) |
         (icmppacket[6]<<8) | icmppacket[7];
  }
  lcrzo_er(lcrzo_priv_data_u16_initm_data(icmppacket+8, (lcrzo_uint16)(icmppacketsize-8), 
					  pbadpacket, pbadpacketsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmpredirect(lcrzo_constdata ippacket,
					   lcrzo_int32 ippacketsize,
					   lcrzo_hdrlip *phdrlip,
					   lcrzo_ipopt ipopt,
					   lcrzo_uint8 *pipoptsize,
					   lcrzo_uint8 *pcode,
					   lcrzo_ipl *pgw,
					   lcrzo_data *pbadpacket, 
					   lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpredirect(ipdata, ipdatasize,
					pcode, pgw, 
					pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmpredirect(lcrzo_constdata ethpacket,
					      lcrzo_int32 ethpacketsize,
					      lcrzo_hdrleth *phdrleth,
					      lcrzo_hdrlip *phdrlip,
					      lcrzo_ipopt ipopt,
					      lcrzo_uint8 *pipoptsize,
					      lcrzo_uint8 *pcode,
					      lcrzo_ipl *pgw,
					      lcrzo_data *pbadpacket, 
					      lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpredirect(ipdata, ipdatasize,
					pcode, pgw,
					pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmpecho(lcrzo_constdata icmppacket,
				  lcrzo_int32 icmppacketsize,
				  lcrzo_uint8 *ptype,
				  lcrzo_uint16 *pid,
				  lcrzo_uint16 *pseqnum,
				  lcrzo_data *pechodata, 
				  lcrzo_uint16 *pechodatasize)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_ECHOREQ && 
       hdrlicmp.type!=LCRZO_ICMPTYPE_ECHOREP )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if (ptype!=NULL) *ptype=hdrlicmp.type;
  if ( pid!=NULL ) *pid=(lcrzo_uint16)((icmppacket[4]<<8) | icmppacket[5]);
  if ( pseqnum!=NULL ) *pseqnum=(lcrzo_uint16)((icmppacket[6]<<8) | icmppacket[7]);
  lcrzo_er(lcrzo_priv_data_u16_initm_data(icmppacket+8, (lcrzo_uint16)(icmppacketsize-8), 
					  pechodata, pechodatasize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmpecho(lcrzo_constdata ippacket,
				       lcrzo_int32 ippacketsize,
				       lcrzo_hdrlip *phdrlip,
				       lcrzo_ipopt ipopt,
				       lcrzo_uint8 *pipoptsize,
				       lcrzo_uint8 *ptype,
				       lcrzo_uint16 *pid,
				       lcrzo_uint16 *pseqnum,
				       lcrzo_data *pechodata, 
				       lcrzo_uint16 *pechodatasize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpecho(ipdata, ipdatasize,
				    ptype, pid, pseqnum,
				    pechodata, pechodatasize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmpecho(lcrzo_constdata ethpacket,
					  lcrzo_int32 ethpacketsize,
					  lcrzo_hdrleth *phdrleth,
					  lcrzo_hdrlip *phdrlip,
					  lcrzo_ipopt ipopt,
					  lcrzo_uint8 *pipoptsize,
					  lcrzo_uint8 *ptype,
					  lcrzo_uint16 *pid,
					  lcrzo_uint16 *pseqnum,
					  lcrzo_data *pechodata, 
					  lcrzo_uint16 *pechodatasize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpecho(ipdata, ipdatasize,
				    ptype, pid, pseqnum,
				    pechodata, pechodatasize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmptimestamp(lcrzo_constdata icmppacket,
				       lcrzo_int32 icmppacketsize,
				       lcrzo_uint8 *ptype,
				       lcrzo_uint16 *pid,
				       lcrzo_uint16 *pseqnum,
				       lcrzo_uint32 *poriginatetimestamp,
				       lcrzo_uint32 *preceivetimestamp,
				       lcrzo_uint32 *ptransmittimestamp)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_TIMESTAMPREQ && 
       hdrlicmp.type!=LCRZO_ICMPTYPE_TIMESTAMPREP )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<20 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if (ptype!=NULL) *ptype=hdrlicmp.type;
  if ( pid!=NULL ) *pid=(lcrzo_uint16)((icmppacket[4]<<8) | icmppacket[5]);
  if ( pseqnum!=NULL ) *pseqnum=(lcrzo_uint16)((icmppacket[6]<<8) | icmppacket[7]);
  if ( poriginatetimestamp!=NULL )
  { *poriginatetimestamp=(icmppacket[8]<<24) | (icmppacket[9]<<16) |
                         (icmppacket[10]<<8) | icmppacket[11];
  }
  if ( preceivetimestamp!=NULL )
  { *preceivetimestamp=(icmppacket[12]<<24) | (icmppacket[13]<<16) |
                         (icmppacket[14]<<8) | icmppacket[15];
  }
  if ( ptransmittimestamp!=NULL )
  { *ptransmittimestamp=(icmppacket[16]<<24) | (icmppacket[17]<<16) |
                         (icmppacket[18]<<8) | icmppacket[19];
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmptimestamp(lcrzo_constdata ippacket,
					    lcrzo_int32 ippacketsize,
					    lcrzo_hdrlip *phdrlip,
					    lcrzo_ipopt ipopt,
					    lcrzo_uint8 *pipoptsize,
					    lcrzo_uint8 *ptype,
					    lcrzo_uint16 *pid,
					    lcrzo_uint16 *pseqnum,
					    lcrzo_uint32 *poriginatetimestamp,
					    lcrzo_uint32 *preceivetimestamp,
					    lcrzo_uint32 *ptransmittimestamp)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmptimestamp(ipdata, ipdatasize,
					 ptype, pid, pseqnum,
					 poriginatetimestamp, 
					 preceivetimestamp,
					 ptransmittimestamp);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmptimestamp(lcrzo_constdata ethpacket,
					       lcrzo_int32 ethpacketsize,
					       lcrzo_hdrleth *phdrleth,
					       lcrzo_hdrlip *phdrlip,
					       lcrzo_ipopt ipopt,
					       lcrzo_uint8 *pipoptsize,
					       lcrzo_uint8 *ptype,
					       lcrzo_uint16 *pid,
					       lcrzo_uint16 *pseqnum,
					     lcrzo_uint32 *poriginatetimestamp,
					     lcrzo_uint32 *preceivetimestamp,
				             lcrzo_uint32 *ptransmittimestamp)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmptimestamp(ipdata, ipdatasize,
					 ptype, pid, pseqnum,
					 poriginatetimestamp,
					 preceivetimestamp,
					 ptransmittimestamp);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmpinfo(lcrzo_constdata icmppacket,
				  lcrzo_int32 icmppacketsize,
				  lcrzo_uint8 *ptype,
				  lcrzo_uint16 *pid,
				  lcrzo_uint16 *pseqnum)
{ lcrzo_hdrpicmp hdrpicmp;
  lcrzo_hdrlicmp hdrlicmp;

  /* parameters verification */
  if ( icmppacket==NULL && icmppacketsize ) return(LCRZO_ERR_PANULLPTRSIZE);
  if ( icmppacketsize<0 ) return(LCRZO_ERR_PATOOLOW);

  /* ICMP header */
  if ((lcrzo_uint32)icmppacketsize<sizeof(lcrzo_hdrpicmp))
    return(LCRZO_ERR_OKNOTDECODED);
  memcpy(&hdrpicmp, icmppacket, sizeof(lcrzo_hdrpicmp));
  lcrzo_er(lcrzo_hdrlicmp_init_hdrpicmp(hdrpicmp, &hdrlicmp));

  /* only this type */
  if ( hdrlicmp.type!=LCRZO_ICMPTYPE_INFOREQ && 
       hdrlicmp.type!=LCRZO_ICMPTYPE_INFOREP )
    return(LCRZO_ERR_OKNOTDECODED);

  /* this is the minimum size */
  if ( icmppacketsize<8 )
    return(LCRZO_ERR_OKNOTDECODED);

  /* set output values */
  if ( ptype!=NULL ) *ptype=hdrlicmp.type;
  if ( pid!=NULL ) *pid=(lcrzo_uint16)((icmppacket[4]<<8) | icmppacket[5]);
  if ( pseqnum!=NULL ) *pseqnum=(lcrzo_uint16)((icmppacket[6]<<8) | icmppacket[7]);

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmpinfo(lcrzo_constdata ippacket,
				       lcrzo_int32 ippacketsize,
				       lcrzo_hdrlip *phdrlip,
				       lcrzo_ipopt ipopt,
				       lcrzo_uint8 *pipoptsize,
				       lcrzo_uint8 *ptype,
				       lcrzo_uint16 *pid,
				       lcrzo_uint16 *pseqnum)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpinfo(ipdata, ipdatasize,
				    ptype, pid, pseqnum);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmpinfo(lcrzo_constdata ethpacket,
					  lcrzo_int32 ethpacketsize,
					  lcrzo_hdrleth *phdrleth,
					  lcrzo_hdrlip *phdrlip,
					  lcrzo_ipopt ipopt,
					  lcrzo_uint8 *pipoptsize,
					  lcrzo_uint8 *ptype,
					  lcrzo_uint16 *pid,
					  lcrzo_uint16 *pseqnum)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmpinfo(ipdata, ipdatasize,
				    ptype, pid, pseqnum);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_icmperror(lcrzo_constdata icmppacket,
				   lcrzo_int32 icmppacketsize,
				   lcrzo_uint8 *ptype,
				   lcrzo_uint8 *pcode,
				   lcrzo_uint8 *ppointer,
				   lcrzo_ipl *pgw,
				   lcrzo_data *pbadpacket, 
				   lcrzo_uint16 *pbadpacketsize)
{ int ret;

  /* try to decode destunreach */
  ret=lcrzo_packet_decodem_icmpdestunreach(icmppacket, icmppacketsize,
					   pcode, pbadpacket, pbadpacketsize);
  if (ret==LCRZO_ERR_OK)
  { if (ptype!=NULL) *ptype=LCRZO_ICMPTYPE_DESTUNREACH;
    return(LCRZO_ERR_OK);
  }

  /* try to decode timeexceed */
  ret=lcrzo_packet_decodem_icmptimeexceed(icmppacket, icmppacketsize,
					   pcode, pbadpacket, pbadpacketsize);
  if (ret==LCRZO_ERR_OK)
  { if (ptype!=NULL) *ptype=LCRZO_ICMPTYPE_TIMEEXCEED;
    return(LCRZO_ERR_OK);
  }

  /* try to decode paraprob */
  ret=lcrzo_packet_decodem_icmpparaprob(icmppacket, icmppacketsize,
					pcode, ppointer,
					pbadpacket, pbadpacketsize);
  if (ret==LCRZO_ERR_OK)
  { if (ptype!=NULL) *ptype=LCRZO_ICMPTYPE_PARAPROB;
    return(LCRZO_ERR_OK);
  }

  /* try to decode srcquench */
  ret=lcrzo_packet_decodem_icmpsrcquench(icmppacket, icmppacketsize,
					 pbadpacket, pbadpacketsize);
  if (ret==LCRZO_ERR_OK)
  { if (ptype!=NULL) *ptype=LCRZO_ICMPTYPE_SRCQUENCH;
    return(LCRZO_ERR_OK);
  }

  /* try to decode redirect */
  ret=lcrzo_packet_decodem_icmpredirect(icmppacket, icmppacketsize,
					pcode, pgw, 
					pbadpacket, pbadpacketsize);
  if (ret==LCRZO_ERR_OK)
  { if (ptype!=NULL) *ptype=LCRZO_ICMPTYPE_REDIRECT;
    return(LCRZO_ERR_OK);
  }

  return(LCRZO_ERR_OKNOTDECODED);
}


/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ipopticmperror(lcrzo_constdata ippacket,
					lcrzo_int32 ippacketsize,
					lcrzo_hdrlip *phdrlip,
					lcrzo_ipopt ipopt,
					lcrzo_uint8 *pipoptsize,
					lcrzo_uint8 *ptype,
					lcrzo_uint8 *pcode,
					lcrzo_uint8 *ppointer,
					lcrzo_ipl *pgw,
					lcrzo_data *pbadpacket, 
					lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ippacket, ippacketsize,
					  &hdrlip, ipopt, pipoptsize,
					  &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmperror(ipdata, ipdatasize,
				     ptype, pcode, ppointer, pgw,
				     pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_packet_decodem_ethipopticmperror(lcrzo_constdata ethpacket,
					   lcrzo_int32 ethpacketsize,
					   lcrzo_hdrleth *phdrleth,
					   lcrzo_hdrlip *phdrlip,
					   lcrzo_ipopt ipopt,
					   lcrzo_uint8 *pipoptsize,
					   lcrzo_uint8 *ptype,
					   lcrzo_uint8 *pcode,
					   lcrzo_uint8 *ppointer,
					   lcrzo_ipl *pgw,
					   lcrzo_data *pbadpacket, 
					   lcrzo_uint16 *pbadpacketsize)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;
  int ret;

  /* decode low level */
  lcrzo_er(lcrzo_packet_decodem_ethipoptdata(ethpacket, ethpacketsize,
					     phdrleth,
					     &hdrlip, ipopt, pipoptsize,
					     &ipdata, &ipdatasize));
  
  /* only ICMP */
  if ( hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP )
  { lcrzo_data_free(ipdata);
    return(LCRZO_ERR_OKNOTDECODED);
  }
  if ( phdrlip!=NULL ) *phdrlip=hdrlip;

  /* try to decode this ICMP type */
  ret=lcrzo_packet_decodem_icmperror(ipdata, ipdatasize,
				     ptype, pcode, ppointer, pgw,
				     pbadpacket, pbadpacketsize);
  lcrzo_data_free(ipdata);
  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_ip64bits_initm_ipdata(lcrzo_hdrlip hdrlip,
				lcrzo_constdata ipdata, 
				lcrzo_uint16 ipdatasize,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_data dataout;
  lcrzo_int32 dataoutsize;

  /* initialize dataout (suppress IP options) */
  hdrlip.totlen=LCRZO_HDRLIP_TOTLEN_DEFVAL;
  hdrlip.ihl=LCRZO_HDRLIP_IHL_DEFVAL;
  hdrlip.check=LCRZO_HDRLIP_CHECK_DEFVAL;
  lcrzo_er(lcrzo_packet_initm_ipoptdata(hdrlip, NULL, 0,
					ipdata, ipdatasize,
					&dataout, &dataoutsize));

  /* we use at most 64 bits of ipdatasize */
  if ( (lcrzo_uint32)dataoutsize > (lcrzo_uint32)sizeof(lcrzo_hdrpip) + 8 )
  { dataoutsize = sizeof(lcrzo_hdrpip) + 8;
    lcrzo_er(lcrzo_data_realloc(dataoutsize, &dataout));
  }

  /* set output values */
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  if (pdataout!=NULL)
  { *pdataout=dataout;
  }
  else
  { lcrzo_data_free(dataout);
  }

  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_ip64bits_initm_ipudp(lcrzo_hdrlip hdrlip,
			       lcrzo_hdrludp hdrludp,
			       lcrzo_data *pdataout,
			       lcrzo_int32 *pdataoutsize)
{ lcrzo_data dataout;
  lcrzo_int32 dataoutsize;

  /* initialize dataout (suppress IP options) */
  hdrlip.totlen=LCRZO_HDRLIP_TOTLEN_DEFVAL;
  hdrlip.ihl=LCRZO_HDRLIP_IHL_DEFVAL;
  hdrlip.check=LCRZO_HDRLIP_CHECK_DEFVAL;
  lcrzo_er(lcrzo_packet_initm_ipoptudpdata(hdrlip, NULL, 0,
					   hdrludp, NULL, 0,
					   &dataout, &dataoutsize));

  /* we use at most 64 bits of ipdatasize */
  if ( (lcrzo_uint32)dataoutsize > (lcrzo_uint32)sizeof(lcrzo_hdrpip) + 8 )
  { dataoutsize = sizeof(lcrzo_hdrpip) + 8;
    lcrzo_er(lcrzo_data_realloc(dataoutsize, &dataout));
  }

  /* set output values */
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  if (pdataout!=NULL)
  { *pdataout=dataout;
  }
  else
  { lcrzo_data_free(dataout);
  }

  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_ip64bits_initm_iptcp(lcrzo_hdrlip hdrlip,
			       lcrzo_hdrltcp hdrltcp,
			       lcrzo_data *pdataout,
			       lcrzo_int32 *pdataoutsize)
{ lcrzo_data dataout;
  lcrzo_int32 dataoutsize;

  /* initialize dataout (suppress IP options) */
  hdrlip.totlen=LCRZO_HDRLIP_TOTLEN_DEFVAL;
  hdrlip.ihl=LCRZO_HDRLIP_IHL_DEFVAL;
  hdrlip.check=LCRZO_HDRLIP_CHECK_DEFVAL;
  lcrzo_er(lcrzo_packet_initm_ipopttcpoptdata(hdrlip, NULL, 0,
					      hdrltcp, NULL, 0, NULL, 0,
					      &dataout, &dataoutsize));

  /* we use at most 64 bits of ipdatasize */
  if ( (lcrzo_uint32)dataoutsize > (lcrzo_uint32)sizeof(lcrzo_hdrpip) + 8 )
  { dataoutsize = sizeof(lcrzo_hdrpip) + 8;
    lcrzo_er(lcrzo_data_realloc(dataoutsize, &dataout));
  }

  /* set output values */
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  if (pdataout!=NULL)
  { *pdataout=dataout;
  }
  else
  { lcrzo_data_free(dataout);
  }

  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_ip64bits_initm_ipicmp(lcrzo_hdrlip hdrlip,
				lcrzo_hdrlicmp hdrlicmp,
				lcrzo_uint8 icmpbyte4,	
				lcrzo_uint8 icmpbyte5,
				lcrzo_uint8 icmpbyte6,
				lcrzo_uint8 icmpbyte7,
				lcrzo_data *pdataout,
				lcrzo_int32 *pdataoutsize)
{ lcrzo_data dataout;
  lcrzo_int32 dataoutsize;
  lcrzo_uint8 arr[4];

  /* first, set the four bytes */
  arr[0]=icmpbyte4;
  arr[1]=icmpbyte5;
  arr[2]=icmpbyte6;
  arr[3]=icmpbyte7;

  /* initialize dataout (suppress IP options) */
  hdrlip.totlen=LCRZO_HDRLIP_TOTLEN_DEFVAL;
  hdrlip.ihl=LCRZO_HDRLIP_IHL_DEFVAL;
  hdrlip.check=LCRZO_HDRLIP_CHECK_DEFVAL;
  lcrzo_er(lcrzo_packet_initm_ipopticmpdata(hdrlip, NULL, 0,
					    hdrlicmp, arr, 4,
					    &dataout, &dataoutsize));

  /* set output values */
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  if (pdataout!=NULL)
  { *pdataout=dataout;
  }
  else
  { lcrzo_data_free(dataout);
  }

  return(LCRZO_ERR_OK); 
}


/*-------------------------------------------------------------*/
int lcrzo_ip64bits_decodem_ipdata(lcrzo_constdata ip64bits,
				  lcrzo_int32 ip64bitssize,
				  lcrzo_hdrlip *phdrip,
				  lcrzo_data *pipdata, 
				  lcrzo_uint16 *pipdatasize)
{
  if ( (lcrzo_uint32)ip64bitssize < (lcrzo_uint32)sizeof(lcrzo_hdrpip) + 8 )
    return (LCRZO_ERR_OKNOTDECODED);

  lcrzo_er(lcrzo_packet_decodem_ipoptdata(ip64bits, ip64bitssize,
					  phdrip, NULL, NULL,
					  pipdata, pipdatasize));

  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_ip64bits_decodem_ipudp(lcrzo_constdata ip64bits,
				 lcrzo_int32 ip64bitssize,
				 lcrzo_hdrlip *phdrip,
				 lcrzo_uint16 *pudpsport,
				 lcrzo_uint16 *pudpdport,
				 lcrzo_uint16 *pudplen,
				 lcrzo_uint16 *pudpcheck)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;

  /* decode low level */
  lcrzo_er(lcrzo_ip64bits_decodem_ipdata(ip64bits, ip64bitssize,
					 &hdrlip, &ipdata, &ipdatasize));

  /* verify if it is udp */
  if (hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_UDP)
  { lcrzo_data_free(ipdata);
    return (LCRZO_ERR_OKNOTDECODED);
  }

  /* set output values (ip64bits_decodem.. verify ipdata contains at least
     8 bytes) */
  if (phdrip!=NULL) *phdrip=hdrlip;
  if (pudpsport!=NULL) *pudpsport=(lcrzo_uint16)((ipdata[0]<<8)|ipdata[1]);
  if (pudpdport!=NULL) *pudpdport=(lcrzo_uint16)((ipdata[2]<<8)|ipdata[3]);
  if (pudplen!=NULL) *pudplen=(lcrzo_uint16)((ipdata[4]<<8)|ipdata[5]);
  if (pudpcheck!=NULL) *pudpcheck=(lcrzo_uint16)((ipdata[6]<<8)|ipdata[7]);

  lcrzo_data_free(ipdata);
  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_ip64bits_decodem_iptcp(lcrzo_constdata ip64bits,
				 lcrzo_int32 ip64bitssize,
				 lcrzo_hdrlip *phdrip,
				 lcrzo_uint16 *ptcpsport,
				 lcrzo_uint16 *ptcpdport,
				 lcrzo_uint32 *ptcpseqnum)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;

  /* decode low level */
  lcrzo_er(lcrzo_ip64bits_decodem_ipdata(ip64bits, ip64bitssize,
					 &hdrlip, &ipdata, &ipdatasize));

  /* verify if it is tcp */
  if (hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_TCP)
  { lcrzo_data_free(ipdata);
    return (LCRZO_ERR_OKNOTDECODED);
  }

  /* set output values (ip64bits_decodem.. verify ipdata contains at least
     8 bytes) */
  if (phdrip!=NULL) *phdrip=hdrlip;
  if (ptcpsport!=NULL) *ptcpsport=(lcrzo_uint16)((ipdata[0]<<8)|ipdata[1]);
  if (ptcpdport!=NULL) *ptcpdport=(lcrzo_uint16)((ipdata[2]<<8)|ipdata[3]);
  if (ptcpseqnum!=NULL)
  { *ptcpseqnum=(ipdata[4]<<24)|(ipdata[5])<<16|(ipdata[6]<<8)|ipdata[7];
  }

  lcrzo_data_free(ipdata);
  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_ip64bits_decodem_ipicmp(lcrzo_constdata ip64bits,
				  lcrzo_int32 ip64bitssize,
				  lcrzo_hdrlip *phdrip,
				  lcrzo_uint8 *picmptype,
				  lcrzo_uint8 *picmpcode,
				  lcrzo_uint16 *picmpcheck,
				  lcrzo_uint8 *picmpbyte4,	
				  lcrzo_uint8 *picmpbyte5,
				  lcrzo_uint8 *picmpbyte6,
				  lcrzo_uint8 *picmpbyte7)
{ lcrzo_hdrlip hdrlip;
  lcrzo_data ipdata;
  lcrzo_uint16 ipdatasize;

  /* decode low level */
  lcrzo_er(lcrzo_ip64bits_decodem_ipdata(ip64bits, ip64bitssize,
					 &hdrlip, &ipdata, &ipdatasize));

  /* verify if it is icmp */
  if (hdrlip.protocol!=LCRZO_HDRLIP_PROTOCOL_ICMP)
  { lcrzo_data_free(ipdata);
    return (LCRZO_ERR_OKNOTDECODED);
  }

  /* set output values (ip64bits_decodem.. verify ipdata contains at least
     8 bytes) */
  if (phdrip!=NULL) *phdrip=hdrlip;
  if (picmptype!=NULL) *picmptype=ipdata[0];
  if (picmpcode!=NULL) *picmpcode=ipdata[1];
  if (picmpcheck!=NULL) *picmpcheck=(lcrzo_uint16)((ipdata[2]<<8)|ipdata[3]);
  if (picmpbyte4!=NULL) *picmpbyte4=ipdata[4];
  if (picmpbyte5!=NULL) *picmpbyte5=ipdata[5];
  if (picmpbyte6!=NULL) *picmpbyte6=ipdata[6];
  if (picmpbyte7!=NULL) *picmpbyte7=ipdata[7];

  lcrzo_data_free(ipdata);
  return(LCRZO_ERR_OK); 
}

/*-------------------------------------------------------------*/
int lcrzo_string_initm_icmptypecode(lcrzo_uint8 type, 
				    lcrzo_uint8 code,
				    lcrzo_string *pstring)
{ lcrzo_string enstr, frstr;
  lcrzo_int16 language; 

  /* init line */
  lcrzo_er(lcrzo_string_initm_text("", &enstr));
  lcrzo_er(lcrzo_string_initm_text("", &frstr));
  switch(type) {
  case LCRZO_ICMPTYPE_DESTUNREACH :
    lcrzo_er(lcrzo_string_appendm_text("destination unreachable - ", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("destination injoignable - ", &frstr));
    switch(code) {
    case LCRZO_ICMPCODE_DESTUNREACH_NET :
      lcrzo_er(lcrzo_string_appendm_text("network", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("reseau", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_HOST :
      lcrzo_er(lcrzo_string_appendm_text("host", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("machine", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_PROTO :
      lcrzo_er(lcrzo_string_appendm_text("protocol", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("protocole", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_PORT :
      lcrzo_er(lcrzo_string_appendm_text("port", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("port", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_FRAG :
      lcrzo_er(lcrzo_string_appendm_text("need frag, but DF set", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("besoin de frag, mais bit DF actif", 
					 &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_SR :
      lcrzo_er(lcrzo_string_appendm_text("source route failed", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("source route echoue", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_NETUNKNO :
      lcrzo_er(lcrzo_string_appendm_text("destination network unknown",
					 &enstr));
      lcrzo_er(lcrzo_string_appendm_text("reseau destination inconnu",
					 &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_HOSTUNKNO :
      lcrzo_er(lcrzo_string_appendm_text("destination host unknown", 
					 &enstr));
      lcrzo_er(lcrzo_string_appendm_text("machine destination inconnue",
					 &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_HOSTISOL :
      lcrzo_er(lcrzo_string_appendm_text("source host isolated", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("machine source isolee", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_NETPROHI :
      lcrzo_er(lcrzo_string_appendm_text("dest. network prohibited", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("reseau dest. interdit", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_HOSTPROHI :
      lcrzo_er(lcrzo_string_appendm_text("dest. host prohibited", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("machine dest. interdite", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_NETTOS :
      lcrzo_er(lcrzo_string_appendm_text("dest. network TOS", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("TOS reseau dest.", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_HOSTTOS :
      lcrzo_er(lcrzo_string_appendm_text("dest. host TOS", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("TOS machine dest.", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_PROHI :
      lcrzo_er(lcrzo_string_appendm_text("admin prohibited", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("admin interdit", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_PRECVIOL :
      lcrzo_er(lcrzo_string_appendm_text("host precedence violation", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("host precedence violation", &frstr));
      break;
    case LCRZO_ICMPCODE_DESTUNREACH_PRECCUT :
      lcrzo_er(lcrzo_string_appendm_text("precedence cutoff", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("precedence cutoff", &frstr));
      break;
    default :
      lcrzo_er(lcrzo_string_appendm_text("unknown code", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("code inconnu", &frstr));
      break;
    }
    break;
  case LCRZO_ICMPTYPE_TIMEEXCEED :
    lcrzo_er(lcrzo_string_appendm_text("time exceeded - ", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("temps expire - ", &frstr));
    switch(code) {
    case LCRZO_ICMPCODE_TIMEEXCEED_TTL :
      lcrzo_er(lcrzo_string_appendm_text("ttl", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("ttl", &frstr));
      break;
    case LCRZO_ICMPCODE_TIMEEXCEED_FRAG :
      lcrzo_er(lcrzo_string_appendm_text("fragment reassembly", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("reassemblage de fragments", &frstr));
      break;
    default :
      lcrzo_er(lcrzo_string_appendm_text("unknown code", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("code inconnu", &frstr));
      break;
    }
    break;
  case LCRZO_ICMPTYPE_PARAPROB :
    lcrzo_er(lcrzo_string_appendm_text("parameter problem - ", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("probleme de parametre - ", &frstr));
    switch(code) {
    case LCRZO_ICMPCODE_PARAPROB_POINTER :
      lcrzo_er(lcrzo_string_appendm_text("pointer indicate error", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("pointeur indique erreur", &frstr));
      break;
    case LCRZO_ICMPCODE_PARAPROB_MISSOPT :
      lcrzo_er(lcrzo_string_appendm_text("missing option", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("option manquante", &frstr));
      break;
    case LCRZO_ICMPCODE_PARAPROB_BADLEN :
      lcrzo_er(lcrzo_string_appendm_text("bad length", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("mauvaise taille", &frstr));
      break;
    default :
      lcrzo_er(lcrzo_string_appendm_text("unknown code", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("code inconnu", &frstr));
      break;
    }
    break;
  case LCRZO_ICMPTYPE_SRCQUENCH :
    lcrzo_er(lcrzo_string_appendm_text("source quench", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("saturation (source quench)", &frstr));
    break;
  case LCRZO_ICMPTYPE_ECHOREQ :
    lcrzo_er(lcrzo_string_appendm_text("echo request", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("echo request", &frstr));
    break;
  case LCRZO_ICMPTYPE_ECHOREP :
    lcrzo_er(lcrzo_string_appendm_text("echo reply", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("echo reply", &frstr));
    break;
  case LCRZO_ICMPTYPE_TIMESTAMPREQ :
    lcrzo_er(lcrzo_string_appendm_text("timestamp request", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("timestamp request", &frstr));
    break;
  case LCRZO_ICMPTYPE_TIMESTAMPREP :
    lcrzo_er(lcrzo_string_appendm_text("timestamp reply", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("timestamp reply", &frstr));
    break;
  case LCRZO_ICMPTYPE_INFOREQ :
    lcrzo_er(lcrzo_string_appendm_text("information request", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("information request", &frstr));
    break;
  case LCRZO_ICMPTYPE_INFOREP :
    lcrzo_er(lcrzo_string_appendm_text("information reply", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("information reply", &frstr));
    break;
  case LCRZO_ICMPTYPE_REDIRECT :
    lcrzo_er(lcrzo_string_appendm_text("redirect - ", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("redirect - ", &frstr));
    switch(code) {
    case LCRZO_ICMPCODE_REDIRECT_NET :
      lcrzo_er(lcrzo_string_appendm_text("network", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("reseau", &frstr));
      break;
    case LCRZO_ICMPCODE_REDIRECT_HOST :
      lcrzo_er(lcrzo_string_appendm_text("host", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("machine", &frstr));
      break;
    case LCRZO_ICMPCODE_REDIRECT_NETTOS :
      lcrzo_er(lcrzo_string_appendm_text("network and tos", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("reseau et tos", &frstr));
      break;
    case LCRZO_ICMPCODE_REDIRECT_HOSTTOS :
      lcrzo_er(lcrzo_string_appendm_text("host and tos", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("machine et tos", &frstr));
      break;
    default :
      lcrzo_er(lcrzo_string_appendm_text("unknown code", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("code inconnu", &frstr));
      break;
    }
    break;
  case LCRZO_ICMPTYPE_ALTHOSTAD :
    lcrzo_er(lcrzo_string_appendm_text("alternate host address", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("alternate host address", &frstr));
    break;
  case LCRZO_ICMPTYPE_ROUTERADVERT :
    lcrzo_er(lcrzo_string_appendm_text("router advertisement", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("annonce de routeur", &frstr));
    break;
  case LCRZO_ICMPTYPE_ROUTERSELECT :
    lcrzo_er(lcrzo_string_appendm_text("router selection", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("selection de routeur", &frstr));
    break;
  case LCRZO_ICMPTYPE_ADMASKREQ :
    lcrzo_er(lcrzo_string_appendm_text("address mask request", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("address mask request", &frstr));
    break;
  case LCRZO_ICMPTYPE_ADMASKREP :
    lcrzo_er(lcrzo_string_appendm_text("address mask reply", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("address mask reply", &frstr));
    break;
  case LCRZO_ICMPTYPE_TRACEROUTE :
    lcrzo_er(lcrzo_string_appendm_text("traceroute", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("traceroute", &frstr));
    break;
  case LCRZO_ICMPTYPE_DATACONVERR :
    lcrzo_er(lcrzo_string_appendm_text("datagram conversion error", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("datagram conversion error", &frstr));
    break;
  case LCRZO_ICMPTYPE_MOBHOSTREDIR :
    lcrzo_er(lcrzo_string_appendm_text("mobile host redirect", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("mobile host redirect", &frstr));
    break;
  case LCRZO_ICMPTYPE_IPV6WHEREYOU :
    lcrzo_er(lcrzo_string_appendm_text("IPv6 where are you", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("IPv6 where are you", &frstr));
    break;
  case LCRZO_ICMPTYPE_IPV6IAMHERE :
    lcrzo_er(lcrzo_string_appendm_text("IPv6 I'am here", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("IPv6 I'am here", &frstr));
    break;
  case LCRZO_ICMPTYPE_MOBREGREQ :
    lcrzo_er(lcrzo_string_appendm_text("mobile registration request", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("mobile registration request", &frstr));
    break;
  case LCRZO_ICMPTYPE_MOBREGREP :
    lcrzo_er(lcrzo_string_appendm_text("mobile registration reply", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("mobile registration reply", &frstr));
    break;
  case LCRZO_ICMPTYPE_SKIP :
    lcrzo_er(lcrzo_string_appendm_text("SKIP", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("SKIP", &frstr));
    break;
  case LCRZO_ICMPTYPE_PHOTURIS :
    lcrzo_er(lcrzo_string_appendm_text("Photuris", &enstr));
    lcrzo_er(lcrzo_string_appendm_text("Photuris", &frstr));
    break;
  default :
      lcrzo_er(lcrzo_string_appendm_text("unknown type", &enstr));
      lcrzo_er(lcrzo_string_appendm_text("type inconnu", &frstr));
    break;
  }

  /* init string */
  lcrzo_er(lcrzo_global_get_language(&language));
  if ( language==LCRZO_GLOBAL_LANG_FR )
  { lcrzo_er(lcrzo_string_initm_text(frstr, pstring));
  }
  else
  { lcrzo_er(lcrzo_string_initm_text(enstr, pstring));
  }
  lcrzo_er(lcrzo_string_free(enstr));
  lcrzo_er(lcrzo_string_free(frstr));

  return (LCRZO_ERR_OK);
}

