/*
		                  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_hdrleth_initdefault(lcrzo_hdrleth *phdrleth)
{ 
  if (phdrleth!=NULL)
  { lcrzo_er(lcrzo_etha_initdefault(phdrleth->dst));
    lcrzo_er(lcrzo_etha_initdefault(phdrleth->src));
    phdrleth->type=LCRZO_HDRLETH_TYPE_DEFVAL;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlip_initdefault(lcrzo_hdrlip *phdrlip)
{ 
  if (phdrlip!=NULL)
  { phdrlip->version  = 4;
    phdrlip->ihl      = LCRZO_HDRLIP_IHL_DEFVAL;
    phdrlip->tos      = 0;
    phdrlip->totlen   = LCRZO_HDRLIP_TOTLEN_DEFVAL;
    lcrzo_er(lcrzo_uint16_init_rand(1, 0xFFFF, &(phdrlip->id)));
    phdrlip->reserve  = 0;
    phdrlip->dontfrag = 0;
    phdrlip->morefrag = 0;
    phdrlip->offsetfrag = 0;
    phdrlip->ttl      = 128;
    phdrlip->protocol = LCRZO_HDRLIP_PROTOCOL_DEFVAL;
    phdrlip->check    = LCRZO_HDRLIP_CHECK_DEFVAL; 
    phdrlip->saddr    = 0;
    phdrlip->daddr    = 0;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrludp_initdefault(lcrzo_hdrludp *phdrludp)
{
  if (phdrludp!=NULL)
  { phdrludp->sport  = 0;
    phdrludp->dport  = 0;
    phdrludp->len    = LCRZO_HDRLUDP_LEN_DEFVAL;
    phdrludp->check  = LCRZO_HDRLUDP_CHECK_DEFVAL;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrltcp_initdefault(lcrzo_hdrltcp *phdrltcp)
{ 
  if (phdrltcp!=NULL)
  { phdrltcp->sport  = 0;
    phdrltcp->dport  = 0;
    lcrzo_er(lcrzo_uint32_init_rand(1, (lcrzo_uint32)0xFFFFFFFFU, 
			       &(phdrltcp->seqnum)));
    phdrltcp->acknum = 0;
    phdrltcp->doff   = LCRZO_HDRLTCP_DOFF_DEFVAL;
    phdrltcp->reserve= 0;
    phdrltcp->urg    = 0;
    phdrltcp->ack    = 0;
    phdrltcp->psh    = 0;
    phdrltcp->rst    = 0;
    phdrltcp->syn    = 0;
    phdrltcp->fin    = 0;
    phdrltcp->window = 1500;
    phdrltcp->check  = LCRZO_HDRLTCP_CHECK_DEFVAL;
    phdrltcp->urgptr = 0;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlicmp_initdefault(lcrzo_hdrlicmp *phdrlicmp)
{
  if (phdrlicmp!=NULL)
  { phdrlicmp->type  = 0;
    phdrlicmp->code  = 0;
    phdrlicmp->check = LCRZO_HDRLICMP_CHECK_DEFVAL;
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlarp_initdefault(lcrzo_hdrlarp *phdrlarp)
{ 
  if (phdrlarp!=NULL)
  { phdrlarp->hw_type=1;
    phdrlarp->prot_type=LCRZO_HDRLETH_TYPE_IP;
    phdrlarp->hw_size=6;
    phdrlarp->prot_size=4;
    phdrlarp->op=0;
    lcrzo_er(lcrzo_etha_initdefault(phdrlarp->hw_src));
    lcrzo_er(lcrzo_ipa_initdefault(phdrlarp->prot_src));
    lcrzo_er(lcrzo_etha_initdefault(phdrlarp->hw_dst));
    lcrzo_er(lcrzo_ipa_initdefault(phdrlarp->prot_dst));
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_hdrpeth_init_hdrleth(lcrzo_hdrleth hdrleth,
			  lcrzo_hdrpeth *phdrpeth)
{
  if (phdrpeth!=NULL)
  { memcpy(phdrpeth->dst, hdrleth.dst, LCRZO_ETHA_MAXBYTES);
    memcpy(phdrpeth->src, hdrleth.src, LCRZO_ETHA_MAXBYTES);
    phdrpeth->type=lcrzo_htons(hdrleth.type);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrpip_init_hdrlip(lcrzo_hdrlip hdrlip,
			lcrzo_hdrpip *phdrpip)
{
  if ( hdrlip.reserve!=0 && hdrlip.reserve!=1 )
    return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrlip.dontfrag!=0 && hdrlip.dontfrag!=1 )
    return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrlip.morefrag!=0 && hdrlip.morefrag!=1 )
    return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrlip.offsetfrag > 0x1FFF )
    return(LCRZO_ERR_SPTOOBIGFORHDRL);

  if (phdrpip!=NULL)
  { phdrpip->version  = hdrlip.version;
    phdrpip->ihl      = hdrlip.ihl;
    phdrpip->tos      = hdrlip.tos;
    phdrpip->totlen   = lcrzo_htons(hdrlip.totlen);
    phdrpip->id       = lcrzo_htons(hdrlip.id);
    phdrpip->fragoff  = (lcrzo_uint16)( LCRZO_HDRPIP_RF_HN(hdrlip.reserve) |
					LCRZO_HDRPIP_DF_HN(hdrlip.dontfrag) | 
				      LCRZO_HDRPIP_MF_HN(hdrlip.morefrag) |
				      LCRZO_HDRPIP_OFF_HN(hdrlip.offsetfrag) );
    phdrpip->ttl      = hdrlip.ttl;
    phdrpip->protocol = hdrlip.protocol;
    phdrpip->check    = lcrzo_htons(hdrlip.check); 
    phdrpip->saddr    = lcrzo_htonl(hdrlip.saddr);
    phdrpip->daddr    = lcrzo_htonl(hdrlip.daddr);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrpudp_init_hdrludp(lcrzo_hdrludp hdrludp,
			  lcrzo_hdrpudp *phdrpudp)
{
  if (phdrpudp!=NULL)
  { phdrpudp->sport  = lcrzo_htons(hdrludp.sport);
    phdrpudp->dport  = lcrzo_htons(hdrludp.dport);
    phdrpudp->len    = lcrzo_htons(hdrludp.len);
    phdrpudp->check  = lcrzo_htons(hdrludp.check);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrptcp_init_hdrltcp(lcrzo_hdrltcp hdrltcp,
			  lcrzo_hdrptcp *phdrptcp)
{

  if ( hdrltcp.reserve > 0x3F )
    return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrltcp.urg!=0 && hdrltcp.urg!=1 ) return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrltcp.ack!=0 && hdrltcp.ack!=1 ) return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrltcp.psh!=0 && hdrltcp.psh!=1 ) return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrltcp.rst!=0 && hdrltcp.rst!=1 ) return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrltcp.syn!=0 && hdrltcp.syn!=1 ) return(LCRZO_ERR_SPTOOBIGFORHDRL);
  if ( hdrltcp.fin!=0 && hdrltcp.fin!=1 ) return(LCRZO_ERR_SPTOOBIGFORHDRL);

  if (phdrptcp!=NULL)
  { phdrptcp->sport  = lcrzo_htons(hdrltcp.sport);
    phdrptcp->dport  = lcrzo_htons(hdrltcp.dport);
    phdrptcp->seqnum = lcrzo_htonl(hdrltcp.seqnum);
    phdrptcp->acknum = lcrzo_htonl(hdrltcp.acknum);
    phdrptcp->doff   = hdrltcp.doff;
    phdrptcp->res1   = (lcrzo_uint8)(hdrltcp.reserve>>2);
    phdrptcp->res2   = (lcrzo_uint8)(hdrltcp.reserve&0x3);
    phdrptcp->urg    = hdrltcp.urg;
    phdrptcp->ack    = hdrltcp.ack;
    phdrptcp->psh    = hdrltcp.psh;
    phdrptcp->rst    = hdrltcp.rst;
    phdrptcp->syn    = hdrltcp.syn;
    phdrptcp->fin    = hdrltcp.fin;
    phdrptcp->window = lcrzo_htons(hdrltcp.window);
    phdrptcp->check  = lcrzo_htons(hdrltcp.check);
    phdrptcp->urgptr = lcrzo_htons(hdrltcp.urgptr);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrpicmp_init_hdrlicmp(lcrzo_hdrlicmp hdrlicmp,
			    lcrzo_hdrpicmp *phdrpicmp)
{
  if (phdrpicmp!=NULL)
  { phdrpicmp->type  = hdrlicmp.type;
    phdrpicmp->code  = hdrlicmp.code;
    phdrpicmp->check = lcrzo_htons(hdrlicmp.check);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrparp_init_hdrlarp(lcrzo_hdrlarp hdrlarp,
			  lcrzo_hdrparp *phdrparp)
{ 
  if (phdrparp!=NULL)
  { phdrparp->hw_type  = lcrzo_htons(hdrlarp.hw_type);
    phdrparp->prot_type= lcrzo_htons(hdrlarp.prot_type);
    phdrparp->hw_size  = hdrlarp.hw_size;
    phdrparp->prot_size= hdrlarp.prot_size;
    phdrparp->op       = lcrzo_htons(hdrlarp.op);
    memcpy(phdrparp->hw_src, hdrlarp.hw_src, LCRZO_ETHA_MAXBYTES);
    memcpy(phdrparp->prot_src, hdrlarp.prot_src, LCRZO_IPA_MAXBYTES);
    memcpy(phdrparp->hw_dst, hdrlarp.hw_dst, LCRZO_ETHA_MAXBYTES);
    memcpy(phdrparp->prot_dst, hdrlarp.prot_dst, LCRZO_IPA_MAXBYTES);
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_hdrleth_init_hdrpeth(lcrzo_hdrpeth hdrpeth,
			  lcrzo_hdrleth *phdrleth)
{
  if (phdrleth!=NULL)
  { memcpy(phdrleth->dst, hdrpeth.dst, LCRZO_ETHA_MAXBYTES);
    memcpy(phdrleth->src, hdrpeth.src, LCRZO_ETHA_MAXBYTES);
    phdrleth->type=lcrzo_ntohs(hdrpeth.type);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlip_init_hdrpip(lcrzo_hdrpip hdrpip,
			lcrzo_hdrlip *phdrlip)
{
  if (phdrlip!=NULL)
  { phdrlip->version  = (lcrzo_uint8)hdrpip.version;
    phdrlip->ihl      = (lcrzo_uint8)hdrpip.ihl;
    phdrlip->tos      = (lcrzo_uint8)hdrpip.tos;
    phdrlip->totlen   = lcrzo_ntohs(hdrpip.totlen);
    phdrlip->id       = lcrzo_ntohs(hdrpip.id);
    phdrlip->reserve  = LCRZO_HDRPIP_RF_NH(hdrpip.fragoff);
    phdrlip->dontfrag = LCRZO_HDRPIP_DF_NH(hdrpip.fragoff);
    phdrlip->morefrag = LCRZO_HDRPIP_MF_NH(hdrpip.fragoff);
    phdrlip->offsetfrag = LCRZO_HDRPIP_OFF_NH(hdrpip.fragoff);
    phdrlip->ttl      = hdrpip.ttl;
    phdrlip->protocol = hdrpip.protocol;
    phdrlip->check    = lcrzo_ntohs(hdrpip.check); 
    phdrlip->saddr    = lcrzo_ntohl(hdrpip.saddr);
    phdrlip->daddr    = lcrzo_ntohl(hdrpip.daddr);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrludp_init_hdrpudp(lcrzo_hdrpudp hdrpudp,
			  lcrzo_hdrludp *phdrludp)
{
  if (phdrludp!=NULL)
  { phdrludp->sport  = lcrzo_ntohs(hdrpudp.sport);
    phdrludp->dport  = lcrzo_ntohs(hdrpudp.dport);
    phdrludp->len    = lcrzo_ntohs(hdrpudp.len);
    phdrludp->check  = lcrzo_ntohs(hdrpudp.check);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrltcp_init_hdrptcp(lcrzo_hdrptcp hdrptcp,
			  lcrzo_hdrltcp *phdrltcp)
{
  if (phdrltcp!=NULL)
  { phdrltcp->sport  = lcrzo_ntohs(hdrptcp.sport);
    phdrltcp->dport  = lcrzo_ntohs(hdrptcp.dport);
    phdrltcp->seqnum = lcrzo_ntohl(hdrptcp.seqnum);
    phdrltcp->acknum = lcrzo_ntohl(hdrptcp.acknum);
    phdrltcp->doff   = (lcrzo_uint8)hdrptcp.doff;
    phdrltcp->reserve= (lcrzo_uint8)((hdrptcp.res1<<2) | hdrptcp.res2);
    phdrltcp->urg    = (lcrzo_int8)(hdrptcp.urg&1);
    phdrltcp->ack    = (lcrzo_int8)(hdrptcp.ack&1);
    phdrltcp->psh    = (lcrzo_int8)(hdrptcp.psh&1);
    phdrltcp->rst    = (lcrzo_int8)(hdrptcp.rst&1);
    phdrltcp->syn    = (lcrzo_int8)(hdrptcp.syn&1);
    phdrltcp->fin    = (lcrzo_int8)(hdrptcp.fin&1);
    phdrltcp->window = lcrzo_ntohs(hdrptcp.window);
    phdrltcp->check  = lcrzo_ntohs(hdrptcp.check);
    phdrltcp->urgptr = lcrzo_ntohs(hdrptcp.urgptr);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlicmp_init_hdrpicmp(lcrzo_hdrpicmp hdrpicmp,
			    lcrzo_hdrlicmp *phdrlicmp)
{
  if (phdrlicmp!=NULL)
  { phdrlicmp->type  = hdrpicmp.type;
    phdrlicmp->code  = hdrpicmp.code;
    phdrlicmp->check = lcrzo_ntohs(hdrpicmp.check);
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlarp_init_hdrparp(lcrzo_hdrparp hdrparp,
			  lcrzo_hdrlarp *phdrlarp)
{ 
  if (phdrlarp!=NULL)
  { phdrlarp->hw_type  = lcrzo_ntohs(hdrparp.hw_type);
    phdrlarp->prot_type= lcrzo_ntohs(hdrparp.prot_type);
    phdrlarp->hw_size  = hdrparp.hw_size;
    phdrlarp->prot_size= hdrparp.prot_size;
    phdrlarp->op       = lcrzo_ntohs(hdrparp.op);
    memcpy(phdrlarp->hw_src, hdrparp.hw_src, LCRZO_ETHA_MAXBYTES);
    memcpy(phdrlarp->prot_src, hdrparp.prot_src, LCRZO_IPA_MAXBYTES);
    memcpy(phdrlarp->hw_dst, hdrparp.hw_dst, LCRZO_ETHA_MAXBYTES);
    memcpy(phdrlarp->prot_dst, hdrparp.prot_dst, LCRZO_IPA_MAXBYTES);
  }
  return(LCRZO_ERR_OK);
}


/*-------------------------------------------------------------*/
int lcrzo_hdrleth_update(lcrzo_hdrleth fieldstomodify,
			 lcrzo_hdrleth *phdreth)
{ lcrzo_hdrleth def;

  if (phdreth==NULL) return(LCRZO_ERR_OK);

  lcrzo_er(lcrzo_hdrleth_initdefault(&def));

  if ( !lcrzo_etha_equal(fieldstomodify.src, def.src) )
    memcpy(phdreth->src, fieldstomodify.src, LCRZO_ETHA_MAXBYTES);
  if ( !lcrzo_etha_equal(fieldstomodify.dst, def.dst) )
    memcpy(phdreth->dst, fieldstomodify.dst, LCRZO_ETHA_MAXBYTES);
  if ( fieldstomodify.type!=def.type)
    phdreth->type=fieldstomodify.type;

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlip_update(lcrzo_hdrlip fieldstomodify,
			lcrzo_hdrlip *phdrip)
{ lcrzo_hdrlip def;

  if (phdrip==NULL) return(LCRZO_ERR_OK);

  lcrzo_er(lcrzo_hdrlip_initdefault(&def));

  if (fieldstomodify.version!=def.version)
    phdrip->version=fieldstomodify.version;
  if (fieldstomodify.ihl!=def.ihl)
    phdrip->ihl=fieldstomodify.ihl;
  if (fieldstomodify.tos!=def.tos)
    phdrip->tos=fieldstomodify.tos;
  if (fieldstomodify.totlen!=def.totlen)
    phdrip->totlen=fieldstomodify.totlen;
  if (fieldstomodify.id!=def.id)
    phdrip->id=fieldstomodify.id;
  if (fieldstomodify.reserve!=def.reserve)
    phdrip->reserve=fieldstomodify.reserve;
  if (fieldstomodify.dontfrag!=def.dontfrag)
    phdrip->dontfrag=fieldstomodify.dontfrag;
  if (fieldstomodify.morefrag!=def.morefrag)
    phdrip->morefrag=fieldstomodify.morefrag;
  if (fieldstomodify.offsetfrag!=def.offsetfrag)
    phdrip->offsetfrag=fieldstomodify.offsetfrag;
  if (fieldstomodify.ttl!=def.ttl)
    phdrip->ttl=fieldstomodify.ttl;
  if (fieldstomodify.protocol!=def.protocol)
    phdrip->protocol=fieldstomodify.protocol;
  phdrip->check=LCRZO_HDRLIP_CHECK_DEFVAL;
  if (fieldstomodify.saddr!=def.saddr)
    phdrip->saddr=fieldstomodify.saddr;
  if (fieldstomodify.daddr!=def.daddr)
    phdrip->daddr=fieldstomodify.daddr;

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrludp_update(lcrzo_hdrludp fieldstomodify,
			 lcrzo_hdrludp *phdrudp)
{ lcrzo_hdrludp def;

  if (phdrudp==NULL) return(LCRZO_ERR_OK);

  lcrzo_er(lcrzo_hdrludp_initdefault(&def));

  if (fieldstomodify.sport!=def.sport)
    phdrudp->sport=fieldstomodify.sport;
  if (fieldstomodify.dport!=def.dport)
    phdrudp->dport=fieldstomodify.dport;
  if (fieldstomodify.len!=def.len)
    phdrudp->len=fieldstomodify.len;
   phdrudp->check=LCRZO_HDRLUDP_CHECK_DEFVAL;

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrltcp_update(lcrzo_hdrltcp fieldstomodify,
			 lcrzo_hdrltcp *phdrtcp)
{ lcrzo_hdrltcp def;

  if (phdrtcp==NULL) return(LCRZO_ERR_OK);

  lcrzo_er(lcrzo_hdrltcp_initdefault(&def));

  if (fieldstomodify.sport!=def.sport)
    phdrtcp->sport=fieldstomodify.sport;
  if (fieldstomodify.dport!=def.dport)
    phdrtcp->dport=fieldstomodify.dport;
  if (fieldstomodify.seqnum!=def.seqnum)
    phdrtcp->seqnum=fieldstomodify.seqnum;
  if (fieldstomodify.acknum!=def.acknum)
    phdrtcp->acknum=fieldstomodify.acknum;
  if (fieldstomodify.doff!=def.doff)
    phdrtcp->doff=fieldstomodify.doff;
  if (fieldstomodify.reserve!=def.reserve)
    phdrtcp->reserve=fieldstomodify.reserve;
  if (fieldstomodify.urg!=def.urg)
    phdrtcp->urg=fieldstomodify.urg;
  if (fieldstomodify.ack!=def.ack)
    phdrtcp->ack=fieldstomodify.ack;
  if (fieldstomodify.psh!=def.psh)
    phdrtcp->psh=fieldstomodify.psh;
  if (fieldstomodify.rst!=def.rst)
    phdrtcp->rst=fieldstomodify.rst;
  if (fieldstomodify.syn!=def.syn)
    phdrtcp->syn=fieldstomodify.syn;
  if (fieldstomodify.fin!=def.fin)
    phdrtcp->fin=fieldstomodify.fin;
  if (fieldstomodify.window!=def.window)
    phdrtcp->window=fieldstomodify.window;
  phdrtcp->check=LCRZO_HDRLTCP_CHECK_DEFVAL;
  if (fieldstomodify.urgptr!=def.urgptr)
    phdrtcp->urgptr=fieldstomodify.urgptr;

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlicmp_update(lcrzo_hdrlicmp fieldstomodify,
			  lcrzo_hdrlicmp *phdricmp)
{ lcrzo_hdrlicmp def;

  if (phdricmp==NULL) return(LCRZO_ERR_OK);

  lcrzo_er(lcrzo_hdrlicmp_initdefault(&def));

  if (fieldstomodify.type!=def.type)
    phdricmp->type=fieldstomodify.type;
  if (fieldstomodify.code!=def.code)
    phdricmp->code=fieldstomodify.code;
  phdricmp->check=LCRZO_HDRLICMP_CHECK_DEFVAL;

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_hdrlarp_update(lcrzo_hdrlarp fieldstomodify,
			 lcrzo_hdrlarp *phdrarp)
{ lcrzo_hdrlarp def;

  if (phdrarp==NULL) return(LCRZO_ERR_OK);

  lcrzo_er(lcrzo_hdrlarp_initdefault(&def));

  if (fieldstomodify.hw_type!=def.hw_type)
    phdrarp->hw_type=fieldstomodify.hw_type;
  if (fieldstomodify.prot_type!=def.prot_type)
    phdrarp->prot_type=fieldstomodify.prot_type;
  if (fieldstomodify.hw_size!=def.hw_size)
    phdrarp->hw_size=fieldstomodify.hw_size;
  if (fieldstomodify.prot_size!=def.prot_size)
    phdrarp->prot_size=fieldstomodify.prot_size;
  if (fieldstomodify.op!=def.op)
    phdrarp->op=fieldstomodify.op;
  if ( !lcrzo_etha_equal(fieldstomodify.hw_src, def.hw_src) )
    memcpy(phdrarp->hw_src, fieldstomodify.hw_src, LCRZO_ETHA_MAXBYTES);
  if ( !lcrzo_etha_equal(fieldstomodify.hw_dst, def.hw_dst) )
    memcpy(phdrarp->hw_dst, fieldstomodify.hw_dst, LCRZO_ETHA_MAXBYTES);
  if ( !lcrzo_ipa_equal(fieldstomodify.prot_src, def.prot_src) )
    memcpy(phdrarp->prot_src, fieldstomodify.prot_src, LCRZO_IPA_MAXBYTES);
  if ( !lcrzo_ipa_equal(fieldstomodify.prot_dst, def.prot_dst) )
    memcpy(phdrarp->prot_dst, fieldstomodify.prot_dst, LCRZO_IPA_MAXBYTES);

  return(LCRZO_ERR_OK);
}
