| 1 |
95b003ff
|
Origo
|
#!/usr/bin/perl
|
| 2 |
|
|
|
| 3 |
|
|
# All rights reserved and Copyright (c) 2020 Origo Systems ApS.
|
| 4 |
|
|
# This file is provided with no warranty, and is subject to the terms and conditions defined in the license file LICENSE.md.
|
| 5 |
|
|
# The license file is part of this source code package and its content is also available at:
|
| 6 |
|
|
# https://www.origo.io/info/stabiledocs/licensing/stabile-open-source-license
|
| 7 |
|
|
|
| 8 |
|
|
package Stabile::Networks;
|
| 9 |
|
|
|
| 10 |
|
|
use Error qw(:try);
|
| 11 |
|
|
use Data::Dumper;
|
| 12 |
|
|
use Time::Local;
|
| 13 |
|
|
use Time::HiRes qw( time );
|
| 14 |
|
|
use Data::UUID;
|
| 15 |
|
|
use Net::Netmask;
|
| 16 |
|
|
use Net::Ping;
|
| 17 |
6372a66e
|
hq
|
use Proc::Daemon;
|
| 18 |
95b003ff
|
Origo
|
use File::Basename;
|
| 19 |
|
|
use List::Util qw(shuffle);
|
| 20 |
|
|
use lib dirname (__FILE__);
|
| 21 |
|
|
use Stabile;
|
| 22 |
|
|
|
| 23 |
2a63870a
|
Christian Orellana
|
($datanic, $extnic) = $main::getNics->();
|
| 24 |
95b003ff
|
Origo
|
$extsubnet = $Stabile::config->get('EXTERNAL_SUBNET_SIZE');
|
| 25 |
|
|
$proxynic = $Stabile::config->get('PROXY_NIC') || $extnic;
|
| 26 |
|
|
$proxyip = $Stabile::config->get('PROXY_IP');
|
| 27 |
|
|
$proxygw = $Stabile::config->get('PROXY_GW') || $proxyip;
|
| 28 |
|
|
$proxysubnet = $Stabile::config->get('PROXY_SUBNET_SIZE');
|
| 29 |
|
|
my $engineid = $Stabile::config->get('ENGINEID') || "";
|
| 30 |
|
|
$dodns = $Stabile::config->get('DO_DNS') || "";
|
| 31 |
71b897d3
|
hq
|
$enginelinked = $Stabile::config->get('ENGINE_LINKED') || "";
|
| 32 |
95b003ff
|
Origo
|
|
| 33 |
|
|
my $tenders = $Stabile::config->get('STORAGE_POOLS_ADDRESS_PATHS');
|
| 34 |
|
|
@tenderlist = split(/,\s*/, $tenders);
|
| 35 |
|
|
my $tenderpaths = $Stabile::config->get('STORAGE_POOLS_LOCAL_PATHS') || "/mnt/stabile/images";
|
| 36 |
|
|
@tenderpathslist = split(/,\s*/, $tenderpaths);
|
| 37 |
|
|
my $tendernames = $Stabile::config->get('STORAGE_POOLS_NAMES') || "Standard storage";
|
| 38 |
|
|
@tendernameslist = split(/,\s*/, $tendernames);
|
| 39 |
|
|
$storagepools = $Stabile::config->get('STORAGE_POOLS_DEFAULTS') || "0";
|
| 40 |
|
|
|
| 41 |
|
|
$uiuuid;
|
| 42 |
|
|
$uistatus;
|
| 43 |
|
|
$help = 0; # If this is set, functions output help
|
| 44 |
|
|
|
| 45 |
|
|
#our %options=();
|
| 46 |
|
|
# -a action -h help -u uuid -m match pattern -f full list, i.e. all users
|
| 47 |
|
|
# -v verbose, include HTTP headers -s impersonate subaccount -t target [uuid or image]
|
| 48 |
|
|
# -g args to gearman task
|
| 49 |
|
|
#Getopt::Std::getopts("a:hfu:g:m:vs:t:", \%options);
|
| 50 |
|
|
|
| 51 |
|
|
try {
|
| 52 |
|
|
Init(); # Perform various initalization tasks
|
| 53 |
|
|
process() if ($package);
|
| 54 |
|
|
|
| 55 |
|
|
} catch Error with {
|
| 56 |
|
|
my $ex = shift;
|
| 57 |
|
|
print header('text/html', '500 Internal Server Error') unless ($console);
|
| 58 |
|
|
if ($ex->{-text}) {
|
| 59 |
|
|
print "Got error: ", $ex->{-text}, " on line ", $ex->{-line}, "\n";
|
| 60 |
|
|
} else {
|
| 61 |
|
|
print "Status=ERROR\n";
|
| 62 |
|
|
}
|
| 63 |
|
|
} finally {
|
| 64 |
|
|
};
|
| 65 |
|
|
|
| 66 |
|
|
1;
|
| 67 |
|
|
|
| 68 |
|
|
sub getObj {
|
| 69 |
|
|
my %h = %{@_[0]};
|
| 70 |
|
|
$console = 1 if $h{"console"};
|
| 71 |
|
|
$api = 1 if $h{"api"};
|
| 72 |
|
|
my $uuid = $h{"uuid"};
|
| 73 |
eb31fb38
|
hq
|
my $obj;
|
| 74 |
|
|
$action = $action || $h{'action'};
|
| 75 |
|
|
if (
|
| 76 |
|
|
$action =~ /^dns/
|
| 77 |
|
|
) {
|
| 78 |
|
|
$obj = \%h;
|
| 79 |
|
|
return $obj;
|
| 80 |
|
|
}
|
| 81 |
95b003ff
|
Origo
|
$uuid = $curuuid if ($uuid eq 'this');
|
| 82 |
d3d1a2d4
|
Origo
|
if ($uuid =~ /(\d+\.\d+\.\d+\.\d+)/) { # ip addresses are unique across networks so we allow this
|
| 83 |
|
|
foreach my $val (values %register) {
|
| 84 |
|
|
if ($val->{'internalip'} eq $uuid || $val->{'externalip'} eq $uuid) {
|
| 85 |
|
|
$uuid = $val->{'uuid'};
|
| 86 |
|
|
last;
|
| 87 |
|
|
}
|
| 88 |
|
|
}
|
| 89 |
|
|
}
|
| 90 |
95b003ff
|
Origo
|
my $dbobj = $register{$uuid} || {};
|
| 91 |
|
|
my $status = $dbobj->{'status'} || $h{"status"}; # Trust db status if it exists
|
| 92 |
c899e439
|
Origo
|
if ((!$uuid && $uuid ne '0') && (!$status || $status eq 'new') && ($action eq 'save')) {
|
| 93 |
95b003ff
|
Origo
|
my $ug = new Data::UUID;
|
| 94 |
|
|
$uuid = $ug->create_str();
|
| 95 |
|
|
$status = 'new';
|
| 96 |
|
|
};
|
| 97 |
|
|
return 0 unless ($uuid && length $uuid == 36);
|
| 98 |
|
|
|
| 99 |
|
|
$uiuuid = $uuid;
|
| 100 |
|
|
$uistatus = $dbobj->{'status'};
|
| 101 |
|
|
|
| 102 |
|
|
my $id = $h{"id"};
|
| 103 |
|
|
my $dbid = 0+$dbobj->{'id'};
|
| 104 |
|
|
if ($status eq 'new' || !$dbid) {
|
| 105 |
|
|
$id = getNextId($id) ;
|
| 106 |
|
|
} else {
|
| 107 |
|
|
$id = $dbid;
|
| 108 |
|
|
}
|
| 109 |
|
|
|
| 110 |
|
|
if ($id > 4095 || $id < 0 || ($id==0 && $uuid!=0) || ($id==1 && $uuid!=1)) {
|
| 111 |
|
|
$postreply .= "Status=ERROR Invalid new network id $id\n";
|
| 112 |
|
|
return;
|
| 113 |
|
|
}
|
| 114 |
|
|
my $name = $h{"name"} || $dbobj->{'name'};
|
| 115 |
|
|
my $internalip = $h{"internalip"} || $dbobj->{'internalip'};
|
| 116 |
|
|
if (!($internalip =~ /\d+\.\d+\.\d+\.\d+/)) {$internalip = ""};
|
| 117 |
|
|
my $externalip = $h{"externalip"} || $dbobj->{'externalip'};
|
| 118 |
|
|
my $ports = $h{"ports"} || $dbobj->{'ports'};
|
| 119 |
|
|
my $type = $h{"type"} || $dbobj->{'type'};
|
| 120 |
d3d1a2d4
|
Origo
|
my $systems = $h{"systems"} || $dbobj->{'systems'};
|
| 121 |
|
|
my $force = $h{"force"};
|
| 122 |
95b003ff
|
Origo
|
my $reguser = $dbobj->{'user'};
|
| 123 |
|
|
# Sanity checks
|
| 124 |
|
|
if (
|
| 125 |
|
|
($name && length $name > 255)
|
| 126 |
|
|
|| ($ports && length $ports > 255)
|
| 127 |
6372a66e
|
hq
|
|| ($type && !($type =~ /gateway|ipmapping|internalip|externalip|remoteip/))
|
| 128 |
95b003ff
|
Origo
|
) {
|
| 129 |
|
|
$postreply .= "Stroke=ERROR Bad network data: $name\n";
|
| 130 |
|
|
return;
|
| 131 |
|
|
}
|
| 132 |
|
|
# Security check
|
| 133 |
d24d9a01
|
hq
|
if (($user ne $reguser && index($privileges,"a")==-1 && $action ne 'save' ) ||
|
| 134 |
95b003ff
|
Origo
|
($reguser && $status eq "new"))
|
| 135 |
|
|
{
|
| 136 |
d24d9a01
|
hq
|
$postreply .= "Stroke=ERROR Bad user: $user, $action\n";
|
| 137 |
95b003ff
|
Origo
|
return;
|
| 138 |
|
|
}
|
| 139 |
|
|
|
| 140 |
6372a66e
|
hq
|
if (!$type ||($type ne 'gateway' && $type ne 'internalip' && $type ne 'ipmapping' && $type ne 'externalip' && $type ne 'remoteip')) {
|
| 141 |
95b003ff
|
Origo
|
$type = "gateway";
|
| 142 |
|
|
if ($internalip && $internalip ne "--" && $externalip && $externalip ne "--") {$type = "ipmapping";}
|
| 143 |
|
|
elsif (($internalip && $internalip ne "--") || $status eq 'new') {$type = "internalip";}
|
| 144 |
|
|
elsif (($externalip && $externalip ne "--") || $status eq 'new') {$type = "externalip";}
|
| 145 |
d3d1a2d4
|
Origo
|
}
|
| 146 |
95b003ff
|
Origo
|
|
| 147 |
|
|
my $obj = {
|
| 148 |
|
|
uuid => $uuid,
|
| 149 |
|
|
id => $id,
|
| 150 |
|
|
name => $name,
|
| 151 |
|
|
status => $status,
|
| 152 |
|
|
type => $type,
|
| 153 |
|
|
internalip => $internalip,
|
| 154 |
|
|
externalip => $externalip,
|
| 155 |
|
|
ports => $ports,
|
| 156 |
d3d1a2d4
|
Origo
|
systems => $systems,
|
| 157 |
|
|
force => $force,
|
| 158 |
95b003ff
|
Origo
|
action => $h{"action"}
|
| 159 |
|
|
};
|
| 160 |
|
|
return $obj;
|
| 161 |
|
|
}
|
| 162 |
|
|
|
| 163 |
|
|
sub Init {
|
| 164 |
|
|
|
| 165 |
|
|
# Tie database tables to hashes
|
| 166 |
|
|
unless ( tie(%register,'Tie::DBI', Hash::Merge::merge({table=>'networks'}, $Stabile::dbopts)) ) {return "Unable to access network register"};
|
| 167 |
|
|
unless ( tie(%domreg,'Tie::DBI', Hash::Merge::merge({table=>'domains'}, $Stabile::dbopts)) ) {return "Unable to access domain register"};
|
| 168 |
|
|
|
| 169 |
|
|
# simplify globals initialized in Stabile.pm
|
| 170 |
|
|
$tktuser = $tktuser || $Stabile::tktuser;
|
| 171 |
|
|
$user = $user || $Stabile::user;
|
| 172 |
|
|
|
| 173 |
|
|
# Create aliases of functions
|
| 174 |
|
|
*header = \&CGI::header;
|
| 175 |
|
|
|
| 176 |
|
|
*Natall = \&Deactivateall;
|
| 177 |
|
|
*Stopall = \&Deactivateall;
|
| 178 |
|
|
*Restoreall = \&Activateall;
|
| 179 |
|
|
|
| 180 |
|
|
*do_save = \&Save;
|
| 181 |
|
|
*do_tablelist = \&do_list;
|
| 182 |
|
|
*do_jsonlist = \&do_list;
|
| 183 |
|
|
*do_listnetworks = \&do_list;
|
| 184 |
|
|
*do_this = \&do_list;
|
| 185 |
|
|
*do_help = \&action;
|
| 186 |
|
|
*do_remove = \&action;
|
| 187 |
|
|
|
| 188 |
|
|
*do_restoreall = \&privileged_action;
|
| 189 |
|
|
*do_activateall = \&privileged_action;
|
| 190 |
|
|
*do_deactivateall = \&privileged_action;
|
| 191 |
|
|
*do_natall = \&privileged_action;
|
| 192 |
|
|
*do_stopall = \&privileged_action;
|
| 193 |
|
|
*do_stop = \&privileged_action;
|
| 194 |
|
|
*do_activate = \&privileged_action;
|
| 195 |
|
|
*do_deactivate = \&privileged_action;
|
| 196 |
|
|
|
| 197 |
|
|
*do_gear_activate = \&do_gear_action;
|
| 198 |
|
|
*do_gear_deactivate = \&do_gear_action;
|
| 199 |
|
|
*do_gear_stop = \&do_gear_action;
|
| 200 |
|
|
*do_gear_activateall = \&do_gear_action;
|
| 201 |
|
|
*do_gear_restoreall = \&do_gear_action;
|
| 202 |
|
|
*do_gear_deactivateall = \&do_gear_action;
|
| 203 |
|
|
*do_gear_stopall = \&do_gear_action;
|
| 204 |
|
|
*do_gear_natall = \&do_gear_action;
|
| 205 |
|
|
|
| 206 |
|
|
$rx; # Global rx count in bytes
|
| 207 |
|
|
$tx; # Global tx count in bytes
|
| 208 |
|
|
$etcpath = "/etc/stabile/networks";
|
| 209 |
|
|
}
|
| 210 |
|
|
|
| 211 |
|
|
sub do_list {
|
| 212 |
d3d1a2d4
|
Origo
|
my ($uuid, $action, $obj) = @_;
|
| 213 |
95b003ff
|
Origo
|
if ($help) {
|
| 214 |
|
|
return <<END
|
| 215 |
d3d1a2d4
|
Origo
|
GET:uuid:
|
| 216 |
95b003ff
|
Origo
|
List networks current user has access to.
|
| 217 |
|
|
END
|
| 218 |
|
|
}
|
| 219 |
|
|
|
| 220 |
|
|
my $res;
|
| 221 |
|
|
my $filter;
|
| 222 |
|
|
my $statusfilter;
|
| 223 |
|
|
my $uuidfilter;
|
| 224 |
d3d1a2d4
|
Origo
|
$uuid = $obj->{'uuid'} if ($obj->{'uuid'});
|
| 225 |
95b003ff
|
Origo
|
|
| 226 |
|
|
if ($curuuid && ($isadmin || $register{$curuuid}->{'user'} eq $user) && $uripath =~ /networks(\.cgi)?\/(\?|)(this)/) {
|
| 227 |
|
|
$uuidfilter = $curuuid;
|
| 228 |
|
|
} elsif ($uripath =~ /networks(\.cgi)?\/(\?|)(name|status)/) {
|
| 229 |
|
|
$filter = $3 if ($uripath =~ /networks(\.cgi)?\/.*name(:|=)(.+)/);
|
| 230 |
|
|
$statusfilter = $3 if ($uripath =~ /networks(\.cgi)?\/.*status(:|=)(\w+)/);
|
| 231 |
|
|
} elsif ($uripath =~ /networks(\.cgi)?\/(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})/) {
|
| 232 |
d3d1a2d4
|
Origo
|
$uuidfilter = $2;
|
| 233 |
|
|
} elsif ($uuid) {
|
| 234 |
|
|
$uuidfilter = $uuid;
|
| 235 |
95b003ff
|
Origo
|
}
|
| 236 |
|
|
$uuidfilter = $options{u} unless $uuidfilter;
|
| 237 |
|
|
$filter = $1 if ($filter =~ /(.*)\*/);
|
| 238 |
|
|
$statusfilter = '' if ($statusfilter eq '*');
|
| 239 |
|
|
|
| 240 |
|
|
my $curnetwork = URI::Escape::uri_unescape($params{'network'});
|
| 241 |
|
|
my $curnetwork1 = URI::Escape::uri_unescape($params{'network1'});
|
| 242 |
|
|
|
| 243 |
|
|
my $sysuuid;
|
| 244 |
|
|
if ($params{'system'}) {
|
| 245 |
|
|
$sysuuid = $params{'system'};
|
| 246 |
|
|
$sysuuid = $cursysuuid || $curdomuuid if ($params{'system'} eq 'this');
|
| 247 |
|
|
}
|
| 248 |
|
|
|
| 249 |
|
|
$res .= header('application/json') unless ($console || $action eq 'tablelist');
|
| 250 |
|
|
my @curregvalues;
|
| 251 |
|
|
|
| 252 |
6372a66e
|
hq
|
updateBilling();
|
| 253 |
95b003ff
|
Origo
|
my @regkeys;
|
| 254 |
|
|
if ($fulllist) {
|
| 255 |
|
|
@regkeys = keys %register;
|
| 256 |
|
|
} elsif ($uuidfilter && $isadmin) {
|
| 257 |
|
|
@regkeys = (tied %register)->select_where("uuid = '$uuidfilter'");
|
| 258 |
|
|
} else {
|
| 259 |
|
|
@regkeys = (tied %register)->select_where("user = '$user' OR user = 'common'");
|
| 260 |
|
|
}
|
| 261 |
|
|
|
| 262 |
|
|
foreach my $k (@regkeys) {
|
| 263 |
|
|
my $valref = $register{$k};
|
| 264 |
|
|
my $uuid = $valref->{'uuid'};
|
| 265 |
|
|
my $dbuser = $valref->{'user'};
|
| 266 |
|
|
my $type = $valref->{'type'};
|
| 267 |
|
|
my $id = $valref->{'id'};
|
| 268 |
|
|
# Only list networks belonging to current user
|
| 269 |
|
|
if ($dbuser eq "common" || $user eq $dbuser || $fulllist || ($uuidfilter && $isadmin)) {
|
| 270 |
|
|
my $dom = $domreg{$valref->{'domains'}};
|
| 271 |
|
|
next unless (!$sysuuid || $dom->{'system'} eq $sysuuid || $valref->{'domains'} eq $sysuuid);
|
| 272 |
|
|
validateStatus($valref);
|
| 273 |
|
|
my %val = %{$valref}; # Deference and assign to new ass array, effectively cloning object
|
| 274 |
|
|
$val{'id'} += 0;
|
| 275 |
|
|
$val{'rx'} = $rx;
|
| 276 |
|
|
$val{'tx'} = $tx;
|
| 277 |
04c16f26
|
hq
|
$val{'domainnames'} = decode('utf8', $val{'domainnames'});
|
| 278 |
95b003ff
|
Origo
|
if ($filter || $statusfilter || $uuidfilter) { # List filtered networks
|
| 279 |
|
|
my $fmatch;
|
| 280 |
|
|
my $smatch;
|
| 281 |
|
|
my $umatch;
|
| 282 |
|
|
$fmatch = 1 if (!$filter || $val{'name'}=~/$filter/i);
|
| 283 |
|
|
$smatch = 1 if (!$statusfilter || $statusfilter eq 'all'
|
| 284 |
|
|
|| $statusfilter eq $val{'status'}
|
| 285 |
|
|
);
|
| 286 |
|
|
$umatch = 1 if ($val{'uuid'} eq $uuidfilter);
|
| 287 |
|
|
if ($fmatch && $smatch && !$uuidfilter) {
|
| 288 |
|
|
push @curregvalues,\%val;
|
| 289 |
|
|
} elsif ($umatch) {
|
| 290 |
|
|
push @curregvalues,\%val;
|
| 291 |
|
|
last;
|
| 292 |
|
|
}
|
| 293 |
|
|
|
| 294 |
|
|
} elsif ($action eq "listnetworks") { # List available networks
|
| 295 |
c899e439
|
Origo
|
if (($id>0 || index($privileges,"a")!=-1) && ((!$valref->{'domains'} && !$valref->{'systems'}) || $type eq 'gateway' || ($curnetwork eq $uuid && !$curnetwork1) || $curnetwork1 eq $uuid)) {
|
| 296 |
95b003ff
|
Origo
|
push @curregvalues,\%val;
|
| 297 |
|
|
}
|
| 298 |
|
|
} else {
|
| 299 |
|
|
push @curregvalues,\%val if ($id>0 || index($privileges,"a")!=-1);
|
| 300 |
|
|
}
|
| 301 |
|
|
}
|
| 302 |
|
|
}
|
| 303 |
|
|
|
| 304 |
|
|
# Sort @curregvalues
|
| 305 |
|
|
my $sort = 'status';
|
| 306 |
|
|
$sort = $2 if ($uripath =~ /sort\((\+|\-)(\S+)\)/);
|
| 307 |
|
|
my $reverse;
|
| 308 |
|
|
$reverse = 1 if ($1 eq '-');
|
| 309 |
|
|
if ($reverse) { # sort reverse
|
| 310 |
|
|
if ($sort =~ /id/) {
|
| 311 |
|
|
@curregvalues = (sort {$b->{$sort} <=> $a->{$sort}} @curregvalues); # Sort as number
|
| 312 |
|
|
} else {
|
| 313 |
|
|
@curregvalues = (sort {$b->{$sort} cmp $a->{$sort}} @curregvalues); # Sort as string
|
| 314 |
|
|
}
|
| 315 |
|
|
} else {
|
| 316 |
|
|
if ($sort =~ /id/) {
|
| 317 |
|
|
@curregvalues = (sort {$a->{$sort} <=> $b->{$sort}} @curregvalues); # Sort as number
|
| 318 |
|
|
} else {
|
| 319 |
|
|
@curregvalues = (sort {$a->{$sort} cmp $b->{$sort}} @curregvalues); # Sort as string
|
| 320 |
|
|
}
|
| 321 |
|
|
}
|
| 322 |
|
|
|
| 323 |
|
|
my %val = ("uuid", "--", "name", "--");
|
| 324 |
a2e0bc7e
|
hq
|
if ($curnetwork1) { # allow second network to be empty
|
| 325 |
95b003ff
|
Origo
|
push @curregvalues, \%val;
|
| 326 |
|
|
}
|
| 327 |
|
|
if ($action eq 'tablelist') {
|
| 328 |
|
|
$res .= header("text/plain") unless ($console);
|
| 329 |
|
|
my $t2 = Text::SimpleTable->new(36,20,10,5,10,14,14,7);
|
| 330 |
|
|
$t2->row('uuid', 'name', 'type', 'id', 'internalip', 'externalip', 'user', 'status');
|
| 331 |
|
|
$t2->hr;
|
| 332 |
|
|
my $pattern = $options{m};
|
| 333 |
|
|
foreach $rowref (@curregvalues){
|
| 334 |
|
|
if ($pattern) {
|
| 335 |
|
|
my $rowtext = $rowref->{'uuid'} . " " . $rowref->{'name'} . " " . $rowref->{'type'} . " " . $rowref->{'id'}
|
| 336 |
|
|
. " " . $rowref->{'internalip'} . " " . $rowref->{'externalip'} . " " . $rowref->{'user'} . " " . $rowref->{'status'};
|
| 337 |
|
|
$rowtext .= " " . $rowref->{'mac'} if ($isadmin);
|
| 338 |
|
|
next unless ($rowtext =~ /$pattern/i);
|
| 339 |
|
|
}
|
| 340 |
|
|
$t2->row($rowref->{'uuid'}, $rowref->{'name'}||'--', $rowref->{'type'}, $rowref->{'id'},
|
| 341 |
|
|
$rowref->{'internalip'}||'--', $rowref->{'externalip'}||'--', $rowref->{'user'}, $rowref->{'status'});
|
| 342 |
|
|
}
|
| 343 |
|
|
$res .= $t2->draw;
|
| 344 |
|
|
} elsif ($console && !$uuidfilter && $action ne 'jsonlist') {
|
| 345 |
|
|
$res .= Dumper(\@curregvalues);
|
| 346 |
|
|
} else {
|
| 347 |
|
|
my $json_text;
|
| 348 |
|
|
if ($uuidfilter) {
|
| 349 |
|
|
$json_text = to_json($curregvalues[0], {pretty => 1}) if (@curregvalues);
|
| 350 |
|
|
} else {
|
| 351 |
|
|
$json_text = to_json(\@curregvalues, {pretty => 1}) if (@curregvalues);
|
| 352 |
|
|
}
|
| 353 |
|
|
$json_text = "[]" unless $json_text;
|
| 354 |
|
|
$json_text =~ s/""/"--"/g;
|
| 355 |
|
|
$json_text =~ s/null/"--"/g;
|
| 356 |
|
|
$json_text =~ s/undef/"--"/g;
|
| 357 |
|
|
$json_text =~ s/\x/ /g;
|
| 358 |
|
|
$res .= qq|{"action": "$action", "identifier": "uuid", "label": "name", "items": | if ($action && $action ne 'jsonlist' && $action ne 'list' && !$uuidfilter);
|
| 359 |
|
|
$res .= $json_text;
|
| 360 |
|
|
$res .= qq|}| if ($action && $action ne 'jsonlist' && $action ne 'list' && !$uuidfilter);
|
| 361 |
|
|
# $res .= "JSON" if (action eq 'jsonlist');
|
| 362 |
|
|
}
|
| 363 |
|
|
return $res;
|
| 364 |
|
|
}
|
| 365 |
|
|
|
| 366 |
|
|
sub do_uuidlookup {
|
| 367 |
|
|
if ($help) {
|
| 368 |
|
|
return <<END
|
| 369 |
|
|
GET:uuid:
|
| 370 |
|
|
Simple action for looking up a uuid or part of a uuid and returning the complete uuid.
|
| 371 |
|
|
END
|
| 372 |
|
|
}
|
| 373 |
|
|
|
| 374 |
|
|
my $res;
|
| 375 |
|
|
$res .= header('text/plain') unless $console;
|
| 376 |
|
|
my $u = $options{u};
|
| 377 |
|
|
$u = $curuuid unless ($u || $u eq '0');
|
| 378 |
|
|
my $ruuid;
|
| 379 |
|
|
if ($u || $u eq '0') {
|
| 380 |
|
|
foreach my $uuid (keys %register) {
|
| 381 |
|
|
if (($register{$uuid}->{'user'} eq $user || $register{$uuid}->{'user'} eq 'common' || $fulllist)
|
| 382 |
|
|
&& ($uuid =~ /^$u/ || $register{$uuid}->{'name'} =~ /^$u/)) {
|
| 383 |
|
|
$ruuid = $uuid;
|
| 384 |
|
|
last;
|
| 385 |
|
|
}
|
| 386 |
|
|
}
|
| 387 |
|
|
if (!$ruuid && $isadmin) { # If no match and user is admin, do comprehensive lookup
|
| 388 |
|
|
foreach $uuid (keys %register) {
|
| 389 |
|
|
if ($uuid =~ /^$u/ || $register{$uuid}->{'name'} =~ /^$u/) {
|
| 390 |
|
|
$ruuid = $uuid;
|
| 391 |
|
|
last;
|
| 392 |
|
|
}
|
| 393 |
|
|
}
|
| 394 |
|
|
}
|
| 395 |
|
|
}
|
| 396 |
|
|
$res .= "$ruuid\n" if ($ruuid);
|
| 397 |
|
|
return $res;
|
| 398 |
|
|
}
|
| 399 |
|
|
|
| 400 |
|
|
sub do_uuidshow {
|
| 401 |
|
|
if ($help) {
|
| 402 |
|
|
return <<END
|
| 403 |
|
|
GET:uuid:
|
| 404 |
|
|
Simple action for showing a single network.
|
| 405 |
|
|
END
|
| 406 |
|
|
}
|
| 407 |
|
|
|
| 408 |
|
|
my $res;
|
| 409 |
|
|
$res .= header('application/json') unless $console;
|
| 410 |
|
|
my $u = $options{u};
|
| 411 |
|
|
$u = $curuuid unless ($u || $u eq '0');
|
| 412 |
|
|
if ($u || $u eq '0') {
|
| 413 |
|
|
foreach my $uuid (keys %register) {
|
| 414 |
|
|
if (($register{$uuid}->{'user'} eq $user || $register{$uuid}->{'user'} eq 'common' || index($privileges,"a")!=-1)
|
| 415 |
|
|
&& $uuid =~ /^$u/) {
|
| 416 |
|
|
my %hash = %{$register{$uuid}};
|
| 417 |
|
|
delete $hash{'action'};
|
| 418 |
|
|
delete $hash{'nextid'};
|
| 419 |
|
|
# my $dump = Dumper(\%hash);
|
| 420 |
|
|
my $dump = to_json(\%hash, {pretty=>1});
|
| 421 |
|
|
$dump =~ s/undef/"--"/g;
|
| 422 |
|
|
$res .= $dump;
|
| 423 |
|
|
last;
|
| 424 |
|
|
}
|
| 425 |
|
|
}
|
| 426 |
|
|
}
|
| 427 |
|
|
return $res;
|
| 428 |
|
|
}
|
| 429 |
|
|
|
| 430 |
|
|
sub do_updateui {
|
| 431 |
|
|
my ($uuid, $action) = @_;
|
| 432 |
|
|
if ($help) {
|
| 433 |
|
|
return <<END
|
| 434 |
|
|
GET:uuid:
|
| 435 |
|
|
Update the web UI for the given uuid (if user has web UI loaded).
|
| 436 |
|
|
END
|
| 437 |
|
|
}
|
| 438 |
|
|
|
| 439 |
|
|
my $res;
|
| 440 |
|
|
$res .= header('text/plain') unless $console;
|
| 441 |
|
|
if ($register{$uuid}) {
|
| 442 |
|
|
my $uistatus = $register{$uuid}->{'status'};
|
| 443 |
|
|
$main::updateUI->({tab=>"networks", user=>$user, uuid=>$uuid, status=>$uistatus});
|
| 444 |
|
|
$res .= "Status=OK Updated UI for $register{$uuid}->{'type'} $register{$uuid}->{'name'}: $uistatus";
|
| 445 |
|
|
} else {
|
| 446 |
|
|
$main::updateUI->({tab=>"networks", user=>$user});
|
| 447 |
|
|
$res .= "Status=OK Updated networks UI for $user";
|
| 448 |
|
|
}
|
| 449 |
|
|
return $res;
|
| 450 |
|
|
|
| 451 |
|
|
}
|
| 452 |
|
|
|
| 453 |
eb31fb38
|
hq
|
sub do_dnslist {
|
| 454 |
95b003ff
|
Origo
|
my ($uuid, $action) = @_;
|
| 455 |
|
|
if ($help) {
|
| 456 |
|
|
return <<END
|
| 457 |
eb31fb38
|
hq
|
GET:domain:
|
| 458 |
|
|
Lists entries in [domain] or if not specified, the default zone: $dnsdomain.
|
| 459 |
95b003ff
|
Origo
|
END
|
| 460 |
|
|
}
|
| 461 |
|
|
|
| 462 |
eb31fb38
|
hq
|
my $res = $main::dnsList->($engineid, $user, $params{'domain'});
|
| 463 |
95b003ff
|
Origo
|
return $res;
|
| 464 |
|
|
}
|
| 465 |
|
|
|
| 466 |
705b5366
|
hq
|
sub do_envdump {
|
| 467 |
|
|
my ($uuid, $action) = @_;
|
| 468 |
|
|
if ($help) {
|
| 469 |
|
|
return <<END
|
| 470 |
|
|
GET::
|
| 471 |
|
|
Dump environment variables
|
| 472 |
|
|
END
|
| 473 |
|
|
}
|
| 474 |
|
|
return to_json(\%ENV, {pretty=>1});
|
| 475 |
|
|
}
|
| 476 |
|
|
|
| 477 |
|
|
|
| 478 |
eb31fb38
|
hq
|
sub do_dnscreate {
|
| 479 |
48fcda6b
|
Origo
|
my ($uuid, $action) = @_;
|
| 480 |
|
|
if ($help) {
|
| 481 |
|
|
return <<END
|
| 482 |
eb31fb38
|
hq
|
GET:name, value, type:
|
| 483 |
|
|
Create a DNS record in the the subdomain belonging to the user's default DNS domain.
|
| 484 |
|
|
<b>name</b> is a domain name in the Engine's zone. <b>value</b> is either an IP address for A records or a domain name for other. <b>[type]</b> is A, CNAME, TXT or MX.
|
| 485 |
48fcda6b
|
Origo
|
END
|
| 486 |
|
|
}
|
| 487 |
|
|
|
| 488 |
eb31fb38
|
hq
|
my $res = $main::dnsCreate->($engineid, $params{'name'}, $params{'value'}, $params{'type'}, $user);
|
| 489 |
48fcda6b
|
Origo
|
return $res;
|
| 490 |
|
|
}
|
| 491 |
|
|
|
| 492 |
eb31fb38
|
hq
|
sub do_dnsupdate {
|
| 493 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 494 |
e9af6c24
|
Origo
|
if ($help) {
|
| 495 |
|
|
return <<END
|
| 496 |
eb31fb38
|
hq
|
GET:name,value,type,oldname,oldvalue:
|
| 497 |
|
|
Updates CNAME records pointing to a A record with value 'value', to point to the new 'name' in the the default DNS domain.
|
| 498 |
e9af6c24
|
Origo
|
END
|
| 499 |
|
|
}
|
| 500 |
|
|
|
| 501 |
eb31fb38
|
hq
|
my $res = $main::dnsUpdate->($engineid, $obj->{'name'}, $obj->{'value'}, $obj->{'type'}, $obj->{'oldname'}, $obj->{'oldvalue'}, $user);
|
| 502 |
e9af6c24
|
Origo
|
return $res;
|
| 503 |
|
|
}
|
| 504 |
|
|
|
| 505 |
|
|
sub do_dnsclean {
|
| 506 |
|
|
my ($uuid, $action) = @_;
|
| 507 |
|
|
if ($help) {
|
| 508 |
|
|
return <<END
|
| 509 |
|
|
GET::
|
| 510 |
|
|
Remove this engines entries in $dnsdomain zone.
|
| 511 |
|
|
END
|
| 512 |
|
|
}
|
| 513 |
|
|
|
| 514 |
|
|
my $res;
|
| 515 |
|
|
$res .= header('text/plain') unless $console;
|
| 516 |
|
|
$res .= $main::dnsClean->($engineid, $user);
|
| 517 |
|
|
return $res;
|
| 518 |
|
|
}
|
| 519 |
|
|
|
| 520 |
95b003ff
|
Origo
|
sub do_dnscheck {
|
| 521 |
|
|
my ($uuid, $action) = @_;
|
| 522 |
|
|
if ($help) {
|
| 523 |
|
|
return <<END
|
| 524 |
|
|
GET:name:
|
| 525 |
|
|
Checks if a domain name (name[.subdomain]) is available, i.e. not registered,
|
| 526 |
|
|
where subdomain is the subdomain belonging to the the registering engine.
|
| 527 |
|
|
END
|
| 528 |
|
|
}
|
| 529 |
|
|
|
| 530 |
|
|
my $res;
|
| 531 |
|
|
$res .= header('text/plain') unless $console;
|
| 532 |
|
|
my $name = $params{'name'};
|
| 533 |
|
|
$name = $1 if ($name =~ /(.+)\.$dnsdomain$/);
|
| 534 |
48fcda6b
|
Origo
|
if (!$enginelinked) {
|
| 535 |
|
|
$res .= "Status=ERROR You cannot create DNS records - your engine is not linked.\n";
|
| 536 |
|
|
} elsif ($name =~ /^\S+$/ && !(`host $name.$dnsdomain authns1.cabocomm.dk` =~ /has address/)
|
| 537 |
95b003ff
|
Origo
|
&& $name ne 'www'
|
| 538 |
|
|
&& $name ne 'mail'
|
| 539 |
|
|
&& $name ne 'info'
|
| 540 |
|
|
&& $name ne 'admin'
|
| 541 |
|
|
&& $name ne 'work'
|
| 542 |
|
|
&& $name ne 'io'
|
| 543 |
|
|
&& $name ne 'cloud'
|
| 544 |
|
|
&& $name ne 'compute'
|
| 545 |
|
|
&& $name ne 'sso'
|
| 546 |
|
|
&& $name !~ /valve/
|
| 547 |
|
|
) {
|
| 548 |
|
|
$res .= "Status=OK $name.$dnsdomain is available\n";
|
| 549 |
|
|
} else {
|
| 550 |
|
|
$res .= "Status=ERROR $name.$dnsdomain is not available\n";
|
| 551 |
|
|
}
|
| 552 |
|
|
return $res;
|
| 553 |
|
|
}
|
| 554 |
|
|
|
| 555 |
|
|
sub do_dnsdelete {
|
| 556 |
|
|
my ($uuid, $action) = @_;
|
| 557 |
|
|
if ($help) {
|
| 558 |
|
|
return <<END
|
| 559 |
ca937547
|
hq
|
GET:name, value, type:
|
| 560 |
95b003ff
|
Origo
|
Delete a DNS record in the configured zone.
|
| 561 |
|
|
END
|
| 562 |
|
|
}
|
| 563 |
|
|
|
| 564 |
ca937547
|
hq
|
my $res = $main::dnsDelete->($engineid, $params{'name'}, $params{'value'}, $params{'type'}, $user);
|
| 565 |
95b003ff
|
Origo
|
return $res;
|
| 566 |
|
|
}
|
| 567 |
|
|
|
| 568 |
|
|
sub do_getappstoreurl {
|
| 569 |
|
|
my ($uuid, $action) = @_;
|
| 570 |
|
|
if ($help) {
|
| 571 |
|
|
return <<END
|
| 572 |
|
|
GET::
|
| 573 |
45cc3024
|
hq
|
Get URL to the app store belonging to engine or user (uverrides engine default).
|
| 574 |
95b003ff
|
Origo
|
END
|
| 575 |
|
|
}
|
| 576 |
|
|
|
| 577 |
|
|
my $res;
|
| 578 |
|
|
# $res .= header('application/json') unless $console;
|
| 579 |
|
|
# $res .= qq|{"url": "$appstoreurl"}\n|;
|
| 580 |
|
|
$res .= "$appstoreurl\n";
|
| 581 |
|
|
return $res;
|
| 582 |
|
|
}
|
| 583 |
|
|
|
| 584 |
eb31fb38
|
hq
|
sub do_listdnsdomains {
|
| 585 |
|
|
my ($uuid, $action) = @_;
|
| 586 |
|
|
if ($help) {
|
| 587 |
|
|
return <<END
|
| 588 |
|
|
GET::
|
| 589 |
|
|
Get the DNS domains current user has access to.
|
| 590 |
|
|
END
|
| 591 |
|
|
}
|
| 592 |
|
|
unless ( tie(%userreg,'Tie::DBI', Hash::Merge::merge({table=>'users', key=>'username', CLOBBER=>1}, $Stabile::dbopts)) ) {return 0};
|
| 593 |
|
|
my $billto = $userreg{$user}->{'billto'};
|
| 594 |
|
|
my $bdomains = ($userreg{$billto})?$userreg{$billto}->{'dnsdomains'}:'';
|
| 595 |
|
|
my $domains = ($enginelinked)?($userreg{$user}->{'dnsdomains'} || $bdomains || $dnsdomain) :'';
|
| 596 |
|
|
untie %userreg;
|
| 597 |
|
|
my @doms = split(/, ?/, $domains);
|
| 598 |
|
|
my $subdomain = ($enginelinked)?substr($engineid, 0, 8):'';
|
| 599 |
|
|
my $linked = ($enginelinked)?'true':'false';
|
| 600 |
|
|
my $res;
|
| 601 |
|
|
$res .= header('application/json') unless $console;
|
| 602 |
|
|
$res .= qq|{"domains": | . to_json(\@doms) . qq|, "subdomain": "$subdomain", "enginelinked": "$linked", "billto": "$billto", "user": "$user"}|;
|
| 603 |
|
|
return $res;
|
| 604 |
|
|
}
|
| 605 |
|
|
|
| 606 |
95b003ff
|
Origo
|
sub do_getdnsdomain {
|
| 607 |
|
|
my ($uuid, $action) = @_;
|
| 608 |
|
|
if ($help) {
|
| 609 |
|
|
return <<END
|
| 610 |
|
|
GET::
|
| 611 |
eb31fb38
|
hq
|
Get the default DNS domain and the subdomain this Engine registers entries in.
|
| 612 |
95b003ff
|
Origo
|
END
|
| 613 |
|
|
}
|
| 614 |
e9af6c24
|
Origo
|
my $domain = ($enginelinked)?$dnsdomain:'';
|
| 615 |
|
|
my $subdomain = ($enginelinked)?substr($engineid, 0, 8):'';
|
| 616 |
|
|
my $linked = ($enginelinked)?'true':'false';
|
| 617 |
95b003ff
|
Origo
|
my $res;
|
| 618 |
e9af6c24
|
Origo
|
$res .= header('application/json') unless $console;
|
| 619 |
|
|
$res .= qq|{"domain": "$domain", "subdomain": "$subdomain", "enginelinked": "$linked"}|;
|
| 620 |
95b003ff
|
Origo
|
return $res;
|
| 621 |
|
|
}
|
| 622 |
|
|
|
| 623 |
|
|
sub xmppsend {
|
| 624 |
|
|
my ($uuid, $action) = @_;
|
| 625 |
|
|
if ($help) {
|
| 626 |
|
|
return <<END
|
| 627 |
|
|
GET:to, msg:
|
| 628 |
|
|
Send out an xmpp alert.
|
| 629 |
|
|
END
|
| 630 |
|
|
}
|
| 631 |
|
|
if ($help) {
|
| 632 |
|
|
return <<END
|
| 633 |
|
|
Send out an xmpp alert
|
| 634 |
|
|
END
|
| 635 |
|
|
}
|
| 636 |
|
|
|
| 637 |
|
|
my $res;
|
| 638 |
|
|
$res .= header('text/plain') unless $console;
|
| 639 |
|
|
$res .= $main::xmppSend->($params{'to'}, $params{'msg'}, $engineid);
|
| 640 |
|
|
return $res;
|
| 641 |
|
|
}
|
| 642 |
|
|
|
| 643 |
|
|
# List available network types. Possibly limited by exhausted IP ranges.
|
| 644 |
|
|
sub do_listnetworktypes {
|
| 645 |
|
|
if ($help) {
|
| 646 |
|
|
return <<END
|
| 647 |
|
|
GET::
|
| 648 |
|
|
List available network types. Possibly limited by exhausted IP ranges.
|
| 649 |
|
|
END
|
| 650 |
|
|
}
|
| 651 |
|
|
|
| 652 |
|
|
my $res;
|
| 653 |
|
|
$res .= header('application/json') unless $console;
|
| 654 |
|
|
# Check if we have exhausted our IP ranges
|
| 655 |
|
|
my $intipavail = getNextInternalIP();
|
| 656 |
|
|
my $extipavail = getNextExternalIP();
|
| 657 |
|
|
my $arpipavail = getNextExternalIP('','',1);
|
| 658 |
|
|
my $json_text;
|
| 659 |
|
|
$json_text .= '{"type": "gateway", "name": "Gateway"}, ';
|
| 660 |
|
|
$json_text .= '{"type": "internalip", "name": "Internal IP"}, ' if ($intipavail);
|
| 661 |
|
|
unless (overQuotas()) {
|
| 662 |
|
|
$json_text .= '{"type": "ipmapping", "name": "IP mapping"}, ' if ($intipavail && $extipavail);
|
| 663 |
|
|
$json_text .= '{"type": "externalip", "name": "External IP"}, 'if ($arpipavail);
|
| 664 |
a2e0bc7e
|
hq
|
$json_text .= '{"type": "remoteip", "name": "Remote IP"}, 'if ($Stabile::remoteipenabled);
|
| 665 |
95b003ff
|
Origo
|
}
|
| 666 |
|
|
$json_text = substr($json_text,0,-2);
|
| 667 |
|
|
$res .= '{"identifier": "type", "label": "name", "items": [' . $json_text . ']}';
|
| 668 |
|
|
return $res;
|
| 669 |
|
|
}
|
| 670 |
|
|
|
| 671 |
|
|
# Simple action for removing all networks belonging to a user
|
| 672 |
|
|
sub do_removeusernetworks {
|
| 673 |
|
|
my ($uuid, $action) = @_;
|
| 674 |
|
|
if ($help) {
|
| 675 |
|
|
return <<END
|
| 676 |
6372a66e
|
hq
|
GET:username:
|
| 677 |
95b003ff
|
Origo
|
Remove all networks belonging to a user.
|
| 678 |
|
|
END
|
| 679 |
|
|
}
|
| 680 |
6372a66e
|
hq
|
my $username = shift;
|
| 681 |
|
|
return unless ($username && ($isadmin || $user eq $username) && !$isreadonly);
|
| 682 |
|
|
$user = $username;
|
| 683 |
95b003ff
|
Origo
|
my $res;
|
| 684 |
|
|
$res .= header('text/plain') unless $console;
|
| 685 |
|
|
if ($readonly) {
|
| 686 |
|
|
$postreply .= "Status=ERROR Not allowed\n";
|
| 687 |
|
|
} else {
|
| 688 |
|
|
Removeusernetworks($user);
|
| 689 |
|
|
}
|
| 690 |
|
|
$res .= $postreply || "Status=OK Nothing to remove\n";
|
| 691 |
|
|
return $res;
|
| 692 |
|
|
}
|
| 693 |
|
|
|
| 694 |
|
|
# Activate all networks. If restoreall (e.g. after reboot) is called, we only activate networks which have entries in /etc/stabile/network
|
| 695 |
|
|
sub Activateall {
|
| 696 |
|
|
my ($nouuid, $action) = @_;
|
| 697 |
|
|
if ($help) {
|
| 698 |
|
|
return <<END
|
| 699 |
|
|
GET::
|
| 700 |
|
|
Tries to activate all networks. If called as restoreall by an admin, will try to restore all user's networks to saved state, e.g. after a reboot.
|
| 701 |
|
|
END
|
| 702 |
|
|
}
|
| 703 |
|
|
my @regkeys;
|
| 704 |
|
|
if (($action eq "restoreall" || $fulllist) && index($privileges,"a")!=-1) { # Only an administrator is allowed to do this
|
| 705 |
|
|
@regkeys = keys %register;
|
| 706 |
|
|
} else {
|
| 707 |
|
|
@regkeys = (tied %register)->select_where("user='$user'");
|
| 708 |
|
|
}
|
| 709 |
|
|
my $i = 0;
|
| 710 |
|
|
if (!$isreadonly) {
|
| 711 |
|
|
foreach my $key (@regkeys) {
|
| 712 |
|
|
my $valref = $register{$key};
|
| 713 |
|
|
my $uuid = $valref->{'uuid'};
|
| 714 |
|
|
my $type = $valref->{'type'};
|
| 715 |
|
|
my $id = $valref->{'id'};
|
| 716 |
|
|
my $name = $valref->{'name'};
|
| 717 |
|
|
my $internalip = $valref->{'internalip'};
|
| 718 |
|
|
my $externalip = $valref->{'externalip'};
|
| 719 |
|
|
if ($id!=0 && $id!=1 && $id<4095) {
|
| 720 |
|
|
my $caction = "nat";
|
| 721 |
|
|
if (-e "$etcpath/dhcp-hosts-$id") {
|
| 722 |
|
|
if ($action eq "restoreall" && $isadmin) { # If restoring, only activate previously active networks
|
| 723 |
|
|
my $hosts;
|
| 724 |
|
|
$hosts = lc `/bin/cat $etcpath/dhcp-hosts-$id` if (-e "$etcpath/dhcp-hosts-$id");
|
| 725 |
|
|
$caction = "activate" if ($hosts =~ /($internalip|$externalip)/);
|
| 726 |
|
|
} elsif ($action eq "activateall") {
|
| 727 |
|
|
$caction = "activate";
|
| 728 |
|
|
}
|
| 729 |
48fcda6b
|
Origo
|
# TODO: investigate why this is necessary - if we don't do it, networks are not activated
|
| 730 |
|
|
$user = $valref->{'user'};
|
| 731 |
|
|
do_list($uuid, 'list');
|
| 732 |
|
|
|
| 733 |
95b003ff
|
Origo
|
my $res = Activate($uuid, $caction);
|
| 734 |
|
|
if ($res =~ /\w+=(\w+) / ) {
|
| 735 |
|
|
$register{$uuid}->{'status'} = $1 unless (uc $1 eq 'ERROR');
|
| 736 |
|
|
$i ++ unless (uc $1 eq 'ERROR');
|
| 737 |
|
|
} else {
|
| 738 |
|
|
$postreply .= "Status=ERROR Cannot $caction $type $name $uuid: $res\n";
|
| 739 |
|
|
}
|
| 740 |
|
|
}
|
| 741 |
|
|
} else {
|
| 742 |
|
|
$postreply .= "Status=ERROR Cannot $action $type $name\n" unless ($id==0 || $id==1);
|
| 743 |
|
|
}
|
| 744 |
|
|
}
|
| 745 |
|
|
} else {
|
| 746 |
|
|
$postreply .= "Status=ERROR Problem activating all networks\n";
|
| 747 |
|
|
}
|
| 748 |
|
|
if ($postreply =~/Status=ERROR /) {
|
| 749 |
|
|
$postreply = header('text/plain', '500 Internal Server Error') . $postreply unless $console;
|
| 750 |
|
|
}
|
| 751 |
|
|
$postreply .= "Status=OK activated $i networks\n";
|
| 752 |
|
|
$main::updateUI->({tab=>"networks", user=>$user});
|
| 753 |
|
|
updateBilling("$action $user");
|
| 754 |
|
|
return $postreply;
|
| 755 |
|
|
}
|
| 756 |
|
|
|
| 757 |
|
|
# Deactivate all networks
|
| 758 |
|
|
sub Deactivateall {
|
| 759 |
|
|
my ($nouuid, $action) = @_;
|
| 760 |
|
|
if ($help) {
|
| 761 |
|
|
return <<END
|
| 762 |
|
|
GET::
|
| 763 |
|
|
Tries to deactivate all networks. May also be called as natall or stopall.
|
| 764 |
|
|
END
|
| 765 |
|
|
}
|
| 766 |
|
|
|
| 767 |
|
|
my @regkeys;
|
| 768 |
|
|
if ($fulllist && index($privileges,"a")!=-1) { # Only an administrator is allowed to do this
|
| 769 |
|
|
@regkeys = keys %register;
|
| 770 |
|
|
} else {
|
| 771 |
|
|
@regkeys = (tied %register)->select_where("user='$user'");
|
| 772 |
|
|
}
|
| 773 |
|
|
if (!$isreadonly) {
|
| 774 |
|
|
my %ids;
|
| 775 |
|
|
foreach my $key (@regkeys) {
|
| 776 |
|
|
my $valref = $register{$key};
|
| 777 |
|
|
my $uuid = $valref->{'uuid'};
|
| 778 |
|
|
my $type = $valref->{'type'};
|
| 779 |
|
|
my $id = $valref->{'id'};
|
| 780 |
|
|
my $name = $valref->{'name'};
|
| 781 |
|
|
if ($id!=0 && $id!=1 && $id<4095) {
|
| 782 |
|
|
if (-e "$etcpath/dhcp-hosts-$id") {
|
| 783 |
|
|
my $caction = "deactivate";
|
| 784 |
|
|
my $result;
|
| 785 |
|
|
if ($action eq "stopall") {
|
| 786 |
|
|
$caction = "stop";
|
| 787 |
|
|
# Stop also deactivates all networks with same id, so only do this once for each id
|
| 788 |
|
|
if ($ids{$id}) {
|
| 789 |
|
|
$result = $valref->{'status'};
|
| 790 |
|
|
} else {
|
| 791 |
|
|
$result = Stop($id, $caction);
|
| 792 |
|
|
}
|
| 793 |
|
|
$ids{$id} = 1;
|
| 794 |
|
|
} else {
|
| 795 |
|
|
my $res = Deactivate($uuid, $caction);
|
| 796 |
|
|
if ($res =~ /\w+=(\w+) /) {
|
| 797 |
|
|
$register{$uuid}->{'status'} = $1;
|
| 798 |
|
|
} else {
|
| 799 |
|
|
$postreply .= "Status=ERROR Cannot $caction $type $name $uuid: $res\n";
|
| 800 |
|
|
}
|
| 801 |
|
|
}
|
| 802 |
|
|
if ($result =~ /\w+=(.\w+) /) {
|
| 803 |
|
|
$register{$uuid}->{'status'} = $uistatus = $1;
|
| 804 |
|
|
$uiuuid = $uuid;
|
| 805 |
|
|
$postreply .= "Status=OK $caction $type $name $uuid\n";
|
| 806 |
|
|
$main::syslogit->($user, "info", "$caction network $uuid ($id) ");
|
| 807 |
|
|
}
|
| 808 |
|
|
}
|
| 809 |
|
|
} else {
|
| 810 |
|
|
$postreply .= "Status=ERROR Cannot $action $type $name\n" unless ($id==0 || $id==1);
|
| 811 |
|
|
}
|
| 812 |
|
|
}
|
| 813 |
|
|
} else {
|
| 814 |
|
|
$postreply .= "Status=ERROR Problem deactivating all networks\n";
|
| 815 |
|
|
}
|
| 816 |
|
|
if ($postreply =~/Status=ERROR /) {
|
| 817 |
|
|
$res = header('text/plain', '500 Internal Server Error') unless $console;
|
| 818 |
|
|
} else {
|
| 819 |
|
|
$res = header('text/plain') unless $console;
|
| 820 |
|
|
}
|
| 821 |
|
|
$main::updateUI->({tab=>"networks", user=>$user});
|
| 822 |
|
|
updateBilling("$action $user");
|
| 823 |
|
|
return $postreply;
|
| 824 |
|
|
}
|
| 825 |
|
|
|
| 826 |
|
|
sub do_updatebilling {
|
| 827 |
|
|
my ($uuid, $action) = @_;
|
| 828 |
|
|
if ($help) {
|
| 829 |
|
|
return <<END
|
| 830 |
|
|
GET:uuid:
|
| 831 |
|
|
Update network billing for current user.
|
| 832 |
|
|
END
|
| 833 |
|
|
}
|
| 834 |
|
|
|
| 835 |
|
|
my $res;
|
| 836 |
|
|
$res .= header('text/plain') unless $console;
|
| 837 |
|
|
if ($isreadonly) {
|
| 838 |
|
|
$res .= "Status=ERROR Not updating network billing for $user\n";
|
| 839 |
|
|
} else {
|
| 840 |
|
|
updateBilling("updatebilling $user");
|
| 841 |
|
|
$res .= "Status=OK Updated network billing for $user\n";
|
| 842 |
|
|
}
|
| 843 |
|
|
return $res;
|
| 844 |
|
|
}
|
| 845 |
|
|
|
| 846 |
|
|
# Print list of available actions on objects
|
| 847 |
|
|
sub do_plainhelp {
|
| 848 |
|
|
my $res;
|
| 849 |
|
|
$res .= header('text/plain') unless $console;
|
| 850 |
|
|
$res .= <<END
|
| 851 |
|
|
* new [type="ipmapping|internalip|externalip|gateway", name="name"]: Creates a new network
|
| 852 |
|
|
* activate: Activates a network. If gateway is down it is brought up.
|
| 853 |
|
|
* stop: Stops the gateway, effectively stopping network communcation with the outside.
|
| 854 |
|
|
* deactivate: Deactivates a network. Removes the associated internal IP address from the DHCP service.
|
| 855 |
|
|
* delete: Deletes a network. Use with care. Network can not be in use.
|
| 856 |
|
|
|
| 857 |
|
|
END
|
| 858 |
|
|
;
|
| 859 |
|
|
}
|
| 860 |
|
|
|
| 861 |
|
|
sub addDHCPAddress {
|
| 862 |
|
|
my $id = shift;
|
| 863 |
|
|
my $uuid = shift;
|
| 864 |
|
|
my $dhcpip = shift;
|
| 865 |
|
|
my $gateway = shift;
|
| 866 |
|
|
my $mac = lc shift;
|
| 867 |
|
|
my $isexternal = !($dhcpip =~ /^10\./);
|
| 868 |
|
|
my $options;
|
| 869 |
|
|
my $interface = "br$id"; #,$extnic.$id
|
| 870 |
|
|
$options = "--strict-order --bind-interfaces --except-interface=lo --interface=$interface " .
|
| 871 |
|
|
($proxyip?"--dhcp-range=tag:external,$proxyip,static ":"") .
|
| 872 |
|
|
"--pid-file=/var/run/stabile-$id.pid --dhcp-hostsfile=$etcpath/dhcp-hosts-$id --dhcp-range=tag:internal,$gateway,static " .
|
| 873 |
|
|
"--dhcp-optsfile=$etcpath/dhcp-options-$id --port=0 --log-dhcp";
|
| 874 |
|
|
|
| 875 |
|
|
my $running;
|
| 876 |
|
|
my $error;
|
| 877 |
|
|
my $psid;
|
| 878 |
|
|
return "Status=ERROR Empty mac or ip when configuing dhcp for $name" unless ($mac && $dhcpip);
|
| 879 |
|
|
|
| 880 |
|
|
eval {
|
| 881 |
|
|
$psid = `/bin/cat /var/run/stabile-$id.pid` if (-e "/var/run/stabile-$id.pid");
|
| 882 |
|
|
chomp $psid;
|
| 883 |
|
|
$running = -e "/proc/$psid" if ($psid);
|
| 884 |
|
|
# `/bin/ps p $psid` =~ /$psid/
|
| 885 |
|
|
# `/bin/ps ax | /bin/grep stabile-$id.pid | /usr/bin/wc -l`; 1;} or do
|
| 886 |
|
|
1;
|
| 887 |
|
|
} or do {$error .= "Status=ERROR Problem configuring dhcp for $name $@\n";};
|
| 888 |
|
|
|
| 889 |
|
|
if (-e "$etcpath/dhcp-hosts-$id") {
|
| 890 |
|
|
open(TEMP1, "<$etcpath/dhcp-hosts-$id") || ($error .= "Status=ERROR Problem reading dhcp hosts\n");
|
| 891 |
|
|
open(TEMP2, ">$etcpath/dhcp-hosts-$id.new") || ($error .= "Status=ERROR Problem writing dhcp hosts $etcpath/dhcp-hosts-$id.new\n");
|
| 892 |
|
|
while (<TEMP1>) {
|
| 893 |
|
|
my $line = $_;
|
| 894 |
|
|
print TEMP2 $line unless (($mac && $line =~ /^$mac/i) || ($line & $line =~ /.+,$dhcpip/));
|
| 895 |
|
|
}
|
| 896 |
|
|
print TEMP2 "$mac," . (($isexternal)?"set:external,":"set:internal,") . "$dhcpip\n";
|
| 897 |
|
|
close(TEMP1);
|
| 898 |
|
|
close(TEMP2);
|
| 899 |
|
|
rename("$etcpath/dhcp-hosts-$id", "$etcpath/dhcp-hosts-$id.old") || ($error .= "Status=ERROR Problem writing dhcp hosts\n");
|
| 900 |
|
|
rename("$etcpath/dhcp-hosts-$id.new", "$etcpath/dhcp-hosts-$id") || ($error .= "Status=ERROR Problem writing dhcp hosts\n");
|
| 901 |
|
|
} else {
|
| 902 |
|
|
open(TEMP1, ">$etcpath/dhcp-hosts-$id") || ($error .= "Status=ERROR Problem writing dhcp options\n");
|
| 903 |
|
|
print TEMP1 "$mac,$dhcpip\n";
|
| 904 |
|
|
close (TEMP1);
|
| 905 |
|
|
}
|
| 906 |
|
|
|
| 907 |
|
|
# unless (-e "$etcpath/dhcp-options-$id") {
|
| 908 |
|
|
my $block = new Net::Netmask("$proxygw/$proxysubnet");
|
| 909 |
|
|
my $proxymask = $block->mask();
|
| 910 |
|
|
open(TEMP1, ">$etcpath/dhcp-options-$id") || ($error .= "Status=ERROR Problem writing dhcp options\n");
|
| 911 |
|
|
|
| 912 |
e837d785
|
hq
|
# Turns out the VM's gateway has to be $proxyip and not $proxygw in our proxyarp setup
|
| 913 |
95b003ff
|
Origo
|
print TEMP1 <<END;
|
| 914 |
e837d785
|
hq
|
tag:external,option:router,$proxyip
|
| 915 |
95b003ff
|
Origo
|
tag:external,option:netmask,$proxymask
|
| 916 |
|
|
tag:external,option:dns-server,$proxyip
|
| 917 |
|
|
tag:internal,option:router,$gateway
|
| 918 |
|
|
tag:internal,option:netmask,255.255.255.0
|
| 919 |
|
|
tag:internal,option:dns-server,$gateway
|
| 920 |
|
|
option:dns-server,1.1.1.1
|
| 921 |
|
|
END
|
| 922 |
|
|
|
| 923 |
|
|
close (TEMP1);
|
| 924 |
|
|
# }
|
| 925 |
|
|
|
| 926 |
|
|
if ($running) {
|
| 927 |
48fcda6b
|
Origo
|
$main::syslogit->($user, 'info', "HUPing dnsmasq 1: $id");
|
| 928 |
95b003ff
|
Origo
|
eval {`/usr/bin/pkill -HUP -f "stabile-$id.pid"`; 1;} or do {$error .= "Status=ERROR Problem configuring dhcp for $name $@\n";};
|
| 929 |
|
|
} else {
|
| 930 |
|
|
eval {`/usr/sbin/dnsmasq $options`;1;} or do {$error .= "Status=ERROR Problem configuring dhcp for $name $@\n";};
|
| 931 |
|
|
}
|
| 932 |
e5789be5
|
hq
|
# Allow access to DHCP service
|
| 933 |
|
|
`iptables -D INPUT -i br$id -p udp -m udp --dport 67 -j ACCEPT`;
|
| 934 |
|
|
`iptables -I INPUT -i br$id -p udp -m udp --dport 67 -j ACCEPT`;
|
| 935 |
|
|
# Allow access to DNS service
|
| 936 |
|
|
`iptables -D INPUT -i br$id -p udp -m udp --dport 53 -j ACCEPT`;
|
| 937 |
|
|
`iptables -I INPUT -i br$id -p udp -m udp --dport 53 -j ACCEPT`;
|
| 938 |
|
|
`iptables -D INPUT -i br$id -p tcp -m tcp --dport 53 -j ACCEPT`;
|
| 939 |
|
|
`iptables -I INPUT -i br$id -p tcp -m tcp --dport 53 -j ACCEPT`;
|
| 940 |
95b003ff
|
Origo
|
|
| 941 |
|
|
return $error?$error:"OK";
|
| 942 |
|
|
}
|
| 943 |
|
|
|
| 944 |
|
|
sub removeDHCPAddress {
|
| 945 |
|
|
my $id = shift;
|
| 946 |
|
|
my $uuid = shift;
|
| 947 |
|
|
my $dhcpip = shift;
|
| 948 |
|
|
my $mac;
|
| 949 |
|
|
$mac = lc $domreg{$uuid}->{'nicmac1'} if ($domreg{$uuid});
|
| 950 |
|
|
my $isexternal = ($dhcpip =~ /^10\./);
|
| 951 |
|
|
my $running;
|
| 952 |
|
|
my $error;
|
| 953 |
|
|
my $psid;
|
| 954 |
|
|
return "Status=ERROR Empty mac or ip when configuring dhcp for $name" unless ($mac || $dhcpip);
|
| 955 |
|
|
|
| 956 |
|
|
eval {
|
| 957 |
|
|
$psid = `/bin/cat /var/run/stabile-$id.pid` if (-e "/var/run/stabile-$id.pid");
|
| 958 |
|
|
chomp $psid;
|
| 959 |
|
|
$running = -e "/proc/$psid" if ($psid);
|
| 960 |
|
|
1;
|
| 961 |
d3d1a2d4
|
Origo
|
} or do {$error .= "Status=ERROR Problem deconfiguring dhcp for $name $@\n";};
|
| 962 |
95b003ff
|
Origo
|
|
| 963 |
|
|
my $keepup;
|
| 964 |
|
|
if (-e "$etcpath/dhcp-hosts-$id") {
|
| 965 |
|
|
open(TEMP1, "<$etcpath/dhcp-hosts-$id") || ($error .= "Status=ERROR Problem reading dhcp hosts\n");
|
| 966 |
|
|
open(TEMP2, ">$etcpath/dhcp-hosts-$id.new") || ($error .= "Status=ERROR Problem writing dhcp hosts\n");
|
| 967 |
|
|
while (<TEMP1>) {
|
| 968 |
|
|
my $line = $_; chomp $line;
|
| 969 |
|
|
if ($line && $line =~ /(.+),.+,($dhcpip)/) { # Release and remove this mac/ip from lease file
|
| 970 |
80e0b3f5
|
hq
|
$main::syslogit->($user, 'info', "Releasing dhcp lease: br$id $dhcpip $1");
|
| 971 |
|
|
`/usr/bin/dhcp_release br$id $dhcpip $1`;
|
| 972 |
95b003ff
|
Origo
|
} elsif ($mac && $line =~ /^$mac/i) {
|
| 973 |
|
|
# If we find a stale assigment to the mac we are removing, remove this also
|
| 974 |
80e0b3f5
|
hq
|
$main::syslogit->($user, 'info', "Releasing stale dhcp lease: br$id $dhcpip $mac");
|
| 975 |
|
|
`/usr/bin/dhcp_release br$id $dhcpip $mac`;
|
| 976 |
95b003ff
|
Origo
|
} else {
|
| 977 |
|
|
# Keep all other leases, and keep up the daemon if any leases found
|
| 978 |
|
|
print TEMP2 "$line\n";
|
| 979 |
|
|
$keepup = 1 if $line;
|
| 980 |
|
|
}
|
| 981 |
|
|
}
|
| 982 |
|
|
close(TEMP1);
|
| 983 |
|
|
close(TEMP2);
|
| 984 |
|
|
rename("$etcpath/dhcp-hosts-$id", "$etcpath/dhcp-hosts-$id.old") || ($error .= "Status=ERROR Problem writing dhcp hosts\n");
|
| 985 |
|
|
rename("$etcpath/dhcp-hosts-$id.new", "$etcpath/dhcp-hosts-$id") || ($error .= "Status=ERROR Problem writing dhcp hosts\n");
|
| 986 |
|
|
}
|
| 987 |
|
|
|
| 988 |
|
|
if ($keepup) {
|
| 989 |
|
|
if ($running) {
|
| 990 |
48fcda6b
|
Origo
|
$main::syslogit->($user, 'info', "HUPing dnsmasq 2: $id");
|
| 991 |
95b003ff
|
Origo
|
eval {`/usr/bin/pkill -HUP -f "stabile-$id.pid"`; 1;} or do {$error .= "Status=ERROR Problem configuring dhcp for $name $@\n";};
|
| 992 |
|
|
}
|
| 993 |
|
|
} else {
|
| 994 |
|
|
unlink "$etcpath/dhcp-options-$id" if (-e "$etcpath/dhcp-options-$id");
|
| 995 |
|
|
if ($running) {
|
| 996 |
e5789be5
|
hq
|
# Disallow access to DHCP service
|
| 997 |
|
|
`iptables -D INPUT -i br$id -p udp -m udp --dport 67 -j ACCEPT`;
|
| 998 |
|
|
# Disallow access to DNS service
|
| 999 |
|
|
`iptables -D INPUT -i br$id -p udp -m udp --dport 53 -j ACCEPT`;
|
| 1000 |
|
|
`iptables -D INPUT -i br$id -p tcp -m tcp --dport 53 -j ACCEPT`;
|
| 1001 |
95b003ff
|
Origo
|
# Take down dhcp server
|
| 1002 |
|
|
$main::syslogit->($user, 'info', "Killing dnsmasq 3: $id");
|
| 1003 |
|
|
eval {`/usr/bin/pkill -f "stabile-$id.pid"`; 1;} or do {$error .= "Status=ERROR Problem configuring dhcp for $name $@\n";};
|
| 1004 |
|
|
}
|
| 1005 |
|
|
}
|
| 1006 |
|
|
|
| 1007 |
|
|
return $error?$error:"OK";
|
| 1008 |
|
|
}
|
| 1009 |
|
|
|
| 1010 |
|
|
# Helper function
|
| 1011 |
|
|
sub save {
|
| 1012 |
|
|
my ($id, $uuid, $name, $status, $type, $internalip, $externalip, $ports, $buildsystem, $username) = @_;
|
| 1013 |
|
|
my $obj = {
|
| 1014 |
|
|
id => $id,
|
| 1015 |
|
|
uuid => $uuid,
|
| 1016 |
|
|
name => $name,
|
| 1017 |
|
|
status => $status,
|
| 1018 |
|
|
type => $type,
|
| 1019 |
|
|
internalip => $internalip,
|
| 1020 |
|
|
externalip => $externalip,
|
| 1021 |
|
|
ports => $ports,
|
| 1022 |
|
|
buildsystem => $buildsystem,
|
| 1023 |
|
|
username => $username
|
| 1024 |
|
|
};
|
| 1025 |
|
|
return Save($uuid, 'save', $obj);
|
| 1026 |
|
|
}
|
| 1027 |
|
|
|
| 1028 |
|
|
sub Save {
|
| 1029 |
|
|
my ($uuid, $action, $obj) = @_;
|
| 1030 |
|
|
if ($help) {
|
| 1031 |
|
|
return <<END
|
| 1032 |
d3d1a2d4
|
Origo
|
POST:uuid, id, name, internalip, externalip, ports, type, systems, activate:
|
| 1033 |
95b003ff
|
Origo
|
To save a collection of networks you either PUT or POST a JSON array to the main endpoint with objects representing the networks with the changes you want.
|
| 1034 |
|
|
Depending on your privileges not all changes are permitted. If you save without specifying a uuid, a new network is created.
|
| 1035 |
d3d1a2d4
|
Origo
|
For now, [activate] only has effect when creating a new connection with a linked system/server.
|
| 1036 |
95b003ff
|
Origo
|
END
|
| 1037 |
|
|
}
|
| 1038 |
d3d1a2d4
|
Origo
|
$uuid = $obj->{'uuid'} if ($obj->{'uuid'});
|
| 1039 |
04c16f26
|
hq
|
my $regnet = $register{$uuid};
|
| 1040 |
95b003ff
|
Origo
|
my $id = $obj->{id};
|
| 1041 |
|
|
my $name = $obj->{name};
|
| 1042 |
|
|
my $status = $obj->{status};
|
| 1043 |
04c16f26
|
hq
|
my $type = $obj->{type} || $regnet->{type};
|
| 1044 |
95b003ff
|
Origo
|
my $internalip = $obj->{internalip};
|
| 1045 |
|
|
my $externalip = $obj->{externalip};
|
| 1046 |
|
|
my $ports = $obj->{ports};
|
| 1047 |
|
|
my $buildsystem = $obj->{buildsystem};
|
| 1048 |
|
|
my $username = $obj->{username};
|
| 1049 |
d3d1a2d4
|
Origo
|
my $systems = $obj->{systems}; # Optionally link this network to a system
|
| 1050 |
95b003ff
|
Origo
|
|
| 1051 |
|
|
$postreply = "" if ($buildsystem);
|
| 1052 |
|
|
$username = $user unless ($username);
|
| 1053 |
|
|
|
| 1054 |
|
|
$status = $regnet->{'status'} || $status; # Trust db status if it exists
|
| 1055 |
|
|
if ((!$uuid && $uuid ne '0') && $status eq 'new') {
|
| 1056 |
|
|
my $ug = new Data::UUID;
|
| 1057 |
|
|
$uuid = $ug->create_str();
|
| 1058 |
|
|
};
|
| 1059 |
|
|
if ($status eq 'new') {
|
| 1060 |
|
|
$name = 'New Connection' unless ($name);
|
| 1061 |
|
|
}
|
| 1062 |
|
|
unless ($uuid && length $uuid == 36) {
|
| 1063 |
|
|
$postreply .= "Status=Error Invalid uuid $uuid\n";
|
| 1064 |
|
|
return $postreply;
|
| 1065 |
|
|
}
|
| 1066 |
d3d1a2d4
|
Origo
|
my $systemnames = $regnet->{'systemnames'};
|
| 1067 |
95b003ff
|
Origo
|
|
| 1068 |
|
|
my $dbid = 0+$regnet->{'id'};
|
| 1069 |
|
|
if ($status eq 'new' || !$dbid) {
|
| 1070 |
|
|
$id = getNextId($id) ;
|
| 1071 |
|
|
} else {
|
| 1072 |
|
|
$id = $dbid;
|
| 1073 |
|
|
}
|
| 1074 |
|
|
if ($id > 4095 || $id < 0 || ($id==0 && $uuid!=0 && $isadmin) || ($id==1 && $uuid!=1 && $isadmin)) {
|
| 1075 |
|
|
$postreply .= "Status=ERROR Invalid network id $id\n";
|
| 1076 |
|
|
return $postreply;
|
| 1077 |
|
|
}
|
| 1078 |
|
|
$name = $name || $regnet->{'name'};
|
| 1079 |
|
|
$internalip = $internalip || $regnet->{'internalip'};
|
| 1080 |
|
|
if (!($internalip =~ /\d+\.\d+\.\d+\.\d+/)) {$internalip = ''};
|
| 1081 |
|
|
$externalip = $externalip || $regnet->{'externalip'};
|
| 1082 |
|
|
$ports = $ports || $regnet->{'ports'};
|
| 1083 |
|
|
my $reguser = $regnet->{'user'};
|
| 1084 |
|
|
# Sanity checks
|
| 1085 |
|
|
if (
|
| 1086 |
|
|
($name && length $name > 255)
|
| 1087 |
|
|
|| ($ports && length $ports > 255)
|
| 1088 |
6372a66e
|
hq
|
|| ($type && !($type =~ /gateway|ipmapping|internalip|externalip|remoteip/))
|
| 1089 |
95b003ff
|
Origo
|
) {
|
| 1090 |
|
|
$postreply .= "Stroke=ERROR Bad data: $name, $ports, $type\n";
|
| 1091 |
|
|
return $postreply;
|
| 1092 |
|
|
}
|
| 1093 |
|
|
# Security check
|
| 1094 |
|
|
if (($reguser && $username ne $reguser && !$isadmin ) ||
|
| 1095 |
|
|
($reguser && $status eq "new"))
|
| 1096 |
|
|
{
|
| 1097 |
|
|
$postreply .= "Status=Error Bad user: $username ($status)\n";
|
| 1098 |
|
|
return $postreply;
|
| 1099 |
|
|
}
|
| 1100 |
6372a66e
|
hq
|
# Check if remoteip is enabled
|
| 1101 |
a2e0bc7e
|
hq
|
if ($type eq 'remoteip' && !$Stabile::remoteipenabled) {
|
| 1102 |
6372a66e
|
hq
|
$postreply .= "Status=Error remoteip is not enabled on this engine\n";
|
| 1103 |
|
|
return $postreply;
|
| 1104 |
|
|
}
|
| 1105 |
95b003ff
|
Origo
|
my $hit = 0;
|
| 1106 |
|
|
# Check if user is allowed to use network
|
| 1107 |
|
|
my @regvalues = values %register;
|
| 1108 |
|
|
foreach my $val (@regvalues) {
|
| 1109 |
|
|
$dbid = $val->{"id"};
|
| 1110 |
|
|
$dbuser = $val->{"user"};
|
| 1111 |
|
|
if ($dbid == $id && $username ne $dbuser && $dbuser ne "common") {
|
| 1112 |
|
|
$hit = 1;
|
| 1113 |
|
|
last;
|
| 1114 |
|
|
}
|
| 1115 |
|
|
}
|
| 1116 |
|
|
if ($hit && !$isadmin) { # Network is nogo (unless you are an admin)
|
| 1117 |
|
|
$postreply .= "Status=ERROR Network id $id not available\n";
|
| 1118 |
|
|
return $postreply;
|
| 1119 |
|
|
} elsif (!$type) {
|
| 1120 |
|
|
$postreply .= "Status=ERROR Network must have a type\n";
|
| 1121 |
|
|
return $postreply;
|
| 1122 |
|
|
} elsif ($status eq 'down' || $status eq 'new' || $status eq 'nat') {
|
| 1123 |
|
|
# Check if network has been modified or is new
|
| 1124 |
|
|
if ($regnet->{'id'} ne $id ||
|
| 1125 |
|
|
$regnet->{'name'} ne $name ||
|
| 1126 |
|
|
$regnet->{'type'} ne $type ||
|
| 1127 |
|
|
$regnet->{'internalip'} ne $internalip ||
|
| 1128 |
|
|
$regnet->{'externalip'} ne $externalip ||
|
| 1129 |
d3d1a2d4
|
Origo
|
$regnet->{'systems'} ne $systems ||
|
| 1130 |
95b003ff
|
Origo
|
$regnet->{'ports'} ne $ports)
|
| 1131 |
|
|
{
|
| 1132 |
|
|
if ($type eq "externalip") {
|
| 1133 |
|
|
$internalip = "--";
|
| 1134 |
|
|
$externalip = getNextExternalIP($externalip, $uuid, 1);
|
| 1135 |
|
|
if (!$externalip) {
|
| 1136 |
|
|
$postreply .= "Status=ERROR Unable to allocate external proxy IP for $name\n";
|
| 1137 |
|
|
$externalip = "--";
|
| 1138 |
|
|
$internalip = getNextInternalIP($internalip, $uuid, $id);
|
| 1139 |
|
|
$type = "internalip";
|
| 1140 |
|
|
} else {
|
| 1141 |
a2e0bc7e
|
hq
|
$postreply .= "Status=OK Allocated external IP: $externalip UUID: $uuid\n" unless ($regnet->{'externalip'} eq $externalip);
|
| 1142 |
95b003ff
|
Origo
|
if ($dodns) {
|
| 1143 |
e9af6c24
|
Origo
|
$main::dnsCreate->($engineid, $externalip, $externalip, 'A', $user);
|
| 1144 |
95b003ff
|
Origo
|
}
|
| 1145 |
|
|
}
|
| 1146 |
|
|
|
| 1147 |
|
|
} elsif ($type eq "ipmapping") {
|
| 1148 |
|
|
$externalip = getNextExternalIP($externalip, $uuid);
|
| 1149 |
|
|
if (!$externalip) {
|
| 1150 |
|
|
$postreply .= "Status=ERROR Unable to allocate external IP for $name\n";
|
| 1151 |
|
|
$externalip = "--";
|
| 1152 |
|
|
$type = "internalip";
|
| 1153 |
|
|
} else {
|
| 1154 |
|
|
$postreply .= "Status=OK Allocated external IP: $externalip\n" unless ($regnet->{'externalip'} eq $externalip);
|
| 1155 |
|
|
if ($dodns) {
|
| 1156 |
eb31fb38
|
hq
|
$postreply .= "Status=OK Trying to register DNS ";
|
| 1157 |
|
|
$main::dnsCreate->($engineid, $externalip, $externalip, 'A', $user);
|
| 1158 |
95b003ff
|
Origo
|
}
|
| 1159 |
|
|
}
|
| 1160 |
|
|
$internalip = getNextInternalIP($internalip, $uuid, $id);
|
| 1161 |
|
|
if (!$internalip) {
|
| 1162 |
|
|
$postreply .= "Status=ERROR Unable to allocate internal IP for $name\n";
|
| 1163 |
|
|
$internalip = "--";
|
| 1164 |
|
|
$type = "gateway";
|
| 1165 |
|
|
} else {
|
| 1166 |
|
|
$postreply .= "Status=OK Allocated internal IP: $internalip for $name\n" unless ($regnet->{'internalip'} eq $internalip);
|
| 1167 |
|
|
}
|
| 1168 |
|
|
|
| 1169 |
6372a66e
|
hq
|
} elsif ($type eq "remoteip") {
|
| 1170 |
|
|
# Check if engine user has been created
|
| 1171 |
a2e0bc7e
|
hq
|
my $uid = `id -u irigo-$Stabile::engineuser`; chomp $uid;
|
| 1172 |
6372a66e
|
hq
|
if (!$uid) {
|
| 1173 |
a2e0bc7e
|
hq
|
$postreply .= "Status=ERROR Local engine user irigo-$Stabile::engineuser has not been created.\n";
|
| 1174 |
|
|
$postmsg = "ERROR Local engine user irigo-$Stabile::engineuser has not been created";
|
| 1175 |
6372a66e
|
hq
|
} else {
|
| 1176 |
a2e0bc7e
|
hq
|
if (!(-e "/home/irigo-$Stabile::engineuser/.ssh/id_rsa.pub")) { # Generate ssh keys if they don't exist
|
| 1177 |
|
|
`sudo -u irigo-$Stabile::engineuser ssh-keygen -t rsa -b 4096 -N '' -f "/home/irigo-$Stabile::engineuser/.ssh/id_rsa" -C $Stabile::engineuser`;
|
| 1178 |
|
|
my $pubkey = `cat "/home/irigo-$Stabile::engineuser/.ssh/id_rsa.pub"`;
|
| 1179 |
6372a66e
|
hq
|
chomp $pubkey;
|
| 1180 |
|
|
# Upload public key to origo registry
|
| 1181 |
|
|
$postreply .= $main::postToOrigo->($engineid, 'uploadpubkey', $pubkey, 'pubkey');
|
| 1182 |
|
|
}
|
| 1183 |
a2e0bc7e
|
hq
|
$internalip = getNextInternalIP($internalip, $uuid, $id);
|
| 1184 |
|
|
if (!$internalip) {
|
| 1185 |
|
|
$postreply .= "Status=ERROR Unable to allocate internal IP for $name\n";
|
| 1186 |
|
|
$internalip = "--";
|
| 1187 |
|
|
$type = "gateway";
|
| 1188 |
|
|
} else {
|
| 1189 |
|
|
$postreply .= "Status=OK Allocated internal IP: $internalip for $name\n" unless ($regnet->{'internalip'} eq $internalip);
|
| 1190 |
|
|
}
|
| 1191 |
|
|
$externalip = getNextRemoteIP($internalip) unless ($externalip && $externalip ne '--' && $regnet->{'externalip'} eq $externalip);
|
| 1192 |
6372a66e
|
hq
|
if (!$externalip) {
|
| 1193 |
|
|
$postreply .= "Status=ERROR Unable to allocate remote IP $externalip for $name\n";
|
| 1194 |
|
|
$postmsg = "Unable to allocate remote IP $externalip for $name";
|
| 1195 |
|
|
$externalip = "--";
|
| 1196 |
|
|
$type = "internalip";
|
| 1197 |
|
|
} else {
|
| 1198 |
|
|
$postreply .= "Status=OK Acquired remote IP: $externalip\n" unless ($regnet->{'externalip'} eq $externalip);
|
| 1199 |
|
|
if ($dodns) {
|
| 1200 |
|
|
$postreply .= "Status=OK Trying to register DNS ";
|
| 1201 |
|
|
$main::dnsCreate->($engineid, $externalip, $externalip, 'A', $user);
|
| 1202 |
|
|
}
|
| 1203 |
|
|
}
|
| 1204 |
|
|
}
|
| 1205 |
a2e0bc7e
|
hq
|
$ports = "80,443,10001" if ($ports eq '--' || $ports eq '');
|
| 1206 |
6372a66e
|
hq
|
|
| 1207 |
95b003ff
|
Origo
|
} elsif ($type eq "internalip") {
|
| 1208 |
|
|
$externalip = "--";
|
| 1209 |
|
|
$ports = "--";
|
| 1210 |
|
|
my $ointip = $internalip;
|
| 1211 |
|
|
$internalip = getNextInternalIP($internalip, $uuid, $id);
|
| 1212 |
|
|
if (!$internalip) {
|
| 1213 |
|
|
$postreply .= "Status=ERROR Unable to allocate internal IP $internalip ($id, $uuid, $ointip) for $name\n";
|
| 1214 |
|
|
$internalip = "--";
|
| 1215 |
|
|
$type = "gateway";
|
| 1216 |
|
|
} else {
|
| 1217 |
d3d1a2d4
|
Origo
|
$postreply .= "Status=OK Allocated internal IP: $internalip for $name\n" unless ($regnet->{'internalip'} eq $internalip);
|
| 1218 |
95b003ff
|
Origo
|
}
|
| 1219 |
|
|
|
| 1220 |
|
|
} elsif ($type eq "gateway") {
|
| 1221 |
|
|
# $internalip = "--";
|
| 1222 |
|
|
# $externalip = "--";
|
| 1223 |
|
|
# $ports = "--";
|
| 1224 |
|
|
} else {
|
| 1225 |
|
|
$postreply .= "Status=ERROR Network must have a valid type\n";
|
| 1226 |
|
|
return $postreply;
|
| 1227 |
|
|
}
|
| 1228 |
|
|
# Validate ports
|
| 1229 |
|
|
my @portslist = split(/, ?| /, $ports);
|
| 1230 |
|
|
if ($ports ne "--") {
|
| 1231 |
|
|
foreach my $port (@portslist) {
|
| 1232 |
|
|
my $p = $port; # Make a copy of var
|
| 1233 |
|
|
if ($p =~ /(\d+\.\d+\.\d+\.\d+):(\d+)/) {
|
| 1234 |
|
|
$p = $2;
|
| 1235 |
|
|
};
|
| 1236 |
|
|
$p = 0 unless ($p =~ /\d+/);
|
| 1237 |
|
|
if ($p<1 || $p>65535) {
|
| 1238 |
|
|
$postreply .= "Status=ERROR Invalid port mapping for $name\n";
|
| 1239 |
a2e0bc7e
|
hq
|
$postmsg = "Invalid port mapping";
|
| 1240 |
|
|
if ($type eq "remoteip") {
|
| 1241 |
|
|
@portslist = (80,443,10001);
|
| 1242 |
|
|
} else {
|
| 1243 |
|
|
$ports = "--";
|
| 1244 |
|
|
}
|
| 1245 |
95b003ff
|
Origo
|
last;
|
| 1246 |
|
|
}
|
| 1247 |
|
|
}
|
| 1248 |
|
|
}
|
| 1249 |
|
|
if ($ports ne "--") {
|
| 1250 |
|
|
$ports = join(',', @portslist);
|
| 1251 |
|
|
}
|
| 1252 |
d3d1a2d4
|
Origo
|
if ($systems ne $regnet->{'systems'}) {
|
| 1253 |
|
|
my $regsystems = $regnet->{'systems'};
|
| 1254 |
|
|
unless (tie(%sysreg,'Tie::DBI', Hash::Merge::merge({table=>'systems'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access systems register"}|; return $res;};
|
| 1255 |
|
|
|
| 1256 |
|
|
# Remove existing link to system
|
| 1257 |
|
|
if ($sysreg{$regsystems}) {
|
| 1258 |
|
|
$sysreg{$regsystems}->{'networkuuids'} =~ s/$uuid,? ?//;
|
| 1259 |
|
|
$sysreg{$regsystems}->{'networknames'} = s/$regnet->{'name'},? ?//;
|
| 1260 |
|
|
} elsif ($domreg{$regsystems}) {
|
| 1261 |
|
|
$domreg{$regsystems}->{'networkuuids'} =~ s/$uuid,? ?//;
|
| 1262 |
|
|
$domreg{$regsystems}->{'networknames'} = s/$regnet->{'name'},? ?//;
|
| 1263 |
|
|
}
|
| 1264 |
|
|
if ($systems) {
|
| 1265 |
|
|
if ($sysreg{$systems}) { # Add new link to system
|
| 1266 |
|
|
$sysreg{$systems}->{'networkuuids'} .= (($sysreg{$systems}->{'networkuuids'}) ? ',' : '') . $uuid;
|
| 1267 |
|
|
$sysreg{$systems}->{'networknames'} .= (($sysreg{$systems}->{'networknames'}) ? ',' : '') . $name;
|
| 1268 |
|
|
$systemnames = $sysreg{$systems}->{'name'};
|
| 1269 |
|
|
} elsif ($domreg{$systems}) {
|
| 1270 |
|
|
$domreg{$systems}->{'networkuuids'} .= (($domreg{$systems}->{'networkuuids'}) ? ',' : '') . $uuid;
|
| 1271 |
|
|
$domreg{$systems}->{'networknames'} .= (($domreg{$systems}->{'networknames'}) ? ',' : '') . $name;
|
| 1272 |
|
|
$systemnames = $domreg{$systems}->{'name'};
|
| 1273 |
|
|
} else {
|
| 1274 |
|
|
$systems = '';
|
| 1275 |
|
|
}
|
| 1276 |
|
|
}
|
| 1277 |
|
|
tied(%sysreg)->commit;
|
| 1278 |
|
|
untie(%sysreg);
|
| 1279 |
|
|
}
|
| 1280 |
6372a66e
|
hq
|
|
| 1281 |
95b003ff
|
Origo
|
$register{$uuid} = {
|
| 1282 |
|
|
uuid=>$uuid,
|
| 1283 |
|
|
user=>$username,
|
| 1284 |
|
|
id=>$id,
|
| 1285 |
|
|
name=>$name,
|
| 1286 |
|
|
internalip=>$internalip,
|
| 1287 |
|
|
externalip=>$externalip,
|
| 1288 |
|
|
ports=>$ports,
|
| 1289 |
|
|
type=>$type,
|
| 1290 |
d3d1a2d4
|
Origo
|
systems=>$systems,
|
| 1291 |
|
|
systemnames=>$systemnames,
|
| 1292 |
95b003ff
|
Origo
|
action=>""
|
| 1293 |
|
|
};
|
| 1294 |
6fdc8676
|
hq
|
my $res = tied(%register)->commit;
|
| 1295 |
|
|
my $obj = $register{$uuid};
|
| 1296 |
95b003ff
|
Origo
|
$postreply .= "Status=OK Network $register{$uuid}->{'name'} saved: $uuid\n";
|
| 1297 |
|
|
$postreply .= "Status=OK uuid: $uuid\n" if ($console && $status eq 'new');
|
| 1298 |
|
|
if ($status eq 'new') {
|
| 1299 |
|
|
validateStatus($register{$uuid});
|
| 1300 |
d3d1a2d4
|
Origo
|
$postmsg = "Created connection $name";
|
| 1301 |
|
|
$uiupdatetype = "update";
|
| 1302 |
95b003ff
|
Origo
|
}
|
| 1303 |
6372a66e
|
hq
|
updateBilling("allocate $externalip") if (($type eq "ipmapping" || $type eq "externalip" || $type eq "remoteip") && $externalip && $externalip ne "--");
|
| 1304 |
95b003ff
|
Origo
|
|
| 1305 |
|
|
} else {
|
| 1306 |
|
|
$postreply = "Status=OK Network $uuid ($id) unchanged\n";
|
| 1307 |
|
|
}
|
| 1308 |
|
|
|
| 1309 |
|
|
if ($params{'PUTDATA'}) {
|
| 1310 |
|
|
my %jitem = %{$register{$uuid}};
|
| 1311 |
|
|
my $json_text = to_json(\%jitem);
|
| 1312 |
|
|
$json_text =~ s/null/"--"/g;
|
| 1313 |
|
|
$json_text =~ s/""/"--"/g;
|
| 1314 |
|
|
$postreply = $json_text;
|
| 1315 |
d3d1a2d4
|
Origo
|
$postmsg = $postmsg || "OK, updated network $name";
|
| 1316 |
95b003ff
|
Origo
|
}
|
| 1317 |
|
|
return $postreply;
|
| 1318 |
|
|
|
| 1319 |
|
|
} else {
|
| 1320 |
a2e0bc7e
|
hq
|
$internalip = '--' unless ($internalip);
|
| 1321 |
|
|
$externalip = '--' unless ($externalip);
|
| 1322 |
95b003ff
|
Origo
|
if ($id ne $regnet->{'id'} ||
|
| 1323 |
|
|
$internalip ne $regnet->{'internalip'} || $externalip ne $regnet->{'externalip'}) {
|
| 1324 |
|
|
return "Status=ERROR Cannot modify active network: $uuid\n";
|
| 1325 |
|
|
} elsif ($name ne $regnet->{'name'}) {
|
| 1326 |
|
|
$register{$uuid}->{'name'} = $name;
|
| 1327 |
|
|
$postreply .= "Status=OK Network \"$register{$uuid}->{'name'}\" saved: $uuid\n";
|
| 1328 |
|
|
if ($params{'PUTDATA'}) {
|
| 1329 |
|
|
my %jitem = %{$register{$uuid}};
|
| 1330 |
|
|
my $json_text = to_json(\%jitem);
|
| 1331 |
|
|
$json_text =~ s/null/"--"/g;
|
| 1332 |
|
|
$postreply = $json_text;
|
| 1333 |
d3d1a2d4
|
Origo
|
$postmsg = "OK, updated network $name";
|
| 1334 |
95b003ff
|
Origo
|
}
|
| 1335 |
|
|
} else {
|
| 1336 |
|
|
$postreply .= "Status=OK Nothing to save\n";
|
| 1337 |
|
|
if ($params{'PUTDATA'}) {
|
| 1338 |
|
|
my %jitem = %{$register{$uuid}};
|
| 1339 |
|
|
my $json_text = to_json(\%jitem);
|
| 1340 |
|
|
$json_text =~ s/null/"--"/g;
|
| 1341 |
|
|
$postreply = $json_text;
|
| 1342 |
|
|
}
|
| 1343 |
|
|
}
|
| 1344 |
|
|
}
|
| 1345 |
a2e0bc7e
|
hq
|
return $postreply;
|
| 1346 |
95b003ff
|
Origo
|
}
|
| 1347 |
|
|
|
| 1348 |
|
|
sub Activate {
|
| 1349 |
d3d1a2d4
|
Origo
|
my ($uuid, $action, $obj) = @_;
|
| 1350 |
95b003ff
|
Origo
|
if ($help) {
|
| 1351 |
|
|
return <<END
|
| 1352 |
|
|
GET:uuid:
|
| 1353 |
|
|
Activate a network which must be in status down or nat.
|
| 1354 |
|
|
END
|
| 1355 |
|
|
}
|
| 1356 |
d3d1a2d4
|
Origo
|
$uuid = $obj->{'uuid'} if ($obj->{'uuid'});
|
| 1357 |
95b003ff
|
Origo
|
$action = 'activate' || $action;
|
| 1358 |
d3d1a2d4
|
Origo
|
my $regnet = $register{$uuid};
|
| 1359 |
|
|
my $id = $regnet->{'id'};
|
| 1360 |
|
|
my $name = $regnet->{'name'};
|
| 1361 |
|
|
my $type = $regnet->{'type'};
|
| 1362 |
|
|
my $status = $regnet->{'status'};
|
| 1363 |
|
|
my $domains = $regnet->{'domains'};
|
| 1364 |
|
|
my $systems = $regnet->{'systems'};
|
| 1365 |
|
|
my $internalip = $regnet->{'internalip'};
|
| 1366 |
|
|
my $externalip = $regnet->{'externalip'};
|
| 1367 |
|
|
my $ports = $regnet->{'ports'};
|
| 1368 |
95b003ff
|
Origo
|
my $idleft = ($id>99)?(substr $id,0,-2)+0 : 0;
|
| 1369 |
|
|
my $idright = (substr $id,-2) + 0;
|
| 1370 |
|
|
my $interfaces = `/sbin/ifconfig`;
|
| 1371 |
|
|
my $dom = $domreg{$domains};
|
| 1372 |
|
|
my $nicindex = ($dom->{'networkuuid1'} eq $uuid)?1:
|
| 1373 |
|
|
($dom->{'networkuuid2'} eq $uuid)?2:
|
| 1374 |
|
|
($dom->{'networkuuid3'} eq $uuid)?3:
|
| 1375 |
|
|
0;
|
| 1376 |
|
|
my $nicmac = $dom->{"nicmac$nicindex"};
|
| 1377 |
|
|
my $e;
|
| 1378 |
|
|
|
| 1379 |
a2e0bc7e
|
hq
|
if (!$id || $id==0 || $id==1 || $id>4095) {
|
| 1380 |
95b003ff
|
Origo
|
$postreply .= "Status=ERROR Invalid ID activating $type\n";
|
| 1381 |
|
|
return $postreply;
|
| 1382 |
|
|
} elsif (overQuotas()) { # Enforce quotas
|
| 1383 |
|
|
$postreply .= "Status=ERROR Over quota activating $type " . overQuotas() . "\n";
|
| 1384 |
|
|
return $postreply;
|
| 1385 |
|
|
} elsif (($status ne 'down' && $status ne 'nat')) {
|
| 1386 |
|
|
$postreply .= "Status=ERROR Cannot activate $type $name (current status is: $status)\n";
|
| 1387 |
|
|
return $postreply;
|
| 1388 |
|
|
}
|
| 1389 |
|
|
|
| 1390 |
|
|
# Check if vlan with $id is created and doing nat, if not create it and create the gateway
|
| 1391 |
|
|
unless (-e "/proc/net/vlan/$datanic.$id") {
|
| 1392 |
f222b89c
|
hq
|
eval {`/sbin/vconfig add $datanic $id`;}; # or do {$e=1; $postreply .= "Status=ERROR Problem adding vlan $datanic.$id $@\n"; return $postreply;};
|
| 1393 |
|
|
eval {`/sbin/ifconfig $datanic.$id up`;}; # or do {$e=1; $postreply .= "Status=ERROR Problem activating vlan $datanic.$id $@\n"; return $postreply;};
|
| 1394 |
95b003ff
|
Origo
|
}
|
| 1395 |
|
|
# if (!($interfaces =~ m/$datanic\.$id /)) {
|
| 1396 |
|
|
if (!($interfaces =~ m/br$id /)) {
|
| 1397 |
|
|
# check if gw is created locally
|
| 1398 |
|
|
unless (`arping -C1 -c2 -D -I $datanic.$id 10.$idleft.$idright.1` =~ /reply from/) { # check if gw is created on another engine
|
| 1399 |
|
|
# Create gw
|
| 1400 |
|
|
# eval {`/sbin/ifconfig $datanic.$id 10.$idleft.$idright.1 netmask 255.255.255.0 broadcast 10.$idleft.$idright.255 up`; 1;} or do {
|
| 1401 |
|
|
# $e=1; $postreply .= "Status=ERROR $@\n"; return $postreply;
|
| 1402 |
|
|
# };
|
| 1403 |
|
|
# To support local instances on valve, gw is now created as a bridge
|
| 1404 |
|
|
eval {`/sbin/brctl addbr br$id`; 1;} or do {$e=1; $postreply .= "Status=ERROR $@\n"; return $postreply; };
|
| 1405 |
|
|
eval {`/sbin/brctl addif br$id $datanic.$id`; 1;} or do {$e=1; $postreply .= "Status=ERROR $@\n"; return $postreply; };
|
| 1406 |
|
|
eval {`/sbin/ifconfig br$id 10.$idleft.$idright.1/24 up`; 1;} or do {
|
| 1407 |
|
|
$e=1; $postreply .= "Status=ERROR $@\n"; return $postreply; }
|
| 1408 |
|
|
} else {
|
| 1409 |
|
|
$postreply .= "Status=OK GW is active on another Engine, assuming this is OK\n";
|
| 1410 |
|
|
}
|
| 1411 |
|
|
}
|
| 1412 |
|
|
my $astatus = "nat" unless ($e);
|
| 1413 |
|
|
`/usr/bin/touch $etcpath/dhcp-hosts-$id` unless (-e "$etcpath/dhcp-hosts-$id");
|
| 1414 |
d3d1a2d4
|
Origo
|
if ($action eq "activate") { #} && $domains) {
|
| 1415 |
6372a66e
|
hq
|
if ($type eq "internalip" || $type eq "ipmapping" || $type eq "remoteip") {
|
| 1416 |
d3d1a2d4
|
Origo
|
# Configure internal dhcp server
|
| 1417 |
|
|
if ($domains) {
|
| 1418 |
|
|
my $result = addDHCPAddress($id, $domains, $internalip, "10.$idleft.$idright.1", $nicmac);
|
| 1419 |
|
|
if ($result eq "OK") {
|
| 1420 |
|
|
$astatus = "up" if ($type eq "internalip");
|
| 1421 |
|
|
} else {
|
| 1422 |
|
|
$e = 1;
|
| 1423 |
|
|
$postreply .= "$result\n";
|
| 1424 |
|
|
}
|
| 1425 |
95b003ff
|
Origo
|
}
|
| 1426 |
|
|
|
| 1427 |
|
|
# Also export storage pools to user's network
|
| 1428 |
|
|
my @spl = split(/,\s*/, $storagepools);
|
| 1429 |
|
|
my $reloadnfs;
|
| 1430 |
|
|
my $uid = `id -u irigo-$user`; chomp $uid;
|
| 1431 |
|
|
$uid = `id -u nobody` unless ($uid =~ /\d+/); chomp $uid;
|
| 1432 |
|
|
my $gid = `id -g irigo-$user`; chomp $gid;
|
| 1433 |
|
|
$gid = `id -g nobody` unless ($gid =~ /\d+/); chomp $gid;
|
| 1434 |
|
|
|
| 1435 |
|
|
# We are dealing with multiple upstream routes - configure local routing
|
| 1436 |
|
|
if ($proxynic && $proxynic ne $extnic) {
|
| 1437 |
|
|
if (-e "/etc/iproute2/rt_tables" && !grep(/1 proxyarp/, `cat /etc/iproute2/rt_tables`)) {
|
| 1438 |
|
|
`/bin/echo "1 proxyarp" >> /etc/iproute2/rt_tables`;
|
| 1439 |
|
|
}
|
| 1440 |
|
|
if (!grep(/$datanic\.$id/, `/sbin/ip route show table proxyarp`)) {
|
| 1441 |
|
|
`/sbin/ip route add "10.$idleft.$idright.0/24" dev $datanic.$id table proxyarp`;
|
| 1442 |
|
|
}
|
| 1443 |
|
|
}
|
| 1444 |
|
|
|
| 1445 |
6372a66e
|
hq
|
# Manuipulate NFS exports and related disk quotas.
|
| 1446 |
|
|
# Not needed for externalip's since they dont have access to the internal 10.x.x.x address space
|
| 1447 |
95b003ff
|
Origo
|
foreach my $p (@spl) {
|
| 1448 |
|
|
if ($tenderlist[$p] && $tenderpathslist[$p]) {
|
| 1449 |
|
|
my $fuelpath = $tenderpathslist[$p] . "/$user/fuel";
|
| 1450 |
|
|
unless (-e $fuelpath) {
|
| 1451 |
1a56bdde
|
Origo
|
if ($tenderlist[$p] eq 'local') { # We only support fuel on local tender for now
|
| 1452 |
|
|
`mkdir "$fuelpath"`;
|
| 1453 |
|
|
`chmod 777 "$fuelpath"`;
|
| 1454 |
|
|
}
|
| 1455 |
95b003ff
|
Origo
|
}
|
| 1456 |
|
|
if ($tenderlist[$p] eq "local") {
|
| 1457 |
|
|
`chown irigo-$user:irigo-$user "$fuelpath"`;
|
| 1458 |
|
|
my $mpoint = `df -P "$fuelpath" | tail -1 | cut -d' ' -f 1`;
|
| 1459 |
|
|
chomp $mpoint;
|
| 1460 |
|
|
my $storagequota = $Stabile::userstoragequota;
|
| 1461 |
|
|
if (!$storagequota) {
|
| 1462 |
|
|
$storagequota = $Stabile::config->get('STORAGE_QUOTA');
|
| 1463 |
|
|
}
|
| 1464 |
|
|
my $nfsquota = $storagequota * 1024 ; # quota is in MB
|
| 1465 |
|
|
$nfsquota = 0 if ($nfsquota < 0); # quota of -1 means no limit
|
| 1466 |
d24d9a01
|
hq
|
`setquota -u irigo-$user $nfsquota $nfsquota 0 0 "$mpoint"` if (-e "$mntpoint");
|
| 1467 |
|
|
if (!(`grep "$fuelpath 10\.$idleft\.$idright" /etc/exports`) && -e $fuelpath) {
|
| 1468 |
95b003ff
|
Origo
|
`echo "$fuelpath 10.$idleft.$idright.0/255.255.255.0(sync,no_subtree_check,all_squash,rw,anonuid=$uid,anongid=$gid)" >> /etc/exports`;
|
| 1469 |
|
|
$reloadnfs = 1;
|
| 1470 |
|
|
}
|
| 1471 |
|
|
}
|
| 1472 |
|
|
}
|
| 1473 |
|
|
}
|
| 1474 |
|
|
`/usr/sbin/exportfs -r` if ($reloadnfs); #Reexport nfs shares
|
| 1475 |
|
|
|
| 1476 |
|
|
} elsif ($type eq "externalip") {
|
| 1477 |
d24d9a01
|
hq
|
# A proxy is needed to route traffic, don't go any further if not configured
|
| 1478 |
95b003ff
|
Origo
|
if ($proxyip) {
|
| 1479 |
d24d9a01
|
hq
|
# Set up proxy
|
| 1480 |
95b003ff
|
Origo
|
if (!($interfaces =~ m/$proxyip/ && $interfaces =~ m/br$id:proxy/)) {
|
| 1481 |
|
|
eval {`/sbin/ifconfig br$id:proxy $proxyip/$proxysubnet up`; 1;}
|
| 1482 |
e837d785
|
hq
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up proxy arp gw $proxyip on br$id:proxy $@\n";};
|
| 1483 |
95b003ff
|
Origo
|
eval {`/sbin/ifconfig $proxynic:proxy $proxyip/$proxysubnet up`; 1;}
|
| 1484 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up proxy arp gw $proxynic $@\n";};
|
| 1485 |
|
|
}
|
| 1486 |
d3d1a2d4
|
Origo
|
my $result = "OK";
|
| 1487 |
d24d9a01
|
hq
|
# Configure dhcp server
|
| 1488 |
d3d1a2d4
|
Origo
|
if ($domains) {
|
| 1489 |
|
|
$result = addDHCPAddress($id, $domains, $externalip, "10.$idleft.$idright.1", $nicmac) if ($domains);
|
| 1490 |
|
|
if ($result eq "OK") {
|
| 1491 |
|
|
;
|
| 1492 |
|
|
} else {
|
| 1493 |
|
|
$e = 1;
|
| 1494 |
|
|
$postreply .= "$result\n";
|
| 1495 |
|
|
}
|
| 1496 |
95b003ff
|
Origo
|
}
|
| 1497 |
|
|
} else {
|
| 1498 |
|
|
$postreply .= "Status=ERROR Cannot set up external IP without Proxy ARP gateway\n";
|
| 1499 |
|
|
}
|
| 1500 |
|
|
}
|
| 1501 |
|
|
|
| 1502 |
d24d9a01
|
hq
|
# Handle routing with Iptables
|
| 1503 |
6372a66e
|
hq
|
if ($type eq "ipmapping" || $type eq "internalip" || $type eq "remoteip") {
|
| 1504 |
d24d9a01
|
hq
|
`iptables -I FORWARD -d $internalip -m state --state ESTABLISHED,RELATED -j RETURN`;
|
| 1505 |
|
|
}
|
| 1506 |
95b003ff
|
Origo
|
# Check if external ip exists and routing configured, if not create and configure it
|
| 1507 |
|
|
if ($type eq "ipmapping") {
|
| 1508 |
2a63870a
|
Christian Orellana
|
if ($internalip && $internalip ne "--" && $externalip && $externalip ne "--" && !($interfaces =~ m/$externalip /g)) { # the space is important
|
| 1509 |
64c667ea
|
hq
|
$externalip =~ /\d+\.\d+\.(\d+)\.(\d+)/;
|
| 1510 |
|
|
my $ipend = "$1$2"; # Linux NIC names are limited to 15 chars - we will have to find a way to support long NIC names and bigger than /24 subnets
|
| 1511 |
|
|
$ipend = $2 if (length("$extnic:$id-$ipend")>15);
|
| 1512 |
95b003ff
|
Origo
|
eval {`/sbin/ifconfig $extnic:$id-$ipend $externalip/$extsubnet up`; 1;}
|
| 1513 |
d3d1a2d4
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem adding interface $extnic:$id-$ipend $@\n";};
|
| 1514 |
48fcda6b
|
Origo
|
unless (`ip addr show dev $extnic` =~ /$externalip/) {
|
| 1515 |
|
|
$e=10;
|
| 1516 |
d3d1a2d4
|
Origo
|
$postreply .= "Status=ERROR Problem adding interface $extnic:$id-$ipend\n";
|
| 1517 |
48fcda6b
|
Origo
|
}
|
| 1518 |
d24d9a01
|
hq
|
# `/sbin/iptables -A POSTROUTING -t nat -s $internalip -j LOG --log-prefix "SNAT-POST"`;
|
| 1519 |
|
|
# `/sbin/iptables -A INPUT -t nat -s $internalip -j LOG --log-prefix "SNAT-INPUT"`;
|
| 1520 |
|
|
# `/sbin/iptables -A OUTPUT -t nat -s $internalip -j LOG --log-prefix "SNAT-OUTPUT"`;
|
| 1521 |
|
|
# `/sbin/iptables -A PREROUTING -t nat -s $internalip -j LOG --log-prefix "SNAT-PRE"`;
|
| 1522 |
95b003ff
|
Origo
|
if ($ports && $ports ne "--") { # Port mapping is defined
|
| 1523 |
|
|
my @portslist = split(/, ?| /, $ports);
|
| 1524 |
a2e0bc7e
|
hq
|
foreach my $port (@portslist) {
|
| 1525 |
95b003ff
|
Origo
|
my $ipfilter;
|
| 1526 |
|
|
if ($port =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)(\/\d+)?:(\d+)/) {
|
| 1527 |
|
|
my $portip = "$1.$2.$3.$4$5";
|
| 1528 |
|
|
$port = $6;
|
| 1529 |
|
|
$ipfilter = "-s $portip";
|
| 1530 |
|
|
} else {
|
| 1531 |
|
|
$port = 0 unless ($port =~ /\d+/);
|
| 1532 |
|
|
}
|
| 1533 |
|
|
if ($port<1 || $port>65535) {
|
| 1534 |
|
|
$postreply .= "Status=ERROR Invalid port mapping for $name\n";
|
| 1535 |
|
|
$ports = "--";
|
| 1536 |
|
|
last;
|
| 1537 |
|
|
}
|
| 1538 |
|
|
if ($port>1 || $port<65535) {
|
| 1539 |
d24d9a01
|
hq
|
# DNAT externalip -> internalip
|
| 1540 |
95b003ff
|
Origo
|
eval {`/sbin/iptables -A PREROUTING -t nat -p tcp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`; 1;}
|
| 1541 |
d24d9a01
|
hq
|
or do {$e=2; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1542 |
95b003ff
|
Origo
|
eval {`/sbin/iptables -A PREROUTING -t nat -p udp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`; 1;}
|
| 1543 |
d24d9a01
|
hq
|
or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1544 |
2a63870a
|
Christian Orellana
|
# PREROUTING is not parsed for packets coming from local host...
|
| 1545 |
|
|
eval {`/sbin/iptables -A OUTPUT -t nat -p tcp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`; 1;}
|
| 1546 |
|
|
or do {$e=2; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1547 |
|
|
eval {`/sbin/iptables -A OUTPUT -t nat -p udp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`; 1;}
|
| 1548 |
|
|
or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1549 |
d24d9a01
|
hq
|
# Allow access to ipmapped internal ip on $port
|
| 1550 |
|
|
`iptables -I FORWARD -d $internalip -p tcp --dport $port -j RETURN`;
|
| 1551 |
|
|
`iptables -I FORWARD -d $internalip -p udp --dport $port -j RETURN`;
|
| 1552 |
95b003ff
|
Origo
|
}
|
| 1553 |
|
|
}
|
| 1554 |
|
|
eval {`/sbin/iptables -D INPUT -d $externalip -j DROP`; 1;} # Drop traffic to all other ports
|
| 1555 |
48fcda6b
|
Origo
|
or do {$e=5; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1556 |
95b003ff
|
Origo
|
eval {`/sbin/iptables -A INPUT -d $externalip -j DROP`; 1;} # Drop traffic to all other ports
|
| 1557 |
48fcda6b
|
Origo
|
or do {$e=6; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1558 |
95b003ff
|
Origo
|
} else {
|
| 1559 |
d24d9a01
|
hq
|
# DNAT externalip -> internalip coming from outside , --in-interface $extnic
|
| 1560 |
95b003ff
|
Origo
|
eval {`/sbin/iptables -A PREROUTING -t nat -d $externalip -j DNAT --to $internalip`; 1;}
|
| 1561 |
48fcda6b
|
Origo
|
or do {$e=7; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1562 |
d24d9a01
|
hq
|
# PREROUTING is not parsed for packets coming from local host...
|
| 1563 |
2a63870a
|
Christian Orellana
|
eval {`/sbin/iptables -A OUTPUT -t nat -d $externalip -j DNAT --to $internalip`; 1;}
|
| 1564 |
|
|
or do {$e=7; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1565 |
d24d9a01
|
hq
|
# Allow blanket access to ipmapped internal ip
|
| 1566 |
|
|
`iptables -I FORWARD -d $internalip -j RETURN`;
|
| 1567 |
|
|
}
|
| 1568 |
|
|
# We masquerade packets going to internalip from externalip to avoid confusion
|
| 1569 |
|
|
#eval {`/sbin/iptables -A POSTROUTING -t nat --out-interface br$id -s $externalip -j MASQUERADE`; 1;}
|
| 1570 |
|
|
# or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1571 |
6fdc8676
|
hq
|
|
| 1572 |
|
|
# Masquerade packets from internal ip's not going to our own subnet
|
| 1573 |
|
|
# `/sbin/iptables -D POSTROUTING -t nat --out-interface br$id ! -d 10.$idleft.$idright.0/24 -j MASQUERADE`;
|
| 1574 |
|
|
#eval {`/sbin/iptables -A POSTROUTING -t nat --out-interface br$id ! -d 10.$idleft.$idright.0/24 -j MASQUERADE`; 1;}
|
| 1575 |
|
|
# or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1576 |
|
|
|
| 1577 |
d24d9a01
|
hq
|
# When receiving packet from client, if it's been routed, and outgoing interface is the external interface, SNAT.
|
| 1578 |
|
|
unless ($Stabile::disablesnat) {
|
| 1579 |
|
|
eval {`/sbin/iptables -A POSTROUTING -t nat -s $internalip ! -d 10.$idleft.$idright.0/24 -j SNAT --to-source $externalip`; 1; }
|
| 1580 |
|
|
or do {$e=4; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1581 |
|
|
# eval {`/sbin/iptables -A POSTROUTING -t nat -s $internalip -j SNAT --to-source $externalip`; 1; }
|
| 1582 |
|
|
# or do {$e=4; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1583 |
|
|
eval {`/sbin/iptables -I INPUT -t nat -s $internalip ! -d 10.$idleft.$idright.0/24 -j SNAT --to-source $externalip`; 1; }
|
| 1584 |
|
|
or do {$e=4; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1585 |
|
|
# eval {`/sbin/iptables -I INPUT -t nat -s $internalip -j SNAT --to-source $externalip`; 1; }
|
| 1586 |
|
|
# or do {$e=4; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1587 |
95b003ff
|
Origo
|
}
|
| 1588 |
6372a66e
|
hq
|
if ($e) {
|
| 1589 |
|
|
$main::syslogit->($user, 'info', "Problem $action network $uuid ($name, $id): $@");
|
| 1590 |
|
|
} else {
|
| 1591 |
|
|
$astatus = "up"
|
| 1592 |
|
|
}
|
| 1593 |
|
|
}
|
| 1594 |
|
|
} elsif ($type eq "remoteip") {
|
| 1595 |
a2e0bc7e
|
hq
|
if ($Stabile::remoteipenabled && -e "/home/irigo-$Stabile::engineuser/.ssh/id_rsa") {
|
| 1596 |
|
|
# First activate the ip on remoteipprovider
|
| 1597 |
|
|
my $res = $main::postToOrigo->($engineid, 'activateremoteip', "$externalip:$internalip", 'remotelocalip');
|
| 1598 |
|
|
my $res_obj = JSON::from_json($res);
|
| 1599 |
|
|
my $pid = '--';
|
| 1600 |
|
|
my @remoteports = (80, 443, 10001);
|
| 1601 |
|
|
my $rports;
|
| 1602 |
|
|
if ($ports && $ports ne "--") {
|
| 1603 |
|
|
# Port mapping is defined
|
| 1604 |
|
|
my @portslist = split(/, ?| /, $ports);
|
| 1605 |
|
|
@remoteports = ();
|
| 1606 |
|
|
foreach my $port (@portslist) {
|
| 1607 |
|
|
if ($port =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)(\/\d+)?:(\d+)/) {
|
| 1608 |
|
|
my $portip = "$1.$2.$3.$4$5";
|
| 1609 |
|
|
$port = $6;
|
| 1610 |
|
|
} else {
|
| 1611 |
|
|
$port = 0 unless ($port =~ /\d+/);
|
| 1612 |
|
|
}
|
| 1613 |
|
|
if ($port < 1 || $port > 65535) {
|
| 1614 |
|
|
$postreply .= "Status=ERROR Invalid port mapping for $name\n";
|
| 1615 |
|
|
$ports = "--";
|
| 1616 |
|
|
last;
|
| 1617 |
|
|
}
|
| 1618 |
|
|
if ($port > 1 || $port < 65535) {
|
| 1619 |
|
|
push @remoteports, $port;
|
| 1620 |
|
|
}
|
| 1621 |
|
|
}
|
| 1622 |
|
|
}
|
| 1623 |
|
|
foreach my $port (@remoteports) {
|
| 1624 |
|
|
$rports .= "-R $externalip:$port:$internalip:$port ";
|
| 1625 |
|
|
}
|
| 1626 |
|
|
if ($res_obj->{status} eq 'OK') {
|
| 1627 |
|
|
# my $cmd = qq|ssh -fN -i /home/irigo-$Stabile::engineuser/.ssh/id_rsa -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -o "ExitOnForwardFailure=yes" -R $externalip:10001:$internalip:10001 -R $externalip:80:$internalip:80 -R $externalip:443:$internalip:443 $Stabile::remoteipprovider|;
|
| 1628 |
|
|
my $cmd = qq|ssh -fN -i /home/irigo-$Stabile::engineuser/.ssh/id_rsa -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -o "ExitOnForwardFailure=yes" $rports $Stabile::remoteipprovider|;
|
| 1629 |
|
|
eval {
|
| 1630 |
|
|
my $daemon = Proc::Daemon->new(
|
| 1631 |
|
|
work_dir => '/home/irigo-o@origo.io',
|
| 1632 |
|
|
exec_command => "$cmd"
|
| 1633 |
|
|
) or do {$postreply .= "Status=ERROR $@";};
|
| 1634 |
|
|
$pid = $daemon->Init();
|
| 1635 |
|
|
$main::syslogit->($user, "info", "Activating remote ip $externalip at $Stabile::remoteipprovider for $Stabile::engineuser, pid=$pid");
|
| 1636 |
|
|
1;
|
| 1637 |
|
|
} or do {$e=4; $postreply .= "Status=ERROR Problem activating remote ip $@\n";};
|
| 1638 |
|
|
# sleep 1;
|
| 1639 |
|
|
} else {
|
| 1640 |
|
|
$postreply .= "Status=Error $res_obj->{message}\n";
|
| 1641 |
|
|
}
|
| 1642 |
|
|
if ($e || !(-e "/proc/$pid")) {
|
| 1643 |
|
|
$main::syslogit->($user, 'info', "Problem $action network $uuid ($e, $name, $id): $@");
|
| 1644 |
|
|
$astatus = $status;
|
| 1645 |
|
|
$postreply .= "Status=OK Waiting to establish remote connetion\n";
|
| 1646 |
48fcda6b
|
Origo
|
} else {
|
| 1647 |
|
|
$astatus = "up"
|
| 1648 |
|
|
}
|
| 1649 |
95b003ff
|
Origo
|
}
|
| 1650 |
|
|
} elsif ($type eq "externalip") {
|
| 1651 |
|
|
my $route = `/sbin/ip route`;
|
| 1652 |
|
|
my $tables = `/sbin/iptables -L -n`;
|
| 1653 |
|
|
|
| 1654 |
d24d9a01
|
hq
|
# Allow external IP send packets out
|
| 1655 |
|
|
`/sbin/iptables -D FORWARD --in-interface br$id -s $externalip -j RETURN`;
|
| 1656 |
|
|
`/sbin/iptables -I FORWARD --in-interface br$id -s $externalip -j RETURN`;
|
| 1657 |
|
|
|
| 1658 |
95b003ff
|
Origo
|
# We are dealing with multiple upstream routes - configure local routing
|
| 1659 |
e837d785
|
hq
|
if ($proxynic && ($proxynic ne $extnic)) {
|
| 1660 |
95b003ff
|
Origo
|
if (-e "/etc/iproute2/rt_tables" && !grep(/1 proxyarp/, `cat /etc/iproute2/rt_tables`)) {
|
| 1661 |
|
|
`/bin/echo "1 proxyarp" >> /etc/iproute2/rt_tables`;
|
| 1662 |
|
|
}
|
| 1663 |
|
|
if (!grep(/$proxygw/, `/sbin/ip route show table proxyarp`)) {
|
| 1664 |
e837d785
|
hq
|
`/sbin/ip route del default dev $proxynic table proxyarp`; # delete first in case proxygw has changed
|
| 1665 |
95b003ff
|
Origo
|
`/sbin/ip route add default via $proxygw dev $proxynic table proxyarp`;
|
| 1666 |
|
|
}
|
| 1667 |
|
|
if (!grep(/proxyarp/, `/sbin/ip rule show`)) {
|
| 1668 |
|
|
`/sbin/ip rule add to $proxygw/$proxysubnet table main`;
|
| 1669 |
|
|
`/sbin/ip rule add from $proxygw/$proxysubnet table proxyarp`;
|
| 1670 |
|
|
}
|
| 1671 |
|
|
my $proxyroute = `/sbin/ip route show table proxyarp`;
|
| 1672 |
|
|
# `/sbin/ip route add $externalip/32 dev $datanic.$id:proxy src $proxyip table proxyarp` unless ($proxyroute =~ /$externalip/);
|
| 1673 |
|
|
`/sbin/ip route add $externalip/32 dev br$id:proxy src $proxyip table proxyarp` unless ($proxyroute =~ /$externalip/);
|
| 1674 |
|
|
}
|
| 1675 |
|
|
eval {`/bin/echo 1 > /proc/sys/net/ipv4/conf/$datanic.$id/proxy_arp`; 1;}
|
| 1676 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up proxy arp $@\n";};
|
| 1677 |
|
|
eval {`/bin/echo 1 > /proc/sys/net/ipv4/conf/$proxynic/proxy_arp`; 1;}
|
| 1678 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up proxy arp $@\n";};
|
| 1679 |
|
|
eval {`/sbin/ip route add $externalip/32 dev br$id:proxy src $proxyip` unless ($route =~ /$externalip/); 1;}
|
| 1680 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up proxy arp $@\n";};
|
| 1681 |
|
|
|
| 1682 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -m state --state ESTABLISHED,RELATED -j RETURN`; 1;}
|
| 1683 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1684 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -A FORWARD -i $proxynic -d $externalip -m state --state ESTABLISHED,RELATED -j RETURN`; 1;}
|
| 1685 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1686 |
|
|
|
| 1687 |
|
|
|
| 1688 |
|
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -j REJECT` if
|
| 1689 |
|
|
($tables =~ /REJECT .+ all .+ $externalip/); 1;}
|
| 1690 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1691 |
|
|
|
| 1692 |
|
|
if ($ports && $ports ne "--") {
|
| 1693 |
|
|
my @portslist = split(/, ?| /, $ports);
|
| 1694 |
|
|
foreach $port (@portslist) {
|
| 1695 |
|
|
my $ipfilter;
|
| 1696 |
|
|
if ($port =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)(\/\d+)?:(\d+)/) {
|
| 1697 |
|
|
my $portip = "$1.$2.$3.$4$5";
|
| 1698 |
|
|
$port = $6;
|
| 1699 |
|
|
$ipfilter = "-s $portip";
|
| 1700 |
|
|
} else {
|
| 1701 |
|
|
$port = 0 unless ($port =~ /\d+/);
|
| 1702 |
|
|
}
|
| 1703 |
|
|
if ($port<1 || $port>65535) {
|
| 1704 |
|
|
$postreply .= "Status=ERROR Invalid port mapping for $name\n";
|
| 1705 |
|
|
$ports = "--";
|
| 1706 |
|
|
last;
|
| 1707 |
|
|
}
|
| 1708 |
|
|
|
| 1709 |
|
|
if ($port>1 && $port<65535 && $port!=67) { # Disallow setting up a dhcp server
|
| 1710 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -A FORWARD -p tcp -i $proxynic $portfilter -d $externalip --dport $port -j RETURN`; 1;}
|
| 1711 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1712 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -A FORWARD -p udp -i $proxynic $portfilter -d $externalip --dport $port -j RETURN`; 1;}
|
| 1713 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1714 |
|
|
}
|
| 1715 |
|
|
}
|
| 1716 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -j REJECT`; 1;} # Drop traffic to all other ports
|
| 1717 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1718 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -A FORWARD -i $proxynic -d $externalip -j REJECT`; 1;} # Drop traffic to all other ports
|
| 1719 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1720 |
|
|
} else {
|
| 1721 |
d24d9a01
|
hq
|
# First allow everything else to this ip
|
| 1722 |
|
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -j RETURN`; 1;}
|
| 1723 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1724 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -A FORWARD -i $proxynic -d $externalip -j RETURN`; 1;}
|
| 1725 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1726 |
d24d9a01
|
hq
|
# Then disallow setting up a dhcp server
|
| 1727 |
|
|
eval {`/sbin/iptables -D FORWARD -p udp -i $proxynic -d $externalip --dport 67 -j REJECT`; 1;}
|
| 1728 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1729 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -A FORWARD -p udp -i $proxynic -d $externalip --dport 67 -j REJECT`; 1;}
|
| 1730 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1731 |
|
|
}
|
| 1732 |
|
|
}
|
| 1733 |
|
|
}
|
| 1734 |
|
|
|
| 1735 |
d24d9a01
|
hq
|
# Allow all inter-VLAN communication
|
| 1736 |
|
|
`iptables -D FORWARD --in-interface br$id --out-interface br$id -j RETURN 2>/dev/null`;
|
| 1737 |
|
|
`iptables -I FORWARD --in-interface br$id --out-interface br$id -j RETURN`;
|
| 1738 |
|
|
# Disallow any access to vlan except mapped from external NIC i.e. ipmappings
|
| 1739 |
|
|
`iptables -D FORWARD ! --in-interface $extnic --out-interface br$id -j DROP 2>/dev/null`;
|
| 1740 |
|
|
`iptables -A FORWARD ! --in-interface $extnic --out-interface br$id -j DROP`;
|
| 1741 |
|
|
|
| 1742 |
95b003ff
|
Origo
|
# Only forward packets coming from subnet assigned to vlan unless we are setting up a gateway on the proxy nic and the proxy nic is on a vlan
|
| 1743 |
d24d9a01
|
hq
|
# `/sbin/iptables --delete FORWARD --in-interface $datanic.$id ! -s 10.$idleft.$idright.0/24 -j DROP`;
|
| 1744 |
95b003ff
|
Origo
|
unless ($proxynic eq "$datanic.$id") {
|
| 1745 |
d24d9a01
|
hq
|
# `/sbin/iptables --append FORWARD --in-interface $datanic.$id ! -s 10.$idleft.$idright.0/24 -j DROP`;
|
| 1746 |
95b003ff
|
Origo
|
}
|
| 1747 |
|
|
|
| 1748 |
a439a9c4
|
hq
|
# Enable nat'ing
|
| 1749 |
|
|
eval {
|
| 1750 |
64c667ea
|
hq
|
#my $masq = `/sbin/iptables -L -n -t nat`;
|
| 1751 |
a439a9c4
|
hq
|
# if (!($masq =~ "MASQUERADE.+all.+--.+0\.0\.0\.0/0")) {
|
| 1752 |
|
|
`/sbin/iptables -D POSTROUTING -t nat --out-interface $extnic -s 10.0.0.0/8 -j MASQUERADE`;
|
| 1753 |
|
|
`/sbin/iptables -A POSTROUTING -t nat --out-interface $extnic -s 10.0.0.0/8 -j MASQUERADE`;
|
| 1754 |
|
|
# Christian's dev environment
|
| 1755 |
|
|
# my $interfaces = `/sbin/ifconfig`;
|
| 1756 |
|
|
# if ($interfaces =~ m/ppp0/) {
|
| 1757 |
|
|
# `/sbin/iptables --table nat --append POSTROUTING --out-interface ppp0 -s 10.0.0.0/8 -j MASQUERADE`;
|
| 1758 |
|
|
# }
|
| 1759 |
|
|
# };
|
| 1760 |
|
|
1;
|
| 1761 |
|
|
} or do {print "Unable to enable masquerading: $@\n";};
|
| 1762 |
|
|
|
| 1763 |
95b003ff
|
Origo
|
$uistatus = ($e)?"":validateStatus($register{$uuid});
|
| 1764 |
f222b89c
|
hq
|
if ($uistatus && $uistatus ne 'down' # && $uistatus ne 'nat'
|
| 1765 |
|
|
) {
|
| 1766 |
95b003ff
|
Origo
|
$uiuuid = $uuid;
|
| 1767 |
|
|
$postreply .= "Status=$uistatus OK $action $type $name\n";
|
| 1768 |
|
|
} else {
|
| 1769 |
|
|
$postreply .= "Status=ERROR Cannot $action $type $name ($uistatus)\n";
|
| 1770 |
|
|
}
|
| 1771 |
|
|
$main::syslogit->($user, 'info', "$action network $uuid ($name, $id) -> $uistatus");
|
| 1772 |
|
|
updateBilling("$uistatus $uuid ($id)");
|
| 1773 |
d24d9a01
|
hq
|
# $main::updateUI->({tab=>"networks", user=>$user, uuid=>$uiuuid, status=>$uistatus}) if ($uistatus);
|
| 1774 |
95b003ff
|
Origo
|
return $postreply;
|
| 1775 |
|
|
}
|
| 1776 |
|
|
|
| 1777 |
|
|
sub Removeusernetworks {
|
| 1778 |
|
|
my $username = shift;
|
| 1779 |
|
|
return unless (($isadmin || $user eq $username) && !$isreadonly);
|
| 1780 |
|
|
$user = $username;
|
| 1781 |
|
|
foreach my $uuid (keys %register) {
|
| 1782 |
|
|
if ($register{$uuid}->{'user'} eq $user) {
|
| 1783 |
6372a66e
|
hq
|
$postreply .= "Removing network $register{$uuid}->{'name'}, $uuid" . ($console?'':'<br>') . "\n";
|
| 1784 |
95b003ff
|
Origo
|
Deactivate($uuid);
|
| 1785 |
6372a66e
|
hq
|
Remove($uuid, 'remove');
|
| 1786 |
95b003ff
|
Origo
|
}
|
| 1787 |
|
|
}
|
| 1788 |
|
|
}
|
| 1789 |
|
|
|
| 1790 |
|
|
sub Remove {
|
| 1791 |
d3d1a2d4
|
Origo
|
my ($uuid, $action, $obj) = @_;
|
| 1792 |
95b003ff
|
Origo
|
if ($help) {
|
| 1793 |
|
|
return <<END
|
| 1794 |
d3d1a2d4
|
Origo
|
DELETE:uuid,force:
|
| 1795 |
|
|
Delete a network which must be in status down or nat and should not be used by any servers, or linked to any stacks.
|
| 1796 |
95b003ff
|
Origo
|
May also be called with endpoints "/stabile/[uuid]" or "/stabile?uuid=[uuid]"
|
| 1797 |
d3d1a2d4
|
Origo
|
Set [force] to remove even if linked to a system.
|
| 1798 |
95b003ff
|
Origo
|
END
|
| 1799 |
|
|
}
|
| 1800 |
d3d1a2d4
|
Origo
|
$uuid = $obj->{'uuid'} if ($curuuid && $obj->{'uuid'}); # we are called from a VM with an ip address as target
|
| 1801 |
|
|
my $force = $obj->{'force'};
|
| 1802 |
95b003ff
|
Origo
|
( my $domains, my $domainnames ) = getDomains($uuid);
|
| 1803 |
d3d1a2d4
|
Origo
|
( my $systems, my $systemnames ) = getSystems($uuid);
|
| 1804 |
95b003ff
|
Origo
|
|
| 1805 |
|
|
if ($register{$uuid}) {
|
| 1806 |
|
|
my $id = $register{$uuid}->{'id'};
|
| 1807 |
|
|
my $name = $register{$uuid}->{'name'};
|
| 1808 |
|
|
utf8::decode($name);
|
| 1809 |
|
|
my $status = $register{$uuid}->{'status'};
|
| 1810 |
|
|
my $type = $register{$uuid}->{'type'};
|
| 1811 |
|
|
my $internalip = $register{$uuid}->{'internalip'};
|
| 1812 |
|
|
my $externalip = $register{$uuid}->{'externalip'};
|
| 1813 |
|
|
|
| 1814 |
|
|
my @regvalues = values %register;
|
| 1815 |
d3d1a2d4
|
Origo
|
if (
|
| 1816 |
|
|
$id!=0 && $id!=1 && (!$domains || $domains eq '--')
|
| 1817 |
2a63870a
|
Christian Orellana
|
&& ((!$systems || $systems eq '--' || $force)
|
| 1818 |
d3d1a2d4
|
Origo
|
# allow internalip's to be removed if active and only linked, i.e. not providing dhcp
|
| 1819 |
2a63870a
|
Christian Orellana
|
|| ($status eq 'down' || $status eq 'new' || $status eq 'nat' || ($type eq 'internalip' && $systems && $systems ne '--')))
|
| 1820 |
d3d1a2d4
|
Origo
|
) {
|
| 1821 |
95b003ff
|
Origo
|
# Deconfigure internal dhcp server and DNS
|
| 1822 |
|
|
if ($type eq "internalip") {
|
| 1823 |
|
|
my $result = removeDHCPAddress($id, $domains, $internalip);
|
| 1824 |
|
|
$postreply .= "$result\n" unless $result eq "OK";
|
| 1825 |
|
|
} elsif ($type eq "ipmapping") {
|
| 1826 |
|
|
my $result = removeDHCPAddress($id, $domains, $internalip);
|
| 1827 |
|
|
$postreply .= "$result\n" unless $result eq "OK";
|
| 1828 |
|
|
if ($dodns) {
|
| 1829 |
e9af6c24
|
Origo
|
$main::dnsDelete->($engineid, $externalip) if ($enginelinked);
|
| 1830 |
95b003ff
|
Origo
|
}
|
| 1831 |
a2e0bc7e
|
hq
|
} elsif ($type eq "externalip" || $type eq "remoteip") {
|
| 1832 |
95b003ff
|
Origo
|
my $result = removeDHCPAddress($id, $domains, $externalip);
|
| 1833 |
|
|
$postreply .= "$result\n" unless $result eq "OK";
|
| 1834 |
|
|
if ($dodns) {
|
| 1835 |
e9af6c24
|
Origo
|
$main::dnsDelete->($engineid, $externalip) if ($enginelinked);
|
| 1836 |
95b003ff
|
Origo
|
}
|
| 1837 |
a2e0bc7e
|
hq
|
# Deactivate the ip on remoteipprovider
|
| 1838 |
|
|
my $res = $main::postToOrigo->($engineid, 'removeremoteip', "$externalip", 'remoteip');
|
| 1839 |
|
|
my $res_obj = JSON::from_json($res);
|
| 1840 |
|
|
if ($res_obj->{status} ne 'OK') {
|
| 1841 |
|
|
$postreply .= "Status=OK There was a problem removing the remote IP\n";
|
| 1842 |
|
|
}
|
| 1843 |
95b003ff
|
Origo
|
}
|
| 1844 |
|
|
if ($status eq 'nat') {
|
| 1845 |
|
|
# Check if last network in vlan. If so take it down
|
| 1846 |
|
|
my $notlast;
|
| 1847 |
|
|
foreach my $val (@regvalues) {
|
| 1848 |
|
|
if ($val->{'user'} eq $user && $val->{'id'} == $id) {
|
| 1849 |
|
|
$notlast = 1;
|
| 1850 |
|
|
}
|
| 1851 |
|
|
}
|
| 1852 |
|
|
if (!$notlast) {
|
| 1853 |
|
|
eval {`/sbin/ifconfig $datanic.$id down`; 1;} or do {;};
|
| 1854 |
|
|
eval {`/sbin/vconfig rem $datanic.$id`; 1;} or do {;};
|
| 1855 |
|
|
}
|
| 1856 |
|
|
}
|
| 1857 |
d3d1a2d4
|
Origo
|
|
| 1858 |
|
|
unless (tie(%sysreg,'Tie::DBI', Hash::Merge::merge({table=>'systems'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access systems register"}|; return $res;};
|
| 1859 |
|
|
if ($sysreg{$systems}) { # Remove existing link to system
|
| 1860 |
|
|
$sysreg{$systems}->{'networkuuids'} =~ s/$uuid,?//;
|
| 1861 |
|
|
$sysreg{$systems}->{'networknames'} = s/$name,?//;
|
| 1862 |
|
|
}
|
| 1863 |
|
|
tied(%sysreg)->commit;
|
| 1864 |
|
|
untie(%sysreg);
|
| 1865 |
|
|
|
| 1866 |
|
|
|
| 1867 |
95b003ff
|
Origo
|
delete $register{$uuid};
|
| 1868 |
|
|
tied(%register)->commit;
|
| 1869 |
|
|
updateBilling("delete $val->{'externalip'}") if ($type eq "ipmapping");
|
| 1870 |
|
|
$main::syslogit->($user, "info", "Deleted network $uuid ($id)");
|
| 1871 |
d3d1a2d4
|
Origo
|
$postreply = "[]" || $postreply;
|
| 1872 |
|
|
$main::updateUI->({tab=>"networks", user=>$user, type=>"update"});
|
| 1873 |
95b003ff
|
Origo
|
} else {
|
| 1874 |
d3d1a2d4
|
Origo
|
$postreply .= "Status=ERROR Cannot remove $uuid which is $status. Cannot delete network 0,1 or a network which is active or in use.\n";
|
| 1875 |
|
|
$main::updateUI->({tab=>"networks", user=>$user, message=>"Cannot remove a network which is active, linked or in use."});
|
| 1876 |
95b003ff
|
Origo
|
}
|
| 1877 |
|
|
} else {
|
| 1878 |
d3d1a2d4
|
Origo
|
$postreply .= "Status=ERROR Network $uuid $ipaddress not found\n";
|
| 1879 |
95b003ff
|
Origo
|
}
|
| 1880 |
|
|
return $postreply;
|
| 1881 |
|
|
}
|
| 1882 |
|
|
|
| 1883 |
|
|
sub Deactivate {
|
| 1884 |
d3d1a2d4
|
Origo
|
my ($uuid, $action, $obj) = @_;
|
| 1885 |
95b003ff
|
Origo
|
|
| 1886 |
|
|
if ($help) {
|
| 1887 |
|
|
return <<END
|
| 1888 |
|
|
GET:uuid:
|
| 1889 |
|
|
Deactivate a network which must be in status up.
|
| 1890 |
|
|
END
|
| 1891 |
|
|
}
|
| 1892 |
d3d1a2d4
|
Origo
|
$uuid = $obj->{'uuid'} if ($obj->{'uuid'});
|
| 1893 |
|
|
|
| 1894 |
|
|
unless ($register{$uuid}) {
|
| 1895 |
|
|
$postreply .= "Status=ERROR Connection with uuid $uuid not found\n";
|
| 1896 |
|
|
return $postreply;
|
| 1897 |
|
|
}
|
| 1898 |
|
|
my $regnet = $register{$uuid};
|
| 1899 |
95b003ff
|
Origo
|
|
| 1900 |
|
|
$action = $action || 'deactivate';
|
| 1901 |
|
|
( my $domains, my $domainnames ) = getDomains($uuid);
|
| 1902 |
|
|
my $interfaces = `/sbin/ifconfig`;
|
| 1903 |
|
|
|
| 1904 |
d3d1a2d4
|
Origo
|
my $id = $regnet->{'id'};
|
| 1905 |
|
|
my $name = $regnet->{'name'};
|
| 1906 |
|
|
my $type = $regnet->{'type'};
|
| 1907 |
|
|
my $internalip = $regnet->{'internalip'};
|
| 1908 |
|
|
my $externalip = $regnet->{'externalip'};
|
| 1909 |
|
|
my $ports = $regnet->{'ports'};
|
| 1910 |
95b003ff
|
Origo
|
|
| 1911 |
|
|
if ($id!=0 && $id!=1 && $status ne 'down') {
|
| 1912 |
|
|
# If gateway is created, take it down along with all user's networks
|
| 1913 |
|
|
if ($action eq "stop") {
|
| 1914 |
|
|
my $res = Stop($id, $action);
|
| 1915 |
|
|
if ($res) {
|
| 1916 |
|
|
unlink "$etcpath/dhcp-hosts-$id" if (-e "$etcpath/dhcp-hosts-$id");
|
| 1917 |
|
|
};
|
| 1918 |
|
|
}
|
| 1919 |
|
|
} else {
|
| 1920 |
|
|
$postreply .= "Status=ERROR Cannot $action network $name\n";
|
| 1921 |
|
|
return $postreply;
|
| 1922 |
|
|
}
|
| 1923 |
|
|
|
| 1924 |
2a63870a
|
Christian Orellana
|
my $idleft = ($id>99)?(substr $id,0,-2)+0 : 0;
|
| 1925 |
|
|
my $idright = (substr $id,-2) + 0;
|
| 1926 |
95b003ff
|
Origo
|
my $e = 0;
|
| 1927 |
2a63870a
|
Christian Orellana
|
my $duprules = 0;
|
| 1928 |
d24d9a01
|
hq
|
|
| 1929 |
6372a66e
|
hq
|
if ($type eq "ipmapping" || $type eq "internalip" || $type eq "remoteip") {
|
| 1930 |
d24d9a01
|
hq
|
`iptables -D FORWARD -d $internalip -m state --state ESTABLISHED,RELATED -j RETURN`;
|
| 1931 |
|
|
}
|
| 1932 |
95b003ff
|
Origo
|
if ($type eq "ipmapping") {
|
| 1933 |
d24d9a01
|
hq
|
# Check if external ip exists and take it down if so
|
| 1934 |
95b003ff
|
Origo
|
if ($internalip && $internalip ne "--" && $externalip && $externalip ne "--" && ($interfaces =~ m/$externalip/g)) {
|
| 1935 |
64c667ea
|
hq
|
$externalip =~ /\d+\.\d+\.(\d+)\.(\d+)/;
|
| 1936 |
|
|
my $ipend = "$1$2"; # Linux NIC names are limited to 15 chars - we will have to find a way to support long NIC names and bigger than /24 subnets
|
| 1937 |
|
|
$ipend = $2 if (length("$extnic:$id-$ipend")>15);
|
| 1938 |
95b003ff
|
Origo
|
eval {`/sbin/ifconfig $extnic:$id-$ipend down`; 1;} or do {$e=1; $postreply .= "Status=ERROR $@\n";};
|
| 1939 |
|
|
|
| 1940 |
|
|
if ($ports && $ports ne "--") { # Port mapping is defined
|
| 1941 |
|
|
my @portslist = split(/, ?| /, $ports);
|
| 1942 |
2a63870a
|
Christian Orellana
|
foreach my $port (@portslist) {
|
| 1943 |
95b003ff
|
Origo
|
my $ipfilter;
|
| 1944 |
|
|
if ($port =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)(\/\d+)?:(\d+)/) {
|
| 1945 |
|
|
my $portip = "$1.$2.$3.$4$5";
|
| 1946 |
|
|
$port = $6;
|
| 1947 |
|
|
$ipfilter = "-s $portip";
|
| 1948 |
|
|
} else {
|
| 1949 |
|
|
$port = 0 unless ($port =~ /\d+/);
|
| 1950 |
|
|
}
|
| 1951 |
|
|
if ($port<1 || $port>65535) {
|
| 1952 |
|
|
$postreply .= "Status=ERROR Invalid port mapping for $name\n";
|
| 1953 |
|
|
$ports = "--";
|
| 1954 |
|
|
last;
|
| 1955 |
|
|
}
|
| 1956 |
d24d9a01
|
hq
|
# Remove DNAT rules
|
| 1957 |
95b003ff
|
Origo
|
if ($port>1 || $port<65535) {
|
| 1958 |
|
|
# repeat for good measure
|
| 1959 |
2a63870a
|
Christian Orellana
|
for (my $di=0; $di < 10; $di++) {
|
| 1960 |
|
|
$duprules = 0;
|
| 1961 |
|
|
eval {$duprules++ if (`/sbin/iptables -D PREROUTING -t nat -p tcp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`); 1;}
|
| 1962 |
95b003ff
|
Origo
|
or do {$postreply .= "Status=ERROR $@\n"; $e=1};
|
| 1963 |
2a63870a
|
Christian Orellana
|
eval {$duprules++ if (`/sbin/iptables -D PREROUTING -t nat -p udp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`); 1;}
|
| 1964 |
95b003ff
|
Origo
|
or do {$postreply .= "Status=ERROR $@\n"; $e=1};
|
| 1965 |
2a63870a
|
Christian Orellana
|
eval {$duprules++ if (`/sbin/iptables -D OUTPUT -t nat -p tcp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`); 1;}
|
| 1966 |
|
|
or do {$postreply .= "Status=ERROR $@\n"; $e=1};
|
| 1967 |
|
|
eval {$duprules++ if (`/sbin/iptables -D OUTPUT -t nat -p udp $ipfilter -d $externalip --dport $port -j DNAT --to $internalip`); 1;}
|
| 1968 |
|
|
or do {$postreply .= "Status=ERROR $@\n"; $e=1};
|
| 1969 |
|
|
eval {$duprules++ if (`/sbin/iptables -D POSTROUTING -t nat --out-interface br$id -s $externalip -j MASQUERADE`); 1;}
|
| 1970 |
|
|
or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1971 |
d24d9a01
|
hq
|
# Remove access to ipmapped internal ip on $port
|
| 1972 |
|
|
eval {$duprules++ if (`/sbin/iptables -D FORWARD -d $internalip -p udp --dport $port -j RETURN`); 1;}
|
| 1973 |
|
|
or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1974 |
|
|
eval {$duprules++ if (`/sbin/iptables -D FORWARD -d $internalip -p tcp --dport $port -j RETURN`); 1;}
|
| 1975 |
|
|
or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1976 |
|
|
last if ($duprules >6);
|
| 1977 |
95b003ff
|
Origo
|
}
|
| 1978 |
|
|
}
|
| 1979 |
|
|
}
|
| 1980 |
d24d9a01
|
hq
|
# Remove SNAT rules
|
| 1981 |
95b003ff
|
Origo
|
# repeat for good measure
|
| 1982 |
2a63870a
|
Christian Orellana
|
for (my $di=0; $di < 10; $di++) {
|
| 1983 |
|
|
$duprules = 0;
|
| 1984 |
|
|
eval {$duprules++ if (`/sbin/iptables -D POSTROUTING -t nat -s $internalip ! -d 10.$idleft.$idright.0/24 -j SNAT --to-source $externalip`); 1; }
|
| 1985 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1986 |
2a63870a
|
Christian Orellana
|
last if ($duprules);
|
| 1987 |
95b003ff
|
Origo
|
}
|
| 1988 |
d24d9a01
|
hq
|
# Remove rule to drop traffic to all other ports
|
| 1989 |
|
|
eval {`/sbin/iptables -D INPUT -d $externalip -j DROP`; 1;}
|
| 1990 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 1991 |
|
|
} else {
|
| 1992 |
d24d9a01
|
hq
|
# Remove DNAT rules
|
| 1993 |
95b003ff
|
Origo
|
# repeat for good measure
|
| 1994 |
2a63870a
|
Christian Orellana
|
for (my $di=0; $di < 10; $di++) {
|
| 1995 |
|
|
$duprules = 0;
|
| 1996 |
|
|
eval {$duprules++ if (`/sbin/iptables -D PREROUTING -t nat -d $externalip -j DNAT --to $internalip`); 1;}
|
| 1997 |
95b003ff
|
Origo
|
or do {$postreply .= "Status=ERROR $@\n"; $e=1};
|
| 1998 |
2a63870a
|
Christian Orellana
|
eval {$duprules++ if (`/sbin/iptables -D OUTPUT -t nat -d $externalip -j DNAT --to $internalip`); 1;}
|
| 1999 |
|
|
or do {$postreply .= "Status=ERROR $@\n"; $e=1};
|
| 2000 |
d24d9a01
|
hq
|
last if ($duprules >1);
|
| 2001 |
95b003ff
|
Origo
|
}
|
| 2002 |
d24d9a01
|
hq
|
# Remove blanket access to ipmapped internal ip
|
| 2003 |
|
|
`iptables -D FORWARD -d $internalip -j RETURN`;
|
| 2004 |
|
|
}
|
| 2005 |
|
|
# Remove SNAT and MASQUERADE rules
|
| 2006 |
|
|
# repeat for good measure
|
| 2007 |
|
|
for (my $di=0; $di < 10; $di++) {
|
| 2008 |
|
|
$duprules = 0;
|
| 2009 |
|
|
# eval {$duprules++ if (`/sbin/iptables -D POSTROUTING -t nat --out-interface br$id -s $externalip -j MASQUERADE`); 1;}
|
| 2010 |
|
|
# or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2011 |
6fdc8676
|
hq
|
eval {$duprules++ if (`/sbin/iptables -D POSTROUTING -t nat --out-interface br$id ! -d 10.$idleft.$idright.0/24 -j MASQUERADE`); 1;}
|
| 2012 |
d24d9a01
|
hq
|
or do {$e=3; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2013 |
|
|
|
| 2014 |
|
|
eval {$duprules++ if (`/sbin/iptables -D POSTROUTING -t nat -s $internalip ! -d 10.$idleft.$idright.0/24 -j SNAT --to-source $externalip`); 1; }
|
| 2015 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2016 |
|
|
# eval {$duprules++ if (`/sbin/iptables -D POSTROUTING -t nat -s $internalip -j SNAT --to-source $externalip`); 1; }
|
| 2017 |
|
|
# or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2018 |
|
|
eval {$duprules++ if (`/sbin/iptables -D INPUT -t nat -s $internalip ! -d 10.$idleft.$idright.0/24 -j SNAT --to-source $externalip`); 1; }
|
| 2019 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2020 |
|
|
# eval {$duprules++ if (`/sbin/iptables -D INPUT -t nat -s $internalip -j SNAT --to-source $externalip`); 1; }
|
| 2021 |
|
|
# or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2022 |
|
|
# eval {$duprules++ if (`/sbin/iptables -D INPUT -t nat -s $internalip ! -d 10.$idleft.$idright.0/24 -j SNAT --to-source $externalip`); 1; }
|
| 2023 |
|
|
# or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2024 |
|
|
# eval {$duprules++ if (`/sbin/iptables -D INPUT -t nat -s $internalip -j SNAT --to-source $externalip`); 1; }
|
| 2025 |
|
|
# or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2026 |
|
|
last if ($duprules >1);
|
| 2027 |
95b003ff
|
Origo
|
}
|
| 2028 |
d24d9a01
|
hq
|
# `/sbin/iptables -D POSTROUTING -t nat -s $internalip -j LOG --log-prefix "SNAT-POST"`;
|
| 2029 |
|
|
# `/sbin/iptables -D INPUT -t nat -s $internalip -j LOG --log-prefix "SNAT-INPUT"`;
|
| 2030 |
|
|
# `/sbin/iptables -D OUTPUT -t nat -s $internalip -j LOG --log-prefix "SNAT-OUTPUT"`;
|
| 2031 |
|
|
# `/sbin/iptables -D PREROUTING -t nat -s $internalip -j LOG --log-prefix "SNAT-PRE"`;
|
| 2032 |
95b003ff
|
Origo
|
}
|
| 2033 |
6372a66e
|
hq
|
} elsif ($type eq "remoteip") {
|
| 2034 |
|
|
`pkill -f 'R $externalip'`;
|
| 2035 |
a2e0bc7e
|
hq
|
# Deactivate the ip on remoteipprovider
|
| 2036 |
|
|
my $res = $main::postToOrigo->($engineid, 'deactivateremoteip', "$externalip", 'remoteip');
|
| 2037 |
|
|
my $res_obj = JSON::from_json($res);
|
| 2038 |
|
|
if ($res_obj->{status} ne 'OK') {
|
| 2039 |
|
|
$postreply .= "Status=OK There was a problem deactivating the remote IP\n";
|
| 2040 |
|
|
}
|
| 2041 |
95b003ff
|
Origo
|
} elsif ($type eq "externalip") {
|
| 2042 |
|
|
if ($externalip && $externalip ne "--") {
|
| 2043 |
|
|
# We are dealing with multiple upstream routes - configure local routing
|
| 2044 |
|
|
if ($proxynic && $proxynic ne $extnic) {
|
| 2045 |
|
|
my $proxyroute = `/sbin/ip route show table proxyarp`;
|
| 2046 |
|
|
`/sbin/ip route del $externalip/32 dev br$id:proxy src $proxyip table proxyarp` if ($proxyroute =~ /$externalip/);
|
| 2047 |
|
|
}
|
| 2048 |
|
|
|
| 2049 |
|
|
eval {`/sbin/ip route del $externalip/32 dev br$id:proxy`; 1;}
|
| 2050 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem deconfiguring proxy arp $@\n";};
|
| 2051 |
|
|
|
| 2052 |
|
|
if ($ports && $ports ne "--") {
|
| 2053 |
|
|
my @portslist = split(/, ?| /, $ports);
|
| 2054 |
2a63870a
|
Christian Orellana
|
foreach my $port (@portslist) {
|
| 2055 |
95b003ff
|
Origo
|
my $ipfilter;
|
| 2056 |
|
|
if ($port =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)(\/\d+)?:(\d+)/) {
|
| 2057 |
|
|
my $portip = "$1.$2.$3.$4$5";
|
| 2058 |
|
|
$port = $6;
|
| 2059 |
|
|
$ipfilter = "-s $portip";
|
| 2060 |
|
|
} else {
|
| 2061 |
|
|
$port = 0 unless ($port =~ /\d+/);
|
| 2062 |
|
|
}
|
| 2063 |
|
|
if ($port<1 || $port>65535) {
|
| 2064 |
|
|
$postreply .= "Status=ERROR Invalid port mapping for $name\n";
|
| 2065 |
|
|
$ports = "--";
|
| 2066 |
|
|
last;
|
| 2067 |
|
|
}
|
| 2068 |
|
|
|
| 2069 |
|
|
if ($port>1 || $port<65535) {
|
| 2070 |
|
|
# repeat for good measure
|
| 2071 |
2a63870a
|
Christian Orellana
|
for (my $di=0; $di < 10; $di++) {
|
| 2072 |
|
|
$duprules = 0;
|
| 2073 |
d24d9a01
|
hq
|
eval {$duprules++ if (`/sbin/iptables -D FORWARD -p tcp -i $proxynic $ipfilter -d $externalip --dport $port -j RETURN`); 1;}
|
| 2074 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2075 |
d24d9a01
|
hq
|
eval {$duprules++ if (`/sbin/iptables -D FORWARD -p udp -i $proxynic $ipfilter -d $externalip --dport $port -j RETURN`); 1;}
|
| 2076 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2077 |
2a63870a
|
Christian Orellana
|
last if ($duprules > 1);
|
| 2078 |
|
|
}
|
| 2079 |
95b003ff
|
Origo
|
}
|
| 2080 |
|
|
}
|
| 2081 |
|
|
}
|
| 2082 |
2a63870a
|
Christian Orellana
|
# Remove rule to allow forwarding from $externalip
|
| 2083 |
d24d9a01
|
hq
|
`/sbin/iptables --delete FORWARD --in-interface br$id -s $externalip -j RETURN`;
|
| 2084 |
95b003ff
|
Origo
|
# Remove rule to disallow setting up a dhcp server
|
| 2085 |
|
|
eval {`/sbin/iptables -D FORWARD -p udp -i $proxynic -d $externalip --dport 67 -j REJECT`; 1;}
|
| 2086 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2087 |
|
|
# Leave outgoing connectivity - not
|
| 2088 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -m state --state ESTABLISHED,RELATED -j RETURN`; 1;}
|
| 2089 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2090 |
d24d9a01
|
hq
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -j RETURN`; 1;}
|
| 2091 |
95b003ff
|
Origo
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2092 |
|
|
# No need to reject - we reject all per default to the subnet
|
| 2093 |
|
|
eval {`/sbin/iptables -D FORWARD -i $proxynic -d $externalip -j REJECT`; 1;}
|
| 2094 |
|
|
or do {$e=1; $postreply .= "Status=ERROR Problem setting up routing $@\n";};
|
| 2095 |
|
|
}
|
| 2096 |
|
|
}
|
| 2097 |
|
|
# Deconfigure internal dhcp server
|
| 2098 |
6372a66e
|
hq
|
if ($type eq "internalip" || $type eq "ipmapping" || $type eq "remoteip") {
|
| 2099 |
95b003ff
|
Origo
|
my $result = removeDHCPAddress($id, $domains, $internalip);
|
| 2100 |
|
|
if ($result ne "OK") {
|
| 2101 |
|
|
$e=1;
|
| 2102 |
|
|
$postreply .= "$result\n";
|
| 2103 |
|
|
}
|
| 2104 |
d3d1a2d4
|
Origo
|
} elsif ($type eq "externalip" && $domains) {
|
| 2105 |
95b003ff
|
Origo
|
my $result = removeDHCPAddress($id, $domains, $externalip);
|
| 2106 |
|
|
if ($result ne "OK") {
|
| 2107 |
|
|
$e=1;
|
| 2108 |
|
|
$postreply .= "$result\n";
|
| 2109 |
|
|
}
|
| 2110 |
|
|
}
|
| 2111 |
|
|
$uistatus = ($e)?"":validateStatus($register{$uuid});
|
| 2112 |
|
|
if ($uistatus) {
|
| 2113 |
|
|
$uiuuid = $uuid;
|
| 2114 |
|
|
$postreply .= "Status=$uistatus OK $action $type $name: $uistatus\n";
|
| 2115 |
|
|
} else {
|
| 2116 |
|
|
$postreply .= "Status=ERROR Cannot $action $type $name: $uistatus\n";
|
| 2117 |
|
|
}
|
| 2118 |
|
|
$main::syslogit->($user, 'info', "$action network $uuid ($name, $id) -> $uistatus");
|
| 2119 |
|
|
updateBilling("$uistatus $uuid ($id)");
|
| 2120 |
d24d9a01
|
hq
|
# $main::updateUI->({tab=>"networks", user=>$user, uuid=>$uiuuid, status=>$uistatus}) if ($uistatus);
|
| 2121 |
95b003ff
|
Origo
|
return $postreply;
|
| 2122 |
|
|
}
|
| 2123 |
|
|
|
| 2124 |
|
|
sub Stop {
|
| 2125 |
|
|
my ($id, $action) = @_;
|
| 2126 |
|
|
# Check if we were passed a uuid
|
| 2127 |
|
|
if ($id =~ /\-/ && $register{$id} && ($register{$id}->{'user'} eq $user || $isadmin)) {
|
| 2128 |
|
|
$id = $register{$id}->{'id'}
|
| 2129 |
|
|
}
|
| 2130 |
|
|
if ($help) {
|
| 2131 |
|
|
return <<END
|
| 2132 |
|
|
GET:uuid:
|
| 2133 |
|
|
Stops a network by removing gateway. Network must be in status up or nat.
|
| 2134 |
|
|
END
|
| 2135 |
|
|
}
|
| 2136 |
|
|
|
| 2137 |
|
|
my $idleft = ($id>99)?(substr $id,0,-2)+0 : 0;
|
| 2138 |
|
|
my $idright = (substr $id,-2) + 0;
|
| 2139 |
|
|
my $e = 0;
|
| 2140 |
|
|
# First deactivate all user's networks with same id
|
| 2141 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user'");
|
| 2142 |
|
|
foreach my $key (@regkeys) {
|
| 2143 |
|
|
my $valref = $register{$key};
|
| 2144 |
|
|
my $cuuid = $valref->{'uuid'};
|
| 2145 |
|
|
my $ctype = $valref->{'type'};
|
| 2146 |
|
|
my $cdbuser = $valref->{'user'};
|
| 2147 |
|
|
my $cid = $valref->{'id'};
|
| 2148 |
|
|
# Only list networks belonging to current user
|
| 2149 |
|
|
if ($user eq $cdbuser && $id eq $cid && $ctype ne "gateway") {
|
| 2150 |
|
|
if ($ctype eq "internalip" || $ctype eq "ipmapping" || $ctype eq "externalip") {
|
| 2151 |
|
|
my $result = Deactivate($cuuid, 'deactivate');
|
| 2152 |
|
|
if ($result =~ /\w+=ERROR (.+)/i) {
|
| 2153 |
|
|
$e = $1;
|
| 2154 |
|
|
}
|
| 2155 |
|
|
}
|
| 2156 |
|
|
}
|
| 2157 |
|
|
}
|
| 2158 |
|
|
my $interfaces = `/sbin/ifconfig br$id`;
|
| 2159 |
|
|
# Only take down interface and vlan if gateway IP is active on interface
|
| 2160 |
|
|
if ($e) {
|
| 2161 |
|
|
$postreply .= "Status=Error Not taking down gateway, got an error: $e\n"
|
| 2162 |
|
|
# } elsif ($interfaces =~ /^$datanic\.$id.+\n.+inet .+10\.$idleft\.$idright\.1/
|
| 2163 |
f222b89c
|
hq
|
} elsif ($interfaces =~ /10\.$idleft\.$idright\.1/) {
|
| 2164 |
95b003ff
|
Origo
|
eval {`/sbin/brctl delif br$id $datanic.$id`; 1;} or do {$e=1;};
|
| 2165 |
|
|
eval {`/sbin/ifconfig br$id down`; 1;} or do {$e=1;};
|
| 2166 |
|
|
eval {`/sbin/ifconfig $datanic.$id down`; 1;} or do {$e=1;};
|
| 2167 |
|
|
eval {`/sbin/vconfig rem $datanic.$id`; 1;} or do {$e=1;};
|
| 2168 |
f222b89c
|
hq
|
eval {`/sbin/brctl delbr br$id`; 1;} or do {$e=1;};
|
| 2169 |
95b003ff
|
Origo
|
} else {
|
| 2170 |
|
|
$postreply .= "Status=Error Not taking down interface, gateway 10.$idleft.$idright.1 is not active on interface br$id - $interfaces.\n"
|
| 2171 |
|
|
}
|
| 2172 |
|
|
# Remove rule to only forward packets coming from subnet assigned to vlan
|
| 2173 |
d24d9a01
|
hq
|
# `/sbin/iptables --delete FORWARD --in-interface $datanic.$id ! -s 10.$idleft.$idright.0/24 -j DROP`;
|
| 2174 |
95b003ff
|
Origo
|
|
| 2175 |
|
|
$uistatus = ($e)?$uistatus:"down";
|
| 2176 |
|
|
if ($uistatus eq 'down') {
|
| 2177 |
|
|
$uiuuid = $uuid;
|
| 2178 |
|
|
$postreply .= "Status=$uistatus OK $action gateway: $uistatus\n";
|
| 2179 |
|
|
} else {
|
| 2180 |
|
|
$postreply .= "Status=Error Cannot $action $type $name: $uistatus\n";
|
| 2181 |
|
|
}
|
| 2182 |
|
|
return $postreply;
|
| 2183 |
|
|
}
|
| 2184 |
|
|
|
| 2185 |
|
|
sub getDomains {
|
| 2186 |
|
|
my $uuid = shift;
|
| 2187 |
|
|
my $domains;
|
| 2188 |
|
|
my $domainnames;
|
| 2189 |
|
|
my @domregvalues = values %domreg;
|
| 2190 |
|
|
foreach my $domval (@domregvalues) {
|
| 2191 |
|
|
if (($domval->{'networkuuid1'} eq $uuid || $domval->{'networkuuid2'} eq $uuid || $domval->{'networkuuid3'} eq $uuid)
|
| 2192 |
|
|
&& $domval->{'user'} eq $user) {
|
| 2193 |
|
|
$domains .= $domval->{'uuid'} . ", ";
|
| 2194 |
|
|
$domainnames .= $domval->{'name'} . ", ";
|
| 2195 |
|
|
}
|
| 2196 |
|
|
}
|
| 2197 |
|
|
$domains = substr $domains, 0, -2;
|
| 2198 |
|
|
$domainnames = substr $domainnames, 0, -2;
|
| 2199 |
|
|
return ($domains, $domainnames);
|
| 2200 |
|
|
}
|
| 2201 |
|
|
|
| 2202 |
d3d1a2d4
|
Origo
|
sub getSystems {
|
| 2203 |
|
|
my $uuid = shift;
|
| 2204 |
|
|
my $systems;
|
| 2205 |
|
|
my $systemnames;
|
| 2206 |
|
|
unless (tie(%sysreg,'Tie::DBI', Hash::Merge::merge({table=>'systems'}, $Stabile::dbopts)) ) {$res .= qq|{"status": "Error": "message": "Unable to access systems register"}|; return $res;};
|
| 2207 |
|
|
my @sysregvalues = values %sysreg;
|
| 2208 |
|
|
foreach my $sysval (@sysregvalues) {
|
| 2209 |
|
|
my $networkuuids = $sysval->{'networkuuids'};
|
| 2210 |
|
|
if ($networkuuids =~ /$uuid/ && $sysval->{'user'} eq $user) {
|
| 2211 |
|
|
$systems = $sysval->{'uuid'};
|
| 2212 |
|
|
$systemnames = $sysval->{'name'};
|
| 2213 |
|
|
last;
|
| 2214 |
|
|
}
|
| 2215 |
|
|
}
|
| 2216 |
|
|
unless ($systems) {
|
| 2217 |
|
|
my @sysregvalues = values %domreg;
|
| 2218 |
|
|
foreach my $sysval (@sysregvalues) {
|
| 2219 |
|
|
my $networkuuids = $sysval->{'networkuuids'};
|
| 2220 |
|
|
if ($networkuuids =~ /$uuid/ && $sysval->{'user'} eq $user) {
|
| 2221 |
|
|
$systems = $sysval->{'uuid'};
|
| 2222 |
|
|
$systemnames = $sysval->{'name'};
|
| 2223 |
|
|
last;
|
| 2224 |
|
|
}
|
| 2225 |
|
|
}
|
| 2226 |
|
|
}
|
| 2227 |
|
|
return ($systems, $systemnames);
|
| 2228 |
|
|
}
|
| 2229 |
|
|
|
| 2230 |
95b003ff
|
Origo
|
sub getNextId {
|
| 2231 |
|
|
# Find the next available vlan id
|
| 2232 |
|
|
my $reqid = shift;
|
| 2233 |
|
|
my $username = shift;
|
| 2234 |
|
|
$username = $user unless ($username);
|
| 2235 |
|
|
my $nextid = 1;
|
| 2236 |
|
|
my $vlanstart = $Stabile::config->get('VLAN_RANGE_START');
|
| 2237 |
|
|
my $vlanend = $Stabile::config->get('VLAN_RANGE_END');
|
| 2238 |
|
|
|
| 2239 |
|
|
if ($reqid eq 0 || $reqid == 1) {
|
| 2240 |
|
|
return $requid;
|
| 2241 |
|
|
} elsif ($reqid && ($reqid > $vlanend || $reqid < $vlanstart)) {
|
| 2242 |
|
|
return -1 unless ($isadmin);
|
| 2243 |
|
|
}
|
| 2244 |
|
|
|
| 2245 |
|
|
$reqid = $reqid + 0;
|
| 2246 |
|
|
|
| 2247 |
|
|
my %ids;
|
| 2248 |
|
|
# First check if the user has an existing vlan, if so use the first we find as default value
|
| 2249 |
|
|
my @regvalues = values %register;
|
| 2250 |
|
|
@regvalues = (sort {$a->{id} <=> $b->{id}} @regvalues);
|
| 2251 |
|
|
foreach my $val (@regvalues) { # Traverse all id's in use
|
| 2252 |
|
|
my $id = 0 + $val->{'id'};
|
| 2253 |
|
|
my $dbuser = $val->{'user'};
|
| 2254 |
|
|
if ($id > 1) {
|
| 2255 |
|
|
if ($username eq $dbuser) { # If a specific id was requested map all id's
|
| 2256 |
|
|
if (!$reqid) {# If no specific id was asked for, stop now, and use the user's first one
|
| 2257 |
|
|
$nextid = $id;
|
| 2258 |
|
|
last;
|
| 2259 |
|
|
}
|
| 2260 |
|
|
} else {
|
| 2261 |
|
|
$ids{$id} = 1; # Mark this id as used (by another user)
|
| 2262 |
|
|
}
|
| 2263 |
|
|
}
|
| 2264 |
|
|
}
|
| 2265 |
|
|
if ($nextid>1) {
|
| 2266 |
|
|
return $nextid;
|
| 2267 |
|
|
} elsif ($reqid) {
|
| 2268 |
|
|
if (!$ids{$reqid} || $isadmin) { # If an admin is requesting id used by another, assume he knows what he is doing
|
| 2269 |
|
|
$nextid = $reqid; # Safe to use
|
| 2270 |
|
|
} else {
|
| 2271 |
|
|
$nextid = -1; # Id already in use by another
|
| 2272 |
|
|
}
|
| 2273 |
|
|
} elsif ($nextid == 1) { # This user is not currently using any vlan's, find the first free one
|
| 2274 |
|
|
for ($n=$vlanstart; $n<$vlanend; $n++) {
|
| 2275 |
|
|
if (!$ids{$n}) { # Don't return an id used (by another user)
|
| 2276 |
|
|
$nextid = $n;
|
| 2277 |
|
|
last;
|
| 2278 |
|
|
}
|
| 2279 |
|
|
}
|
| 2280 |
|
|
}
|
| 2281 |
|
|
return $nextid;
|
| 2282 |
|
|
}
|
| 2283 |
|
|
|
| 2284 |
6372a66e
|
hq
|
sub getNextRemoteIP {
|
| 2285 |
a2e0bc7e
|
hq
|
my $internalip = shift;
|
| 2286 |
|
|
my $nextip = "";
|
| 2287 |
6372a66e
|
hq
|
my $oc = overQuotas(1);
|
| 2288 |
|
|
if ($oc) { # Enforce quotas
|
| 2289 |
|
|
$postreply .= "Status=ERROR Over quota allocating external IP\n";
|
| 2290 |
|
|
} else {
|
| 2291 |
a2e0bc7e
|
hq
|
my $res = $main::postToOrigo->($engineid, 'provisionremoteip', $internalip, 'internalip');
|
| 2292 |
|
|
my $res_obj = JSON::from_json($res);
|
| 2293 |
|
|
$nextip = $res_obj->{remoteip} if ($res_obj->{remoteip});
|
| 2294 |
6372a66e
|
hq
|
}
|
| 2295 |
|
|
$postreply .= "Status=ERROR No more ($oc) remote IPs available\n" unless ($nextip);
|
| 2296 |
|
|
return $nextip;
|
| 2297 |
|
|
|
| 2298 |
|
|
}
|
| 2299 |
95b003ff
|
Origo
|
sub getNextExternalIP {
|
| 2300 |
|
|
# Find the next available IP
|
| 2301 |
|
|
my $extip = shift;
|
| 2302 |
|
|
my $extuuid = shift;
|
| 2303 |
|
|
my $proxyarp = shift; # Are we trying to assign a proxy arp's external IP?
|
| 2304 |
6372a66e
|
hq
|
$extip = "" if ($extip eq "--");
|
| 2305 |
95b003ff
|
Origo
|
|
| 2306 |
|
|
my $extipstart;
|
| 2307 |
|
|
my $extipend;
|
| 2308 |
|
|
|
| 2309 |
|
|
if ($proxyarp) {
|
| 2310 |
|
|
$extipstart = $Stabile::config->get('PROXY_IP_RANGE_START');
|
| 2311 |
|
|
$extipend = $Stabile::config->get('PROXY_IP_RANGE_END');
|
| 2312 |
|
|
} else {
|
| 2313 |
|
|
$extipstart = $Stabile::config->get('EXTERNAL_IP_RANGE_START');
|
| 2314 |
|
|
$extipend = $Stabile::config->get('EXTERNAL_IP_RANGE_END');
|
| 2315 |
|
|
}
|
| 2316 |
|
|
|
| 2317 |
|
|
return "" unless ($extipstart && $extipend);
|
| 2318 |
|
|
|
| 2319 |
|
|
my $interfaces = `/sbin/ifconfig`;
|
| 2320 |
|
|
# $interfaces =~ m/eth0 .+\n.+inet addr:(\d+\.\d+\.\d+)\.(\d+)/;
|
| 2321 |
|
|
$extipstart =~ m/(\d+\.\d+\.\d+)\.(\d+)/;
|
| 2322 |
|
|
my $bnet1 = $1;
|
| 2323 |
|
|
my $bhost1 = $2+0;
|
| 2324 |
|
|
$extipend =~ m/(\d+\.\d+\.\d+)\.(\d+)/;
|
| 2325 |
|
|
my $bnet2 = $1;
|
| 2326 |
|
|
my $bhost2 = $2+0;
|
| 2327 |
|
|
my $nextip = "";
|
| 2328 |
|
|
if ($bnet1 ne $bnet2) {
|
| 2329 |
|
|
print "Status=ERROR Only 1 class C subnet is supported for $name\n";
|
| 2330 |
|
|
return "";
|
| 2331 |
|
|
}
|
| 2332 |
|
|
my %ids;
|
| 2333 |
|
|
# First create map of IP's reserved by other servers in DB
|
| 2334 |
|
|
my @regvalues = values %register;
|
| 2335 |
|
|
foreach my $val (@regvalues) {
|
| 2336 |
|
|
my $ip = $val->{'externalip'};
|
| 2337 |
|
|
# $ip =~ m/(\d+\.\d+\.\d+)\.(\d+)/;
|
| 2338 |
|
|
# my $id = $2;
|
| 2339 |
|
|
$ids{$ip} = $val->{'uuid'} unless ($extuuid eq $val->{'uuid'});
|
| 2340 |
|
|
}
|
| 2341 |
54401133
|
hq
|
my $oc = overQuotas(1);
|
| 2342 |
|
|
if ($oc) { # Enforce quotas
|
| 2343 |
95b003ff
|
Origo
|
$postreply .= "Status=ERROR Over quota allocating external IP\n";
|
| 2344 |
|
|
} elsif ($extip && $extip =~ m/($bnet1)\.(\d+)/ && $2>=$bhost1 && $2<$bhost2) {
|
| 2345 |
|
|
# An external ip was supplied - check if it's free and ok
|
| 2346 |
|
|
if (!$ids{$extip} && !($interfaces =~ m/$extip.+\n.+inet addr:$extip/) && $extip=~/$bnet$\.(\d)/) {
|
| 2347 |
|
|
$nextip = $extip;
|
| 2348 |
|
|
}
|
| 2349 |
|
|
} else {
|
| 2350 |
|
|
# Find random IP not reserved, and check it is not in use (for other purposes)
|
| 2351 |
|
|
my @bhosts = ($bhost1..$bhost2);
|
| 2352 |
|
|
my @rbhosts = shuffle @bhosts;
|
| 2353 |
|
|
for ($n=0; $n<$bhost2-$bhost1; $n++) {
|
| 2354 |
|
|
my $nb = $rbhosts[$n];
|
| 2355 |
|
|
if (!$ids{"$bnet1.$nb"}) {
|
| 2356 |
|
|
if (!($interfaces =~ m/$extip.+\n.+inet addr:$bnet1\.$nb/)) {
|
| 2357 |
|
|
$nextip = "$bnet1.$nb";
|
| 2358 |
|
|
last;
|
| 2359 |
|
|
}
|
| 2360 |
|
|
}
|
| 2361 |
|
|
}
|
| 2362 |
|
|
}
|
| 2363 |
54401133
|
hq
|
$postreply .= "Status=ERROR No more ($oc) external IPs available\n" unless ($nextip);
|
| 2364 |
95b003ff
|
Origo
|
return $nextip;
|
| 2365 |
|
|
}
|
| 2366 |
|
|
|
| 2367 |
|
|
sub ip2domain {
|
| 2368 |
|
|
my $ip = shift;
|
| 2369 |
|
|
my $ruuid;
|
| 2370 |
|
|
if ($ip) {
|
| 2371 |
|
|
my @regkeys = (tied %register)->select_where("internalip = '$ip' OR externalip = '$ip'");
|
| 2372 |
|
|
foreach my $k (@regkeys) {
|
| 2373 |
|
|
my $valref = $register{$k};
|
| 2374 |
|
|
if ($valref->{'internalip'} eq $ip || $valref->{'externalip'} eq $ip) {
|
| 2375 |
|
|
$ruuid = $valref->{'domains'};
|
| 2376 |
|
|
last;
|
| 2377 |
|
|
}
|
| 2378 |
|
|
}
|
| 2379 |
|
|
}
|
| 2380 |
|
|
return $ruuid;
|
| 2381 |
|
|
}
|
| 2382 |
|
|
|
| 2383 |
|
|
sub getNextInternalIP {
|
| 2384 |
|
|
my $intip = shift;
|
| 2385 |
|
|
my $uuid = shift;
|
| 2386 |
|
|
my $id = shift;
|
| 2387 |
|
|
my $username = shift;
|
| 2388 |
|
|
$username = $user unless ($username);
|
| 2389 |
|
|
my $nextip = "";
|
| 2390 |
|
|
my $intipnum;
|
| 2391 |
|
|
my $subnet;
|
| 2392 |
|
|
my %ids;
|
| 2393 |
|
|
my $ping = Net::Ping->new();
|
| 2394 |
|
|
|
| 2395 |
|
|
$id = getNextId() unless ($id);
|
| 2396 |
|
|
my $idleft = ($id>99)?(substr $id,0,-2)+0 : 0;
|
| 2397 |
|
|
my $idright = (substr $id,-2) + 0;
|
| 2398 |
|
|
$intip = "10.$idleft.$idright.0" if (!$intip || $intip eq '--');
|
| 2399 |
|
|
|
| 2400 |
|
|
return '' unless ($intip =~ m/(\d+\.\d+\.\d+)\.(\d+)/ );
|
| 2401 |
|
|
$subnet = $1;
|
| 2402 |
|
|
$intipnum = $2;
|
| 2403 |
|
|
|
| 2404 |
|
|
# First create hash of IP's reserved by other servers in DB
|
| 2405 |
|
|
my @regvalues = values %register;
|
| 2406 |
|
|
foreach my $val (@regvalues) {
|
| 2407 |
|
|
if ($val->{'user'} eq $username) {
|
| 2408 |
|
|
my $ip = $val->{'internalip'} ;
|
| 2409 |
|
|
$ids{$ip} = $val->{'uuid'};
|
| 2410 |
|
|
}
|
| 2411 |
|
|
}
|
| 2412 |
|
|
|
| 2413 |
|
|
if ($intipnum && $intipnum>1 && $intipnum<255) {
|
| 2414 |
|
|
# An internal ip was supplied - check if it's free, if not keep the ip already registered in the db
|
| 2415 |
|
|
if (!$ids{$intip}
|
| 2416 |
|
|
# && !($ping->ping($intip, 0.1)) # 0.1 secs timeout, check if ip is in use, possibly on another engine
|
| 2417 |
|
|
&& !(`arping -C1 -c2 -D -I $datanic.$id $intip` =~ /reply from/) # check if ip is created on another engine
|
| 2418 |
|
|
) {
|
| 2419 |
|
|
$nextip = $intip;
|
| 2420 |
|
|
} else {
|
| 2421 |
|
|
$nextip = $register{$uuid}->{'internalip'}
|
| 2422 |
|
|
}
|
| 2423 |
|
|
} else {
|
| 2424 |
|
|
# Find first IP not reserved
|
| 2425 |
|
|
for ($n=2; $n<255; $n++) {
|
| 2426 |
|
|
if (!$ids{"$subnet.$n"}
|
| 2427 |
|
|
# TODO: The arping check takes too long - two networks created by the same user can too easily be assigned the same IP's
|
| 2428 |
|
|
# && !(`arping -f -c2 -D -I $datanic.$id $subnet.$n` =~ /reply from/) # check if ip is created on another engine
|
| 2429 |
|
|
) {
|
| 2430 |
|
|
$nextip = "$subnet.$n";
|
| 2431 |
|
|
last;
|
| 2432 |
|
|
}
|
| 2433 |
|
|
}
|
| 2434 |
|
|
}
|
| 2435 |
|
|
$postreply .= "Status=ERROR No more internal IPs available\n" if (!$nextip);
|
| 2436 |
|
|
return $nextip;
|
| 2437 |
|
|
}
|
| 2438 |
|
|
|
| 2439 |
|
|
sub validateStatus {
|
| 2440 |
|
|
my $valref = shift;
|
| 2441 |
|
|
|
| 2442 |
f222b89c
|
hq
|
my $interfaces = `/sbin/ifconfig -a | grep inet`;
|
| 2443 |
95b003ff
|
Origo
|
my $uuid = $valref->{'uuid'};
|
| 2444 |
|
|
my $type = $valref->{'type'};
|
| 2445 |
|
|
my $id = $valref->{'id'};
|
| 2446 |
|
|
my $idleft = ($id>99)?(substr $id,0,-2)+0 : 0;
|
| 2447 |
|
|
my $idright = (substr $id,-2) + 0;
|
| 2448 |
|
|
|
| 2449 |
|
|
( $valref->{'domains'}, $valref->{'domainnames'} ) = getDomains($uuid);
|
| 2450 |
d3d1a2d4
|
Origo
|
my ( $systems, $systemnames ) = getSystems($uuid);
|
| 2451 |
95b003ff
|
Origo
|
my $extip = $valref->{'externalip'};
|
| 2452 |
|
|
my $intip = $valref->{'internalip'};
|
| 2453 |
|
|
|
| 2454 |
|
|
if ($type eq "gateway") {
|
| 2455 |
|
|
$valref->{'internalip'} = "10.$idleft.$idright.1" if ($id>1);
|
| 2456 |
|
|
} else {
|
| 2457 |
|
|
if ($intip && $intip ne "--" && $extip && $extip ne "--") {
|
| 2458 |
6372a66e
|
hq
|
$type = "ipmapping" unless ($type eq 'remoteip');
|
| 2459 |
95b003ff
|
Origo
|
} elsif ($intip && $intip ne "--") {
|
| 2460 |
|
|
$type = "internalip";
|
| 2461 |
|
|
} elsif ($extip && $extip ne "--") {
|
| 2462 |
|
|
$type = "externalip";
|
| 2463 |
6372a66e
|
hq
|
} else {
|
| 2464 |
|
|
$type = "gateway";
|
| 2465 |
95b003ff
|
Origo
|
}
|
| 2466 |
|
|
$valref->{'type'} = $type;
|
| 2467 |
|
|
}
|
| 2468 |
|
|
|
| 2469 |
|
|
$valref->{'status'} = "down";
|
| 2470 |
|
|
my $nat;
|
| 2471 |
|
|
if ($id == 0 || $id == 1) {
|
| 2472 |
|
|
$valref->{'status'} = "nat";
|
| 2473 |
|
|
# Check if vlan $id is created (and doing nat)
|
| 2474 |
|
|
# } elsif ($interfaces =~ m/$datanic\.$id.+\n.+10\.$idleft\.$idright\.1/) {
|
| 2475 |
|
|
} elsif (-e "/proc/net/vlan/$datanic.$id") {
|
| 2476 |
|
|
$nat = 1;
|
| 2477 |
|
|
}
|
| 2478 |
d24d9a01
|
hq
|
|
| 2479 |
6372a66e
|
hq
|
if ($type eq "internalip" || $type eq "ipmapping" || $type eq "remoteip") {
|
| 2480 |
95b003ff
|
Origo
|
$valref->{'status'} = "nat" if ($nat);
|
| 2481 |
|
|
my $dhcprunning;
|
| 2482 |
|
|
my $dhcpconfigured;
|
| 2483 |
|
|
eval {
|
| 2484 |
|
|
my $psid;
|
| 2485 |
|
|
$psid = `/bin/cat /var/run/stabile-$id.pid` if (-e "/var/run/stabile-$id.pid");
|
| 2486 |
|
|
chomp $psid;
|
| 2487 |
|
|
$dhcprunning = -e "/proc/$psid" if ($psid);
|
| 2488 |
|
|
my $dhcphosts;
|
| 2489 |
|
|
$dhcphosts = lc `/bin/cat $etcpath/dhcp-hosts-$id` if (-e "$etcpath/dhcp-hosts-$id");
|
| 2490 |
|
|
$dhcpconfigured = ($dhcphosts =~ /$intip/);
|
| 2491 |
|
|
1;
|
| 2492 |
|
|
} or do {;};
|
| 2493 |
|
|
|
| 2494 |
6372a66e
|
hq
|
if ($type eq "internalip" || $type eq "remoteip") {
|
| 2495 |
95b003ff
|
Origo
|
# Check if external ip has been created and dhcp is ok
|
| 2496 |
d3d1a2d4
|
Origo
|
if ($nat && (($dhcprunning && $dhcpconfigured) || $systems)) {
|
| 2497 |
a2e0bc7e
|
hq
|
if ($type eq "remoteip") {
|
| 2498 |
|
|
if (`pgrep -f 'ssh .* $externalip'`) {
|
| 2499 |
|
|
$valref->{'status'} = "up";
|
| 2500 |
|
|
}
|
| 2501 |
|
|
} else {
|
| 2502 |
|
|
$valref->{'status'} = "up";
|
| 2503 |
|
|
}
|
| 2504 |
95b003ff
|
Origo
|
}
|
| 2505 |
|
|
} elsif ($type eq "ipmapping") {
|
| 2506 |
|
|
# Check if external ip has been created, dhcp is ok and vlan interface is created
|
| 2507 |
d3d1a2d4
|
Origo
|
# An ipmapping linked to a system is considered up if external interface exists
|
| 2508 |
6372a66e
|
hq
|
# Update: It appears that ip addresses on virtual interfaces are periodically lost for some reason
|
| 2509 |
|
|
# the interface however still responds to the ip address if iptables rules referencing this exists
|
| 2510 |
|
|
# so we have relaxed the up requirement
|
| 2511 |
|
|
if ($nat
|
| 2512 |
|
|
# && $interfaces =~ m/$extip/ # interfaces seem to drop out of sight after while even if still active
|
| 2513 |
f222b89c
|
hq
|
&& (($dhcprunning && $dhcpconfigured) || ($systems && $interfaces =~ m/$extip/))
|
| 2514 |
|
|
) {
|
| 2515 |
95b003ff
|
Origo
|
$valref->{'status'} = "up";
|
| 2516 |
|
|
}
|
| 2517 |
|
|
}
|
| 2518 |
|
|
|
| 2519 |
|
|
} elsif ($type eq "externalip") {
|
| 2520 |
|
|
my $dhcprunning;
|
| 2521 |
|
|
my $dhcpconfigured;
|
| 2522 |
|
|
eval {
|
| 2523 |
|
|
my $psid;
|
| 2524 |
|
|
$psid = `/bin/cat /var/run/stabile-$id.pid` if (-e "/var/run/stabile-$id.pid");
|
| 2525 |
|
|
chomp $psid;
|
| 2526 |
|
|
$dhcprunning = -e "/proc/$psid" if ($psid);
|
| 2527 |
|
|
my $dhcphosts;
|
| 2528 |
|
|
$dhcphosts = `/bin/cat $etcpath/dhcp-hosts-$id` if (-e "$etcpath/dhcp-hosts-$id");
|
| 2529 |
|
|
$dhcpconfigured = ($dhcphosts =~ /$extip/);
|
| 2530 |
|
|
1;
|
| 2531 |
|
|
} or do {;};
|
| 2532 |
|
|
|
| 2533 |
|
|
my $vproxy = `/bin/cat /proc/sys/net/ipv4/conf/$datanic.$id/proxy_arp`; chomp $vproxy;
|
| 2534 |
|
|
my $eproxy = `/bin/cat /proc/sys/net/ipv4/conf/$proxynic/proxy_arp`; chomp $eproxy;
|
| 2535 |
|
|
my $proute = `/sbin/ip route | grep "$extip dev"`; chomp $proute;
|
| 2536 |
d3d1a2d4
|
Origo
|
if ($vproxy && $eproxy && $proute) {
|
| 2537 |
|
|
if ((($dhcprunning && $dhcpconfigured) || $systems)) {
|
| 2538 |
|
|
$valref->{'status'} = "up";
|
| 2539 |
|
|
} elsif (!$valref->{'domains'}) {
|
| 2540 |
|
|
$valref->{'status'} = "nat";
|
| 2541 |
|
|
}
|
| 2542 |
95b003ff
|
Origo
|
} else {
|
| 2543 |
|
|
#print "$vproxy && $eproxy && $proute && $dhcprunning && $dhcpconfigured :: $extip\n";
|
| 2544 |
|
|
}
|
| 2545 |
|
|
|
| 2546 |
|
|
} elsif ($type eq "gateway") {
|
| 2547 |
|
|
if ($nat || $id == 0 || $id == 1) {$valref->{'status'} = "up";}
|
| 2548 |
|
|
}
|
| 2549 |
|
|
return $valref->{'status'};
|
| 2550 |
|
|
}
|
| 2551 |
|
|
|
| 2552 |
|
|
sub trim{
|
| 2553 |
|
|
my $string = shift;
|
| 2554 |
|
|
$string =~ s/^\s+|\s+$//g;
|
| 2555 |
|
|
return $string;
|
| 2556 |
|
|
}
|
| 2557 |
|
|
|
| 2558 |
|
|
sub overQuotas {
|
| 2559 |
|
|
my $reqips = shift; # number of new ip's we are asking for
|
| 2560 |
|
|
my $usedexternalips = 0;
|
| 2561 |
|
|
my $overquota = 0;
|
| 2562 |
|
|
return $overquota if ($Stabile::userprivileges =~ /a/); # Don't enforce quotas for admins
|
| 2563 |
|
|
|
| 2564 |
54401133
|
hq
|
my $externalipquota = $Stabile::userexternalipquota;
|
| 2565 |
95b003ff
|
Origo
|
if (!$externalipquota) {
|
| 2566 |
|
|
$externalipquota = $Stabile::config->get('EXTERNAL_IP_QUOTA');
|
| 2567 |
|
|
}
|
| 2568 |
|
|
|
| 2569 |
54401133
|
hq
|
my $rxquota = $Stabile::userrxquota;
|
| 2570 |
95b003ff
|
Origo
|
if (!$rxquota) {
|
| 2571 |
|
|
$rxquota = $Stabile::config->get('RX_QUOTA');
|
| 2572 |
|
|
}
|
| 2573 |
|
|
|
| 2574 |
54401133
|
hq
|
my $txquota = $Stabile::usertxquota;
|
| 2575 |
95b003ff
|
Origo
|
if (!$txquota) {
|
| 2576 |
|
|
$txquota = $Stabile::config->get('TX_QUOTA');
|
| 2577 |
|
|
}
|
| 2578 |
|
|
|
| 2579 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user'");
|
| 2580 |
|
|
foreach my $k (@regkeys) {
|
| 2581 |
|
|
my $val = $register{$k};
|
| 2582 |
|
|
if ($val->{'user'} eq $user && $val->{'externalip'} && $val->{'externalip'} ne "--" ) {
|
| 2583 |
|
|
$usedexternalips += 1;
|
| 2584 |
|
|
}
|
| 2585 |
|
|
}
|
| 2586 |
54401133
|
hq
|
if ((($usedexternalips + $reqips) > $externalipquota) && $externalipquota > 0) { # -1 means no quota
|
| 2587 |
95b003ff
|
Origo
|
$overquota = $usedexternalips;
|
| 2588 |
|
|
} elsif ($rx > $rxquota*1024 && $rxquota > 0) {
|
| 2589 |
|
|
$overquota = -1;
|
| 2590 |
|
|
} elsif ($tx > $txquota*1024 && $txquota > 0) {
|
| 2591 |
|
|
$overquota = -2;
|
| 2592 |
|
|
}
|
| 2593 |
|
|
return $overquota;
|
| 2594 |
|
|
}
|
| 2595 |
|
|
|
| 2596 |
|
|
sub updateBilling {
|
| 2597 |
|
|
my $event = shift;
|
| 2598 |
|
|
my %billing;
|
| 2599 |
|
|
my @regkeys = (tied %register)->select_where("user = '$user' or user = 'common'") unless ($fulllist);
|
| 2600 |
|
|
foreach my $k (@regkeys) {
|
| 2601 |
|
|
my $valref = $register{$k};
|
| 2602 |
|
|
my %val = %{$valref}; # Deference and assign to new array, effectively cloning object
|
| 2603 |
|
|
if ($val{'user'} eq $user && ($val{'type'} eq 'ipmapping' || $val{'type'} eq 'externalip') && $val{'externalip'} ne '--') {
|
| 2604 |
|
|
$billing{$val{'id'}}->{'externalip'} += 1;
|
| 2605 |
|
|
}
|
| 2606 |
|
|
}
|
| 2607 |
|
|
|
| 2608 |
|
|
my %billingreg;
|
| 2609 |
|
|
my $monthtimestamp = timelocal(0,0,0,1,$mon,$year); #$sec,$min,$hour,$mday,$mon,$year
|
| 2610 |
|
|
|
| 2611 |
|
|
unless ( tie(%billingreg,'Tie::DBI', Hash::Merge::merge({table=>'billing_networks', key=>'useridtime'}, $Stabile::dbopts)) ) {return "Unable to access billing register"};
|
| 2612 |
|
|
|
| 2613 |
|
|
my $rx_bytes_total = 0;
|
| 2614 |
|
|
my $tx_bytes_total = 0;
|
| 2615 |
|
|
|
| 2616 |
|
|
my $prevmonth = $month-1;
|
| 2617 |
|
|
my $prevyear = $year;
|
| 2618 |
|
|
if ($prevmonth == 0) {$prevmonth=12; $prevyear--;};
|
| 2619 |
|
|
$prevmonth = substr("0" . $prevmonth, -2);
|
| 2620 |
|
|
my $prev_rx_bytes_total = 0;
|
| 2621 |
|
|
my $prev_tx_bytes_total = 0;
|
| 2622 |
|
|
|
| 2623 |
|
|
foreach my $id (keys %billing) {
|
| 2624 |
|
|
my $b = $billing{$id};
|
| 2625 |
|
|
my $externalip = $b->{'externalip'};
|
| 2626 |
|
|
my $externalipavg = 0;
|
| 2627 |
|
|
my $startexternalipavg = 0;
|
| 2628 |
|
|
my $starttimestamp = $current_time;
|
| 2629 |
|
|
my $rx_bytes = 0;
|
| 2630 |
|
|
my $tx_bytes = 0;
|
| 2631 |
6372a66e
|
hq
|
# my $rx_stats = "/sys/class/net/$datanic.$id/statistics/rx_bytes";
|
| 2632 |
|
|
# my $tx_stats = "/sys/class/net/$datanic.$id/statistics/tx_bytes";
|
| 2633 |
|
|
my $rx_stats = "/sys/class/net/br$id/statistics/rx_bytes";
|
| 2634 |
|
|
my $tx_stats = "/sys/class/net/br$id/statistics/tx_bytes";
|
| 2635 |
95b003ff
|
Origo
|
$rx_bytes = `/bin/cat $rx_stats` if (-e $rx_stats);
|
| 2636 |
|
|
chomp $rx_bytes;
|
| 2637 |
|
|
$tx_bytes = `/bin/cat $tx_stats` if (-e $tx_stats);
|
| 2638 |
|
|
chomp $tx_bytes;
|
| 2639 |
|
|
|
| 2640 |
|
|
if ($current_time - $monthtimestamp < 4*3600) {
|
| 2641 |
|
|
$starttimestamp = $monthtimestamp;
|
| 2642 |
|
|
$externalipavg = $externalip;
|
| 2643 |
|
|
$startexternalipavg = $externalip;
|
| 2644 |
|
|
}
|
| 2645 |
|
|
|
| 2646 |
|
|
my $bill = $billingreg{"$user-$id-$year-$month"};
|
| 2647 |
|
|
my $regrx_bytes = $bill->{'rx'};
|
| 2648 |
|
|
my $regtx_bytes = $bill->{'tx'};
|
| 2649 |
|
|
$rx_bytes += $regrx_bytes if ($regrx_bytes > $rx_bytes); # Network interface was reloaded
|
| 2650 |
|
|
$tx_bytes += $regtx_bytes if ($regtx_bytes > $tx_bytes); # Network interface was reloaded
|
| 2651 |
|
|
|
| 2652 |
|
|
# Update timestamp and averages on existing row
|
| 2653 |
|
|
if ($billingreg{"$user-$id-$year-$month"}) {
|
| 2654 |
|
|
$startexternalipavg = $bill->{'startexternalipavg'};
|
| 2655 |
|
|
$starttimestamp = $bill->{'starttimestamp'};
|
| 2656 |
|
|
|
| 2657 |
|
|
$externalipavg = ($startexternalipavg*($starttimestamp - $monthtimestamp) + $externalip*($current_time - $starttimestamp)) /
|
| 2658 |
|
|
($current_time - $monthtimestamp);
|
| 2659 |
|
|
|
| 2660 |
|
|
$billingreg{"$user-$id-$year-$month"}->{'externalip'} = $externalip;
|
| 2661 |
|
|
$billingreg{"$user-$id-$year-$month"}->{'externalipavg'} = $externalipavg;
|
| 2662 |
|
|
$billingreg{"$user-$id-$year-$month"}->{'timestamp'} = $current_time;
|
| 2663 |
|
|
$billingreg{"$user-$id-$year-$month"}->{'rx'} = $rx_bytes;
|
| 2664 |
|
|
$billingreg{"$user-$id-$year-$month"}->{'tx'} = $tx_bytes;
|
| 2665 |
|
|
}
|
| 2666 |
|
|
|
| 2667 |
|
|
# No row found or something happened which justifies writing a new row
|
| 2668 |
|
|
if (!$billingreg{"$user-$id-$year-$month"}
|
| 2669 |
|
|
|| ($b->{'externalip'} != $bill->{'externalip'})
|
| 2670 |
|
|
) {
|
| 2671 |
|
|
|
| 2672 |
|
|
my $inc = 0;
|
| 2673 |
|
|
if ($billingreg{"$user-$id-$year-$month"}) {
|
| 2674 |
|
|
$startexternalipavg = $externalipavg;
|
| 2675 |
|
|
$starttimestamp = $current_time;
|
| 2676 |
|
|
$inc = $bill->{'inc'};
|
| 2677 |
|
|
}
|
| 2678 |
|
|
# Write a new row
|
| 2679 |
|
|
$billingreg{"$user-$id-$year-$month"} = {
|
| 2680 |
|
|
externalip=>$externalip+0,
|
| 2681 |
|
|
externalipavg=>$externalipavg,
|
| 2682 |
|
|
startexternalipavg=>$startexternalipavg,
|
| 2683 |
|
|
timestamp=>$current_time,
|
| 2684 |
|
|
starttimestamp=>$starttimestamp,
|
| 2685 |
|
|
event=>$event,
|
| 2686 |
|
|
inc=>$inc+1,
|
| 2687 |
|
|
rx=>$rx_bytes,
|
| 2688 |
|
|
tx=>$tx_bytes
|
| 2689 |
|
|
};
|
| 2690 |
|
|
}
|
| 2691 |
|
|
|
| 2692 |
|
|
$rx_bytes_total += $rx_bytes;
|
| 2693 |
|
|
$tx_bytes_total += $tx_bytes;
|
| 2694 |
|
|
my $prevbill = $billingreg{"$user-$id-$prevyear-$prevmonth"};
|
| 2695 |
|
|
$prev_rx_bytes_total += $prevbill->{'rx'};
|
| 2696 |
|
|
$prev_tx_bytes_total += $prevbill->{'tx'};
|
| 2697 |
|
|
}
|
| 2698 |
|
|
untie %billingreg;
|
| 2699 |
|
|
$rx = ($rx_bytes_total>$prev_rx_bytes_total)?$rx_bytes_total - $prev_rx_bytes_total:$rx_bytes_total;
|
| 2700 |
|
|
$tx = ($tx_bytes_total>$prev_tx_bytes_total)?$tx_bytes_total - $prev_tx_bytes_total:$tx_bytes_total;
|
| 2701 |
|
|
my $oq = overQuotas();
|
| 2702 |
54401133
|
hq
|
if ($oq && $oq<0) {
|
| 2703 |
95b003ff
|
Origo
|
foreach my $id (keys %billing) {
|
| 2704 |
|
|
$main::syslogit->($user, 'info', "$user over rx/tx quota ($oq) stopping network $id");
|
| 2705 |
|
|
Stop($id, 'stop');
|
| 2706 |
|
|
}
|
| 2707 |
|
|
}
|
| 2708 |
|
|
}
|
| 2709 |
|
|
|
| 2710 |
|
|
sub Bit2netmask {
|
| 2711 |
|
|
my $netbit = shift;
|
| 2712 |
|
|
my $_bit = ( 2 ** (32 - $netbit) ) - 1;
|
| 2713 |
|
|
my ($full_mask) = unpack( "N", pack( "C4", split(/./, '255.255.255.255') ) );
|
| 2714 |
|
|
my $netmask = join( '.', unpack( "C4", pack( "N", ( $full_mask ^ $_bit ) ) ) );
|
| 2715 |
|
|
return $netmask;
|
| 2716 |
|
|
} |