#!/usr/bin/perl $debug = 0; BEGIN {push @INC, '/www/cgi-bin'}; use perlfunc; use channelmaps; # # load the config parms # read_postdata(); ($config = $parms{config}) or ($config = nvram_get("config") and -d "/etc/config.$config") or ($config = "mesh"); # convert the %parms into scalars for convenience if($parms{button_default}) { load_cfg("/etc/config.$config/_setup.default"); foreach(keys %cfg) { eval (sprintf "\$$_ = \"%s\"", quotemeta $cfg{$_}); } } else { foreach(keys %parms) { next unless /^\w+$/; $parms{$_} =~ s/^\s+//; $parms{$_} =~ s/\s+$//; eval (sprintf "\$$_ = \"%s\"", quotemeta $parms{$_}); } if($button_reset or $config ne $oldconfig) { load_cfg("/etc/config.$config/_setup"); foreach(keys %cfg) { eval (sprintf "\$$_ = \"%s\"", quotemeta $cfg{$_}); } } } if($parms{button_reset} or $parms{button_default} or (not $nodetac and not keys %parms)) { $nodetac = nvram_get("node"); $tactical = nvram_get("tactical"); $nodetac .= " / $tactical" if $tactical; } else { $nodetac = $parms{nodetac}; } # make sure unchecked checkboxes are accounted for foreach(qw(lan_dhcp olsrd_bridge olsrd_gw wifi_hidden)) { $parms{$_} = 0 unless $parms{$_}; } # lan is always static $lan_proto = "static"; # enforce direct mode settings # (formerly known as dmz mode) $dmz_mode = 0 unless $config eq "mesh"; $dmz_mode = 2 if $dmz_mode != 0 and $dmz_mode < 2; $dmz_mode = 4 if $dmz_mode > 4; if($dmz_mode) { $ipshift = (ip2decimal($wifi_ip) << $dmz_mode) & 0xffffff; $dmz_lan_ip = add_ip_address("1" . decimal2ip($ipshift), 1); $dmz_lan_mask = decimal2ip(0xffffffff << $dmz_mode); ($octet) = $dmz_lan_ip =~ /\d+\.\d+\.\d+\.(\d+)/; $dmz_dhcp_start = $octet + 1; $dmz_dhcp_end = $dmz_dhcp_start + (1 << $dmz_mode) - 4; $parms{dmz_lan_ip} = $dmz_lan_ip; $parms{dmz_lan_mask} = $dmz_lan_mask; $parms{dmz_dhcp_start} = $dmz_dhcp_start; $parms{dmz_dhcp_end} = $dmz_dhcp_end; } # derive values which are not explicitly defined $parms{dhcp_limit} = $dhcp_limit = $dhcp_end - $dhcp_start; $parms{dmz_dhcp_limit} = $dmz_dhcp_limit = $dmz_dhcp_end - $dmz_dhcp_start; # # get the active wifi settings on a fresh page load # unless($parms{reload}) { ($wifi_txpower) = `iwinfo wlan0 info 2>/dev/null` =~ /Tx-Power: (\d+)/; (my $doesiwoffset) = `iwinfo wlan0 info 2>/dev/null` =~ /TX power offset: (\d+)/; if ( $doesiwoffset ) { $wifi_txpower -= $1; } if (wifi_useschains()){ $wifi_txant = `cat /sys/kernel/debug/ieee80211/phy0/ath9k/tx_chainmask`; $wifi_rxant = `cat /sys/kernel/debug/ieee80211/phy0/ath9k/rx_chainmask`; $wifi_txant = hex($wifi_txant); $wifi_rxant = hex($wifi_rxant); } else { foreach ( `iw phy phy0 info` ) { next unless /Configured Antennas: TX 0x([\d]+) RX 0x([\d]+)/; $wifi_txant = $1; $wifi_rxant = $2; } } $slottime = ""; } # sanitize the active settings $valid_ant = wifi_validant(); $wifi_txpower = wifi_maxpower() if not defined $wifi_txpower or $wifi_txpower > wifi_maxpower(); $wifi_txpower = 1 if $wifi_txpower < 1; $wifi_rxant = wifi_defaultant() if not defined $wifi_rxant or not exists $valid_ant->{$wifi_rxant}; $wifi_txant = wifi_defaultant() if not defined $wifi_txant or not exists $valid_ant->{$wifi_txant}; $wifi_distance = 0 unless defined $wifi_distance; $wifi_distance = 0 if $wifi_distance =~ /\D/; # stuff the sanitized data back into the parms hash # so they get saved correctly $parms{wifi_distance} = $wifi_distance; $parms{wifi_txpower} = $wifi_txpower; $parms{wifi_txant} = $wifi_txant; $parms{wifi_rxant} = $wifi_rxant; # # apply the wifi settings # if($parms{button_apply} or $parms{button_save}) { $cmd = ""; if(wifi_useschains()){ $cmd .= "echo $wifi_rxant > /sys/kernel/debug/ieee80211/phy0/ath9k/rx_chainmask;"; $cmd .= "echo $wifi_txant > /sys/kernel/debug/ieee80211/phy0/ath9k/tx_chainmask;"; } else { $cmd .= "ifdown wifi >/dev/null 2>&1;"; $cmd .= "ifdown wifi_mon >/dev/null 2>&1;"; $cmd .= "iw phy phy0 set antenna $wifi_txantenna $wifi_rxantenna >/dev/null 2>&1;"; $cmd .= "ifup wifi >/dev/null 2>&1;"; $cmd .= "ifup wifi_mon >/dev/null 2>&1;"; } $cmd .= "iw phy phy0 set distance $wifi_distance >/dev/null 2>&1;"; $cmd .= "iw dev wlan0 set txpower fixed ${wifi_txpower}00 >/dev/null 2>&1;"; system $cmd; } # validate and save configuration @errors = (); if($parms{button_save}) { if($wifi_proto eq "static") { if(not validate_netmask($wifi_mask)) { push @errors, "invalid WiFi netmask"; } elsif(not validate_ip_netmask($wifi_ip, $wifi_mask)) { push @errors, "invalid WiFi IP address"; } } push (@errors, "invalid WiFi SSID") unless length $wifi_ssid <= 32; if ( is_channel_valid($wifi_channel) != 1 ) { push (@errors, "invalid WiFi channel") } push (@errors, "invalid WiFi distance") if $wifi_distance < 0 or $wifi_distance =~ /\D/; $wifi_country_validated=0; foreach my $testcountry (split(',',"00,HX,AD,AE,AL,AM,AN,AR,AT,AU,AW,AZ,BA,BB,BD,BE,BG,BH,BL,BN,BO,BR,BY,BZ,CA,CH,CL,CN,CO,CR,CY,CZ,DE,DK,DO,DZ,EC,EE,EG,ES,FI,FR,GE,GB,GD,GR,GL,GT,GU,HN,HK,HR,HT,HU,ID,IE,IL,IN,IS,IR,IT,JM,JP,JO,KE,KH,KP,KR,KW,KZ,LB,LI,LK,LT,LU,LV,MC,MA,MO,MK,MT,MY,MX,NL,NO,NP,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PR,QA,RO,RS,RU,RW,SA,SE,SG,SI,SK,SV,SY,TW,TH,TT,TN,TR,UA,US,UY,UZ,VE,VN,YE,ZA,ZW")) { if ( $testcountry eq $wifi_country ) { $wifi_country_validated=1; break; } } if ( $wifi_country_validated ne 1 ) { $wifi_country="00"; push (@errors, "Invalid country"); } if($lan_proto eq "static") { if(not validate_netmask($lan_mask)) { push @errors, "invalid LAN netmask"; } elsif($lan_mask !~ /^255\.255\.255\./) { push @errors, "LAN netmask must begin with 255.255.255"; } elsif(not validate_ip_netmask($lan_ip, $lan_mask)) { push @errors, "invalid LAN IP address"; } else { if($lan_dhcp) { my $start_addr = change_ip_address($lan_ip, $dhcp_start); my $end_addr = change_ip_address($lan_ip, $dhcp_end); unless(validate_ip_netmask($start_addr, $lan_mask) and validate_same_subnet($start_addr, $lan_ip, $lan_mask)) { push @errors, "invalid DHCP start address"; } unless(validate_ip_netmask($end_addr, $lan_mask) and validate_same_subnet($end_addr, $lan_ip, $lan_mask)) { push @errors, "invalid DHCP end address"; } if($dhcp_start > $dhcp_end) { push @errors, "invalid DHCP start/end addresses"; } } if($lan_gw and not (validate_ip_netmask($lan_gw, $lan_mask) and validate_same_subnet($lan_ip, $lan_gw, $lan_mask))) { push @errors, "invalid LAN gateway"; } } } if($wan_proto eq "static") { if(not validate_netmask($wan_mask)) { push @errors, "invalid WAN netmask"; } elsif(not validate_ip_netmask($wan_ip, $wan_mask)) { push @errors, "invalid WAN IP address"; } else { unless (validate_ip_netmask($wan_gw, $wan_mask) and validate_same_subnet($wan_ip, $wan_gw, $wan_mask)) { push @errors, "invalid WAN gateway"; } } } push (@errors, "invalid WAN DNS 1") unless validate_ip($wan_dns1); push (@errors, "invalid WAN DNS 2") if $wan_dns2 ne "" and not validate_ip($wan_dns2); if($passwd1 or $passwd2) { push (@errors, "passwords do not match") if $passwd1 ne $passwd2; push (@errors, "passwords cannot contain '#'") if $passwd1 =~ /#/; push (@errors, "password must be changed") if $passwd1 eq "hsmm"; } elsif(-f "/etc/config/unconfigured") { push @errors, "password must be changed during initial configuration"; } if($aprs_lat or $aprs_lon) { push (@errors, "invalid latitude") unless validate_latitude($aprs_lat); push (@errors, "invalid longitude") unless validate_longitude($aprs_lon); } if($nodetac =~ /\//) { $nodetac =~ /^\s*([\w\-]+)\s*\/\s*([\w\-]+)\s*$/; $node = $1; $tactical = $2; push(@errors, "invalid node/tactical name") if not $2; } else { $node = $nodetac; $tactical = ""; push(@errors, "you must set the node name") if $node eq ""; } if($node and ($node =~ /[^\w\-]/ or $node =~ /_/)) { push(@errors, "invalid node name"); } if($tactical =~ /[^\w\-]/ or $tactical =~ /_/) { push(@errors, "invalid tactical name"); } if($debug == 3) # don't save the config, just validate it { push (@errors, "OK") unless @errors; } unless(@errors) { $parms{node} = $node; $parms{tactical} = $tactical; system "touch /tmp/unconfigured" if -f "/etc/config/unconfigured"; $rc = save_setup("/etc/config.$config/_setup"); if(-s "/tmp/web/save/node-setup.out") { push @errors, `cat /tmp/web/save/node-setup.out`; } elsif(not $rc) { push @errors, "error saving setup"; } reboot_page("/cgi-bin/status") if -f "/tmp/unconfigured" and not @errors; } } system "rm -rf /tmp/web/save"; reboot_page("/cgi-bin/status") if $parms{button_reboot}; # # generate the page # http_header() unless $debug == 2; html_header(nvram_get("node") . " setup", 1); print "