/*
		                  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"


/*-------------------------------------------------------------*/
#if LCRZODEF_LIBPCAPINSTALLED==1
 #include <pcap.h>
#endif


/*-------------------------------------------------------------*/
int lcrzo_priv_record_rewind(lcrzo_record *precord);
int lcrzo_priv_record_rewind(lcrzo_record *precord)
{ int ret;

  ret=fseek(precord->pf, 0, SEEK_SET);
  if (ret) return(LCRZO_ERR_FUFSEEK);
  precord->justbeforeposition=1;
  precord->column=0;
  precord->row=1;
  
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_record_printtype_canread(lcrzo_printtype printtype);
int lcrzo_priv_record_printtype_canread(lcrzo_printtype printtype)
{ switch(printtype&0xFF)
  { case LCRZO_PRINTTYPE_NOTHING_:   return(LCRZO_ERR_OK);
    case LCRZO_PRINTTYPE_SYNTH_:     return(LCRZO_ERR_SPRECORDPRINTTYPE);
    case LCRZO_PRINTTYPE_TEXT_:      return(LCRZO_ERR_SPRECORDPRINTTYPE);
    case LCRZO_PRINTTYPE_PTEXT_:     return(LCRZO_ERR_SPRECORDPRINTTYPE);
    case LCRZO_PRINTTYPE_BASE64_:    return(LCRZO_ERR_SPRECORDPRINTTYPE);
    case LCRZO_PRINTTYPE_ARRAY_:     return(LCRZO_ERR_SPRECORDPRINTTYPE);
    case LCRZO_PRINTTYPE_DUMP_:      return(LCRZO_ERR_OK);
    case LCRZO_PRINTTYPE_HEXA_:      return(LCRZO_ERR_OK);
    case LCRZO_PRINTTYPE_MIXED_:     return(LCRZO_ERR_OK);
    case LCRZO_PRINTTYPE_CMH_:       return(LCRZO_ERR_OK);
    case LCRZO_PRINTTYPE_CHM_:       return(LCRZO_ERR_OK);
    default:                         
      return(lcrzo_ieuv("lcrzo_priv_record_printtype_canread", 
			"printtype&0xFF"));
  }
  return(lcrzo_ierp("lcrzo_priv_record_printtype_canread"));
}

/*-------------------------------------------------------------*/
int lcrzo_priv_record_printprofile_canread(lcrzo_printprofile printprofile);
int lcrzo_priv_record_printprofile_canread(lcrzo_printprofile printprofile)
{
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdr));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdreth));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdrip));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdrudp));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdrtcp));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdricmp));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.hdrarp));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.data));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.dataeth));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.dataip));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.dataudp));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.datatcp));
  lcrzo_er(lcrzo_priv_record_printtype_canread(printprofile.dataicmp));
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_record_open(lcrzo_record *precord, const char *chemin,
		      lcrzo_int16 opentype)
{ lcrzo_file file;
  lcrzo_bool mustbeanexistentfile, mustbeanewfile;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);

  /*initialisation*/
  precord->pf=NULL;
  precord->opentype=opentype;
  precord->justbeforeposition=1;
  precord->column=0;
  precord->row=1;
      
  /*ouverture*/
  if (opentype==LCRZO_RECORD_OPEN_READ)
  { lcrzo_er(lcrzo_file_open_read(chemin, &file));
  }
  else if (opentype==LCRZO_RECORD_OPEN_WRITE)
  { lcrzo_er(lcrzo_global_get_record_open_existentfile(&mustbeanexistentfile));
    lcrzo_er(lcrzo_global_get_record_open_newfile(&mustbeanewfile));
    lcrzo_er(lcrzo_file_open_write(chemin, 
				 mustbeanexistentfile,
				 mustbeanewfile,
				 &file));
  }
  else if (opentype==LCRZO_RECORD_OPEN_APPEND)
  { lcrzo_er(lcrzo_global_get_record_open_existentfile(&mustbeanexistentfile));
    lcrzo_er(lcrzo_file_open_append(chemin, mustbeanexistentfile, &file));
  }
  else
    return(LCRZO_ERR_PAUNKNOWNTYPE);
  lcrzo_er(lcrzo_stream_init_file(&file, &(precord->pf)));
  lcrzo_er(lcrzo_file_close(&file));

  /*ecriture de l'entete*/
  if (opentype==LCRZO_RECORD_OPEN_WRITE)
  { fprintf(precord->pf, "#The format used in this file is :\n");
    fprintf(precord->pf, "# what is following a # is a comment\n");
    fprintf(precord->pf, "# 01 DB 4c8e # hexadecimal data\n");
    fprintf(precord->pf, "# 'string with a '' in the middle'\n");
    fprintf(precord->pf, "# 'mixed' 03 4D 'line' DEFF 01\n");
    fprintf(precord->pf, "# a blank line separates two packets\n");
    precord->row+=6;
    fprintf(precord->pf, "#Le format de ce fichier de donnees est :\n");
    fprintf(precord->pf, "# ce qui suit un # est un commentaire\n");
    fprintf(precord->pf, "# 01 DB 4c8e # donnees en hexadecimal\n");
    fprintf(precord->pf, "# 'chaine avec un '' au milieu'\n");
    fprintf(precord->pf, "# 'ligne' 03 4D 'mixte' DEFF 01\n");
    fprintf(precord->pf, "# une ligne vide separe 2 packets\n");
    precord->row+=6;
  }
  else if (opentype==LCRZO_RECORD_OPEN_APPEND)
  { fprintf(precord->pf, "# opened in append mode\n");
    precord->row++;
    fprintf(precord->pf, "# ouverture en append\n");
    precord->row++;
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
#define LCRZO_PRIV_RECORD_CLOSE  0
int lcrzo_record_close(lcrzo_record *precord)
{ 
  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype==LCRZO_PRIV_RECORD_CLOSE)
    return(LCRZO_ERR_LOALREADYCLOSED);

  lcrzo_er(lcrzo_stream_close(precord->pf));
  precord->opentype=LCRZO_PRIV_RECORD_CLOSE;
  precord->justbeforeposition=1;
  precord->column=0;
  precord->row=0;
  return(LCRZO_ERR_OK);
}  

/*-------------------------------------------------------------*/
int lcrzo_printtype_init_stdin_record(const char *message,
				 lcrzo_printtype defautprinttype,
				 lcrzo_printtype *pprinttype)
{ lcrzo_printtype ttypaff[LCRZO_PRIV_PRINTTYPE_COUNT+1];
  lcrzo_bool valeurdefauttrouvee;
  lcrzo_uint32 numeroprinttypechoisi, numeroprinttypedefaut;
  lcrzo_int32 count, i, countr;
  lcrzo_int16 language;

  /*initialization*/
  lcrzo_er(lcrzo_printtype_count(&count));
  valeurdefauttrouvee=0;
  if (message!=NULL) if (strlen(message)) printf("%s\n", message);
  numeroprinttypedefaut=0; /*pour faire plaisir au compilateur*/
  /*affichage des choix possibles*/
  countr=1;
  for ( i=1 ; i<=count ; i++ )
  { /*affichage*/
    lcrzo_er(lcrzo_printtype_value_pos(i, &(ttypaff[countr])));
    if ( lcrzo_priv_record_printtype_canread(ttypaff[countr])==LCRZO_ERR_OK )
    { lcrzo_int32_print(" ", countr, "%2d", " - ");
      lcrzo_printtype_print(ttypaff[countr]);
      printf("\n");
      /*a t'on trouve la valeur par defaut proposee ?*/
      if ( ttypaff[countr] == defautprinttype )
      { valeurdefauttrouvee=1;
        numeroprinttypedefaut=countr;
      }
      countr++;
    }
  }

  /*si la valeur par defaut n'a pas ete trouvee*/
  if (!valeurdefauttrouvee)
  { return(LCRZO_ERR_PADEFAULTNOTINRANGE);
  }

  /*demande a entrer le choix voulu*/
  lcrzo_er(lcrzo_global_get_language(&language));
  lcrzo_er(lcrzo_uint32_init_stdin((language==LCRZO_GLOBAL_LANG_FR)?
                              "Entrez votre choix":"Enter your choice", 
                              1, countr-1, numeroprinttypedefaut,
                              &numeroprinttypechoisi));
  if (pprinttype!=NULL) *pprinttype=ttypaff[numeroprinttypechoisi];
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_printprofile_init_stdin_record(const char *message,
				    lcrzo_printprofile defaultprintprofile,
				    lcrzo_printprofile *ppp)
{ lcrzo_printprofile tpp[LCRZO_PRIV_PRINTPROFILE_COUNT+1], printprofile;
  lcrzo_bool valeurdefauttrouvee;
  lcrzo_uint32 numeroprintprofilechoisi, numeroprintprofiledefaut;
  lcrzo_int32 count, i, countr;
  lcrzo_int16 language;
  char c;

  /*initialization*/
  lcrzo_er(lcrzo_printprofile_count(&count));
  valeurdefauttrouvee=0;
  if (message!=NULL) if (strlen(message)) printf("%s\n", message);
  numeroprintprofiledefaut=0; /*pour faire plaisir au compilateur*/

  /*affichage des choix possibles*/
  defaultprintprofile.lastused=LCRZO_PRINTTYPE_START;/*to be able to compare*/
  countr=1;
  for ( i=1 ; i<=count ; i++ )
  { /*affichage*/
    lcrzo_er(lcrzo_printprofile_value_pos(i, &(tpp[countr])));
    if ( lcrzo_priv_record_printprofile_canread(tpp[countr])==LCRZO_ERR_OK )
    { lcrzo_int32_print(" ", countr, "%2d", " - ");
      lcrzo_printprofile_print(tpp[countr]);
      printf("\n");
      /*a t'on trouve la valeur par defaut proposee ?*/
      if ( !memcmp(&(tpp[countr]), &defaultprintprofile,
		   sizeof(lcrzo_printprofile)) )
      { valeurdefauttrouvee=1;
        numeroprintprofiledefaut=countr;
      }
      countr++;
    }
  }

  /*si la valeur par defaut n'a pas ete trouvee*/
  if (!valeurdefauttrouvee)
  { return(LCRZO_ERR_PADEFAULTNOTINRANGE);
  }

  /*demande a entrer le choix voulu*/ 
  lcrzo_er(lcrzo_global_get_language(&language));
  lcrzo_int32_print(" ", countr, "%2d", " - ");
  if (language==LCRZO_GLOBAL_LANG_FR)
    printf("profil personnalise\n");
  else
    printf("personalized profile\n");
  lcrzo_er(lcrzo_uint32_init_stdin((language==LCRZO_GLOBAL_LANG_FR)?
                              "Choisissez le profil voulu":
                              "Choose the profile",
                              1, countr, numeroprintprofiledefaut,
                              &numeroprintprofilechoisi));

  /*standard profile*/
  if ((lcrzo_int32)numeroprintprofilechoisi<countr)
  { if (ppp!=NULL) *ppp=tpp[numeroprintprofilechoisi];
    return(LCRZO_ERR_OK);  
  }

  /*personalized profile*/
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_er(lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes",
					  LCRZO_PRINTTYPE_HEXAN,
					  &printprofile.hdr));
    lcrzo_er(lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les donnees",
					  LCRZO_PRINTTYPE_DUMP,
					  &printprofile.data));
    lcrzo_stdin_char("Voulez-vous affiner la definition du profil",
                     (const lcrzo_uint8 *)"oOnN", 'n', (lcrzo_uint8 *)&c);
  }
  else
  { lcrzo_er(lcrzo_printtype_init_stdin_record("Choose the printtype for headers",
				 LCRZO_PRINTTYPE_HEXAN, &printprofile.hdr));
    lcrzo_er(lcrzo_printtype_init_stdin_record("Choose the printtype for data",
				 LCRZO_PRINTTYPE_DUMP, &printprofile.data));
    lcrzo_stdin_char("Do you want to refine the profile",
                     (const lcrzo_uint8 *)"yYnN", 'n', (lcrzo_uint8 *)&c);
  }
  if ( c=='o' || c=='O' || c=='y' || c=='Y' )
  { if (language==LCRZO_GLOBAL_LANG_FR)
    { lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes ETH", printprofile.hdr, &printprofile.hdreth);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes IP", printprofile.hdr, &printprofile.hdrip);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes UDP", printprofile.hdr, &printprofile.hdrudp);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes TCP", printprofile.hdr, &printprofile.hdrtcp);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes ICMP", printprofile.hdr, &printprofile.hdricmp);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les entetes ARP", printprofile.hdr, &printprofile.hdrarp);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les donnees ETH", printprofile.data, &printprofile.dataeth);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les donnees IP", printprofile.data, &printprofile.dataip);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les donnees UDP", printprofile.data, &printprofile.dataudp);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les donnees TCP", printprofile.data, &printprofile.datatcp);
      lcrzo_printtype_init_stdin_record("Choisissez le type d'affichage pour les donnees ICMP", printprofile.data, &printprofile.dataicmp);
    }
    else
    { lcrzo_printtype_init_stdin_record("Choose the printtype for headers ETH", 
				   printprofile.hdr, &printprofile.hdreth);
      lcrzo_printtype_init_stdin_record("Choose the printtype for headers IP", 
				   printprofile.hdr, &printprofile.hdrip);
      lcrzo_printtype_init_stdin_record("Choose the printtype for headers UDP",
				   printprofile.hdr, &printprofile.hdrudp);
      lcrzo_printtype_init_stdin_record("Choose the printtype for headers TCP",
				   printprofile.hdr, &printprofile.hdrtcp);
      lcrzo_printtype_init_stdin_record("Choose the printtype for headers ICMP", 
				   printprofile.hdr, &printprofile.hdricmp);
      lcrzo_printtype_init_stdin_record("Choose the printtype for headers ARP",
				   printprofile.hdr, &printprofile.hdrarp);
      lcrzo_printtype_init_stdin_record("Choose the printtype for data ETH",
				   printprofile.data, &printprofile.dataeth);
      lcrzo_printtype_init_stdin_record("Choose the printtype for data IP",
				   printprofile.data, &printprofile.dataip);
      lcrzo_printtype_init_stdin_record("Choose the printtype for data UDP",
				   printprofile.data, &printprofile.dataudp);
      lcrzo_printtype_init_stdin_record("Choose the printtype for data TCP",
				   printprofile.data, &printprofile.datatcp);
      lcrzo_printtype_init_stdin_record("Choose the printtype for data ICMP",
				   printprofile.data, &printprofile.dataicmp);
    }
  }
  else
  { printprofile.hdreth=printprofile.hdr;
    printprofile.hdrip=printprofile.hdr;
    printprofile.hdrudp=printprofile.hdr;
    printprofile.hdrtcp=printprofile.hdr;
    printprofile.hdricmp=printprofile.hdr;
    printprofile.hdrarp=printprofile.hdr;
    printprofile.dataeth=printprofile.data;
    printprofile.dataip=printprofile.data;
    printprofile.dataudp=printprofile.data;
    printprofile.datatcp=printprofile.data;
    printprofile.dataicmp=printprofile.data;
  }
  printprofile.lastused=LCRZO_PRINTTYPE_START;
  if (ppp!=NULL) *ppp=printprofile;
  return(LCRZO_ERR_OK);  
}

/*-------------------------------------------------------------*/
int lcrzo_priv_ecrittransitionfin(LCRZOFILE *pf, 
				  lcrzo_printprofile *pprintprofile);
int lcrzo_record_write_data(lcrzo_record *precord, 
			    lcrzo_constdata packet,
			    lcrzo_int32 nboctpacket,
			    lcrzo_printtype printtype)
{ lcrzo_printprofile printprofile;
  lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printtype_canread(printtype));

  /*affichage du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : DATA\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : DATA\n");
  }
  lcrzo_er(lcrzo_data_fprint(precord->pf, packet, nboctpacket, printtype));
  /*saut de ligne eventuel en fin*/
  printprofile.lastused=printtype;
  lcrzo_er(lcrzo_priv_ecrittransitionfin(precord->pf, &printprofile));
  /* separateur */
  fprintf(precord->pf, "\n");
  fflush(precord->pf);

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_write_eth(lcrzo_record *precord, 
			   lcrzo_constdata packet,
			   lcrzo_int32 nboctpacket,
			   lcrzo_printprofile printprofile)
{ lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printprofile_canread(printprofile));

  /*ecriture du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : ETH\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : ETH\n");
  }
  lcrzo_packet_fprint_eth(precord->pf, packet, nboctpacket, printprofile);

  /*fin*/
  fprintf(precord->pf, "\n");
  fflush(precord->pf);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_write_ip(lcrzo_record *precord, 
			  lcrzo_constdata packet,
			  lcrzo_int32 nboctpacket,
			  lcrzo_printprofile printprofile)
{ lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printprofile_canread(printprofile));

  /*ecriture du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : IP\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : IP\n");
  }
  lcrzo_packet_fprint_ip(precord->pf, packet, nboctpacket, printprofile);

  /*fin*/
  fprintf(precord->pf, "\n");
  fflush(precord->pf);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_write_udp(lcrzo_record *precord, 
			   lcrzo_constdata packet,
			   lcrzo_int32 nboctpacket,
			   lcrzo_printprofile printprofile)
{ lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printprofile_canread(printprofile));

  /*ecriture du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : UDP\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : UDP\n");
  }
  lcrzo_packet_fprint_udp(precord->pf, packet, nboctpacket, printprofile);

  /*fin*/
  fprintf(precord->pf, "\n");
  fflush(precord->pf);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_write_tcp(lcrzo_record *precord, 
			   lcrzo_constdata packet,
			   lcrzo_int32 nboctpacket,
			   lcrzo_printprofile printprofile)
{ lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printprofile_canread(printprofile));

  /*ecriture du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : TCP\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : TCP\n");
  }
  lcrzo_packet_fprint_tcp(precord->pf, packet, nboctpacket, printprofile);

  /*fin*/
  fprintf(precord->pf, "\n");
  fflush(precord->pf);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_write_icmp(lcrzo_record *precord, 
			    lcrzo_constdata packet,
			    lcrzo_int32 nboctpacket,
			    lcrzo_printprofile printprofile)
{ lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printprofile_canread(printprofile));

  /*ecriture du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : ICMP\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : ICMP\n");
  }
  lcrzo_packet_fprint_icmp(precord->pf, packet, nboctpacket, printprofile);

  /*fin*/
  fprintf(precord->pf, "\n");
  fflush(precord->pf);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_write_arp(lcrzo_record *precord, 
			   lcrzo_constdata packet,
			   lcrzo_int32 nboctpacket,
			   lcrzo_printprofile printprofile)
{ lcrzo_int16 language;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_WRITE &&
      precord->opentype!=LCRZO_RECORD_OPEN_APPEND)
    return(LCRZO_ERR_LONOTOPENFORWRITING);
  lcrzo_er(lcrzo_priv_record_printprofile_canread(printprofile));

  /*ecriture du packet*/
  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_int32_fprint(precord->pf, "#paquet ", precord->justbeforeposition++, 
		       "%d", " : ARP\n");
  }
  else
  { lcrzo_int32_fprint(precord->pf, "#packet ", precord->justbeforeposition++, 
		       "%d", " : ARP\n");
  }
  lcrzo_packet_fprint_arp(precord->pf, packet, nboctpacket, printprofile);

  /*fin*/
  fprintf(precord->pf, "\n");
  fflush(precord->pf);
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_record_msgerr(lcrzo_record *precord, int codeerr);
int lcrzo_priv_record_msgerr(lcrzo_record *precord, int codeerr)
{ lcrzo_string errstr;
  lcrzo_int16 language;

  lcrzo_er(lcrzo_global_get_language(&language));
  if (language==LCRZO_GLOBAL_LANG_FR)
  { lcrzo_string_initm_text("erreur ligne ", &errstr);
    lcrzo_string_appendm_int(precord->row, "%d", &errstr);
    lcrzo_string_appendm_text(" et colonne ", &errstr);
    lcrzo_string_appendm_int(precord->column, "%d", &errstr);
  }
  else  
  { lcrzo_string_initm_text("error row ", &errstr);
    lcrzo_string_appendm_int(precord->row, "%d", &errstr);
    lcrzo_string_appendm_text(" and column ", &errstr);
    lcrzo_string_appendm_int(precord->column, "%d", &errstr);
  }
  lcrzo_er(lcrzo_priv_global_set_errmsglcrzo(errstr));
  lcrzo_er(lcrzo_string_free(errstr));
  /*just in case the user wants to ignore the error and to continue
    to use the file. We need to rewind to be sure to be in a stable
    state after an error.*/
  lcrzo_priv_record_rewind(precord);
  return(codeerr);
}

/*-------------------------------------------------------------*/
int lcrzo_record_count(lcrzo_record *precord, 
		       lcrzo_int32 *pcount)
{ lcrzo_bool lastcharisnewline;
  lcrzo_int32 count;
  int c;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_READ)
    return(LCRZO_ERR_LONOTOPENFORREADING);

  /*besoin de faire un rewind*/
  if ( precord->justbeforeposition!=1 )
  { lcrzo_er(lcrzo_priv_record_rewind(precord));
  }

  /*lecture*/
  lastcharisnewline=1;
  count=0;
  while (!feof((FILE *)(precord->pf)))
  { c=fgetc(precord->pf);
    if ( c==EOF && feof((FILE *)(precord->pf)) ) continue;
    precord->column++;
    /*putchar(c);*/

    /*test du passage au packet suivant*/
    if ( c==' ' || c=='\t' || c==0x0D ){}
    else if ( c==0x0A )
    { precord->column=0;
      precord->row++;
      if (lastcharisnewline)
      { count++;
      }
      lastcharisnewline=1;
    }
    else
      lastcharisnewline=0;
  }

  if (pcount!=NULL) *pcount=count;
  precord->justbeforeposition=count+1;
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
#define LCRZO_PRIV_RECORD_READSIZE 2000
int lcrzo_priv_record_valuem_pos(lcrzo_record *precord, 
				 lcrzo_int32 pos,
				 lcrzo_data *pdataout,
				 lcrzo_int32 *pdataoutsize);
int lcrzo_priv_record_valuem_pos(lcrzo_record *precord, 
				 lcrzo_int32 pos,
				 lcrzo_data *pdataout,
				 lcrzo_int32 *pdataoutsize)
{ int mode; /* 0:commentaire ; 1:hexa ; 2:ascii */
  int quartet, quartet1, quartet1rempli;
  int c, derniercarestsautrow;
  lcrzo_int32 dataoutsize, arraysize;
  lcrzo_uint8 array[LCRZO_PRIV_RECORD_READSIZE];

  if ( pos < precord->justbeforeposition )
    return(lcrzo_ie("lcrzo_priv_record_valuem_pos", 
		    "pos < precord->justbeforeposition", NULL));

  /*go just before the elem we want to read*/
  while ( precord->justbeforeposition < pos )
  {
    /*initialisations*/
    mode=1;
    quartet1rempli=0;
    derniercarestsautrow=1;
    precord->column=0;
    
    /*lecture*/
    while (!feof((FILE *)(precord->pf)))
    { c=fgetc(precord->pf);
      if ( c==EOF && feof((FILE *)(precord->pf)) ) break;
      precord->column++;
      /*putchar(c);*/
      
      /*test du passage au packet suivant*/
      if ( c==' ' || c=='\t' || c==0x0D ){}
      else if ( c==0x0A )
      { precord->column=0;
	precord->row++;
	if (derniercarestsautrow) break;
	derniercarestsautrow=1;
      }
      else
	derniercarestsautrow=0;
      
      /*lecture des donnees*/
      switch(mode)
      { case 0: /*commentaire*/
	  /*fin de commentaire*/
	  if (c==0x0A) mode=1;
	  break;
	case 1: /*hexa*/
	  /*changement de mode*/
	  if (c=='#') mode=0;
	  else if (c=='\'') mode=2;
	  if ( mode!=1 )
	  { if (quartet1rempli ) 
	    { return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMHEXAODD));
	    }
  	    continue;
	  }
	  /*calcul de la valeur hexa*/
	  if ( isxdigit(c) )
	  { if (quartet1rempli) quartet1rempli=0;
	    else quartet1rempli=1;
	  }
	  else if ( c==' ' || c==0x0D || c==0x0A || c=='\t' ) {continue;}
	  else
	  { return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMHEXACHAR));
	  }	  
	  break;
        case 2: /*ascii*/
	  if (c=='\'')
	  { if (feof((FILE *)(precord->pf))) {mode=1; continue;}
	    c=fgetc(precord->pf);
	    if (c!='\'') {ungetc(c, precord->pf); mode=1;}
	  }
	  else if ( c==0x0A ) 
	  { return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMMIXED));
	  }
	  break;
      }
    } 

    /*cas d'erreur*/
    if ( mode==1 && quartet1rempli ) 
    { return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMHEXAODD));
    }
    else if ( mode==2 ) 
    { return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMMIXED));
    }
    precord->justbeforeposition++;

    /*pas de donnees lues*/
    if ( feof((FILE *)(precord->pf)) && (pos > precord->justbeforeposition) )
      return(LCRZO_ERR_POTOOBIG);
  }

  /*now, we read the elem*/
  /*initialisations*/
  mode=1;
  dataoutsize=arraysize=0;
  quartet1rempli=0;
  quartet=quartet1=0;
  derniercarestsautrow=1;
  precord->column=0;
  lcrzo_er(lcrzo_data_initm_text("", pdataout, pdataoutsize));
    
  /*lecture*/
  while (!feof((FILE *)(precord->pf)))
  { 
    /*need to append*/
    if (arraysize>=LCRZO_PRIV_RECORD_READSIZE)
    { lcrzo_er(lcrzo_data_appendm_data(array, arraysize, dataoutsize,
				       pdataout, pdataoutsize));
      dataoutsize+=arraysize;
      arraysize=0;
    }

    /*get a character*/
    c=fgetc(precord->pf);
    if ( c==EOF && feof((FILE *)(precord->pf)) ) break;
    precord->column++;
    /*putchar(c);*/
      
    /*test du passage au packet suivant*/
    if ( c==' ' || c=='\t' || c==0x0D ){}
    else if ( c==0x0A )
    { precord->column=0;
      precord->row++;
      if (derniercarestsautrow) break;
      derniercarestsautrow=1;
    }
    else
      derniercarestsautrow=0;
      
    /*lecture des donnees*/
    switch(mode)
    { case 0: /*commentaire*/
        /*fin de commentaire*/
        if (c==0x0A) mode=1;
	break;
      case 1: /*hexa*/
	/*changement de mode*/
	if (c=='#') mode=0;
	else if (c=='\'') mode=2;
	if ( mode!=1 )
	{ if (quartet1rempli ) 
	  { lcrzo_data_free(*pdataout);
	    return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMHEXAODD));
	  }
	  continue;
	}
	/*calcul de la valeur hexa*/
	if ( isxdigit(c) )
	{ if (c>='0'&&c<='9') quartet=c-'0';
	  else if (c>='a'&&c<='f') quartet=c-'a'+10;
	  else if (c>='A'&&c<='F') quartet=c-'A'+10;
	  if (quartet1rempli) 
	  { array[arraysize]=(lcrzo_uint8)( (quartet1<<4)|quartet );
	    arraysize++;
	    quartet1rempli=0;
	  }
	  else
	  { quartet1=quartet;
	    quartet1rempli=1;
	  }
	}
	else if ( c==' ' || c==0x0D || c==0x0A || c=='\t' ) {continue;}
	else
	{ lcrzo_data_free(*pdataout);
	  return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMHEXACHAR));
	}	  
	break;
      case 2: /*ascii*/
	if (c=='\'')
	{ if (feof((FILE *)(precord->pf))) {mode=1; continue;}
	  c=fgetc(precord->pf);
	  if (c=='\'') 
	  { array[arraysize]='\'';
	    arraysize++;
	  }
	  else {ungetc(c, precord->pf); mode=1;}
	}
	else if ( c==0x0A ) 
	{ lcrzo_data_free(*pdataout);
	  return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMMIXED));
	}
	else
	{ array[arraysize]=(lcrzo_uint8)(c);
	  arraysize++;
	}
	break;
    }
  } 

  /*cas d'erreur*/
  if ( mode==1 && quartet1rempli ) 
  { lcrzo_data_free(*pdataout);
    return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMHEXAODD));
  }
  else if ( mode==2 ) 
  { lcrzo_data_free(*pdataout);
    return(lcrzo_priv_record_msgerr(precord, LCRZO_ERR_FMMIXED));
  }
  precord->justbeforeposition++;

  /*append*/
  lcrzo_er(lcrzo_data_appendm_data(array, arraysize, dataoutsize,
				   pdataout, pdataoutsize));
  dataoutsize+=arraysize;
  if (pdataoutsize!=NULL) *pdataoutsize=dataoutsize;
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_valuem_pos(lcrzo_record *precord, 
			    lcrzo_int32 pos,
			    lcrzo_data *pdataout,
			    lcrzo_int32 *pdataoutsize)
{ lcrzo_int32 count;
  lcrzo_int32 pospos;
  
  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_READ)
    return(LCRZO_ERR_LONOTOPENFORREADING);

  /*verification des parametres et affectation des positions*/
  lcrzo_er(lcrzo_record_count(precord, &count));
  lcrzo_er(lcrzo_priv_manageelempos(count, pos, 0, NULL, &pospos, NULL,NULL));

  /*besoin de faire un rewind*/
  if ( pospos < precord->justbeforeposition )
  { lcrzo_er(lcrzo_priv_record_rewind(precord));
  }

  lcrzo_er(lcrzo_priv_record_valuem_pos(precord, pospos,
					pdataout, pdataoutsize));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_valuem_first(lcrzo_record *precord, 
			      lcrzo_data *pdataout,
			      lcrzo_int32 *pdataoutsize)
{ return(lcrzo_record_valuem_pos(precord, +1, pdataout, pdataoutsize));
}

/*-------------------------------------------------------------*/
int lcrzo_record_valuem_last(lcrzo_record *precord, 
			     lcrzo_data *pdataout,
			     lcrzo_int32 *pdataoutsize)
{ return(lcrzo_record_valuem_pos(precord, -1, pdataout, pdataoutsize));
}


/*-------------------------------------------------------------*/
int lcrzo_record_loop_range(lcrzo_record *precord, 
			    lcrzo_int32 startpos,
			    lcrzo_int32 endpos,
			    int (*pfonc)(void *packet,
					 lcrzo_int32 nboctpacket,
					 void *pinfos),
			    void *pinfos)
{ lcrzo_int32 count, suppos, infpos, i;
  lcrzo_data packet;
  lcrzo_int32 nboctpacket;

  /*parameters verification*/
  if (precord==NULL) return(LCRZO_ERR_PANULLPTR);
  if (pfonc==NULL) return(LCRZO_ERR_PANULLPTR);
  if (precord->opentype!=LCRZO_RECORD_OPEN_READ)
    return(LCRZO_ERR_LONOTOPENFORREADING);

  /*verification des parametres et affectation des positions*/
  lcrzo_er(lcrzo_record_count(precord, &count));
  if ( count==0 && startpos==+1 && endpos==-1 )
    return(LCRZO_ERR_OK);
  lcrzo_er(lcrzo_priv_manageelemrange(count, startpos, endpos,
				      NULL, &infpos, NULL, &suppos,
				      NULL,NULL,NULL,NULL));

  /*besoin de faire un rewind*/
  if ( infpos < precord->justbeforeposition )
  { lcrzo_er(lcrzo_priv_record_rewind(precord));
  }

  /*verification des parametres et affectation des positions*/
  if (suppos>=infpos)
  { /*loop*/
    for ( i=infpos ; i<=suppos ; i++ )
    { lcrzo_er(lcrzo_priv_record_valuem_pos(precord, i, 
					    &packet, &nboctpacket));
      lcrzo_efr(((*pfonc)(packet, nboctpacket, pinfos)), 
		lcrzo_data_free(packet));
      lcrzo_data_free(packet);
    }
  }
  else
  { /*loop*/
    for ( i=infpos ; i>=suppos ; i-- )
    { lcrzo_er(lcrzo_priv_record_valuem_pos(precord, i, 
					    &packet, &nboctpacket));
      lcrzo_efr(((*pfonc)(packet, nboctpacket, pinfos)),
		lcrzo_data_free(packet));
      lcrzo_data_free(packet);
      /*always do a rewind*/
      lcrzo_er(lcrzo_priv_record_rewind(precord));
    }
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_record_loop_all(lcrzo_record *precord, 
			  int (*pfonc)(void *packet,
				       lcrzo_int32 nboctpacket,
				       void *pinfos),
			  void *pinfos)
{ return(lcrzo_record_loop_range(precord, +1, -1, pfonc, pinfos));
}

/*-------------------------------------------------------------*/
int lcrzo_record_recfile_init_pcapfile(lcrzo_conststring pcapfile,
				       lcrzo_conststring recfile)
#if LCRZODEF_LIBPCAPINSTALLED==1
{ pcap_t *pt;
  const lcrzo_uint8 *pptr;
  lcrzo_int32 hdr_caplen;
  lcrzo_data data;
  lcrzo_int32 datasize;
  lcrzo_uint32 linktype;
  lcrzo_record record;
  lcrzo_string errmsg;
  int ret;

  /* parameters verification */
  if (pcapfile==NULL) return(LCRZO_ERR_PANULLPTR);
  if (recfile==NULL) return(LCRZO_ERR_PANULLPTR);

  /* open the pcap file */
  lcrzo_er(lcrzo_string_alloc(PCAP_ERRBUF_SIZE, &errmsg));
  pt=pcap_open_offline(pcapfile, errmsg);
  if ( pt == NULL )
  { lcrzo_priv_global_set_errmsgsys(errmsg);
    lcrzo_string_free(errmsg);
    return(LCRZO_ERR_FUPCAPOPENOFFLINE);
  }
  lcrzo_string_free(errmsg);

  /* get the link type */
  linktype=pcap_datalink(pt);
  lcrzo_er(lcrzo_priv_datalink_verifknown(linktype));

  /* open the record file */
  ret=lcrzo_record_open(&record, recfile, LCRZO_RECORD_OPEN_WRITE);
  if (ret!=LCRZO_ERR_OK)
  { pcap_close(pt);
    return(ret);
  }

  /* loop through each packet */
  while(LCRZO_TRUE)
  { /* get a packet */
#if LCRZODEF_LIBPCAPFROMREDHAT==1
    struct pcap_pkthdr hdr[3];
    /* In this function, we use an array for hdr, even if it
       should not be necessary. Indeed, there is an overflow 
       in libpcap package modified by RedHat, so we have
       to use this trick ... (note : there is no problem
       with tcpdump because they only use pcap_loop) */
    memset((char*)hdr, 0, 3*sizeof(struct pcap_pkthdr));
    pptr = pcap_next(pt, &(hdr[1]));
    if ( pptr==NULL ) break;
    hdr_caplen=hdr[1].caplen;
#else
    struct pcap_pkthdr hdr;
    memset(&hdr, 0, sizeof(struct pcap_pkthdr));
    pptr = pcap_next(pt, &hdr);
    if ( pptr==NULL ) break;
    hdr_caplen=hdr.caplen;
#endif

    /* eventually modify header */
    ret=lcrzo_priv_datalink_modifyheader(linktype, pptr, hdr_caplen, 
					 &data, &datasize);
    if (ret!=LCRZO_ERR_OK)
    { pcap_close(pt);
      return(ret);
    }

    /* write packet */
    /*lcrzo_data_print(data, datasize, LCRZO_PRINTTYPE_DUMP);*/
    ret=lcrzo_record_write_eth(&record, data, datasize, 
			       LCRZO_PRINTPROFILE_HEXANCHMS);
    if (ret!=LCRZO_ERR_OK)
    { pcap_close(pt);
      return(ret);
    }

    /* free memory */
    lcrzo_data_free(data);
  }

  /* close the record file */
  ret=lcrzo_record_close(&record);

  /* close the pcap file */
  pcap_close(pt);

  return(ret);
}
#else
{ return(lcrzo_priv_checkpcapincluded("lcrzo_record_recfile_init_pcapfile"));
  /*just for the compiler warning*/
  pcapfile=pcapfile;
  recfile=recfile;
}
#endif

/*-------------------------------------------------------------*/
int lcrzo_record_pcapfile_init_recfile(lcrzo_conststring recfile,
				       lcrzo_conststring pcapfile)
#if LCRZODEF_LIBPCAPINSTALLED==1
{ pcap_t *pt;
  void *pdt; /* should be pcap_dumper_t*, but pcap_dump uses a char*,
                and this causes a SIGBUS (alignment error) on Solaris 2.5.
		Anyone knows why pcap's developers didn't use 
                a correct type ?
             */
  struct pcap_pkthdr ph;  
  lcrzo_data data;
  lcrzo_int32 datasize, i, count;
  lcrzo_record record;
  int ret;

  /* parameters verification */
  if (recfile==NULL) return(LCRZO_ERR_PANULLPTR);
  if (pcapfile==NULL) return(LCRZO_ERR_PANULLPTR);

  /* open the record file */
  lcrzo_er(lcrzo_record_open(&record, recfile, LCRZO_RECORD_OPEN_READ));
  /* initialize the pcap type */
#if LCRZODEF_HAVEFONC_PCAP_OPENDEAD==1
  pt=pcap_open_dead(DLT_EN10MB, 0xFFFF);
#else
  /* On older versions of libpcap, we have to open a live session.
     This is a problem on computers having no network cards :(
  */
  { lcrzo_uint32 mtu;
    lcrzo_device device;
    lcrzo_string errmsg;
    lcrzo_er(lcrzo_device_value_pos(LCRZO_DEVICE_TYPE_ONLYBOARDS, 1, device));
    lcrzo_er(lcrzo_mtu_init_device(device, &mtu));
    lcrzo_er(lcrzo_string_alloc(PCAP_ERRBUF_SIZE, &errmsg));
    pt = pcap_open_live(device, mtu, 1, 500, errmsg);
    if ( pt == NULL )
    { lcrzo_er(lcrzo_priv_global_set_errmsgsys(errmsg));
    }
    lcrzo_string_free(errmsg);
  }
#endif

  /* check error */
  if ( pt == NULL )
  { lcrzo_record_close(&record);
#if LCRZODEF_HAVEFONC_PCAP_OPENDEAD==1
    return(LCRZO_ERR_FUPCAPOPENDEAD);
#else
    return(LCRZO_ERR_FUPCAPOPEN);
#endif
  }

  /* open the pcap file */
  pdt=pcap_dump_open(pt, pcapfile);
  if ( pdt == NULL )
  { pcap_close(pt);
    lcrzo_record_close(&record);
    return(LCRZO_ERR_FUPCAPDUMPOPEN);
  }

  /* loop through each packet */
  ret=lcrzo_record_count(&record, &count); 
  if (ret!=LCRZO_ERR_OK)
  { pcap_close(pt);
    lcrzo_record_close(&record);
    return(ret);
  }

  for ( i=1 ; i<=count ; i++ )
  { /* get the packet */
    ret=lcrzo_record_valuem_pos(&record, i, &data, &datasize); 
    if (ret!=LCRZO_ERR_OK)
    { pcap_close(pt);
      lcrzo_record_close(&record);
      return(ret);
    }

    /* write packet */
    /*lcrzo_data_print(data, datasize, LCRZO_PRINTTYPE_DUMP);*/
    ph.ts.tv_sec=i;
    ph.ts.tv_usec=0;
    ph.caplen=datasize;
    ph.len=datasize;
    pcap_dump(pdt, &ph, data);

    /* free memory */
    lcrzo_data_free(data);
  }

  /* close the pcap file */
  pcap_dump_close(pdt);
  pcap_close(pt);

  /* close the record file */
  lcrzo_er(lcrzo_record_close(&record));

  return(LCRZO_ERR_OK);
}

#else
{ return(lcrzo_priv_checkpcapincluded("lcrzo_record_pcapfile_init_recfile"));
  /*just for the compiler warning*/
  pcapfile=pcapfile;
  recfile=recfile;
}
#endif

