Ignore:
Timestamp:
01/14/05 18:03:44 (19 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Complete merge of code rewrite from /trunk ~r104 to r124

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/cgi-bin/main.cgi

    r124 r125  
    1414use DBI;
    1515use CommonWeb qw(:ALL);
    16 use IPDB qw(:ALL);
     16use IPDB 2.0 qw(:ALL);
    1717use CustIDCK;
    1818use POSIX qw(ceil);
     
    3333syslog "debug", "$authuser active";
    3434
    35 checkDBSanity();
     35# Why not a global DB handle?  (And a global statement handle, as well...)
     36# Use the connectDB function, otherwise we end up confusing ourselves
     37my $ip_dbh;
     38my $sth;
     39my $errstr;
     40($ip_dbh,$errstr) = connectDB("ipdb", "ipdb", "ipdbpwd");
     41if (!$ip_dbh) {
     42  printAndExit("Failed to connect to database: $errstr\n");
     43}
     44checkDBSanity($ip_dbh);
     45initIPDBGlobals($ip_dbh);
    3646
    3747#prototypes
     
    4858
    4959# Stuff that gets loaded from the database
    50 my @masterblocks;
    51 my @citylist;
    52 my @poplist;
    53 my %disp_alloctypes;
    54 my %list_alloctypes;
    55 my %allocated;  # Count for allocated blocks in a master block
    56 my %free;       # Count for free blocks (routed and unrouted) in a master block
    57 my %bigfree;    # Tracking largest free block in a master block
    58 my %routed;     # Number of routed blocks in a master block
    59 
    60 # Why not a global DB handle?  (And a global statement handle, as well...)
    61 # We already know the DB is happy, (checkDBSanity) otherwise we wouldn't be here.
    62 # Use the connectDB function, otherwise we end up confusing ourselves
    63 my $ip_dbh = connectDB;
    64 my $sth;
     60#my @citylist;
     61#my @poplist;
     62#my %allocated; # Count for allocated blocks in a master block
     63#my %free;      # Count for free blocks (routed and unrouted) in a master block
     64#my %bigfree;   # Tracking largest free block in a master block
     65#my %routed;    # Number of routed blocks in a master block
    6566
    6667# Slurp up the master block list - we need this several places
    6768# While we're at it, initialize the related hashes.
    68 $sth = $ip_dbh->prepare("select * from masterblocks order by cidr");
    69 $sth->execute;
    70 for (my $i=0; my @data = $sth->fetchrow_array(); $i++) {
    71   $masterblocks[$i] = new NetAddr::IP $data[0];
    72   $allocated{"$masterblocks[$i]"} = 0;
    73   $free{"$masterblocks[$i]"} = 0;
    74   $bigfree{"$masterblocks[$i]"} = 128;  # Larger number means smaller block.
    75                                         # Set to 128 to prepare for IPv6
    76   $routed{"$masterblocks[$i]"} = 0;
    77 }
    78 
    79 # Initialize the city and poplist arrays
    80 $sth = $ip_dbh->prepare("select * from cities order by city");
    81 $sth->execute;
    82 my $i = 0;
    83 my $j = 0;
    84 while (my @data = $sth->fetchrow_array) {
    85   $citylist[$i++] = $data[0];
    86   if ($data[1] eq 'y') {
    87     $poplist[$j++] = $data[0];
    88   }
    89 }
    90 
    91 # Initialize alloctypes hashes
    92 $sth = $ip_dbh->prepare("select * from alloctypes order by listorder");
    93 $sth->execute;
    94 while (my @data = $sth->fetchrow_array) {
    95   $disp_alloctypes{$data[0]} = $data[2];
    96   if ($data[3] < 900) {
    97     $list_alloctypes{$data[0]} = $data[1];
    98   }
    99 }
     69#$sth = $ip_dbh->prepare("select * from masterblocks order by cidr");
     70#$sth->execute;
     71#for (my $i=0; my @data = $sth->fetchrow_array(); $i++) {
     72#  $masterblocks[$i] = new NetAddr::IP $data[0];
     73#  $allocated{"$masterblocks[$i]"} = 0;
     74#  $free{"$masterblocks[$i]"} = 0;
     75#  $bigfree{"$masterblocks[$i]"} = 128; # Larger number means smaller block.
     76#                                       # Set to 128 to prepare for IPv6
     77#  $routed{"$masterblocks[$i]"} = 0;
     78#}
     79
    10080
    10181
     
    11494  my $cidr = new NetAddr::IP $webvar{cidr};
    11595
    116   print "<div type=heading align=center>Adding $cidr as master block....\n";
     96  print "<div type=heading align=center>Adding $cidr as master block....</div>\n";
    11797
    11898  # Allow transactions, and raise an exception on errors so we can catch it later.
     
    142122    eval { $ip_dbh->rollback; };
    143123    syslog "err", "Could not add master block '$webvar{cidr}' to database: '$@'";
    144     printAndExit("Could not add master block $webvar{cidr} to database: $@");
    145   }
    146 
    147   print "Success!</div>\n";
    148 
    149   printFooter;
     124    printError("Could not add master block $webvar{cidr} to database: $@");
     125  } else {
     126    print "<div type=heading align=center>Success!</div>\n";
     127    syslog "info", "$authuser added master block $webvar{cidr}";
     128  }
     129
    150130} # end add new master
    151131
     
    169149    viewBy($webvar{searchfor}, $webvar{input});
    170150  }
    171   printFooter();
    172151}
    173152
     
    208187  printAndExit("Error $boing:  ".$excuses[$rnd/30.0]);
    209188}
    210 
    211 
    212 #end main()
    213 
    214 # Shut up error log warning about not disconnecting.  Maybe.
    215 $ip_dbh->disconnect;
    216 # Just in case something waaaayyy down isn't in place properly...
    217 exit 0;
     189## Finally! Done with that NASTY "case" emulation!
     190
     191
     192
     193# Clean up IPDB globals, DB handle, etc.
     194finish($ip_dbh);
     195# We print the footer here, so we don't have to do it elsewhere.
     196printFooter;
     197# Just in case something waaaayyy down isn't in place
     198# properly... we exit explicitly.
     199exit;
     200
    218201
    219202
     
    314297    } else {
    315298      # This shouldn't happen, but if it does, whoever gets it deserves what they get...
    316       printAndExit("Invalid query.");
     299      printError("Invalid query.");
    317300    }
    318301  } else {
    319302    # This shouldn't happen, but if it does, whoever gets it deserves what they get...
    320     printAndExit("Invalid searchfor.");
     303    printError("Invalid searchfor.");
    321304  }
    322305} # viewBy
     
    425408
    426409# Initial display:  Show master blocks with total allocated subnets, total free subnets
    427 sub showSummary
    428 {
     410sub showSummary {
     411  # this is horrible-ugly-bad and will Go Away real soon now(TM)
    429412  print "Content-type: text/html\n\n";
    430413
     
    432415        'Free netblocks', 'Largest free block');
    433416
    434 # Snag the allocations.
    435 # I think it's too confusing to leave out internal allocations.
    436   $sth = $ip_dbh->prepare("select * from allocations");
    437   $sth->execute();
    438   while (my @data = $sth->fetchrow_array()) {
    439     # cidr,custid,type,city,description
    440     # We only need the cidr
    441     my $cidr = new NetAddr::IP $data[0];
    442     foreach my $master (@masterblocks) {
    443       if ($master->contains($cidr)) {
    444         $allocated{"$master"}++;
    445       }
    446     }
    447   }
    448 
    449 # Snag routed blocks
    450   $sth = $ip_dbh->prepare("select * from routed");
    451   $sth->execute();
    452   while (my @data = $sth->fetchrow_array()) {
    453     # cidr,maskbits,city
    454     # We only need the cidr
    455     my $cidr = new NetAddr::IP $data[0];
    456     foreach my $master (@masterblocks) {
    457       if ($master->contains($cidr)) {
    458         $routed{"$master"}++;
    459       }
    460     }
    461   }
    462 
    463 # Snag the free blocks.
    464   $sth = $ip_dbh->prepare("select * from freeblocks");
    465   $sth->execute();
    466   while (my @data = $sth->fetchrow_array()) {
    467     # cidr,maskbits,city
    468     # We only need the cidr
    469     my $cidr = new NetAddr::IP $data[0];
    470     foreach my $master (@masterblocks) {
    471       if ($master->contains($cidr)) {
    472         $free{"$master"}++;
    473         if ($cidr->masklen < $bigfree{"$master"}) { $bigfree{"$master"} = $cidr->masklen; }
    474       }
    475     }
    476   }
    477 
    478 # Print the data.
     417  my %allocated;
     418  my %free;
     419  my %routed;
     420  my %bigfree;
     421
     422  # Count the allocations.
     423  $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?");
     424  foreach my $master (@masterblocks) {
     425    $sth->execute("$master");
     426    $sth->bind_columns(\$allocated{"$master"});
     427    $sth->fetch();
     428  }
     429
     430  # Count routed blocks
     431  $sth = $ip_dbh->prepare("select count(*) from routed where cidr <<= ?");
     432  foreach my $master (@masterblocks) {
     433    $sth->execute("$master");
     434    $sth->bind_columns(\$routed{"$master"});
     435    $sth->fetch();
     436  }
     437
     438  # Count the free blocks.
     439  $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ?");
     440  foreach my $master (@masterblocks) {
     441    $sth->execute("$master");
     442    $sth->bind_columns(\$free{"$master"});
     443    $sth->fetch();
     444  }
     445
     446  # Find the largest free block in each master
     447  $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? order by maskbits limit 1");
     448  foreach my $master (@masterblocks) {
     449    $sth->execute("$master");
     450    $sth->bind_columns(\$bigfree{"$master"});
     451    $sth->fetch();
     452  }
     453
     454  # Print the data.
    479455  my $count=0;
    480456  foreach my $master (@masterblocks) {
     
    492468  print "Note:  Free blocks noted here include both routed and unrouted blocks.\n";
    493469
    494   # Because of the way this sub gets called, we don't need to print the footer here.
    495   # (index.shtml makes an SSI #include call to cgi-bin/main.cgi?action=index)
    496   # If we do, the footer comes in twice...
    497   #printFooter;
    498470} # showSummary
    499471
     
    510482        qq($webvar{block}:</div></center><br>\n);
    511483
     484  my %allocated;
     485  my %free;
     486  my %routed;
     487  my %bigfree;
     488
    512489  my $master = new NetAddr::IP $webvar{block};
    513490  my @localmasters;
    514491
    515   $sth = $ip_dbh->prepare("select * from routed order by cidr");
     492  # Fetch only the blocks relevant to this master
     493  $sth = $ip_dbh->prepare("select * from routed where cidr <<= '$master' order by cidr");
    516494  $sth->execute();
    517495
     
    519497  while (my @data = $sth->fetchrow_array()) {
    520498    my $cidr = new NetAddr::IP $data[0];
    521     if ($master->contains($cidr)) {
    522       $localmasters[$i++] = $cidr;
    523       $free{"$cidr"} = 0;
    524       $allocated{"$cidr"} = 0;
     499    $localmasters[$i++] = $cidr;
     500    $free{"$cidr"} = 0;
     501    $allocated{"$cidr"} = 0;
     502    $bigfree{"$cidr"} = 128;
    525503    # Retain the routing destination
    526       $routed{"$cidr"} = $data[2];
    527     }
    528   }
    529 
    530 # Check if there were actually any blocks routed from this master
     504    $routed{"$cidr"} = $data[2];
     505  }
     506
     507  # Check if there were actually any blocks routed from this master
    531508  if ($i > 0) {
    532509    startTable('Routed block','Routed to','Allocated blocks',
    533510        'Free blocks','Largest free block');
    534511
    535   # Count the allocations
    536     $sth = $ip_dbh->prepare("select * from allocations");
    537     $sth->execute();
    538     while (my @data = $sth->fetchrow_array()) {
    539       # cidr,custid,type,city,description
    540       # We only need the cidr
    541       my $cidr = new NetAddr::IP $data[0];
    542       foreach my $master (@localmasters) {
    543         if ($master->contains($cidr)) {
    544           $allocated{"$master"}++;
    545         }
    546       }
    547     }
    548 
    549     # initialize bigfree base points
    550     foreach my $lmaster (@localmasters) {
    551       $bigfree{"$lmaster"} = 128;
    552     }
    553 
    554     # Snag the free blocks.
    555     $sth = $ip_dbh->prepare("select * from freeblocks");
    556     $sth->execute();
    557     while (my @data = $sth->fetchrow_array()) {
    558       # cidr,maskbits,city
    559       # We only need the cidr
    560       my $cidr = new NetAddr::IP $data[0];
    561       foreach my $lmaster (@localmasters) {
    562         if ($lmaster->contains($cidr)) {
    563           $free{"$lmaster"}++;
    564           if ($cidr->masklen < $bigfree{"$lmaster"}) {
    565             $bigfree{"$lmaster"} = $cidr->masklen;
    566           }
    567         }
    568         # check for largest free block
    569       }
     512    # Count the allocations
     513    $sth = $ip_dbh->prepare("select count(*) from allocations where cidr <<= ?");
     514    foreach my $master (@localmasters) {
     515      $sth->execute("$master");
     516      $sth->bind_columns(\$allocated{"$master"});
     517      $sth->fetch();
     518    }
     519
     520    # Count the free blocks.
     521    $sth = $ip_dbh->prepare("select count(*) from freeblocks where cidr <<= ?");
     522    foreach my $master (@localmasters) {
     523      $sth->execute("$master");
     524      $sth->bind_columns(\$free{"$master"});
     525      $sth->fetch();
     526    }
     527
     528    # Get the size of the largest free block
     529    $sth = $ip_dbh->prepare("select maskbits from freeblocks where cidr <<= ? order by maskbits limit 1");
     530    foreach my $master (@localmasters) {
     531      $sth->execute("$master");
     532      $sth->bind_columns(\$bigfree{"$master"});
     533      $sth->fetch();
    570534    }
    571535
     
    603567  # Snag the free blocks.
    604568  my $count = 0;
    605   $sth = $ip_dbh->prepare("select * from freeblocks where routed='n' order by cidr");
     569  $sth = $ip_dbh->prepare("select cidr from freeblocks where cidr <<='$master' and ".
     570        "routed='n' order by cidr");
    606571  $sth->execute();
    607572  while (my @data = $sth->fetchrow_array()) {
    608     # cidr,maskbits,city
    609     # We only need the cidr
    610573    my $cidr = new NetAddr::IP $data[0];
    611     if ($master->contains($cidr)) {
    612       my @row = ("$cidr", $cidr->range);
    613       printRow(\@row, 'color1' ) if($count%2==0);
    614       printRow(\@row, 'color2' ) if($count%2!=0);
    615       $count++;
    616     }
     574    my @row = ("$cidr", $cidr->range);
     575    printRow(\@row, 'color1' ) if($count%2==0);
     576    printRow(\@row, 'color2' ) if($count%2!=0);
     577    $count++;
    617578  }
    618579
    619580  print "</table>\n";
    620   printFooter;
    621581} # showMaster
    622582
     
    641601        qq($master ($data[2]):</div></center><br>\n);
    642602
    643   $sth = $ip_dbh->prepare("select * from allocations order by cidr");
     603  startTable('CIDR allocation','Customer Location','Type','CustID','Description/Name');
     604
     605  # Snag the allocations for this block
     606  $sth = $ip_dbh->prepare("select * from allocations where cidr <<= '$master' order by cidr");
    644607  $sth->execute();
    645 
    646   startTable('CIDR allocation','Customer Location','Type','CustID','Description/Name');
    647608
    648609  my $count=0;
    649610  while (my @data = $sth->fetchrow_array()) {
    650     # cidr,custid,type,city,description,notes,maskbits
     611    # cidr,custid,type,city,description,notes,maskbits,circuitid
    651612    my $cidr = new NetAddr::IP $data[0];
    652     if (!$master->contains($cidr)) { next; }
    653613
    654614    # Clean up extra spaces that are borking things.
     
    691651  # unrouted free blocks, but it's better to let the database do the work if we can.
    692652  $count = 0;
    693   $sth = $ip_dbh->prepare("select * from freeblocks where routed='y' order by cidr");
     653  $sth = $ip_dbh->prepare("select * from freeblocks where routed='y' and cidr <<= '$master' order by cidr");
    694654  $sth->execute();
    695655  while (my @data = $sth->fetchrow_array()) {
    696656    # cidr,maskbits,city
    697657    my $cidr = new NetAddr::IP $data[0];
    698     if ($master->contains($cidr)) {
    699       my @row = ("<a href=\"/ip/cgi-bin/main.cgi?action=assign&block=$cidr\">$cidr</a>",
     658    my @row = ("<a href=\"/ip/cgi-bin/main.cgi?action=assign&block=$cidr\">$cidr</a>",
    700659        $cidr->range);
    701       printRow(\@row, 'color1') if ($count%2 == 0);
    702       printRow(\@row, 'color2') if ($count%2 != 0);
    703       $count++;
    704     }
     660    printRow(\@row, 'color1') if ($count%2 == 0);
     661    printRow(\@row, 'color2') if ($count%2 != 0);
     662    $count++;
    705663  }
    706664
    707665  print "</table>\n";
    708   printFooter;
    709666} # showRBlock
    710667
     
    762719  print "</table>\n";
    763720
    764   printFooter;
    765721} # end listPool
    766722
    767723
    768 # Should this maybe just be a full static page?  It just spews out some predefined HTML.
     724# Show "Add new allocation" page.  Note that the actual page may
     725# be one of two templates, and the lists come from the database.
    769726sub assignBlock {
    770727  printHeader('');
     
    824781  print $html;
    825782
    826   printFooter();
    827783} # assignBlock
    828784
     
    837793  # Going to manually validate some items.
    838794  # custid and city are automagic.
    839   validateInput();
    840 
    841 # This isn't always useful.
    842 #  if (!$webvar{maskbits}) {
    843 #    printAndExit("Please enter a CIDR block length.");
    844 #  }
     795  return if !validateInput();
    845796
    846797# Several different cases here.
     
    860811        " ptype='$base' and (city='Sudbury' or city='North Bay')";
    861812    } else {
    862 ## $city doesn't seem to get defined here.
    863 my $city;       # Shut up Perl's "strict" scoping/usage check.
    864813      $sql = "select * from poolips where available='y' and".
    865814        " ptype='$base' and city='$webvar{pop}'";
     
    891840
    892841      if (!$webvar{maskbits}) {
    893         printAndExit("Please specify a CIDR mask length.");
     842        printError("Please specify a CIDR mask length.");
     843        return;
    894844      }
    895845      my $sql;
     
    908858          " a set of smaller netblocks or a single smaller netblock.";
    909859      } else {
     860##fixme
     861# This section needs serious Pondering.
    910862        if ($webvar{alloctype} =~ /^[cdsmw]p$/) {
    911863          if (($webvar{city} !~ /^(Sudbury|North Bay)$/) && ($webvar{alloctype} eq 'dp')) {
    912             printAndExit("You must chose Sudbury or North Bay for DSL pools."); }
     864            printError("You must chose Sudbury or North Bay for DSL pools.");
     865            return;
     866          }
    913867          $city = $webvar{city};
    914868          $failmsg = "No suitable free block found.<br>\nYou will have to route another".
    915             " superblock <br>\nfrom one of the master blocks in Sudbury or chose a smaller".
     869            " superblock from one of the<br>\nmaster blocks in Sudbury or chose a smaller".
    916870            " block size for the pool.";
    917871        } else {
     
    933887      my @data = $sth->fetchrow_array();
    934888      if ($data[0] eq "") {
    935         printAndExit($failmsg);
     889        printError($failmsg);
     890        return;
    936891      }
    937892      $cidr = new NetAddr::IP $data[0];
     
    982937  print $html;
    983938
    984   printFooter;
    985939} # end confirmAssign
    986940
     
    990944  # Some things are done more than once.
    991945  printHeader('');
    992   validateInput();
    993 
    994   # Set some things that may be needed
    995   # Don't set $cidr here as it may not even be a valid IP address.
    996   my $alloc_from = new NetAddr::IP $webvar{alloc_from};
    997 
    998 # dynDSL (dy), sIP DSL(dp), and server pools (sp) are nominally allocated to Sudbury
    999 # no matter what else happens.
    1000 #  if ($webvar{alloctype} =~ /^([sd]p|dy)$/) { $webvar{city} = "Sudbury"; }
    1001 # OOPS.  forgot about North Bay DSL.
    1002 #### Gotta make this cleaner and more accurate
    1003 #  if ($webvar{alloctype} eq "sp") { $webvar{city} = "Sudbury"; }
    1004 
    1005 # Same ordering as confirmation page
    1006 
    1007   if ($webvar{alloctype} =~ /^[cdsmw]i$/) {
    1008     my ($base,$tmp) = split //, $webvar{alloctype};     # split into individual chars
    1009 
    1010     # We'll just have to put up with the oddities caused by SQL (un)sort order
    1011     $sth = $ip_dbh->prepare("select * from poolips where pool='$webvar{alloc_from}'".
    1012         " and available='y' order by ip");
    1013     $sth->execute;
    1014 
    1015     my @data = $sth->fetchrow_array;
    1016     my $cidr = $data[1];
    1017 
    1018     $sth = $ip_dbh->prepare("update poolips set custid='$webvar{custid}',".
    1019         "city='$webvar{city}',available='n',description='$webvar{desc}',".
    1020         "circuitid='$webvar{circid}'".
    1021         " where ip='$cidr'");
    1022     $sth->execute;
    1023     if ($sth->err) {
    1024       syslog "err", "Allocation of $cidr to $webvar{custid} by $authuser failed: ".
    1025         "'".$sth->errstr."'";
    1026       printAndExit("Allocation of $cidr to $webvar{custid} failed: '".$sth->errstr."'");
    1027     }
    1028     print qq(<div class="center"><div class="heading">The IP $cidr has been allocated to customer $webvar{custid}</div></div>);
    1029     syslog "notice", "$authuser allocated $cidr to $webvar{custid}";
    1030 # Notify tech@example.com
    1031     mailNotify('tech@example.com',"$disp_alloctypes{$webvar{alloctype}} allocation",
    1032         "$disp_alloctypes{$webvar{alloctype}} $cidr allocated to customer $webvar{custid}\n".
    1033         "Description: $webvar{desc}\n\nAllocated by: $authuser\n");
    1034 
    1035   } else { # end IP-from-pool allocation
    1036 
    1037     # Set $cidr here as it may not be a valid IP address elsewhere.
    1038     my $cidr = new NetAddr::IP $webvar{fullcidr};
    1039 
    1040 # Allow transactions, and make errors much easier to catch.
    1041 # Much as I would like to error-track specifically on each ->execute,
    1042 # that's a LOT of code, and some SQL blocks MUST be atomic at a
    1043 # multi-statement level.  :/
    1044     local $ip_dbh->{AutoCommit} = 0;    # These need to be local so we don't
    1045     local $ip_dbh->{RaiseError} = 1;    # step on our toes by accident.
    1046 
    1047     if ($webvar{fullcidr} eq $webvar{alloc_from}) {
    1048       # Easiest case- insert in one table, delete in the other, and go home.  More or less.
    1049       # insert into allocations values (cidr,custid,type,city,desc) and
    1050       # delete from freeblocks where cidr='cidr'
    1051       # For data safety on non-transaction DBs, we delete first.
    1052 
    1053       eval {
    1054         if ($webvar{alloctype} eq 'rr') {
    1055           $sth = $ip_dbh->prepare("update freeblocks set routed='y',city='$webvar{city}'".
    1056             " where cidr='$webvar{fullcidr}'");
    1057           $sth->execute;
    1058           $sth = $ip_dbh->prepare("insert into routed values ('$webvar{fullcidr}',".
    1059             $cidr->masklen.",'$webvar{city}')");
    1060           $sth->execute;
    1061         } else {
    1062           # common stuff for end-use, dialup, dynDSL, pools, etc, etc.
    1063 
    1064           # city has to be reset for DSL/server pools;  nominally to Sudbury.
    1065           ## Gotta rethink this;  DSL pools can be in North Bay as well.  :/
    1066           #if ($webvar{alloctype} =~ /^[sd]p$/) { $webvar{city} = 'Sudbury'; }
    1067 
    1068           $sth = $ip_dbh->prepare("delete from freeblocks where cidr='$webvar{fullcidr}'");
    1069           $sth->execute;
    1070 
    1071           $sth = $ip_dbh->prepare("insert into allocations values ('$webvar{fullcidr}',".
    1072             "'$webvar{custid}','$webvar{alloctype}','$webvar{city}','$webvar{desc}',".
    1073             "'$webvar{notes}',".$cidr->masklen.",'$webvar{circid}')");
    1074           $sth->execute;
    1075         } # routing vs non-routing netblock
    1076         $ip_dbh->commit;
    1077       };  # end of eval
    1078       if ($@) {
    1079         carp "Transaction aborted because $@";
    1080         eval { $ip_dbh->rollback; };
    1081         syslog "err", "Allocation of '$webvar{fullcidr}' to '$webvar{custid}' as ".
    1082                 "'$webvar{alloctype}' by $authuser failed: '$@'";
    1083         printAndExit("Allocation of $cidr as $disp_alloctypes{$webvar{alloctype}} failed.\n");
    1084       }
    1085 
    1086       # If we get here, the DB transaction has succeeded.
    1087       syslog "notice", "$authuser allocated '$webvar{fullcidr}' to '$webvar{custid}' as '$webvar{alloctype}'";
    1088 
    1089 # How to log SQL without munging too many error-checking wrappers in?
    1090 #      syslog "info", "
    1091 # We don't.  GRRR.
    1092 
    1093     } else { # webvar{fullcidr} != webvar{alloc_from}
    1094       # Hard case.  Allocation is smaller than free block.
    1095       my $wantmaskbits = $cidr->masklen;
    1096       my $maskbits = $alloc_from->masklen;
    1097 
    1098       my @newfreeblocks;        # Holds free blocks generated from splitting the source freeblock.
    1099 
    1100       my $i=0;
    1101       while ($maskbits++ < $wantmaskbits) {
    1102         my @subblocks = $alloc_from->split($maskbits);
    1103         $newfreeblocks[$i++] = $subblocks[1];
    1104       } # while
    1105 
    1106       # Begin SQL transaction block
    1107       eval {
    1108         # Delete old freeblocks entry
    1109         $sth = $ip_dbh->prepare("delete from freeblocks where cidr='$webvar{alloc_from}'");
    1110         $sth->execute();
    1111 
    1112         # now we have to do some magic for routing blocks
    1113         if ($webvar{alloctype} eq 'rr') {
    1114           # Insert the new freeblocks entries
    1115           # Note that non-routed blocks are assigned to <NULL>
    1116           $sth = $ip_dbh->prepare("insert into freeblocks values (?, ?, '<NULL>','n')");
    1117           foreach my $block (@newfreeblocks) {
    1118             $sth->execute("$block", $block->masklen);
    1119           }
    1120           # Insert the entry in the routed table
    1121           $sth = $ip_dbh->prepare("insert into routed values ('$cidr',".
    1122             $cidr->masklen.",'$webvar{city}')");
    1123           $sth->execute;
    1124           # Insert the (almost) same entry in the freeblocks table
    1125           $sth = $ip_dbh->prepare("insert into freeblocks values ('$cidr',".
    1126             $cidr->masklen.",'$webvar{city}','y')");
    1127           $sth->execute;
    1128 
    1129         } else { # done with alloctype == rr
    1130 
    1131           # Insert the new freeblocks entries
    1132           $sth = $ip_dbh->prepare("insert into freeblocks values (?, ?, (select city from routed where cidr >> '$cidr'),'y')");
    1133           foreach my $block (@newfreeblocks) {
    1134             $sth->execute("$block", $block->masklen);
    1135           }
    1136           # Insert the allocations entry
    1137           $sth = $ip_dbh->prepare("insert into allocations values ('$webvar{fullcidr}',".
    1138             "'$webvar{custid}','$webvar{alloctype}','$webvar{city}',".
    1139             "'$webvar{desc}','$webvar{notes}',".$cidr->masklen.",'$webvar{circid}')");
    1140           $sth->execute;
    1141         } # done with netblock alloctype != rr
    1142         $ip_dbh->commit;
    1143       }; # end eval
    1144       if ($@) {
    1145         carp "Transaction aborted because $@";
    1146         eval { $ip_dbh->rollback; };
    1147         syslog "err", "Allocation of '$webvar{fullcidr}' to '$webvar{custid}' as ".
    1148                 "'$webvar{alloctype}' by $authuser failed: '$@'";
    1149         printAndExit("Allocation of $cidr as $disp_alloctypes{$webvar{alloctype}} failed.\n");
    1150       }
    1151       syslog "notice", "$authuser allocated '$webvar{fullcidr}' to '$webvar{custid}' as '$webvar{alloctype}'";
    1152 
    1153     } # end fullcidr != alloc_from
    1154 
    1155     # Begin SQL transaction block
    1156     eval {
    1157       # special extra handling for pools.
    1158       # Note that this must be done for ANY pool allocation!
    1159       if ( my ($pooltype) = ($webvar{alloctype} =~ /^([cdsmw])p$/) ) {
    1160         # have to insert all pool IPs into poolips table as "unallocated".
    1161         $sth = $ip_dbh->prepare("insert into poolips values ('$webvar{fullcidr}',".
    1162           " ?, '6750400', '$webvar{city}', '$pooltype', 'y', '', '', '')");
    1163         my @poolip_list = $cidr->hostenum;
    1164         for (my $i=1; $i<=$#poolip_list; $i++) {
    1165           $sth->execute($poolip_list[$i]->addr);
    1166         }
    1167       } # end pool special
    1168       $ip_dbh->commit;
    1169     }; # end eval
    1170     if ($@) {
    1171       carp "Transaction aborted because $@";
    1172       eval { $ip_dbh->rollback; };
    1173       syslog "err", "Initialization of pool '$webvar{fullcidr}' by $authuser failed: '$@'";
    1174       printAndExit("$disp_alloctypes{$webvar{alloctype}} $webvar{fullcidr} not completely initialized.");
    1175     }
    1176     syslog "notice", "$disp_alloctypes{$webvar{alloctype}} '$webvar{fullcidr}' successfully initialized by $authuser";
    1177 
    1178     print qq(<div class="center"><div class="heading">The block $webvar{fullcidr} was sucessfully added as type '$webvar{alloctype}' ($disp_alloctypes{$webvar{alloctype}})</div></div>);
    1179 
    1180     if ($webvar{alloctype} eq 'cn') {
     946  return if !validateInput();
     947
     948  # $code is "success" vs "failure", $msg contains OK for a
     949  # successful netblock allocation, the IP allocated for static
     950  # IP, or the error message if an error occurred.
     951  my ($code,$msg) = allocateBlock($ip_dbh, $webvar{fullcidr}, $webvar{alloc_from},
     952        $webvar{custid}, $webvar{alloctype}, $webvar{city}, $webvar{desc}, $webvar{notes},
     953        $webvar{circid});
     954
     955  if ($code eq 'OK') {
     956    if ($webvar{alloctype} =~ /^.i$/) {
     957      print qq(<div class="center"><div class="heading">The IP $msg has been allocated to customer $webvar{custid}</div></div>);
    1181958      # Notify tech@example.com
    1182959      mailNotify('tech@example.com',"$disp_alloctypes{$webvar{alloctype}} allocation",
    1183         "$disp_alloctypes{$webvar{alloctype}} $cidr allocated to customer $webvar{custid}\n".
     960        "$disp_alloctypes{$webvar{alloctype}} $msg allocated to customer $webvar{custid}\n".
    1184961        "Description: $webvar{desc}\n\nAllocated by: $authuser\n");
    1185     }
    1186 
    1187   } # end static-IP vs netblock allocation
    1188 
    1189   printFooter();
     962    } else {
     963      print qq(<div class="center"><div class="heading">The block $webvar{fullcidr} was ).
     964        "sucessfully added as type '$webvar{alloctype}' ".
     965        "($disp_alloctypes{$webvar{alloctype}})</div></div>";
     966    }
     967    syslog "notice", "$authuser allocated '$webvar{fullcidr}' to '$webvar{custid}' as ".
     968        "'$webvar{alloctype}'";
     969  } else {
     970    syslog "err", "Allocation of '$webvar{fullcidr}' to '$webvar{custid}' as ".
     971        "'$webvar{alloctype}' by $authuser failed: '$msg'";
     972    printError("Allocation of $webvar{fullcidr} as $disp_alloctypes{$webvar{alloctype}}".
     973        " failed: $msg\n");
     974  }
     975
    1190976} # end insertAssign()
    1191977
     
    1196982sub validateInput {
    1197983  if ($webvar{city} eq '-') {
    1198     printAndExit("Please choose a city.");
     984    printError("Please choose a city.");
     985    return;
    1199986  }
    1200987  chomp $webvar{alloctype};
     
    1202989  if ($webvar{alloctype} =~ /^(ci|di|cn|mi|wi)$/) {
    1203990    if (!$webvar{custid}) {
    1204       printAndExit("Please enter a customer ID.");
     991      printError("Please enter a customer ID.");
     992      return;
    1205993    }
    1206994    if ($webvar{custid} !~ /^(?:\d{10}|\d{7}|STAFF)(?:-\d\d?)?$/) {
     
    1209997      # Crosscheck with ... er...  something.
    1210998      my $status = CustIDCK->custid_exist($webvar{custid});
    1211       printAndExit("Error verifying customer ID: ".$CustIDCK::ErrMsg)
    1212         if $CustIDCK::Error;
    1213       printAndExit("Customer ID not valid.  Make sure the Customer ID ".
    1214         "is correct.<br>\nUse STAFF for staff static IPs, and 6750400 for any other ".
    1215         "non-customer assignments.")
    1216         if !$status;
     999      if ($CustIDCK::Error) {
     1000        printError("Error verifying customer ID: ".$CustIDCK::ErrMsg);
     1001        return;
     1002      }
     1003      if (!$status) {
     1004        printError("Customer ID not valid.  Make sure the Customer ID ".
     1005          "is correct.<br>\nUse STAFF for staff static IPs, and 6750400 for any other ".
     1006          "non-customer assignments.");
     1007        return;
     1008      }
    12171009#"Please enter a valid customer ID- this must be a 7- or 10-digit number, or STAFF for
    12181010#static IPs for staff.");
    12191011    }
    12201012#    print "<!-- [ In validateInput().  Insert customer ID cross-check here. ] -->\n";
    1221   } elsif ($webvar{alloctype} =~ /^([cdsmw]p|si|dn|dy|dc|ee|rr|ii)$/){
     1013  } elsif ($webvar{alloctype} =~ /^([cdsmw]p|si|dn|dy|dc|ee|rr|in)$/){
    12221014    # All non-customer allocations MUST be entered with "our" customer ID.
    12231015    # I have Defined this as 6750400 for consistency.
     
    12261018      $webvar{custid} = "6750400";
    12271019    }
    1228     if ($webvar{alloctype} eq 'rr') {
    1229       my $flag;
    1230       foreach (@poplist) {
    1231         if (/^$webvar{city}$/) {
    1232           $flag = 'y'; last;
    1233         }
    1234       }
    1235       if (!$flag) {
    1236         printAndExit("Please choose a valid POP location for a routed netblock.  Valid ".
    1237                 "POP locations are currently:<br>\n".join (" - ", @poplist));
    1238       }
    1239     }
    12401020  } else {
    12411021    # Danger! Danger!  alloctype should ALWAYS be set by a dropdown.  Anyone
    12421022    # managing to call things in such a way as to cause this deserves a cryptic error.
    1243     printAndExit("Invalid alloctype");
    1244   }
    1245   return 0;
     1023    printError("Invalid alloctype");
     1024    return;
     1025  }
     1026
     1027  # Check POP location
     1028  my $flag;
     1029  if ($webvar{alloctype} eq 'rr') {
     1030    $flag = 'for a routed netblock';
     1031    foreach (@poplist) {
     1032      if (/^$webvar{city}$/) {
     1033        $flag = 'n';
     1034        last;
     1035      }
     1036    }
     1037  } else {
     1038    $flag = 'n';
     1039    if ($webvar{pop} =~ /^-$/) {
     1040      $flag = 'to route the block from/through';
     1041    }
     1042  }
     1043  if ($flag ne 'n') {
     1044    printError("Please choose a valid POP location $flag.  Valid ".
     1045        "POP locations are currently:<br>\n".join (" - ", @poplist));
     1046    return;
     1047  }
     1048
     1049  return 'OK';
    12461050} # end validateInput
    12471051
     
    13181122  print $html;
    13191123
    1320   printFooter();
    13211124} # edit()
    13221125
     
    13521155    eval { $ip_dbh->rollback; };
    13531156    syslog "err", "$authuser could not update block/IP '$webvar{block}': '$@'";
    1354     printAndExit("Could not update block/IP $webvar{block}: $@");
     1157    printError("Could not update block/IP $webvar{block}: $@");
     1158    return;
    13551159  }
    13561160
     
    13581162  syslog "notice", "$authuser updated $webvar{block}";
    13591163  open (HTML, "../updated.html")
    1360         or croak "Could not open updated.html :$!";
     1164        or croak "Could not open updated.html :$!";
    13611165  my $html = join('', <HTML>);
    13621166
     
    13761180  print $html;
    13771181
    1378   printFooter;
    13791182} # update()
    13801183
    13811184
    13821185# Delete an allocation.
    1383 sub remove
    1384 {
     1186sub remove {
    13851187  printHeader('');
    13861188  #show confirm screen.
     
    13921194  # Serves'em right for getting here...
    13931195  if (!defined($webvar{block})) {
    1394     printAndExit("Error 332");
     1196    printError("Error 332");
     1197    return;
    13951198  }
    13961199
     
    14661269
    14671270  print $html;
    1468   printFooter;
    14691271} # end edit()
    14701272
     
    14771279  printHeader('');
    14781280
    1479   # Enable transactions and exception-on-errors... but only for this sub
    1480   local $ip_dbh->{AutoCommit} = 0;
    1481   local $ip_dbh->{RaiseError} = 1;
    1482 
    1483   if ($webvar{alloctype} =~ /^[cdsmw]i$/) {
    1484 
    1485     eval {
    1486       $sth = $ip_dbh->prepare("select * from poolips where ip='$webvar{block}'");
    1487       $sth->execute;
    1488       my @data = $sth->fetchrow_array;
    1489       $sth = $ip_dbh->prepare("select city from allocations where cidr='$data[0]'");
    1490       $sth->execute;
    1491       @data = $sth->fetchrow_array;
    1492       $sth = $ip_dbh->prepare("update poolips set custid='6750400', available='y',".
    1493         " city='$data[0]', description='', notes='', circuitid='' where ip='$webvar{block}'");
    1494       $sth->execute;
    1495       $ip_dbh->commit;
    1496     };
    1497     if ($@) {
    1498       carp "Transaction aborted because $@";
    1499       eval { $ip_dbh->rollback; };
    1500       syslog "err", "$authuser could not deallocate static IP '$webvar{block}': '$@'";
    1501       printAndExit("Could not deallocate static IP $webvar{block}: $@");
    1502     }
     1281  my ($code,$msg) = deleteBlock($ip_dbh, $webvar{block}, $webvar{alloctype});
     1282
     1283  if ($code eq 'OK') {
    15031284    print "<div class=heading align=center>Success!  $webvar{block} deallocated.</div>\n";
    1504     syslog "notice", "$authuser deallocated static IP $webvar{block}";
    1505 
    1506   } elsif ($webvar{alloctype} eq 'mm') { # end alloctype = [cdsmw]i
    1507 
    1508     eval {
    1509       $sth = $ip_dbh->prepare("delete from masterblocks where cidr='$webvar{block}'");
    1510       $sth->execute;
    1511       $sth = $ip_dbh->prepare("delete from freeblocks where cidr='$webvar{block}'");
    1512       $sth->execute;
    1513       $ip_dbh->commit;
    1514     };
    1515     if ($@) {
    1516       carp "Transaction aborted because $@";
    1517       eval { $ip_dbh->rollback; };
    1518       syslog "err", "$authuser could not remove master block '$webvar{block}': '$@'";
    1519       printAndExit("Could not remove master block $webvar{block}: $@");
    1520     }
    1521     print "<div class=heading align=center>Success!  Master $webvar{block} removed.</div>\n";
    1522     syslog "notice", "$authuser removed master block $webvar{block}";
    1523 
    1524   } else { # end alloctype master block case
    1525 
    1526     ## This is a big block; but it HAS to be done in a chunk.  Any removal
    1527     ## of a netblock allocation may result in a larger chunk of free
    1528     ## contiguous IP space - which may in turn be combined into a single
    1529     ## netblock rather than a number of smaller netblocks.
    1530 
    1531     eval {
    1532 
    1533       my $cidr = new NetAddr::IP $webvar{block};
    1534       if ($webvar{alloctype} eq 'rr') {
    1535 
    1536         $sth = $ip_dbh->prepare("delete from routed where cidr='$webvar{block}'");
    1537         $sth->execute;
    1538         # Make sure block getting deleted is properly accounted for.
    1539         $sth = $ip_dbh->prepare("update freeblocks set routed='n',city='<NULL>'".
    1540                 " where cidr='$webvar{block}'");
    1541         $sth->execute;
    1542         # Set up query to start compacting free blocks.
    1543         $sth = $ip_dbh->prepare("select * from freeblocks where ".
    1544                 "maskbits<=".$cidr->masklen." and routed='n' order by maskbits desc");
    1545 
    1546       } else { # end alloctype routing case
    1547 
    1548         $sth = $ip_dbh->prepare("delete from allocations where cidr='$webvar{block}'");
    1549         $sth->execute;
    1550         # Special case - delete pool IPs
    1551         if ($webvar{alloctype} =~ /^[cdsmw]p$/) {
    1552           # We have to delete the IPs from the pool listing.
    1553           $sth = $ip_dbh->prepare("delete from poolips where pool='$webvar{block}'");
    1554           $sth->execute;
    1555         }
    1556 
    1557         # Set up query for compacting free blocks.
    1558         $sth = $ip_dbh->prepare("select * from freeblocks where cidr << ".
    1559                 "(select cidr from routed where cidr >> '$cidr') ".
    1560                 " and maskbits<=".$cidr->masklen." and routed='y' order by maskbits desc");
    1561 
    1562       } # end alloctype general case
    1563 
    1564 ##TEMP
    1565 ## Temporary wrapper to "properly" deallocate sIP PPPoE/DSL "netblocks" in 209.91.185.0/24
    1566 my $staticpool = new NetAddr::IP "209.91.185.0/24";
    1567 ##TEMP
    1568 if ($cidr->within($staticpool)) {
    1569 ##TEMP
    1570   # We've already deleted the block, now we have to stuff its IPs into the pool.
    1571   $sth = $ip_dbh->prepare("insert into poolips values ('209.91.185.0/24',?,'6750400','Sudbury','d','y','','','')");
    1572   $sth->execute($cidr->addr);
    1573   foreach my $ip ($cidr->hostenum) {
    1574     $sth->execute("$ip");
    1575   }
    1576   $cidr--;
    1577   $sth->execute($cidr->addr);
    1578 
    1579 ##TEMP
    1580 } else {
    1581 ##TEMP
    1582 
    1583       # Now we look for larger-or-equal-sized free blocks in the same master (routed)
    1584       # (super)block. If there aren't any, we can't combine blocks anyway.  If there
    1585       # are, we check to see if we can combine blocks.
    1586       # Execute the statement prepared in the if-else above.
    1587 
    1588       $sth->execute;
    1589 
    1590 # NetAddr::IP->compact() attempts to produce the smallest inclusive block
    1591 # from the caller and the passed terms.
    1592 # EG:  if you call $cidr->compact($ip1,$ip2,$ip3) when $cidr, $ip1, $ip2,
    1593 #       and $ip3 are consecutive /27's starting on .0 (.0-.31, .32-.63,
    1594 #       .64-.95, and .96-.128), you will get an array containing a single
    1595 #       /25 as element 0 (.0-.127).  Order is not important;  you could have
    1596 #       $cidr=.32/27, $ip1=.96/27, $ip2=.0/27, and $ip3=.64/27.
    1597 
    1598       my (@together, @combinelist);
    1599       my $i=0;
    1600       while (my @data = $sth->fetchrow_array) {
    1601         my $testIP = new NetAddr::IP $data[0];
    1602         @together = $testIP->compact($cidr);
    1603         my $num = @together;
    1604         if ($num == 1) {
    1605           $cidr = $together[0];
    1606           $combinelist[$i++] = $testIP;
    1607         }
    1608       }
    1609 
    1610       # Clear old freeblocks entries - if any.  $i==0 if not.
    1611       if ($i>0) {
    1612         $sth = $ip_dbh->prepare("delete from freeblocks where cidr=?");
    1613         foreach my $block (@combinelist) {
    1614           $sth->execute("$block");
    1615         }
    1616       }
    1617 
    1618       # insert "new" freeblocks entry
    1619       if ($webvar{alloctype} eq 'rr') {
    1620         $sth = $ip_dbh->prepare("insert into freeblocks values ('$cidr',".$cidr->masklen.
    1621                 ",'<NULL>','n')");
    1622       } else {
    1623         $sth = $ip_dbh->prepare("insert into freeblocks values ('$cidr',".$cidr->masklen.
    1624                 ",(select city from routed where cidr >>= '$cidr'),'y')");
    1625       }
    1626       $sth->execute;
    1627 
    1628 ##TEMP
    1629 }
    1630 ##TEMP
    1631 
    1632       # If we got here, we've succeeded.  Whew!
    1633       $ip_dbh->commit;
    1634     }; # end eval
    1635     if ($@) {
    1636       carp "Transaction aborted because $@";
    1637       eval { $ip_dbh->rollback; };
    1638       syslog "err", "$authuser could not deallocate netblock '$webvar{block}': '$@'";
    1639       printAndExit("Could not deallocate netblock $webvar{block}: $@");
    1640     }
    1641     print "<div class=heading align=center>Success!  $webvar{block} deleted.</div>\n";
    16421285    syslog "notice", "$authuser deallocated '$webvar{alloctype}'-type netblock $webvar{block}";
    1643 
    1644   } # end alloctype != netblock
    1645 
    1646   printFooter;
     1286  } else {
     1287    if ($webvar{alloctype} =~ /^.i$/) {
     1288      syslog "err", "$authuser could not deallocate static IP '$webvar{block}': '$msg'";
     1289      printError("Could not deallocate static IP $webvar{block}: $msg");
     1290    } else {
     1291      syslog "err", "$authuser could not deallocate netblock '$webvar{block}': '$msg'";
     1292      printError("Could not deallocate netblock $webvar{block}: $msg");
     1293    }
     1294  }
     1295
    16471296} # finalDelete
    16481297
Note: See TracChangeset for help on using the changeset viewer.