#!/usr/bin/perl -w
#
# Copyright 2005 Stichting Wireless Leiden
# maart 2004 rick@wirelessleiden.nl
#

# Config located at other file
my $conf_file="./genesis.conf";
do($conf_file) || die("Cann't open $conf_file");
################ END OF CONFIG ##########################

#variablen
my $time=gmtime();
my $source=`/bin/hostname`;
chomp($source);


#slurp IP berekeningen info
do ("$IP_pmPath") || die ("Cann't open $IP_pmPath");
#slurp dns info
#do ("$dnsheader_confPath") || die ("Cann't open $dnsheader_confPath");


#zoek uit of het master_ip addr voorkomt in de configs
#belangrijk van aliassen
sub master_ipNotUsed {
  if( $debug ) {
    print "running master_ipNotUsed...\n";
  }
  foreach my $if (keys %config) {
    if( $IP{$if} =~ /([0-9\.]+).*/ ) {
      if( $1 eq $master_ip ) {
        return(0);
      };
    };
  };
  return(1);
};



sub genHeader {
  my $comment = $_[0];
  my $output =
  "$comment This file specific to wireless\n" .
  "$comment leiden. Please make all changes in Genesis.\n" .
  "$comment\n" .
  "$comment Generated by $source\n" .
  "$comment on $time\n" .
  "$comment\n" .
  "$comment  $author\n" .
  "$comment\n\n\n";
  return ($output);
};


sub txtconfig {
  my $output = "";
  foreach $interface (keys %config) {
    $output .= $config{$interface};
  };
  return($output);
};


sub dnsmasq_conf {
  my $output = genHeader("#");
  $output .=
    "# DHCP server options \n" .
    "dhcp-authoritative \n" .
    "dhcp-fqdn \n" .
    "domain=dhcp.$nodename.$domain. \n" .
    "domain-needed \n" .
    "expand-hosts \n" .
    "\n" .
    "# Low memory footprint \n" .
    "cache-size=10000 \n" .
    "\n";

  foreach my $interface (sort keys %config) {
    if( $interface =~ /^[a-z]+[0-9]+$/i ) {
      (my $ip, my $netmask) = split('/', $IP{$interface});
      my $subnet = IP::toSubnet($netmask);
      
      $output .=
      "## $interface $DESC{$interface}\n";
      
      if ( $DHCP{$interface} =~ /[0-9]+\-[0-9]+/i ) {
        my $dhcp_part = $ip;
        $dhcp_part =~ s/[0-9]+$//;
        (my $dhcp_start, my $dhcp_stop) = $DHCP{$interface} =~ /([0-9]+)\-([0-9]+)/i;
        $dhcp_start = $dhcp_part . $dhcp_start;
        $dhcp_stop = $dhcp_part . $dhcp_stop;
        $output .= "dhcp-range=$interface,$dhcp_start,$dhcp_stop,$subnet,4h\n";
        foreach my $dhcp_static (split(';', $DHCP_STATIC{$interface})) {
          $output .= "dhcp-host=$dhcp_static\n";
        };
        $output .= "\n";
      }
      else {
       $output .= "# not autoritive \n\n";
      };

    };
  };
  
  return($output);
};


sub dhcpd_conf {
  my $output = genHeader("#");
  $output .=
  "option domain-name \"$domain\";\n" .
  " \n" .
  "default-lease-time 7200;\n" .
  "max-lease-time 2592000;\n" .
  "\n" .
  "ddns-update-style none;\n" .
  "\n" .
  "# Hack for the WET11\n" .
  "#\n" .
  "always-broadcast on;\n" .
  "\n" .
  "option domain-name-servers ${master_ip};\n" .
  "\n";

  foreach my $interface (sort keys %config) {
    if( $interface =~ /^[a-z]+[0-9]+$/i ) {
      (my $ip, my $netmask) = split('/', $IP{$interface});
      my $subnet = IP::toSubnet($netmask);
      my $broadcast = IP::getBroadcastAddr($ip, $subnet);
      my $network = IP::getNetworkAddr($ip, $subnet);
      
      $output .=
      "# $interface $DESC{$interface}\n";
      
      if ( $DHCP{$interface} =~ /[0-9]+\-[0-9]+/i ) {
        my $dhcp_part = $ip;
        $dhcp_part =~ s/[0-9]+$//;
        (my $dhcp_start, my $dhcp_stop) = $DHCP{$interface} =~ /([0-9]+)\-([0-9]+)/i;
        $dhcp_start = $dhcp_part . $dhcp_start;
        $dhcp_stop = $dhcp_part . $dhcp_stop;
        $output .=
        "subnet $network netmask $subnet {\n" .
        "  range $dhcp_start $dhcp_stop;\n" .
        "  option broadcast-address $broadcast;\n" .
        "  option subnet-mask $subnet;\n" .
        "  option routers $ip;\n" .
	$DHCP_STATIC{$if} .
        "}\n" .
        "\n";
      }
      else {
       $output .=
       "subnet $network netmask $subnet {not authoritative; }\n" .
       "\n";
      };
    };
  };
  
  return($output);
};

sub named_conf {
  my $output = genHeader("#");
  $output .=
  "options {\n" .
  "  directory \"/etc/namedb\"\;\n" .
  "  pid-file \"/var/run/named/pid\"\;\n" .
  "  forwarders {\n";
  foreach my $forward (@forwarder) {
    $output .= "$forward;\n";
  };
  $output .= 
  "  };\n" .
  "};\n" .
  "\n" .
  "\n" .
  "zone \"\.\" {\n" .
  "  type hint;\n" .
  "  file \"/etc/namedb/named.root\"\;\n" .
  "}\;\n" .
  "\n" .
  "zone \"0\.0\.127\.IN-ADDR.ARPA\" {\n" .
  "  type master\;\n" .
  "  file \"/etc/namedb/master/localhost.rev\"\;\n" .
  "}\;\n" .
  "\n" .
  "zone \"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.INT\" {\n" .
  "  type master\;\n" .
  "  file \"/etc/namedb/master/localhost-v6.rev\"\;\n" .
  "};\n" .
  "\n";


  foreach my $tmpZone (sort keys %zone) {
    my $dnsZone = $zone{$tmpZone};
    $output .= 
    "zone \"$tmpZone\" {\n" .
    "  type slave\;\n" .
    "  file \"slave/slave-$tmpZone\"\;\n" .
    "  masters {\n";
    foreach my $tmpIP (sort @$dnsZone) {
      $output .= "    $tmpIP\;\n";
    };
    $output .= 
    "  };\n" .
    "};\n" .
    "\n";
  };
  
  return($output);
};

sub wleiden_conf {
  # Generate our header
  my $output = genHeader("#");

  # Get al proxies
  opendir(BIN, $ndir) or die "Can't open $dir: $!";
  @proxyfiles = grep(/proxy/, readdir(BIN));
  closedir(BIN);

  # Walk through all our config files and get master_ip (and are up)
  @proxies = ();
  foreach $file (@proxyfiles) {
    $nfile = "$ndir/$file/wleiden.conf";
    parse_config($nfile);
    if ($status == "up") {
      $proxies[$proxyid] = $master_ip;
    }
  }

  # Print the Ip's in shell variable script format
  $output .= "PROXIES=`cat <<EOF\n";
  foreach $ip (@proxies) {
    if ($ip) {
      $output .= "$ip\n";
    }
  }
  $output .= "`\n";
}

sub rc_conf_local {
  my $output = genHeader("#");
  my $masterNotUsed = master_ipNotUsed();
  $output.=
  "hostname=\"$nodetype$nodename.$domain\"\n" .
  "location=\"$location\"\n" .
  "\n";

  if( $tproxy ) {
    if( $tproxy =~ m/\d+\.\d+\.\d+\.\d+\/\d+/ ) {
      $output .=
      "# Tproxy is ran on this system\n".
      "tproxy_enable='YES'\n".
      "tproxy_range='$tproxy'\n".
      "\n";
    }
    elsif( $tproxy !~ m/no/i ) {
      $output .= "# WARNING - specification propably wrong - check " .
      "genesis. It should be a pure CIDR\n";
    };
  };
  
  $iplist = "172.31.255.1/32";
  if( $masterNotUsed ) {
    $iplist .= " $master_ip/32";
  }
  $output .= "ipv4_addrs_lo0=\"127.0.0.1/8 $iplist\"\n";

  @whitelist = ();
  @dhcp_interfaces = ();
  $WLAN_NR = 0;
  foreach my $interface (sort keys %config) {
    (my $if, my $number) = split(/:/, $interface);
      if( not defined $number ) {
        # No special syntax for aliases anymore
        $IFNAME = $if;
        if( $TYPE{$if} =~ /wireless/i ) {
          $IFNAME = "wlan$WLAN_NR";
          $WLAN_NR++;
          $output .= "wlans_$if=\"$IFNAME\"\n";
          $output .= "create_args_$IFNAME=\"";
   	  if( $MODE{$if} =~/master/i ) {
            $output .= "wlanmode ap";
          } else {
            $output .= "wlanmode sta"
          }
          if ( $SUBTYPE{$if} =~ /802.11a/i ) {
            $output .= " mode 11a";
          } elsif ( $SUBTYPE{$if} =~ /802.11g/i ) {
            $output .= " mode 11g";
          } else {
            # Default output
            $output .= " mode 11b";
          }
          $output .= " ssid $ESSID{$interface} regdomain ETSI country NL";
   	  if( $MODE{$if} =~/master/i ) {
            $output .= " channel $CHANNEL{$interface}";
          }
          $output .= "\"\n";
        }

        if ( $CAPTIVE_PORTAL_WHITELIST{$if} ) {
          push(@whitelist, $CAPTIVE_PORTAL_WHITELIST{$if});
        }
        if ($DHCP{$if} =~ /[0-9]+\-[0-9]+/i) {
          push(@dhcp_interfaces, $IFNAME);
        }

        @iplist = ();
        foreach my $interface (sort keys %config) {
          (my $if_t, my $number) = split(/:/, $interface);
            if ( $if_t eq $if ) {
                push(@iplist,$IP{$interface});
            };
        };
        $output .= "ipv4_addrs_$IFNAME=\"" . join(' ',@iplist) . "\"\n";
        $output .= "\n";
      };
  };
  $output .= "\ncaptive_portal_whitelist=\"" .join(' ',@whitelist) . "\"\n";
  $output .= "captive_portal_interfaces=\"" .join(' ',@dhcp_interfaces) . "\"\n";
  return($output);
};


sub resolv_conf {
  my $output = genHeader"#";

  $output .= 
  "search wleiden.net\n" .
  "# Try local (cache) first \n" .
  "nameserver 127.0.0.1\n" .
  "\n";

  $output .=
  "# proxies are also nameservers \n" .
  "nameserver 172.17.8.68    # proxy1\n" .
  "nameserver 172.17.143.4   # proxy2\n" .
  "nameserver 172.20.128.98  # proxy3\n" .
  "nameserver 172.16.2.254   # proxy4\n" .
  "nameserver 172.19.168.66  # proxy5\n" .
  "nameserver 172.16.3.146   # proxy6\n" .
  "nameserver 172.17.16.66   # proxy62\n" .
  "nameserver 172.17.0.1     # proxy7\n" .
  "nameserver 172.16.4.54    # proxy9\n" .
  "nameserver 172.22.0.66    # proxy10\n" .
  "nameserver 172.23.25.66   # proxy11\n" .
  "nameserver 172.17.169.66  # proxy97\n";

  return($output);
};


sub parse_config {
  my $workingfile = $_[0];
  do($workingfile) || die("Cann't open/parse $workingfile");
  foreach my $if (keys %config) {
    my $cfg=$config{$if};
    while ($cfg) {
      $cfg=~s/^([^\n\r]+)[\r\n]*//m;
      my $line=$1;
      $line=~s/\s*#.*//;
      if (((my $name, my $value)=split(/=/,$line)) eq 2) {
        my $doit="if (exists(\$$name\{\"$if\"\})) {\$$name\{\"$if\"\}.=\";$value\";} else {\$$name\{\"$if\"\}.=\"$value\";}";
        eval($doit);
      };
      $cfg=~s/[\r\n]*$//m;
    };
  };
};

sub authorized_keys {
  my $output = genHeader("#");
  if( -e "$global_keyPath" ) {
    open( GLOBAL, "$global_keyPath" ) || die ("Cann't open $global_keyPath");
      $output .= join("", <GLOBAL>);
    close( GLOBAL );
  }
  else {
    $output .= "# No $global_keyPath\n";
  };
 
  if( -e "$ndir/$nodetype$nodename/$ssh_file" ) {
    open( NODE, "$ndir/$nodetype$nodename/$ssh_file" ) || die ("Cann't open $home/$nodename/$ssh_file");
      $output .= join("", <NODE>);
    close( NODE );
  }
  else {
    $output .= "# No $ndir/$nodetype$nodename/$ssh_file\n";
  };
  
  return($output);
};

sub do_it {
  my $file = $_[0];
  my $body = "";
  
  $file =~ s/\./_/g;
  $body=&$file;
  return($body);
};

if( exists $ARGV[0] ) {
  if( exists $ARGV[1] ) {
    parse_config($ARGV[0]);
    print do_it($ARGV[1]);
  }
  else {
    print "Usage `perl wleiden.pl 'inputfile' 'outputfile'`\n";
  };
};

1;
