/* This file is part of Lcrzo.
*/

/* This file is part of Lcrzo.
*/

#ifdef LCRZODEF_SYSTEM_Unix
  /* this function is not needed*/

#elif defined LCRZODEF_SYSTEM_Windows

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_debug_fprint(LCRZOFILE *pf);
int lcrzo_priv_conf_localip_debug_fprint(LCRZOFILE *pf)
{ lcrzo_priv_confvars *ptrcv;
  lcrzo_ipl ip;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_iplist_value_first(&ptrcv->list_localip, &ip));
  while (LCRZO_TRUE)
  { lcrzo_er(lcrzo_iplist_value_next(&ptrcv->list_localip, ip, &ip));
    lcrzo_ipl_fprint(pf, " ip=", ip, "\n");
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_init_iphlpapi(void);
int lcrzo_priv_conf_localip_init_iphlpapi(void)
{ lcrzo_priv_confvars *ptrcv;
  lcrzo_priv_iphlpapidll iphlpapidll;
  lcrzo_uint32 bufsize, i;
  lcrzo_ipl ip;
  PMIB_IPADDRTABLE pipaddrtable;
  int ret;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  /* first, delete old entries set by uncomplete executions */
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  /* load the library */
  lcrzo_er(lcrzo_priv_iphlpapidll_init(&iphlpapidll));

  /* get the IP table size */
  bufsize=0;
  ret=(iphlpapidll.GetIpAddrTable)(NULL, &bufsize, FALSE);
  if ( ret!=ERROR_INSUFFICIENT_BUFFER )
  { return(LCRZO_ERR_FUGETIPADDRTABLE);
  }

  /* allocate data */
  pipaddrtable=(PMIB_IPADDRTABLE)GlobalAlloc(GPTR, bufsize);
  if (pipaddrtable==NULL)
  { return(LCRZO_ERR_FUGLOBALALLOC);
  }
  
  /* get the IP table */
  ret=iphlpapidll.GetIpAddrTable(pipaddrtable, &bufsize, FALSE);
  if ( ret!=NO_ERROR )
  { GlobalFree(pipaddrtable);
    return(LCRZO_ERR_FUGETIPADDRTABLE);
  }

  /* loop through each entry */
  for ( i=0 ; i<pipaddrtable->dwNumEntries && ret==LCRZO_ERR_OK ; i++ )
  { ip=lcrzo_htonl(pipaddrtable->table[i].dwAddr);
    ret=lcrzo_iplist_add_range(&ptrcv->list_localip, ip, ip);
  }

  GlobalFree(pipaddrtable);
  lcrzo_er(lcrzo_priv_iphlpapidll_close(&iphlpapidll));
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_init_snmpdll(void);
int lcrzo_priv_conf_localip_init_snmpdll(void)
{ lcrzo_priv_snmpdll snmpdll;
  lcrzo_priv_snmpdllreq snmpdllreqip;
  lcrzo_priv_confvars *ptrcv;
  AsnObjectIdentifier oid0;
  lcrzo_ipl ipaddress;
  unsigned int old;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  /* first, delete old entries set by uncomplete executions */
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  lcrzo_er(lcrzo_priv_snmpdll_init(&snmpdll));

  /* get characteristics of the IP addresses */
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid0, 1, 3, 6, 1, 2, 1, 4, 20, 1, 1, -1));
  lcrzo_er(lcrzo_priv_snmpdllreq_init(&snmpdllreqip, &oid0, NULL, NULL, NULL, NULL));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid0));
  lcrzo_er(lcrzo_priv_snmpdllreq_getnext(&snmpdll, &snmpdllreqip));
  old=0;
  while ( snmpdllreqip.varBindList.list[0].name.ids[7] == 20 &&
          snmpdllreqip.varBindList.list[0].name.ids[9] == 1 && 
          (unsigned int)snmpdllreqip.varBindList.list[0].name.ids[10] >= old )
  { //lcrzo_er(lcrzo_priv_snmpdllreq_print(&snmpdllreqip));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreqip, 0, &ipaddress));
    lcrzo_er(lcrzo_iplist_add_range(&ptrcv->list_localip, ipaddress, ipaddress));
    old=snmpdllreqip.varBindList.list[0].name.ids[10];
    lcrzo_er(lcrzo_priv_snmpdllreq_getnext(&snmpdll, &snmpdllreqip));
  }

  /* end */
  lcrzo_er(lcrzo_priv_snmpdllreq_close(&snmpdllreqip));
  lcrzo_er(lcrzo_priv_snmpdll_close(&snmpdll));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_init_gethostbyname(void);
int lcrzo_priv_conf_localip_init_gethostbyname(void)
{ lcrzo_priv_confvars *ptrcv;
  lcrzo_ipl ip;
  lcrzo_hs hs;
  struct hostent *phe;
  int ret, i;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  /* first, delete old entries set by uncomplete executions */
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
 
  /* get the local hostname */
  ret=gethostname(hs, LCRZO_HS_MAXBYTES);
  if (ret!=0) return(LCRZO_ERR_OKUNRESOLVED);

  /* get the corresponding IP addresses */
  phe=gethostbyname(hs);
  if (phe==NULL) return(LCRZO_ERR_OKUNRESOLVED);
  if (phe->h_addrtype!=AF_INET) return(LCRZO_ERR_OKUNRESOLVED);
  if (phe->h_length!=LCRZO_IPA_MAXBYTES) return(LCRZO_ERR_OKUNRESOLVED);

  /* loop through each device */
  i=0;
  while ( phe->h_addr_list[i] != NULL )
  { ip=((lcrzo_uint8)phe->h_addr_list[i][0])<<24;
    ip|=((lcrzo_uint8)phe->h_addr_list[i][1])<<16;
    ip|=((lcrzo_uint8)phe->h_addr_list[i][2])<<8;
    ip|=((lcrzo_uint8)phe->h_addr_list[i][3]);
    lcrzo_er(lcrzo_iplist_add_range(&ptrcv->list_localip, ip, ip));
    i++;
  }

  /* add loopback */
  ip=0x7F000001;
  lcrzo_er(lcrzo_iplist_add_range(&ptrcv->list_localip, ip, ip));

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_init(void);
int lcrzo_priv_conf_localip_init(void)
{ int ret;

  ret=lcrzo_priv_conf_localip_init_iphlpapi();
  if (ret!=LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_localip_init_snmpdll();
  }
  if (ret!=LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_localip_init_gethostbyname();
  }
  if (ret!=LCRZO_ERR_OK)
  { /* Could also use :
       - packet.dll with PacketGetNetInfo, but this function doesn't work properly
       - NT registery, but this function is currently not used under NT
       - Win registery, but result are incomplete because of DhcpInfoxx. Moreover,
         DhcpInfoxx are associated thanks to this function, so can not do a recursive loop
    */
  }

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_eventuallyinit(void);
int lcrzo_priv_conf_localip_eventuallyinit(void)
{ lcrzo_priv_confvars *ptrcv;
  lcrzo_int32 count;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_list_count(&ptrcv->list_localip, &count));
  if (count==0)
  { lcrzo_er(lcrzo_priv_conf_localip_init());
  }
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localip_init_debug_fprint(LCRZOFILE *pf);
int lcrzo_priv_conf_localip_init_debug_fprint(LCRZOFILE *pf)
{ lcrzo_priv_confvars *ptrcv;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));

  fprintf(pf, "\n\nEntries in list_localip after lcrzo_priv_conf_localip_init\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localip_init());
  lcrzo_priv_conf_localip_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localip after lcrzo_priv_conf_localip_init_iphlpapi\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localip_init_iphlpapi());
  lcrzo_priv_conf_localip_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localip after lcrzo_priv_conf_localip_init_snmpdll\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localip_init_snmpdll());
  lcrzo_priv_conf_localip_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localip after lcrzo_priv_conf_localip_init_gethostbyname\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localip_init_gethostbyname());
  lcrzo_priv_conf_localip_debug_fprint(pf);

  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localip));
  return(LCRZO_ERR_OK);
}


#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif
