/* 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_localeth_debug_fprint(LCRZOFILE *pf);
int lcrzo_priv_conf_localeth_debug_fprint(LCRZOFILE *pf)
{ lcrzo_priv_confvars *ptrcv;
  lcrzo_priv_conf_deviceeth de;
  lcrzo_int32 i, count;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_list_count(&ptrcv->list_localeth, &count));
  for ( i=1 ; i<=count ; i++ )
  { lcrzo_er(lcrzo_list_value_pos(&ptrcv->list_localeth, i, &de));
    lcrzo_device_fprint(pf, " dev=", de.device, "\t");
    lcrzo_etha_fprint(pf, " eth=", de.eth, "\n");
  }

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_add(lcrzo_device device,
                                 lcrzo_etha etha);
int lcrzo_priv_conf_localeth_add(lcrzo_device device,
                                 lcrzo_etha etha)
{ lcrzo_priv_confvars *ptrcv;
  lcrzo_priv_conf_deviceeth de;

  if ( etha[0]==0 && etha[1]==0 && etha[2]==0 && etha[3]==0 && etha[4]==0 && etha[5]==0 )
  { /* do not add bad addresses */
    return(LCRZO_ERR_OK);
  }

  lcrzo_er(lcrzo_device_init(device, de.device));
  memcpy(de.eth, etha, LCRZO_ETHA_MAXBYTES);

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_list_add_last(&ptrcv->list_localeth, &de));

  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_init_packetdll(void);
int lcrzo_priv_conf_localeth_init_packetdll(void)
{ lcrzo_int32 i, count;
  lcrzo_device device;
  lcrzo_etha etha;
  lcrzo_list list;
  int ret;
  
  lcrzo_er(lcrzo_priv_conf_packetgetadapternames(&list));

  /* loop for each adapter name */
  ret=lcrzo_list_count(&list, &count);
  if (ret==LCRZO_ERR_OK)
  {
    for ( i=1 ; i<=count && ret==LCRZO_ERR_OK ; i++ )
    { ret=lcrzo_priv_conf_packetgetadapternames_get(&list, i, device);
      if (ret==LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_etha_init_device_packetdll(device, etha);
        if (ret==LCRZO_ERR_OK)
        { ret=lcrzo_priv_conf_localeth_add(device, etha);
        }
      }
    }
  }
  lcrzo_list_close(&list);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_init_iphlpapi(void);
int lcrzo_priv_conf_localeth_init_iphlpapi(void)
{ lcrzo_priv_iphlpapidll iphlpapidll;
  lcrzo_uint32 bufsize, i;
  PMIB_IFTABLE piftable;
  int ret;

  /* load the library */
  lcrzo_er(lcrzo_priv_iphlpapidll_init(&iphlpapidll));

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

  /* allocate data */
  piftable=(PMIB_IFTABLE)GlobalAlloc(GPTR, bufsize);
  if (piftable==NULL)
  { return(LCRZO_ERR_FUGLOBALALLOC);
  }
  
  /* get the IP table */
  ret=iphlpapidll.GetIfTable(piftable, &bufsize, FALSE);
  if ( ret!=NO_ERROR )
  { GlobalFree(piftable);
    return(LCRZO_ERR_FUGETIFTABLE);
  }

  /* loop through each entry */
  for ( i=0 ; i<piftable->dwNumEntries && ret==LCRZO_ERR_OK ; i++ )
  { ret=lcrzo_priv_conf_localeth_add("",  piftable->table[i].bPhysAddr);
  }

  GlobalFree(piftable);
  lcrzo_er(lcrzo_priv_iphlpapidll_close(&iphlpapidll));
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_init_snmpdll(void);
int lcrzo_priv_conf_localeth_init_snmpdll(void)
{ lcrzo_priv_snmpdll snmpdll;
  lcrzo_priv_snmpdllreq snmpdllreqdev;
  AsnObjectIdentifier oid0, oid1;
  lcrzo_uint32 i, numberofcards, mactype;
  lcrzo_etha etha;
  
  lcrzo_er(lcrzo_priv_snmpdll_init(&snmpdll));

  /* get the number of interfaces */
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid0, 1, 3, 6, 1, 2, 1, 2, 1, -1));
  lcrzo_er(lcrzo_priv_snmpdllreq_init(&snmpdllreqdev, &oid0, NULL, NULL, NULL, NULL));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid0));
  lcrzo_er(lcrzo_priv_snmpdllreq_getnext(&snmpdll, &snmpdllreqdev));
  //lcrzo_er(lcrzo_priv_snmpdllreq_print(&snmpdllreqdev));
  lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreqdev, 0, &numberofcards));
  //printf("Number of cards = %d\n", numberofcards);
  lcrzo_er(lcrzo_priv_snmpdllreq_close(&snmpdllreqdev));

  lcrzo_er(lcrzo_priv_AsnOid_init(&oid0, 1, 3, 6, 1, 2, 1, 2, 2, 1, 6, -1));
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid1, 1, 3, 6, 1, 2, 1, 2, 2, 1, 3, -1));
  lcrzo_er(lcrzo_priv_snmpdllreq_init(&snmpdllreqdev, &oid0, &oid1, NULL, NULL, NULL));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid1));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid0));
  for ( i=0 ; i<numberofcards ; i++ )
  { lcrzo_er(lcrzo_priv_snmpdllreq_getnext(&snmpdll, &snmpdllreqdev));
    //lcrzo_er(lcrzo_priv_snmpdllreq_print(&snmpdllreqdev));
    lcrzo_er(lcrzo_priv_snmpdllreq__etha(&snmpdllreqdev, 0, etha));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreqdev, 1, &mactype));
    /* if it's Ethernet */
    if (mactype==6)
    { lcrzo_priv_conf_localeth_add("",  etha);
    }
  }

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

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_init_netbios(void);
int lcrzo_priv_conf_localeth_init_netbios(void)
{ lcrzo_etha etha;
  int ret, i;

  ret=LCRZO_ERR_OK;
  i=1;
  while (ret==LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_etha_init_cardnumber_netbios(i, i, etha);
    if (ret==LCRZO_ERR_OK)
    { ret=lcrzo_priv_conf_localeth_add("", etha);
      i++;
    }
  }
  if (ret==LCRZO_ERR_OKUNRESOLVED) ret=LCRZO_ERR_OK;

  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_init_uuidcreate(void);
int lcrzo_priv_conf_localeth_init_uuidcreate(void)
{ lcrzo_etha etha;
  int ret;

  ret=lcrzo_priv_conf_etha_init_cardnumber_uuidcreate(1, etha);
  if (ret==LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_localeth_add("", etha);
  }

  return(ret);
}


/*-------------------------------------------------------------*/
int lcrzo_priv_conf_localeth_init(void);
int lcrzo_priv_conf_localeth_init(void)
{ lcrzo_priv_confvars *ptrcv;
  int ret, retp;

  /* first, delete old entries set by uncomplete executions */
  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  
  retp=lcrzo_priv_conf_localeth_init_packetdll();
  /* even if packetdll is OK, we have to do at least one other because
     packetdll is unfortunately incomplete */
  ret=lcrzo_priv_conf_localeth_init_iphlpapi();
  if (ret!=LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_localeth_init_snmpdll();
  }
  if (ret!=LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_localeth_init_netbios();
  }
  if (ret!=LCRZO_ERR_OK)
  { ret=lcrzo_priv_conf_localeth_init_uuidcreate();
  }
  if (ret!=LCRZO_ERR_OK)
  { /* Could also use :
       - NDIS, but this function is currently not used under NT
       - uuid Win reg, but this function is currently not used under NT
       - 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
    */
  }
  if (retp!=LCRZO_ERR_OK) return(ret);

  return(LCRZO_ERR_OK);
}

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

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

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

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));

  fprintf(pf, "\n\nEntries in list_localeth after lcrzo_priv_conf_localeth_init\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localeth_init());
  lcrzo_priv_conf_localeth_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localeth after lcrzo_priv_conf_localeth_init_packetdll\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localeth_init_packetdll());
  lcrzo_priv_conf_localeth_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localeth after lcrzo_priv_conf_localeth_init_iphlpapi\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localeth_init_iphlpapi());
  lcrzo_priv_conf_localeth_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localeth after lcrzo_priv_conf_localeth_init_snmpdll\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localeth_init_snmpdll());
  lcrzo_priv_conf_localeth_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localeth after lcrzo_priv_conf_localeth_init_netbios\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localeth_init_netbios());
  lcrzo_priv_conf_localeth_debug_fprint(pf);

  fprintf(pf, "\n\nEntries in list_localeth after lcrzo_priv_conf_localeth_init_uuidcreate\n");
  lcrzo_er(lcrzo_list_remove_all(&ptrcv->list_localeth));
  lcrzo_err_fprint(pf, lcrzo_priv_conf_localeth_init_uuidcreate());
  lcrzo_priv_conf_localeth_debug_fprint(pf);

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


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