Ignore:
Timestamp:
05/15/13 16:17:00 (11 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Merge SQL changes and other miscellaneous fixes from /trunk through r553.

Location:
branches/stable
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/stable

  • branches/stable/cgi-bin/main.cgi

    r593 r594  
    6060# Use the connectDB function, otherwise we end up confusing ourselves
    6161my $ip_dbh;
    62 my $sth;
    6362my $errstr;
    6463($ip_dbh,$errstr) = connectDB_My;
     
    9089my $page;
    9190if (-e "$ENV{HTML_TEMPLATE_ROOT}/$webvar{action}.tmpl") {
    92   $page = HTML::Template->new(filename => "$webvar{action}.tmpl");
     91  $page = HTML::Template->new(filename => "$webvar{action}.tmpl", loop_context_vars => 1, global_vars => 1);
    9392} else {
    9493  $page = HTML::Template->new(filename => "dunno.tmpl");
     
    129128}
    130129elsif($webvar{action} eq 'listpool') {
    131   listPool();
     130  showPool();
    132131}
    133132
     
    155154}
    156155elsif ($webvar{action} eq 'nodesearch') {
    157   $sth = $ip_dbh->prepare("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id");
    158   $sth->execute() or $page->param(errmsg => $sth->errstr);
    159   my @nodelist;
    160   while (my ($nid,$nname) = $sth->fetchrow_array()) {
    161     my %row = (nodeid => $nid, nodename => $nname);
    162     push @nodelist, \%row;
    163   }
    164   $page->param(nodelist => \@nodelist);
     156  my $nodelist = getNodeList($ip_dbh);
     157  $page->param(nodelist => $nodelist);
    165158}
    166159
     
    201194}
    202195
    203 
    204196# Clean up IPDB globals, DB handle, etc.
    205197finish($ip_dbh);
     
    224216# Initial display:  Show master blocks with total allocated subnets, total free subnets
    225217sub showSummary {
    226   my %allocated;
    227   my %free;
    228   my %routed;
    229   my %bigfree;
    230 
    231   # Count the allocations.
    232   $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?");
    233   foreach my $master (@masterblocks) {
    234     $sth->execute("$master");
    235     $sth->bind_columns(\$allocated{"$master"});
    236     $sth->fetch();
    237   }
    238 
    239   # Count routed blocks
    240   $sth = $ip_dbh->prepare("select count(*) from routed where cidr <<= ?");
    241   foreach my $master (@masterblocks) {
    242     $sth->execute("$master");
    243     $sth->bind_columns(\$routed{"$master"});
    244     $sth->fetch();
    245   }
    246 
    247   # Count the free blocks.
    248   $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ? and ".
    249         "(routed='y' or routed='n')");
    250   foreach my $master (@masterblocks) {
    251     $sth->execute("$master");
    252     $sth->bind_columns(\$free{"$master"});
    253     $sth->fetch();
    254   }
    255 
    256   # Find the largest free block in each master
    257   $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? and ".
    258         "(routed='y' or routed='n') order by maskbits limit 1");
    259   foreach my $master (@masterblocks) {
    260     $sth->execute("$master");
    261     $sth->bind_columns(\$bigfree{"$master"});
    262     $sth->fetch();
    263   }
    264 
    265   # Assemble the data to stuff into the template.
    266   my @masterlist;
    267   my $rowclass=0;
    268   foreach my $master (@masterblocks) {
    269     my %row = (
    270         rowclass => $rowclass++ % 2,
    271         master => "$master",
    272         routed => $routed{"$master"},
    273         allocated => $allocated{"$master"},
    274         free => $free{"$master"},
    275         bigfree => ( ($bigfree{"$master"} eq '') ? ("&lt;NONE&gt;") : ("/".$bigfree{"$master"}) )
    276         );
    277     push (@masterlist, \%row);
    278   }
    279   $page->param(masterlist => \@masterlist);
     218  my $masterlist = listSummary($ip_dbh);
     219  $page->param(masterlist => $masterlist);
    280220
    281221  $page->param(addmaster => ($IPDBacl{$authuser} =~ /a/) );
    282 
    283222} # showSummary
    284223
     
    292231
    293232  $page->param(master => $webvar{block});
    294 
    295   my %allocated;
    296   my %free;
    297   my %cities;
    298   my %bigfree;
    299 
    300   my $master = new NetAddr::IP $webvar{block};
    301   my @localmasters;
    302 
    303   # Fetch only the blocks relevant to this master
    304   $sth = $ip_dbh->prepare("select cidr,city from routed where cidr <<= '$master' order by cidr");
    305   $sth->execute();
    306 
    307   my $i=0;
    308   while (my @data = $sth->fetchrow_array()) {
    309     my $cidr = new NetAddr::IP $data[0];
    310     $localmasters[$i++] = $cidr;
    311     $free{"$cidr"} = 0;
    312     $allocated{"$cidr"} = 0;
    313     $bigfree{"$cidr"} = 128;
    314     # Retain the routing destination
    315     $cities{"$cidr"} = $data[1];
    316   }
    317 
    318   # Check if there were actually any blocks routed from this master
    319   if ($i > 0) {
    320 
    321     # Count the allocations
    322     $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?");
    323     foreach my $master (@localmasters) {
    324       $sth->execute("$master");
    325       $sth->bind_columns(\$allocated{"$master"});
    326       $sth->fetch();
    327     }
    328 
    329     # Count the free blocks.
    330     $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ? and ".
    331         "(routed='y' or routed='n')");
    332     foreach my $master (@localmasters) {
    333       $sth->execute("$master");
    334       $sth->bind_columns(\$free{"$master"});
    335       $sth->fetch();
    336     }
    337 
    338     # Get the size of the largest free block
    339     $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? and ".
    340         "(routed='y' or routed='n') order by maskbits limit 1");
    341     foreach my $master (@localmasters) {
    342       $sth->execute("$master");
    343       $sth->bind_columns(\$bigfree{"$master"});
    344       $sth->fetch();
    345     }
    346 
    347     my @routed;
    348     my $rowclass = 0;
    349     foreach my $master (@localmasters) {
    350       my %row = (
    351         rowclass => $rowclass++ % 2,
    352         block => "$master",
    353         city => $cities{"$master"},
    354         nsubs => $allocated{"$master"},
    355         nfree => $free{"$master"},
    356         lfree => ( ($bigfree{"$master"} eq 128) ? ("&lt;NONE&gt;") : ("/".$bigfree{"$master"}) )
    357         );
    358       push @routed, \%row;
    359     }
    360     $page->param(routedlist => \@routed);
    361 
    362   } # end check for existence of routed blocks in master
    363 
    364233  $page->param(delmaster => ($IPDBacl{$authuser} =~ /d/));
    365234
    366   # Snag the free blocks.
    367   my $count = 0;
    368   $sth = $ip_dbh->prepare("select cidr from freeblocks where cidr <<='$master' and ".
    369         "routed='n' order by cidr");
    370   $sth->execute();
    371   my @unrouted;
    372   my $rowclass = 0;
    373   while (my @data = $sth->fetchrow_array()) {
    374     my $cidr = new NetAddr::IP $data[0];
    375     my %row = (
    376         rowclass => $rowclass++ % 2,
    377         fblock => "$cidr",
    378         frange => $cidr->range
    379         );
    380     push @unrouted, \%row;
    381   }
    382   $page->param(unrouted => \@unrouted);
    383 
     235  my $rlist = listMaster($ip_dbh, $webvar{block});
     236  $page->param(routedlist => $rlist);
     237
     238  my $flist = listFree($ip_dbh, $webvar{block});
     239  $page->param(unrouted => $flist);
    384240} # showMaster
    385241
     
    394250sub showRBlock {
    395251
    396   my $master = new NetAddr::IP $webvar{block};
    397 
    398   $sth = $ip_dbh->prepare("select city from routed where cidr='$master'");
    399   $sth->execute;
    400   my ($rcity) = $sth->fetchrow_array;
    401 
    402   $page->param(master => "$master");
     252  $page->param(master => $webvar{block});
     253  $page->param(delrouted => $IPDBacl{$authuser} =~ /d/);
     254
     255  my $rcity = getRoutedCity($ip_dbh, $webvar{block});
    403256  $page->param(rcity => $rcity);
    404257
    405   # Snag the allocations for this block
    406   $sth = $ip_dbh->prepare("select cidr,city,type,custid,swip,description".
    407         " from allocations where cidr <<= '$master' order by cidr");
    408   $sth->execute();
    409 
    410   # hack hack hack
    411   # set up to flag swip=y records if they don't actually have supporting data in the customers table
    412   my $custsth = $ip_dbh->prepare("select count(*) from customers where custid=?");
    413 
    414   my $rowclass = 0;
    415   my @blocklist;
    416   while (my ($cidr,$city,$type,$custid,$swip,$desc) = $sth->fetchrow_array()) {
    417     $custsth->execute($custid);
    418     my ($ncust) = $custsth->fetchrow_array();
    419 
    420     my %row = (
    421         rowclass => $rowclass++ % 2,
    422         block => $cidr,
    423         city => $city,
    424         type => $disp_alloctypes{$type},
    425         custid => $custid,
    426         swip => ($swip eq 'y' ? ($ncust == 0 ? 'Yes<small>*</small>' : 'Yes') : 'No'),
    427         desc => $desc
    428         );
    429     $row{subblock} = ($type =~ /^.r$/);         # hmf.  wonder why these won't work in the hash declaration...
    430     $row{listpool} = ($type =~ /^.[pd]$/);
    431     push (@blocklist, \%row);
    432   }
    433   $page->param(blocklist => \@blocklist);
    434 
    435   $page->param(delrouted => $IPDBacl{$authuser} =~ /d/);
    436 
    437   # Snag the free blocks.  We don't really *need* to be pedantic about avoiding
    438   # unrouted free blocks, but it's better to let the database do the work if we can.
    439   $rowclass = 0;
    440   my @unassigned;
    441   $sth = $ip_dbh->prepare("select cidr,routed from freeblocks where cidr <<= '$master'".
    442         " order by cidr");
    443   $sth->execute();
    444   while (my ($cidr_db,$routed) = $sth->fetchrow_array()) {
    445     my $cidr = new NetAddr::IP $cidr_db;
    446 
    447     my %row = (
    448         rowclass => $rowclass++ % 2,
    449         subblock => ($routed ne 'y' && $routed ne 'n'),
    450         fblock => $cidr_db,
    451         fbtype => $routed,
    452         frange => $cidr->range,
    453         );
    454     push @unassigned, \%row;
    455   }
    456   $page->param(unassigned => \@unassigned);
    457 
     258  my $blist = listRBlock($ip_dbh, $webvar{block});
     259  $page->param(blocklist => $blist);
     260
     261  my $flist = listFree($ip_dbh, $webvar{block}, 'y');
     262  $page->param(unassigned => $flist);
    458263} # showRBlock
    459264
    460265
    461266# List the IPs used in a pool
    462 sub listPool {
     267sub showPool {
    463268
    464269  my $cidr = new NetAddr::IP $webvar{pool};
     
    473278
    474279  # Snag pool info for heading
    475   $sth = $ip_dbh->prepare("select type,city from allocations where cidr=?");
    476   $sth->execute($webvar{pool});
    477   my ($pooltype, $poolcity) = $sth->fetchrow_array;
    478 
    479   $page->param(disptype => $disp_alloctypes{$pooltype});
    480   $page->param(city => $poolcity);
     280  my $poolinfo = getBlockData($ip_dbh, $webvar{pool});
     281
     282  $page->param(disptype => $disp_alloctypes{$poolinfo->{type}});
     283  $page->param(city => $poolinfo->{city});
    481284
    482285  # Only display net/gw/bcast if it's a "real" netblock and not a PPP(oE) lunacy
    483   $page->param(realblock => $pooltype =~ /^.d$/);
     286  $page->param(realblock => $poolinfo->{type} =~ /^.d$/);
    484287
    485288# probably have to add an "edit IP allocation" link here somewhere.
    486289
    487   $sth = $ip_dbh->prepare("select ip,custid,available,description,type".
    488         " from poolips where pool='$webvar{pool}' order by ip");
    489   $sth->execute;
    490   my @poolips;
    491   my $rowclass = 0;
    492   while (my ($ip,$custid,$available,$desc,$type) = $sth->fetchrow_array) {
    493     my %row = (
    494         rowclass => $rowclass++ % 2,
    495         ip => $ip,
    496         custid => $custid,
    497         available => $available,
    498         desc => $desc,
    499         maydel => $IPDBacl{$authuser} =~ /d/,
    500         delme => $available eq 'n'
    501         );
    502     push @poolips, \%row;
    503   }
    504   $page->param(poolips => \@poolips);
    505 
    506 } # end listPool
     290  my $plist = listPool($ip_dbh, $webvar{pool});
     291  # technically slightly more efficient to check the ACL in an if () once outside the foreach
     292  foreach (@{$plist}) {
     293    $$_{maydel} = $IPDBacl{$authuser} =~ /d/;
     294  }
     295  $page->param(poolips => $plist);
     296} # end showPool
    507297
    508298
     
    535325    if ($webvar{fbtype} ne 'y') {
    536326      # Snag the type of the container block from the database.
    537       $sth = $ip_dbh->prepare("select type from allocations where cidr >>='$block'");
    538       $sth->execute;
    539       my @data = $sth->fetchrow_array;
    540       $data[0] =~ s/c$/r/;      # Munge the type into the correct form
    541       $page->param(fbdisptype => $list_alloctypes{$data[0]});
    542       $page->param(type => $data[0]);
     327## hmm.  need a flag for parent class/type, sort of?
     328      my $pblock = subParent($ip_dbh, $webvar{block});
     329      my $ptype = $pblock->{type};
     330      $ptype =~ s/c$/r/;
     331      $page->param(fbdisptype => $list_alloctypes{$ptype});
     332      $page->param(type => $ptype);
    543333    } else {
    544       $sth = $ip_dbh->prepare("select type,listname from alloctypes where listorder < 500 ".
    545         "and type not like '_i' order by listorder");
    546       $sth->execute;
    547       my @typelist;
    548       my $selflag = 0;
    549       while (my @data = $sth->fetchrow_array) {
    550         my %row = (tval => $data[0],
    551                 type => $data[1],
    552                 sel => ($selflag == 0 ? ' selected' : '')
    553                 );
    554         push (@typelist, \%row);
    555         $selflag++;
    556       }
    557       $page->param(typelist => \@typelist);
     334      # get "primary" alloctypes, since these are all that can correctly be assigned if we're in this branch
     335      my $tlist = getTypeList($ip_dbh, 'p');
     336      $tlist->[0]->{sel} = 1;
     337      $page->param(typelist => $tlist);
    558338    }
    559339  } else {
    560     my @masterlist;
    561     foreach my $master (@masterblocks) {
    562       my %row = (master => "$master");
    563       push (@masterlist, \%row);
    564     }
    565     $page->param(masterlist => \@masterlist);
     340    my $mlist = getMasterList($ip_dbh, 'c');
     341    $page->param(masterlist => $mlist);
    566342
    567343    my @pops;
     
    572348    $page->param(pops => \@pops);
    573349
    574     # could arguably include routing (500) in the list, but ATM it doesn't
    575     # make sense, and in any case that shouldn't be structurally possible here.
    576     $sth = $ip_dbh->prepare("select type,listname from alloctypes where listorder <= 500 order by listorder");
    577     $sth->execute;
    578     my @typelist;
    579     my $selflag = 0;
    580     while (my @data = $sth->fetchrow_array) {
    581       my %row = (tval => $data[0],
    582         type => $data[1],
    583         sel => ($selflag == 0 ? ' selected' : '')
    584         );
    585       push (@typelist, \%row);
    586       $selflag++;
    587     }
    588     $page->param(typelist => \@typelist);
     350    # get all standard alloctypes
     351    my $tlist = getTypeList($ip_dbh, 'a');
     352    $tlist->[0]->{sel} = 1;
     353    $page->param(typelist => $tlist);
    589354  }
    590355
     
    597362
    598363## node hack
    599   $sth = $ip_dbh->prepare("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id");
    600   $sth->execute() or print "DEBUG: failed retrieval from nodes: ".$sth->errstr,"<br>\n";
    601   my @nodes;
    602   while (my ($nid,$nname) = $sth->fetchrow_array()) {
    603     my %row = (nid => $nid, nname => $nname);
    604     push (@nodes, \%row);
    605   }
    606   $page->param(nodelist => \@nodes);
     364  my $nlist = getNodeList($ip_dbh);
     365  $page->param(nodelist => $nlist);
    607366## end node hack
    608367
     
    632391
    633392  if ($webvar{alloctype} =~ /^.i$/ && $webvar{fbassign} ne 'y') {
    634     my ($base,undef) = split //, $webvar{alloctype};    # split into individual chars
    635 
    636 # Ewww.  But it works.
    637     $sth = $ip_dbh->prepare("SELECT (SELECT city FROM allocations WHERE cidr=poolips.pool), ".
    638         "poolips.pool, COUNT(*) FROM poolips,allocations WHERE poolips.available='y' AND ".
    639         "poolips.pool=allocations.cidr AND allocations.city='$webvar{pop}' AND poolips.type LIKE '".$base."_' ".
    640         "GROUP BY pool");
    641     $sth->execute;
    642     my $optionlist;
    643 
    644     my @poollist;
    645     while (my ($poolcit,$poolblock,$poolfree) = $sth->fetchrow_array) {
    646       # city,pool cidr,free IP count
    647       if ($poolfree > 0) {
    648         my %row = (poolcit => $poolcit, poolblock => $poolblock, poolfree => $poolfree);
    649         push (@poollist, \%row);
    650       }
    651     }
     393    my $plist = getPoolSelect($ip_dbh, $webvar{alloctype}, $webvar{pop});
    652394    $page->param(staticip => 1);
    653     $page->param(poollist => \@poollist);
     395    $page->param(poollist => $plist) if $plist;
    654396    $cidr = "Single static IP";
    655397##fixme:  need to handle "no available pools"
     
    657399  } else { # end show pool options
    658400
    659     if ($webvar{fbassign} eq 'y') {
     401    if ($webvar{fbassign} && $webvar{fbassign} eq 'y') {
    660402      $alloc_from = new NetAddr::IP $webvar{allocfrom};
    661403## possibly messy behaviour:  force the _from and block to be the network addr?
     
    669411        return;
    670412      }
    671       my $sql;
    672       my $city;
    673       my $failmsg;
    674       my $extracond = '';
    675       if ($webvar{allocfrom} eq '-') {
    676         $extracond = ($webvar{allowpriv} eq 'on' ? '' :
    677                 " and not (cidr <<= '192.168.0.0/16'".
    678                         " or cidr <<= '10.0.0.0/8'".
    679                         " or cidr <<= '172.16.0.0/12')");
    680       }
    681       my $sortorder;
     413
     414##fixme ick, ew, bleh.  gotta handle the failure message generation better.  push it into findAllocateFrom()?
     415      my $failmsg = "No suitable free block found.<br>\n";
    682416      if ($webvar{alloctype} eq 'rm') {
    683         if ($webvar{allocfrom} ne '-') {
    684           $sql = "select * from freeblocks where maskbits<=$webvar{maskbits} and routed='n'".
    685                 " and cidr <<= '$webvar{allocfrom}'";
    686           $sortorder = "maskbits desc";
    687         } else {
    688           $sql = "select * from freeblocks where maskbits<=$webvar{maskbits} and routed='n'";
    689           $sortorder = "maskbits desc";
    690         }
    691         $failmsg = "No suitable free block found.<br>\nWe do not have a free".
    692           " routeable block of that size.<br>\nYou will have to either route".
    693           " a set of smaller netblocks or a single smaller netblock.";
     417        $failmsg .= "We do not have a free routeable block of that size.<br>\n".
     418                "You will have to either route a set of smaller netblocks or a single smaller netblock.";
    694419      } else {
    695 ##fixme
    696 # This section needs serious Pondering.
    697         # Pools of most types get assigned to the POP they're "routed from"
    698         # This includes WAN blocks and other netblock "containers"
    699         # This does NOT include cable pools.
    700420        if ($webvar{alloctype} =~ /^.[pc]$/) {
    701           $city = $webvar{city};
    702           $failmsg = "No suitable free block found.<br>\nYou will have to route another".
    703             " superblock from one of the<br>\nmaster blocks or chose a smaller".
    704             " block size for the pool.";
     421          $failmsg .= "You will have to route another superblock from one of the<br>\n".
     422                "master blocks or chose a smaller block size for the pool.";
    705423        } else {
    706424          if (!$webvar{pop}) {
     
    708426            return;
    709427          }
    710           $city = $webvar{pop};
    711           $failmsg = "No suitable free block found.<br>\nYou will have to route another".
    712             " superblock to $webvar{pop}<br>\nfrom one of the master blocks or".
    713             " chose a smaller blocksize.";
    714         }
    715         if (defined $webvar{allocfrom} && $webvar{allocfrom} ne '-') {
    716           $sql = "select cidr from freeblocks where city='$city' and maskbits<=$webvar{maskbits}".
    717                 " and cidr <<= '$webvar{allocfrom}' and routed='".
    718                 (($webvar{alloctype} =~ /^(.)r$/) ? "$1" : 'y')."'";
    719           $sortorder = "maskbits desc,cidr";
    720         } else {
    721           $sql = "select cidr from freeblocks where city='$city' and maskbits<=$webvar{maskbits}".
    722                 " and routed='".(($webvar{alloctype} =~ /^(.)r$/) ? "$1" : 'y')."'";
    723           $sortorder = "maskbits desc,cidr";
     428          $failmsg .= "You will have to route another superblock to $webvar{pop}<br>\n".
     429                "from one of the master blocks or chose a smaller blocksize.";
    724430        }
    725431      }
    726       $sql = $sql.$extracond." order by ".$sortorder;
    727       $sth = $ip_dbh->prepare($sql);
    728       $sth->execute;
    729       my @data = $sth->fetchrow_array();
    730       if ($data[0] eq "") {
     432
     433      $cidr = findAllocateFrom($ip_dbh, $webvar{maskbits}, $webvar{alloctype}, $webvar{city}, $webvar{pop},
     434        (master => $webvar{allocfrom}, allowpriv => $webvar{allowpriv}) );
     435      if (!$cidr) {
    731436        $page->param(err => $failmsg);
    732437        return;
    733438      }
    734       $cidr = new NetAddr::IP $data[0];
     439      $cidr = new NetAddr::IP $cidr;
    735440
    736441# this chunk now specific to "guided" allocation;  freeblock-select can now slice-n-dice on its own.
     
    754459## node hack
    755460  if ($webvar{node} && $webvar{node} ne '-') {
    756     $sth = $ip_dbh->prepare("SELECT node_name FROM nodes WHERE node_id=?");
    757     $sth->execute($webvar{node});
    758     my ($nodename) = $sth->fetchrow_array();
     461    my $nodename = getNodeName($ip_dbh, $webvar{node});
    759462    $page->param(nodename => $nodename);
    760463    $page->param(nodeid => $webvar{node});
     
    875578      return;
    876579    }
    877     if ($webvar{custid} !~ /^(?:\d{10}|\d{7}|STAFF)(?:-\d\d?)?$/) {
    878       # Force uppercase for now...
    879       $webvar{custid} =~ tr/a-z/A-Z/;
    880       # Crosscheck with billing.
    881       my $status = CustIDCK->custid_exist($webvar{custid});
    882       if ($CustIDCK::Error) {
    883         $page->param(err => "Error verifying customer ID: ".$CustIDCK::ErrMsg);
    884         return;
    885       }
    886       if (!$status) {
    887         $page->param(err => "Customer ID not valid.  Make sure the Customer ID ".
    888           "is correct.<br>\nUse STAFF for staff static IPs, and $IPDB::defcustid for any other ".
    889           "non-customer assignments.");
    890         return;
    891       }
     580    # Crosscheck with billing.
     581    my $status = CustIDCK->custid_exist($webvar{custid});
     582    if ($CustIDCK::Error) {
     583      $page->param(err => "Error verifying customer ID: ".$CustIDCK::ErrMsg);
     584      return;
     585    }
     586    if (!$status) {
     587      $page->param(err => "Customer ID not valid.  Make sure the Customer ID ".
     588        "is correct.<br>\nUse STAFF for staff static IPs, and $IPDB::defcustid for any other ".
     589        "non-customer assignments.");
     590      return;
    892591    }
    893592#    print "<!-- [ In validateInput().  Insert customer ID cross-check here. ] -->\n";
     
    913612##fixme:  hook to force-set POP or city on certain alloctypes
    914613# if ($webvar{alloctype =~ /foo,bar,bz/ { $webvar{pop} = 'blah'; }
    915     if ($webvar{pop} =~ /^-$/) {
     614    if ($webvar{pop} && $webvar{pop} =~ /^-$/) {
    916615      $flag = 'to route the block from/through';
    917616    }
     
    935634sub edit {
    936635
    937   my $sql;
    938 
    939   # Two cases:  block is a netblock, or block is a static IP from a pool
    940   # because I'm lazy, we'll try to make the SELECT's bring out identical)ish) data
    941 ##fixme:  allow "SWIP" (publication to rWHOIS) of static IP data
    942   if ($webvar{block} =~ /\/32$/) {
    943     $sql = "select ip,custid,type,city,circuitid,description,notes,modifystamp,privdata from poolips where ip='$webvar{block}'";
    944   } else {
    945     $sql = "select cidr,custid,type,city,circuitid,description,notes,modifystamp,privdata,swip from allocations where cidr='$webvar{block}'"
    946   }
    947 
    948   # gotta snag block info from db
    949   $sth = $ip_dbh->prepare($sql);
    950   $sth->execute;
    951   my @data = $sth->fetchrow_array;
    952 
    953   # Clean up extra whitespace on alloc type
    954   $data[2] =~ s/\s//;
    955 
    956   # We can't let the city be changed here;  this block is a part of
    957   # a larger routed allocation and therefore by definition can't be moved.
    958   # block and city are static.
    959 ##fixme
    960 # Needs thinking.  Have to allow changes to city to correct errors, no?
    961 # Also have areas where a routed block at a POP serves "many" cities/towns/named crossroads
    962 
    963 # @data: cidr,custid,type,city,circuitid,description,notes,modifystamp,privdata,swip
     636  # snag block info from db
     637  my $blockinfo = getBlockData($ip_dbh, $webvar{block});
     638
     639  # Clean up extra whitespace on alloc type.  Mainly a legacy-data cleanup.
     640  $blockinfo->{type} =~ s/\s//;
    964641
    965642  $page->param(block => $webvar{block});
    966643
    967   $page->param(custid => $data[1]);
    968   $page->param(city => $data[3]);
    969   $page->param(circid => $data[4]);
    970   $page->param(desc => $data[5]);
    971   $page->param(notes => $data[6]);
     644  $page->param(custid   => $blockinfo->{custid});
     645  $page->param(city     => $blockinfo->{city});
     646  $page->param(circid   => $blockinfo->{circuitid});
     647  $page->param(desc     => $blockinfo->{description});
     648  $page->param(notes    => $blockinfo->{notes});
    972649
    973650##fixme The check here should be built from the database
    974651# Need to expand to support pool types too
    975   if ($data[2] =~ /^.[ne]$/ && $IPDBacl{$authuser} =~ /c/) {
     652  if ($blockinfo->{type} =~ /^.[ne]$/ && $IPDBacl{$authuser} =~ /c/) {
    976653    $page->param(changetype => 1);
    977654    $page->param(alloctype => [
    978                 { selme => ($data[2] eq 'me'), type => "me", disptype => "Dialup netblock" },
    979                 { selme => ($data[2] eq 'de'), type => "de", disptype => "Dynamic DSL netblock" },
    980                 { selme => ($data[2] eq 'ce'), type => "ce", disptype => "Dynamic cable netblock" },
    981                 { selme => ($data[2] eq 'we'), type => "we", disptype => "Dynamic wireless netblock" },
    982                 { selme => ($data[2] eq 'cn'), type => "cn", disptype => "Customer netblock" },
    983                 { selme => ($data[2] eq 'en'), type => "en", disptype => "End-use netblock" },
    984                 { selme => ($data[2] eq 'in'), type => "in", disptype => "Internal netblock" },
     655                { selme => ($blockinfo->{type} eq 'me'), type => "me", disptype => "Dialup netblock" },
     656                { selme => ($blockinfo->{type} eq 'de'), type => "de", disptype => "Dynamic DSL netblock" },
     657                { selme => ($blockinfo->{type} eq 'ce'), type => "ce", disptype => "Dynamic cable netblock" },
     658                { selme => ($blockinfo->{type} eq 'we'), type => "we", disptype => "Dynamic wireless netblock" },
     659                { selme => ($blockinfo->{type} eq 'cn'), type => "cn", disptype => "Customer netblock" },
     660                { selme => ($blockinfo->{type} eq 'en'), type => "en", disptype => "End-use netblock" },
     661                { selme => ($blockinfo->{type} eq 'in'), type => "in", disptype => "Internal netblock" },
    985662                ]
    986663        );
    987664  } else {
    988     $page->param(disptype => $disp_alloctypes{$data[2]});
    989     $page->param(type => $data[2]);
     665    $page->param(disptype => $disp_alloctypes{$blockinfo->{type}});
     666    $page->param(type => $blockinfo->{type});
    990667  }
    991668
    992669## node hack
    993   $sth = $ip_dbh->prepare("SELECT nodes.node_id,node_name FROM nodes INNER JOIN noderef".
    994         " ON nodes.node_id=noderef.node_id WHERE noderef.block='$webvar{block}'");
    995   $sth->execute;
    996   my ($nodeid,$nodename) = $sth->fetchrow_array();
     670  my ($nodeid,$nodename) = getNodeInfo($ip_dbh, $webvar{block});
    997671  $page->param(havenodeid => $nodeid);
    998672
    999   if ($data[2] eq 'fr' || $data[2] eq 'bi') {
     673  if ($blockinfo->{type} eq 'fr' || $blockinfo->{type} eq 'bi') {
    1000674    $page->param(typesupportsnodes => 1);
    1001675    $page->param(nodename => $nodename);
     
    1006680#  (currently) have a nodeid set in the first place.
    1007681    if ($IPDBacl{$authuser} =~ /c/) {
    1008       $sth = $ip_dbh->prepare("SELECT node_id, node_name FROM nodes ORDER BY node_type,node_id");
    1009       $sth->execute;
    1010       my @nodelist;
    1011       while (my ($nid,$nname) = $sth->fetchrow_array()) {
    1012         my %row = (
    1013                 selme => ($nodeid == $nid),
    1014                 nodeid => $nid,
    1015                 nodename => $nname,
    1016                 );
    1017         push (@nodelist, \%row);
     682      my $nlist = getNodeList($ip_dbh);
     683      foreach (@{$nlist}) {
     684        $$_{selme} = ($$_{node_id} == $nodeid);
    1018685      }
    1019       $page->param(nodelist => \@nodelist);
     686      $page->param(nodelist => $nlist);
    1020687    }
    1021688  }
    1022689## end node hack
    1023690
    1024   my ($lastmod,undef) = split /\s+/, $data[7];
     691  my ($lastmod,undef) = split /\s+/, $blockinfo->{lastmod};
    1025692  $page->param(lastmod => $lastmod);
    1026693
    1027694  # not happy with the upside-down logic, but...
    1028   $page->param(swipable => $data[2] !~ /.i/);
    1029   $page->param(swip => $data[10] ne 'n');
     695  $page->param(swipable => $blockinfo->{type} !~ /.i/);
     696  $page->param(swip => $blockinfo->{swip} ne 'n') if $blockinfo->{swip};
    1030697
    1031698  # Check to see if we can display sensitive data
    1032699  $page->param(nocling => $IPDBacl{$authuser} =~ /s/);
    1033   $page->param(privdata => $data[8]);
     700  $page->param(privdata => $blockinfo->{privdata});
    1034701
    1035702  # ACL trickery - these two template booleans control the presence of all form/input tags
     
    1048715  }
    1049716
    1050   # Check to see if we can update restricted data
    1051   my $privdata = '';
    1052   if ($IPDBacl{$authuser} =~ /s/) {
    1053     $privdata = ",privdata='$webvar{privdata}'";
    1054   }
    1055 
    1056717  # Make sure incoming data is in correct format - custID among other things.
    1057718  return if !validateInput;
    1058719
    1059   # SQL transaction wrapper
    1060   eval {
    1061     # Relatively simple SQL transaction here.
    1062     my $sql;
    1063     if (my $pooltype = ($webvar{alloctype} =~ /^(.)i$/) ) {
    1064       $sql = "UPDATE poolips SET custid='$webvar{custid}',".
    1065         "city=?,description=?,notes=?,".
    1066         "circuitid='$webvar{circid}',".
    1067         "$privdata where ip='$webvar{block}'";
    1068     } else {
    1069       $sql = "UPDATE allocations SET custid='$webvar{custid}',".
    1070         "city=?,description=?,notes=?,".
    1071         "circuitid='$webvar{circid}'$privdata,".
    1072         "type='$webvar{alloctype}',".
    1073         "swip='".($webvar{swip} eq 'on' ? 'y' : 'n')."' ".
    1074         "where cidr='$webvar{block}'";
    1075     }
    1076     # Log the details of the change.
    1077     syslog "debug", $sql;
    1078     $sth = $ip_dbh->prepare($sql);
    1079     $sth->execute($webvar{city}, $webvar{desc}, $webvar{notes});
    1080 ## node hack
    1081     if ($webvar{node}) {
    1082       # done with delete/insert so we don't have to worry about funkyness updating a node ref that isn't there
    1083       $ip_dbh->do("DELETE FROM noderef WHERE block='$webvar{block}'");
    1084       $sth = $ip_dbh->prepare("INSERT INTO noderef (block,node_id) VALUES (?,?)");
    1085       $sth->execute($webvar{block},$webvar{node});
    1086     }
    1087 ## end node hack
    1088     $ip_dbh->commit;
    1089   };
    1090   if ($@) {
    1091     my $msg = $@;
    1092     eval { $ip_dbh->rollback; };
     720  $webvar{swip} = 'n' if !$webvar{swip};
     721
     722  my %updargs = (
     723        custid          => $webvar{custid},
     724        city            => $webvar{city},
     725        description     => $webvar{desc},
     726        notes           => $webvar{notes},
     727        circuitid       => $webvar{circid},
     728        block           => $webvar{block},
     729        type            => $webvar{alloctype},
     730        swip            => $webvar{swip},
     731        );
     732
     733  # Semioptional values
     734  $updargs{privdata} = $webvar{privdata} if $IPDBacl{$authuser} =~ /s/;
     735  $updargs{node} = $webvar{node} if $webvar{node};
     736
     737  my ($code,$msg) = updateBlock($ip_dbh, %updargs);
     738
     739  if ($code eq 'FAIL') {
    1093740    syslog "err", "$authuser could not update block/IP '$webvar{block}': '$msg'";
    1094741    $page->param(err => "Could not update block/IP $webvar{block}: $msg");
     
    1098745  # If we get here, the operation succeeded.
    1099746  syslog "notice", "$authuser updated $webvar{block}";
     747##fixme:  log details of the change?  old way is in the .debug stream anyway.
    1100748##fixme:  need to wedge something in to allow "update:field" notifications
    1101749## hmm.  how to tell what changed?  O_o
     
    1105753## node hack
    1106754  if ($webvar{node} && $webvar{node} ne '-') {
    1107     $sth = $ip_dbh->prepare("SELECT node_name FROM nodes WHERE node_id=?");
    1108     $sth->execute($webvar{node});
    1109     my ($nodename) = $sth->fetchrow_array();
     755    my $nodename = getNodeName($ip_dbh, $webvar{node});
    1110756    $page->param(nodename => $nodename);
    1111757  }
     
    1113759
    1114760  # Link back to browse-routed or list-pool page on "Update complete" page.
    1115   my $cblock;   # to contain the CIDR of the container block we're retrieving.
    1116   my $sql;
     761  my $cblock;
    1117762  if (my $pooltype = ($webvar{alloctype} =~ /^(.)i$/) ) {
    1118763    $page->param(backpool => 1);
    1119     $sql = "select pool from poolips where ip='$webvar{block}'";
     764    $cblock = ipParent($ip_dbh, $webvar{block});
    1120765  } else {
    1121     $sql = "select cidr from routed where cidr >>= '$webvar{block}'";
    1122   }
    1123   # I define there to be no errors on this operation...  so we don't need to check for them.
    1124   $sth = $ip_dbh->prepare($sql);
    1125   $sth->execute;
    1126   $sth->bind_columns(\$cblock);
    1127   $sth->fetch();
    1128   $sth->finish;
    1129   $page->param(backblock => $cblock);
     766    $cblock = blockParent($ip_dbh, $webvar{block});
     767  }
     768  $page->param(backblock => $cblock->{cidr});
     769
     770  # Do some HTML fiddling here instead of using ESCAPE=HTML in the template,
     771  # because otherwise we can't convert \n to <br>.  *sigh*
     772  $webvar{notes} = $q->escapeHTML($webvar{notes});      # escape first...
     773  $webvar{notes} =~ s/\n/<br>\n/;                       # ... then convert newlines
     774  $webvar{privdata} = ($webvar{privdata} ? $q->escapeHTML($webvar{privdata}) : "&nbsp;");
     775  $webvar{privdata} =~ s/\n/<br>\n/;
    1130776
    1131777  $page->param(cidr => $webvar{block});
     
    1134780  $page->param(custid => $webvar{custid});
    1135781  $page->param(swip => $webvar{swip} eq 'on' ? 'Yes' : 'No');
    1136   $page->param(circid => $q->escapeHTML($webvar{circid}));
    1137   $page->param(desc => $q->escapeHTML($webvar{desc}));
    1138   $page->param(notes => $q->escapeHTML($webvar{notes}));
    1139   $webvar{privdata} = ($webvar{privdata} ? $q->escapeHTML($webvar{privdata}) : "&nbsp;");
     782  $page->param(circid => $webvar{circid});
     783  $page->param(desc => $webvar{desc});
     784  $page->param(notes => $webvar{notes});
    1140785  $page->param(privdata => $webvar{privdata})
    1141786        if $IPDBacl{$authuser} =~ /s/;
     
    1157802  }
    1158803
    1159   my ($cidr, $custid, $type, $city, $circid, $desc, $notes, $alloctype, $privdata);
     804  my $blockdata;
    1160805
    1161806  if ($webvar{alloctype} eq 'rm') {
    1162     $sth = $ip_dbh->prepare("select cidr,city from routed where cidr='$webvar{block}'");
    1163     $sth->execute();
    1164 
    1165 # This feels...  extreme.
    1166     croak $sth->errstr() if($sth->errstr());
    1167 
    1168     $sth->bind_columns(\$cidr,\$city);
    1169     $sth->execute();
    1170     $sth->fetch || croak $sth->errstr();
    1171     $custid = "N/A";
    1172     $alloctype = $webvar{alloctype};
    1173     $circid = "N/A";
    1174     $desc = "N/A";
    1175     $notes = "N/A";
    1176     $privdata = "N/A";
     807
     808    $blockdata->{block} = $webvar{block};
     809    $blockdata->{city} = getRoutedCity($ip_dbh, $webvar{block});
     810    $blockdata->{custid} = "N/A";
     811    $blockdata->{type} = $webvar{alloctype};
     812    $blockdata->{circuitid} = "N/A";
     813    $blockdata->{description} = "N/A";
     814    $blockdata->{notes} = "N/A";
     815    $blockdata->{privdata} = "N/A";
    1177816
    1178817  } elsif ($webvar{alloctype} eq 'mm') {
    1179818
    1180     $cidr = $webvar{block};
    1181     $city = "N/A";
    1182     $custid = "N/A";
    1183     $alloctype = $webvar{alloctype};
    1184     $circid = "N/A";
    1185     $desc = "N/A";
    1186     $notes = "N/A";
    1187     $privdata = "N/A";
    1188 
    1189   } elsif ($webvar{alloctype} =~ /^.i$/) { # done with alloctype=[rm]m
    1190 
    1191     # Unassigning a static IP
    1192     my $sth = $ip_dbh->prepare("select ip,custid,city,type,notes,circuitid,privdata".
    1193         " from poolips where ip='$webvar{block}'");
    1194     $sth->execute();
    1195 #  croak $sth->errstr() if($sth->errstr());
    1196 
    1197     $sth->bind_columns(\$cidr, \$custid, \$city, \$alloctype, \$notes, \$circid,
    1198         \$privdata);
    1199     $sth->fetch() || croak $sth->errstr;
    1200 
    1201   } else { # done with alloctype=~ /^.i$/
    1202 
    1203     my $sth = $ip_dbh->prepare("select cidr,custid,type,city,circuitid,description,notes,privdata".
    1204         " from allocations where cidr='$webvar{block}'");
    1205     $sth->execute();
    1206 #       croak $sth->errstr() if($sth->errstr());
    1207 
    1208     $sth->bind_columns(\$cidr, \$custid, \$alloctype, \$city, \$circid, \$desc,
    1209         \$notes, \$privdata);
    1210     $sth->fetch() || carp $sth->errstr;
     819    $blockdata->{block} = $webvar{block};
     820    $blockdata->{city} = "N/A";
     821    $blockdata->{custid} = "N/A";
     822    $blockdata->{type} = $webvar{alloctype};
     823    $blockdata->{circuitid} = "N/A";
     824    $blockdata->{description} = "N/A";
     825    $blockdata->{notes} = "N/A";
     826    $blockdata->{privdata} = "N/A";
     827
     828  } else {
     829
     830    $blockdata = getBlockData($ip_dbh, $webvar{block})
     831
    1211832  } # end cases for different alloctypes
    1212833
    1213   $page->param(block => $cidr);
    1214   $page->param(disptype => $disp_alloctypes{$alloctype});
    1215   $page->param(type => $alloctype);
    1216   $page->param(city => $city);
    1217   $page->param(custid => $custid);
    1218   $page->param(circid => $circid);
    1219   $page->param(desc => $desc);
    1220   $page->param(notes => $notes);
    1221   $privdata = '&nbsp;' if $privdata eq '';
    1222   $page->param(privdata => $privdata) if $IPDBacl{$authuser} =~ /s/;
    1223   $page->param(delpool => $alloctype =~ /^.[pd]$/);
     834  $page->param(block => $blockdata->{block});
     835  $page->param(disptype => $disp_alloctypes{$blockdata->{type}});
     836  $page->param(type => $blockdata->{type});
     837  $page->param(city => $blockdata->{city});
     838  $page->param(custid => $blockdata->{custid});
     839  $page->param(circid => $blockdata->{circuitid});
     840  $page->param(desc => $blockdata->{description});
     841  $blockdata->{notes} = $q->escapeHTML($blockdata->{notes});
     842  $blockdata->{notes} =~ s/\n/<br>\n/;
     843  $page->param(notes => $blockdata->{notes});
     844  $blockdata->{privdata} = $q->escapeHTML($blockdata->{privdata});
     845  $blockdata->{privdata} = '&nbsp;' if !$blockdata->{privdata};
     846  $blockdata->{privdata} =~ s/\n/<br>\n/;
     847  $page->param(privdata => $blockdata->{privdata}) if $IPDBacl{$authuser} =~ /s/;
     848  $page->param(delpool => $blockdata->{type} =~ /^.[pd]$/);
    1224849
    1225850} # end remove()
     
    1237862
    1238863  # need to retrieve block data before deleting so we can notify on that
    1239   my ($cidr,$custid,$type,$city,$description) = getBlockData($ip_dbh, $webvar{block});
     864  my $blockinfo = getBlockData($ip_dbh, $webvar{block});
    1240865
    1241866  my ($code,$msg) = deleteBlock($ip_dbh, $webvar{block}, $webvar{alloctype});
     
    1243868  $page->param(block => $webvar{block});
    1244869  if ($code eq 'OK') {
    1245     syslog "notice", "$authuser deallocated '$webvar{alloctype}'-type netblock $webvar{block}".
    1246         " $custid, $city, desc='$description'";
     870    syslog "notice", "$authuser deallocated '$webvar{alloctype}'-type netblock $webvar{block} ".
     871        $blockinfo->{custid}.", ".$blockinfo->{city}.", desc='".$blockinfo->{description}."'";
    1247872    mailNotify($ip_dbh, 'da', "REMOVED: $disp_alloctypes{$webvar{alloctype}} $webvar{block}",
    1248873        "$disp_alloctypes{$webvar{alloctype}} $webvar{block} deallocated by $authuser\n".
    1249         "CustID: $custid\nCity: $city\nDescription: $description\n");
     874        "CustID: ".$blockinfo->{custid}."\nCity: ".$blockinfo->{city}.
     875        "\nDescription: ".$blockinfo->{description}."\n");
    1250876  } else {
    1251877    $page->param(failmsg => $msg);
Note: See TracChangeset for help on using the changeset viewer.