/* This file is part of Lcrzo.
*/

/* cette fonction interroge la table ARP locale (arp -a)*/
#if defined LCRZODEF_SYSTEM_Linux
int lcrzo_priv_etha_init_ipa_ioctlarp2(const lcrzo_ipa ipa, 
					 const lcrzo_device device,
					 lcrzo_etha etha);
int lcrzo_priv_etha_init_ipa_ioctlarp2(const lcrzo_ipa ipa, 
					 const lcrzo_device device,
					 lcrzo_etha etha)
{ int sfd, retour, ret;
  struct arpreq	ar;
  struct sockaddr_in sain;
  lcrzo_ipl ipl;

  lcrzo_er(lcrzo_ipl_init_ipa(ipa, &ipl));

  memset(&sain, 0, sizeof(sain));
  sain.sin_family = AF_INET;
  memcpy(&sain.sin_addr.s_addr, ipa, LCRZO_IPA_MAXBYTES);

  memset(&ar, 0, sizeof(ar));
  memcpy(&ar.arp_pa, &sain, sizeof(sain));
  strncpy(ar.arp_dev, device, sizeof(ar.arp_dev)-1);

  sfd=socket(AF_INET, SOCK_DGRAM, 0);
  if ( sfd == -1 ) return(LCRZO_ERR_FUSOCKET);

  retour=ioctl(sfd, SIOCGARP, (char *)&ar);
  ret=close(sfd);
  if ( retour == -1 ) return(LCRZO_ERR_FUIOCTL);
  if ( ret == -1 ) return(LCRZO_ERR_FUCLOSE);

  lcrzo_er(lcrzo_priv_conf_arp_add_system(device, 
					  (lcrzo_data)ar.arp_ha.sa_data,
					  ipl, LCRZO_FALSE));
  if (etha!=NULL) memcpy(etha, ar.arp_ha.sa_data, LCRZO_ETHA_MAXBYTES);
  lcrzo_err_purge();
  return(LCRZO_ERR_OK);
}
int lcrzo_priv_etha_init_ipa_ioctlarp(const lcrzo_ipa ipa, lcrzo_etha etha)
{ lcrzo_device device;
  lcrzo_int32 count, i;
  int ret;

  lcrzo_er(lcrzo_device_count(LCRZO_DEVICE_TYPE_ONLYBOARDS, &count));
  for ( i=1 ; i<=count ; i++ )
  { lcrzo_er(lcrzo_device_value_pos(LCRZO_DEVICE_TYPE_ONLYBOARDS, i, device));
    ret=lcrzo_priv_etha_init_ipa_ioctlarp2(ipa, device, etha);
    if (ret==LCRZO_ERR_OK)
    { return(LCRZO_ERR_OK);
    }
  }

  /*adresse non resolue*/
  return(LCRZO_ERR_OKUNRESOLVED);
}
#elif defined LCRZODEF_SYSTEM_Solaris
int lcrzo_priv_etha_init_ipa_ioctlarp(const lcrzo_ipa ipa, 
					lcrzo_etha etha)
{ int sfd, retour, ret;
  struct arpreq	ar;
  struct sockaddr_in sain;
  lcrzo_ipl ipl;

  lcrzo_er(lcrzo_ipl_init_ipa(ipa, &ipl));

  memset(&sain, 0, sizeof(sain));
  sain.sin_family = AF_INET;
  memcpy(&sain.sin_addr.s_addr, ipa, LCRZO_IPA_MAXBYTES);

  memset(&ar, 0, sizeof(ar));
  memcpy(&ar.arp_pa, &sain, sizeof(sain));

  sfd=socket(AF_INET, SOCK_DGRAM, 0);
  if ( sfd == -1 ) return(LCRZO_ERR_FUSOCKET);

  retour=ioctl(sfd, SIOCGARP, (char *)&ar);
  ret=close(sfd);
  if ( retour == -1 ) return(LCRZO_ERR_FUIOCTL);
  if ( ret == -1 ) return(LCRZO_ERR_FUCLOSE);

  lcrzo_er(lcrzo_priv_conf_arp_add_system("", (lcrzo_data)ar.arp_ha.sa_data,
					  ipl, LCRZO_FALSE));
  if (etha!=NULL) memcpy(etha, ar.arp_ha.sa_data, LCRZO_ETHA_MAXBYTES);
  lcrzo_err_purge();
  return(LCRZO_ERR_OK);
}
#elif defined LCRZODEF_SYSTEM_FreeBSD || defined LCRZODEF_SYSTEM_OpenBSD || defined LCRZODEF_SYSTEM_Windows
int lcrzo_priv_etha_init_ipa_ioctlarp(const lcrzo_ipa ipa, lcrzo_etha etha)
{ return(LCRZO_ERR_OKUNRESOLVED);
  { int i; 
    /* just for the compiler warning */
    if (ipa==NULL && etha==NULL) i=0;
  }
}
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif

