/* This file is part of Lcrzo.
*/

#ifdef LCRZODEF_SYSTEM_Linux

#elif defined LCRZODEF_SYSTEM_FreeBSD || defined LCRZODEF_SYSTEM_OpenBSD

int lcrzo_priv_conf_device_init_ifnumber(lcrzo_int32 ifnumber,
				         lcrzo_device device);
int lcrzo_priv_conf_device_init_ifnumber(lcrzo_int32 ifnumber,
				         lcrzo_device device)
{ int mib[6];
  LAURENT_size_t len;
  char *buf, *lim, *next;
  struct  if_msghdr *ifm;
  struct  sockaddr_dl *sdl;

  mib[0] = CTL_NET;         /*reseau*/
  mib[1] = PF_ROUTE;        /*famille de protocole*/
  mib[2] = 0;               /*numero de protocole*/
  mib[3] = AF_INET;         /*famille d'adresse*/
  mib[4] = NET_RT_IFLIST;   /*liste des interfaces*/
  mib[5] = 0;

  /*on fait d'abord un premier appel pour connaitre la taille a allouer*/
  if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
  { return (LCRZO_ERR_FUSYSCTL);
  }
  
  /*on alloue la taille necessaire*/
  lcrzo_er(lcrzo_string_alloc(len, &buf));

  /*on fait le vrai appel*/
  if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
  { lcrzo_string_free(buf);
    return (LCRZO_ERR_FUSYSCTL);
  }
  lim = buf + len;

  /*on parcours les elements de la liste trouvee*/
  next = buf;
  while (next < lim)
  { ifm = (struct if_msghdr *)next;
    next += ifm->ifm_msglen;

    /* a new device */
    if (ifm->ifm_type == RTM_IFINFO)
    { if ( ifm->ifm_index == ifnumber )
      { sdl = (struct sockaddr_dl *)(ifm + 1);
        /* sdl->sdl_nlen contains the device name len, not terminated by 0 */
        if ( sdl->sdl_nlen>LCRZO_DEVICE_MAXBYTES )
          return(LCRZO_ERR_PAOVERFLOW);
        lcrzo_string_init_text(sdl->sdl_data, LCRZO_DEVICE_MAXBYTES, device);
        device[sdl->sdl_nlen]='\0';
        lcrzo_string_free(buf);
        return(LCRZO_ERR_OK);
      }
    }
  }

  lcrzo_string_free(buf);
  lcrzo_device_init("", device);
  return(LCRZO_ERR_OK);
}

#elif defined LCRZODEF_SYSTEM_Solaris

#elif defined LCRZODEF_SYSTEM_Windows

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_init_routes_NTregistery(void);
int lcrzo_priv_conf_init_routes_NTregistery(void)
{ lcrzo_list list, devgwlist;
  lcrzo_data devname, gwaddress;
  lcrzo_int32 devnamesize, gwaddresssize, count, i, devgwcount, devi;
  lcrzo_uint32 dhcpenabled;
  lcrzo_string shortdevname, devkey;
  lcrzo_device device;
  lcrzo_ipl gw;
  char *pc;
  int ret;

  lcrzo_er(lcrzo_priv_winreg_datalist_get(HKEY_LOCAL_MACHINE,
           "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", "Bind",
           &list));
  lcrzo_efr(lcrzo_list_count(&list, &count), lcrzo_list_close(&list));
  for ( i=1 ; i<=count ; i++ )
  { 
    /* get the device full name */
    ret=lcrzo_datalist_valuem_pos(&list, i, NULL, &devname, &devnamesize);
    if (ret!=LCRZO_ERR_OK) goto badend1;
    devname[devnamesize]='\0';

    /* compute the short device name */
    pc=strrchr((lcrzo_string)devname, '\\');
    if ( pc == NULL ) pc=(lcrzo_string)devname;
    ret=lcrzo_string_initm_text(pc+1, &shortdevname);
    if (ret!=LCRZO_ERR_OK) goto badend2;

    /* construct the key needed to access its parameters */
    ret=lcrzo_string_initm_text("SYSTEM\\CurrentControlSet\\Services\\", &devkey);
    if (ret!=LCRZO_ERR_OK) goto badend3;
    ret=lcrzo_string_appendm_text(shortdevname, &devkey);
    if (ret!=LCRZO_ERR_OK) goto badend3;
    ret=lcrzo_string_appendm_text("\\Parameters\\Tcpip", &devkey);
    if (ret!=LCRZO_ERR_OK) goto badend3;

    /* check if DHCP is enabled */
    ret=lcrzo_priv_winreg_uint32_get(HKEY_LOCAL_MACHINE, devkey, "EnableDHCP", &dhcpenabled);
    if (ret!=LCRZO_ERR_OK) dhcpenabled=LCRZO_FALSE;

    /* ask the default gateways value for this key */
    ret= ! LCRZO_ERR_OK;
    if (dhcpenabled)
    { ret=lcrzo_priv_winreg_datalist_get(HKEY_LOCAL_MACHINE, devkey, "DhcpDefaultGateway", &devgwlist);
    }
    if ( ret!=LCRZO_ERR_OK )
    { ret=lcrzo_priv_winreg_datalist_get(HKEY_LOCAL_MACHINE, devkey, "DefaultGateway", &devgwlist);
    }
    if ( ret==LCRZO_ERR_OK )
    { ret=lcrzo_list_count(&devgwlist, &devgwcount);
      if ( ret!=LCRZO_ERR_OK ) goto badend5;
      /* get values */        
      for ( devi=1 ; devi<=devgwcount ; devi++ )
      { /* get the GW address */
        ret=lcrzo_datalist_valuem_pos(&devgwlist, devi, NULL, &gwaddress, &gwaddresssize);
        if ( ret!=LCRZO_ERR_OK ) goto badend5;
        /* convert to string */
        gwaddress[gwaddresssize]='\0';
        /* update conf */
        if ( ret!=LCRZO_ERR_OK ) goto badend6;
        ret=lcrzo_ipl_init_ips((lcrzo_string)gwaddress, &gw);
        if ( ret!=LCRZO_ERR_OK ) goto badend6;
        lcrzo_priv_conf_device_init_devicealias(shortdevname, 1, device);
        ret=lcrzo_priv_conf_routes_add_system(device, 0, 0, 0, gw, 1, LCRZO_TRUE);
        if ( ret!=LCRZO_ERR_OK ) goto badend6;
        /* free */
        lcrzo_data_free(gwaddress);
      }
    }
    ret=lcrzo_list_close(&devgwlist);
    if ( ret!=LCRZO_ERR_OK ) goto badend4;
    lcrzo_string_free(devkey);
    lcrzo_string_free(shortdevname);
    lcrzo_data_free(devname);
  }
  lcrzo_er(lcrzo_list_close(&list));
  return(LCRZO_ERR_OK);

  /**/
badend6:
  lcrzo_data_free(gwaddress);
badend5:
  lcrzo_list_close(&devgwlist);
badend4:
  lcrzo_string_free(devkey);
badend3:
  lcrzo_string_free(shortdevname);
badend2:
  lcrzo_string_free((lcrzo_string)devname);
badend1:
  lcrzo_list_close(&list);
  return(ret);
}

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_init_routes_W9xregistery(void);
int lcrzo_priv_conf_init_routes_W9xregistery(void)
{ /* use the device function, which set routes */
  return(lcrzo_priv_conf_init_dev_W9xregistery());
}

/*-------------------------------------------------------------*/
/* Important note : the MIB cannot store several gateways for
   one destination. So it is not possible to retrieve all default
   gateways for example. This is quite annoying. */
int lcrzo_priv_conf_init_routes_snmpdll(void);
int lcrzo_priv_conf_init_routes_snmpdll(void)
{ lcrzo_priv_snmpdll snmpdll;
  lcrzo_priv_snmpdllreq snmpdllreq;
  lcrzo_priv_confvars *ptrcv;
  AsnObjectIdentifier oid0, oid1, oid2, oid3, oid4;
  lcrzo_uint32 ifindex, metric;
  lcrzo_ipl ipaddress, ipnetmask, ipsrc, ipgw;
  lcrzo_bool islocal;
  
  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_priv_conf_localip_init_snmpdll());
  /* load the DLL, and init functions */
  lcrzo_er(lcrzo_priv_snmpdll_init(&snmpdll));

  /* get characteristics of the routing table */
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid0, 1, 3, 6, 1, 2, 1, 4, 21, 1, 1, -1));
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid1, 1, 3, 6, 1, 2, 1, 4, 21, 1, 2, -1));
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid2, 1, 3, 6, 1, 2, 1, 4, 21, 1, 3, -1));
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid3, 1, 3, 6, 1, 2, 1, 4, 21, 1, 7, -1));
  lcrzo_er(lcrzo_priv_AsnOid_init(&oid4, 1, 3, 6, 1, 2, 1, 4, 21, 1, 11, -1));
  lcrzo_er(lcrzo_priv_snmpdllreq_init(&snmpdllreq, &oid0, &oid1, &oid2, &oid3, &oid4));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid0));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid1));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid2));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid3));
  lcrzo_er(lcrzo_priv_AsnOid_close(&oid4));
  lcrzo_er(lcrzo_priv_snmpdllreq_getnext(&snmpdll, &snmpdllreq));
  while ( snmpdllreq.varBindList.list[0].name.ids[7] == 21 &&
          snmpdllreq.varBindList.list[0].name.ids[9] == 1)
  { //lcrzo_er(lcrzo_priv_snmpdllreq_print(&snmpdllreq));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreq, 0, &ipaddress));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreq, 1, &ifindex));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreq, 2, &metric));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreq, 3, &ipgw));
    lcrzo_er(lcrzo_priv_snmpdllreq__uint32(&snmpdllreq, 4, &ipnetmask));
    if ( ! ( ipaddress==0xFFFFFFFFu && ipnetmask==0xFFFFFFFFu ) )
    { ipsrc=0;
      if (ipgw==0x7F000001) ipgw=0;
      if (ipgw!=0)
      { lcrzo_er(lcrzo_iplist_isinlist(&ptrcv->list_localip, ipgw, &islocal));
        if (islocal)
        { ipsrc=ipgw;
          ipgw=0;
        }
      }
      lcrzo_priv_conf_devicenumbername_routes_add_system(ifindex, ipaddress, ipnetmask, ipsrc, ipgw, metric, LCRZO_TRUE);
    }

    lcrzo_er(lcrzo_priv_snmpdllreq_getnext(&snmpdll, &snmpdllreq));
  }
  lcrzo_er(lcrzo_priv_snmpdllreq_close(&snmpdllreq));

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

/*-------------------------------------------------------------*/
int lcrzo_priv_conf_init_routes_iphlpapidll(void);
int lcrzo_priv_conf_init_routes_iphlpapidll(void)
{ lcrzo_priv_iphlpapidll iphlpapidll;
  lcrzo_priv_confvars *ptrcv;
  lcrzo_uint32 bufsize, i, devicenumber;
  PMIB_IPFORWARDTABLE pipforwardtable;
  lcrzo_ipl ip, mask, ipsrc, gw;
  lcrzo_bool islocal;
  int ret;

  lcrzo_er(lcrzo_priv_confvars_ptr_get(&ptrcv));
  lcrzo_er(lcrzo_priv_conf_localip_init_iphlpapi());

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

  /* get the routing table size */
  bufsize=0;
  ret=iphlpapidll.GetIpForwardTable(NULL, &bufsize, FALSE);
  if ( ret!=ERROR_INSUFFICIENT_BUFFER )
  { lcrzo_er(lcrzo_priv_iphlpapidll_close(&iphlpapidll));
    return(LCRZO_ERR_FUGETIPFORWARDTABLE);
  }

  /* allocate data */
  pipforwardtable=(PMIB_IPFORWARDTABLE)GlobalAlloc(GPTR, bufsize);
  if (pipforwardtable==NULL)
  { lcrzo_er(lcrzo_priv_iphlpapidll_close(&iphlpapidll));
    return(LCRZO_ERR_FUGLOBALALLOC);
  }
  
  /* get the routing table */
  ret=iphlpapidll.GetIpForwardTable(pipforwardtable, &bufsize, FALSE);
  if ( ret!=NO_ERROR )
  { GlobalFree(pipforwardtable);
    lcrzo_er(lcrzo_priv_iphlpapidll_close(&iphlpapidll));
    return(LCRZO_ERR_FUGETIPFORWARDTABLE);
  }
  
  /* loop through each entry */
  for ( i=0 ; i<pipforwardtable->dwNumEntries ; i++ )
  { devicenumber=pipforwardtable->table[i].dwForwardIfIndex;
    ip=lcrzo_htonl(pipforwardtable->table[i].dwForwardDest);
    mask=lcrzo_htonl(pipforwardtable->table[i].dwForwardMask);
    gw=lcrzo_htonl(pipforwardtable->table[i].dwForwardNextHop);

    if ( ! ( ip==0xFFFFFFFFu && mask==0xFFFFFFFFu ) )
    { ipsrc=0;
      if (gw==0x7F000001) gw=0;
      if (gw!=0)
      { lcrzo_er(lcrzo_iplist_isinlist(&ptrcv->list_localip, gw, &islocal));
        if (islocal)
        { ipsrc=gw;
          gw=0;
        }
      }
      lcrzo_priv_conf_devicenumbername_routes_add_system(devicenumber, ip, mask, ipsrc, gw, 
                                                    pipforwardtable->table[i].dwForwardMetric1,
                                                    LCRZO_TRUE);
    }
  }

  /* unload the library */
  GlobalFree(pipforwardtable);
  lcrzo_er(lcrzo_priv_iphlpapidll_close(&iphlpapidll));
  return(LCRZO_ERR_OK);
}

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


/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/

int lcrzo_priv_conf_init_routes(void)
/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#if defined LCRZODEF_SYSTEM_Linux
{ int ret, c, fieldnumber;
  FILE *pf;
  lcrzo_device device;
  lcrzo_ipl dest, gw, mask;
  lcrzo_bool isup;
  unsigned int flags;
  int refcnt, use, metric, mtu, window, irrt;

  /*ouverture du procfs*/
  pf=fopen("/proc/net/route", "r");
  if (pf==NULL) 
  { /* because route may not exist on the system */
    lcrzo_err_purge();
    return (LCRZO_ERR_OK);
  }

  /*on passe l'entete*/
  c=fgetc(pf);
  while ( c!=0x0A && c!=EOF ) c=fgetc(pf);

  /*on lit les entrees*/
  while(!feof(pf))
  {
#if LCRZODEF_INT32_ARELONGS == 1
    fieldnumber=fscanf(pf, "%16s %lX %lX %X %d %d %d %lX %d %d %d\n",
#else
    fieldnumber=fscanf(pf, "%16s %X %X %X %d %d %d %X %d %d %d\n",
#endif
		       device, &dest, &gw, &flags, &refcnt, &use, &metric,
		       &mask, &mtu, &window, &irrt);

    if (fieldnumber<8 )
    { /*on n'en a pas lu assez, on ignore et passe a la ligne suivante*/
      c=fgetc(pf);
      while ( c!=0x0A && c!=EOF ) c=fgetc(pf);
    }
    else   
    { isup = flags&RTF_UP;
      if ( ! (flags&RTF_GATEWAY) )
      { /* it is not a gateway, so we put zero */
        gw=0;
      }
      /* add it */
      lcrzo_efr(lcrzo_priv_conf_routes_add_system(device,
						  lcrzo_ntohl(dest),
						  lcrzo_ntohl(mask),
						  0, lcrzo_ntohl(gw),
						  metric,
						  isup), 
		fclose(pf));
    }
  }
  ret=fclose(pf);
  if ( ret == -1 ) return(LCRZO_ERR_FUFCLOSE);
  return(LCRZO_ERR_OK);
}
/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#elif defined LCRZODEF_SYSTEM_FreeBSD || defined LCRZODEF_SYSTEM_OpenBSD
{ int mib[6], flags;
  LAURENT_size_t len;
  char *buf, *lim, *next;
  struct rt_msghdr *rtm;
  lcrzo_device device;
  lcrzo_ipl dest, gw, mask, ipsource;
  lcrzo_bool isup, ishost, hasgateway;
  lcrzo_bool destset, gwset, maskset;
  lcrzo_int32 ifnumber;
  lcrzo_uint32 metric;

  mib[0] = CTL_NET;         /*reseau*/
  mib[1] = PF_ROUTE;        /*famille de protocole*/
  mib[2] = 0;               /*numero de protocole*/
  mib[3] = AF_INET;         /*famille d'adresse*/
  mib[4] = NET_RT_DUMP;     /*list of routes*/
  mib[5] = 0;

  /*on fait d'abord un premier appel pour connaitre la taille a allouer*/
  if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
  { return (LCRZO_ERR_FUSYSCTL);
  }
  
  /*on alloue la taille necessaire*/
  lcrzo_er(lcrzo_string_alloc(len, &buf));

  /*on fait le vrai appel*/
  if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
  { lcrzo_string_free(buf);
    return (LCRZO_ERR_FUSYSCTL);
  }
  lim = buf + len;

  /*on parcours les elements de la liste trouvee*/
  for ( next=buf ; next<lim ; next += rtm->rtm_msglen )
  { int rtmaddr, i;
    struct sockaddr *psa;
    struct sockaddr_in *psai;

    /* the stored item is a rtm */
    rtm = (struct rt_msghdr *)next;
    /* get flags */
    flags=rtm->rtm_flags;
    if ( flags & RTF_UP )
      isup=LCRZO_TRUE;
    else
      isup=LCRZO_FALSE;
    if ( flags & RTF_GATEWAY )
      hasgateway=LCRZO_TRUE;
    else
      hasgateway=LCRZO_FALSE;
    if ( flags & RTF_HOST )
      ishost=LCRZO_TRUE;
    else
      ishost=LCRZO_FALSE;
    /* get bitmask of stored sockaddr types */
    rtmaddr=rtm->rtm_addrs;
    /* save the number of this interface */
    ifnumber=rtm->rtm_index;
    /* set metric (I'am not sure this is the correct parameter to use */
    metric=rtm->rtm_rmx.rmx_hopcount;

 /* lcrzo_data_print((char*)rtm, rtm->rtm_msglen, LCRZO_PRINTTYPE_DUMP);
*/

    /* initialize the pointer to the first sockaddr */
    psa=(struct sockaddr *)((char*)(rtm + 1));
    /* we look each sockaddr */
    destset=LCRZO_FALSE;
    gwset=LCRZO_FALSE;
    maskset=LCRZO_FALSE;
    dest=0; /* just for the compiler */
    gw=0; /* just for the compiler */
    mask=0; /* just for the compiler */
    for ( i=0 ; i<RTAX_MAX ; i++ )
    { if ( rtmaddr & (1<<i) )
      { /* we are only interested by DST, GATEWAY and NETMASK */
        if ( i==RTAX_DST || i==RTAX_GATEWAY || i==RTAX_NETMASK  )
        { psai=(struct sockaddr_in *)psa;
          if ( i==RTAX_DST && psai->sin_family==AF_INET )
          { if ( psai->sin_len )
            { dest=lcrzo_ntohl(psai->sin_addr.s_addr);
              destset=LCRZO_TRUE;
            }
          }
          else if ( i==RTAX_GATEWAY )
          { if ( psai->sin_len && psai->sin_family==AF_INET )
            { gw=lcrzo_ntohl(psai->sin_addr.s_addr);
              gwset=LCRZO_TRUE;
            }
          }
          else if ( i==RTAX_NETMASK )
          { if ( psai->sin_len )
            { mask=lcrzo_ntohl(psai->sin_addr.s_addr);
              maskset=LCRZO_TRUE;
            }
          }
        }
       
        /* psa points to the next item */
        psa=(struct sockaddr *)(((char *)psa) + FB_ROUNDUP(psa->sa_len));
      }
    }
    /* we add the route */
    if ( destset )
    { /* ignore route cache entries*/
      if ( !maskset && !gwset ) continue;
      /* set the mask */
      if ( !maskset )
      { if (ishost) mask=0xFFFFFFFFu;
        else mask=0;
      }
      /* set the gateway */
      if ( !gwset ) gw=0;
      /* set ipsource */
      if ( hasgateway )
      { ipsource=0;
      }
      else
      { ipsource=gw;
        gw=0;
      }
      /* add it */
      lcrzo_efr(lcrzo_priv_conf_device_init_ifnumber(ifnumber, device),
	        lcrzo_string_free(buf));
      lcrzo_efr(lcrzo_priv_conf_routes_add_system(device, dest, mask, 
						  ipsource, gw, 
						  metric, isup),
                lcrzo_string_free(buf));
    }
  }
  lcrzo_string_free(buf);
  return(LCRZO_ERR_OK);
}
/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#elif defined LCRZODEF_SYSTEM_Solaris
{ int ret, c, nbchamps;
  FILE *pf;
  char ligne[120], dest[17], mask[17], gateway[17], device[20], mxfrg[11];
  char flags[11];
  int rtt, ref, out, infwd;
  lcrzo_ipl ipdest, ipmask, ipgateway, ipsource;
  lcrzo_bool isup;

  /*ouverture du procfs*/
  pf=popen("/bin/netstat -rvn", "r");
  if (pf==NULL) return(LCRZO_ERR_FUPOPEN);

  /*on passe l'entete */
  c=fgetc(pf); while ( c!=0x0A && c!=EOF ) c=fgetc(pf);

  /*on lit les entrees*/
  while(!feof(pf))
  { fgets(ligne, 119, pf);
    nbchamps=sscanf(ligne, "%16s %16s %16s %20s %10s %d %d %10s %d %d\n",
		    dest, mask, gateway, device, mxfrg, &rtt, &ref, flags,
		    &out, &infwd);
    if (nbchamps<8 )
    { nbchamps=sscanf(ligne, "%16s %16s %16s %10s %d %d %10s %d %d\n",
		      dest, mask, gateway, mxfrg, &rtt, &ref, flags,
		      &out, &infwd);
      device[0]=0;
      if (nbchamps<8 )
      { /*on n'en a pas lu assez, on ignore et passe a la ligne suivante*/
        c=fgetc(pf);
        while ( c!=0x0A && c!=EOF ) c=fgetc(pf);
	continue;
      }
    }
    if ( strcmp(dest, "default") )
    { ret=lcrzo_ipl_init_ips(dest, &ipdest);
      if ( ret!=LCRZO_ERR_OK ) continue;
    }
    else
    { ipdest=0;
    }
    ret=lcrzo_ipl_init_ips(mask, &ipmask);
    if ( ret!=LCRZO_ERR_OK ) continue;
    ret=lcrzo_ipl_init_ips(gateway, &ipgateway);
    if ( ret!=LCRZO_ERR_OK ) continue;
    /* check if flag up 'U' is present */
    ret=lcrzo_string_search_char(flags, LCRZO_FALSE, +1, -1, 'U', NULL, NULL);
    if ( ret==LCRZO_ERR_OK )
      isup=LCRZO_TRUE;
    else
      isup=LCRZO_FALSE;
    /* check if flag gateway 'G' is present */
    ret=lcrzo_string_search_char(flags, LCRZO_FALSE, +1, -1, 'G', NULL, NULL);
    if ( ret!=LCRZO_ERR_OK )
    { ipsource=ipgateway;
      ipgateway=0;
    }
    else
    { ipsource=0;
    }
    /* add it */
    lcrzo_er(lcrzo_priv_conf_routes_add_system(device, ipdest, ipmask, 
					       ipsource, ipgateway, 1,
					       isup));
  }

  ret=pclose(pf);
  if ( ret == -1 ) return(LCRZO_ERR_FUPCLOSE);
  lcrzo_err_purge(); /*because Solaris set errno*/
  return (LCRZO_ERR_OK);
}
/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#elif defined LCRZODEF_SYSTEM_Windows
{ int ret;
  lcrzo_priv_globalvars *ptrglo;

  lcrzo_er(lcrzo_priv_globalvars_ptr_get(&ptrglo));
  switch(ptrglo->windows_systemversion)
  { case LCRZO_WINDOWS_SYSTEMVERSION_nt4:
    case LCRZO_WINDOWS_SYSTEMVERSION_2k:
    case LCRZO_WINDOWS_SYSTEMVERSION_xp:
      ret=lcrzo_priv_conf_init_routes_iphlpapidll();
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_snmpdll();
      }
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_NTregistery();
      }
      break;

    case LCRZO_WINDOWS_SYSTEMVERSION_95:
      ret=lcrzo_priv_conf_init_routes_snmpdll();
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_W9xregistery(); 
      }
      break;

    case LCRZO_WINDOWS_SYSTEMVERSION_98:
    case LCRZO_WINDOWS_SYSTEMVERSION_me:
      ret=lcrzo_priv_conf_init_routes_iphlpapidll();
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_snmpdll();
      }
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_W9xregistery();
      }
      break;

    default:
      ret=lcrzo_priv_conf_init_routes_iphlpapidll();
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_snmpdll();
      }
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_NTregistery();
      }
      if (ret!=LCRZO_ERR_OK)
      { ret=lcrzo_priv_conf_init_routes_W9xregistery();
      }
      break;
  }

  /* return OK even if nothing was initialized */
  return(LCRZO_ERR_OK);
}

/*-------------------------------------------------------------*/
/*-------------------------------------------------------------*/
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif


/*-------------------------------------------------------------*/
int lcrzo_priv_conf_routes_debug_fprint(LCRZOFILE *pf)
#ifdef LCRZODEF_SYSTEM_Unix
{ return(LCRZO_ERR_OK);
  pf=pf;
}
#elif defined LCRZODEF_SYSTEM_Windows
{ lcrzo_priv_confvars *ptrcv;
  
  lcrzo_epr(lcrzo_priv_confvars_ptr_get(&ptrcv));

  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_routes_iphlpapidll\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_iphlpapidll());
  lcrzo_conf_fprint(pf);

  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_dev+routes_iphlpapidll+verify\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_dev_iphlpapidll());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_iphlpapidll());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_system_verify_routes(ptrcv));
  lcrzo_conf_fprint(pf);
  lcrzo_priv_conf_devicenumbername_debug_fprint(pf);


  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_routes_snmpdll\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_snmpdll());
  lcrzo_conf_fprint(pf);

  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_dev+routes_snmpdll+verify\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_dev_snmpdll());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_snmpdll());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_system_verify_routes(ptrcv));
  lcrzo_conf_fprint(pf);
  lcrzo_priv_conf_devicenumbername_debug_fprint(pf);


  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_routes_NTregistery\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_NTregistery());
  lcrzo_conf_fprint(pf);

  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_dev+routes_NTregistery+verify\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_dev_NTregistery());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_NTregistery());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_system_verify_routes(ptrcv));
  lcrzo_conf_fprint(pf);


  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_routes_W9xregistery\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_W9xregistery());
  lcrzo_conf_fprint(pf);

  fprintf(pf, "\n\n++++++++++++++++++++++++++++++++\n");
  fprintf(pf, "Configuration obtained with lcrzo_priv_conf_init_dev+routes_W9xregistery+verify\n");
  lcrzo_conf_flush_system();
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_dev_W9xregistery());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_init_routes_W9xregistery());
  lcrzo_err_fprint(pf, lcrzo_priv_conf_system_verify_routes(ptrcv));
  lcrzo_conf_fprint(pf);

  return(LCRZO_ERR_OK);
}
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif

