initfwvars.pl.in 7.85 KB
Newer Older
1 2
#!/usr/bin/perl -w
#
3
# Copyright (c) 2005-2017 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#

#CREATE TABLE firewall_vars (
#  name varchar(255) NOT NULL default '',
#  value text,
#  PRIMARY KEY  (name)
#) TYPE=MyISAM;

my $doit = 1;

use English;
use Socket;

use lib "@prefix@/lib";
use libdb;

my $CONTROL_NETWORK    = "@CONTROL_NETWORK@";
my $CONTROL_NETMASK    = "@CONTROL_NETMASK@";
41 42
my $PRIVATE_NETWORK    = "@PRIVATE_NETWORK@";
my $PRIVATE_NETMASK    = "@PRIVATE_NETMASK@";
43 44 45 46
my $PUBLIC_NETWORK     = "@PUBLIC_NETWORK@";
my $PUBLIC_NETMASK     = "@PUBLIC_NETMASK@";
my $VIRTNODE_NETWORK   = "@VIRTNODE_NETWORK@";
my $VIRTNODE_NETMASK   = "@VIRTNODE_NETMASK@";
47
my $BOSSNODE_IP        = "@BOSSNODE_IP@";
48 49
my $USERNODE_IP        = "@USERNODE_IP@";
my $FSNODE_IP          = "@FSNODE_IP@";
50 51
my $FRISBEE_MCASTADDR  = "@FRISEBEEMCASTADDR@";
my $FRISBEE_MCASTPORT  = "@FRISEBEEMCASTPORT@";
52
my $FRISBEE_MCNUMPORT  = "@FRISEBEENUMPORTS@";
53 54 55 56 57 58
#
# Sorry these are hardwired; boss/ops addresses on the virtual control
# network, on non-segmented networks like the IG racks.
#
my $EMULAB_VCBOSS      = "172.17.254.254";
my $EMULAB_VCOPS       = "172.17.253.254";
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

#
# Untaint the path
# 
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

# Simple is good. I stole this out of a google search.
my @NETMASKS =
    (0x10000000,                                             # 0
     0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,         #  1 -  4
     0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,         #  5 -  8
     0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,         #  9 - 12
     0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,         # 13 - 16
     0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,         # 17 - 20
     0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,         # 21 - 24
     0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,         # 25 - 28
     0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF          # 29 - 32
);

79 80 81 82
sub getcidrnet($)
{
    my ($mask) = @_;
    my $cidrnet = "24";
83

84 85 86 87 88 89 90
    for (my $i = 0; $i < scalar(@NETMASKS); $i++) {
	my $foo = pack("N", $NETMASKS[$i]);

	if ($mask eq inet_ntoa($foo)) {
	    $cidrnet = "$i";
	    last;
	}
91
    }
92 93

    return $cidrnet;
94 95 96
}

my $str;
97
my $res;
98
my $subbosses = 0;
99

100 101 102 103
if (@ARGV > 0 && $ARGV[0] eq "-n") {
    $doit = 0;
}

104 105 106 107 108 109 110 111 112
#
# Create EMULAB_BOSSES variable.
#

# There is boss...
my @bosses = "boss";
# ...and any subbosses
$res = DBQueryFatal("select distinct subboss_id from subbosses");
while (my ($sb) = $res->fetchrow_array()) {
113 114
    push(@bosses, $sb);
    $subbosses++;
115 116 117 118
}

my $bstr = join(',', @bosses);
$str = "replace into default_firewall_vars values ('EMULAB_BOSSES', '$bstr')";
119 120 121 122 123
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
#
# Create EMULAB_SERVERS variable
#

# Start with bosses...
my @servers = @bosses;
# ...add ops...
push(@servers, "ops");
# ...and fs if it exists
if ($FSNODE_IP ne $USERNODE_IP) {
    push(@servers, "fs");
}

my $sstr = join(',', @servers);
$str = "replace into default_firewall_vars values ('EMULAB_SERVERS', '$sstr')";
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

#
# Create EMULAB_NS variable
#

148 149 150 151 152 153 154
# Use boss IP as "ns" since that is what we assume everywhere else
$str = "replace into default_firewall_vars values ('EMULAB_NS', '$BOSSNODE_IP')";
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

155 156 157 158
#
# Create EMULAB_CNET variable
#

159
# Add the control net in CIDR notation
160 161 162 163 164 165 166 167 168 169
my $cidrnet = getcidrnet($CONTROL_NETMASK);
$str = "replace into default_firewall_vars values ('EMULAB_CNET', '$CONTROL_NETWORK/$cidrnet')";
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

# And the virtnode control net in CIDR notation
$cidrnet = getcidrnet($VIRTNODE_NETMASK);
$str = "replace into default_firewall_vars values ('EMULAB_VCNET', '$VIRTNODE_NETWORK/$cidrnet')";
170 171 172 173 174
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

175 176 177 178 179 180 181 182 183 184 185 186 187
#
# Create EMULAB_VGWIP defined
# EMULAB_GWIP comes from the DB via tmcd.
#
if ($VIRTNODE_NETWORK =~ /^(\d+\.\d+\.\d+)\.0$/) {
    my $vgwip = "$1.1";
    $str = "replace into default_firewall_vars values ('EMULAB_VGWIP', '$vgwip')";
    print "$str\n"
	if (!$doit);
    DBQueryFatal($str)
	if ($doit);
}

188
#
189
# Boss/Ops on the virtual control network, non-segmented.
190 191
#
$str = "replace into default_firewall_vars values ".
192 193
    "('EMULAB_VCBOSS', '$EMULAB_VCBOSS'), ".
    "('EMULAB_VCOPS',  '$EMULAB_VCOPS')";
194 195 196 197 198 199

print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

200 201 202 203 204 205 206 207 208 209 210 211
#
# FS can have a virtual control network address, but ignore fs/ops
# distinction. 
#
$str = "replace into default_firewall_vars values ".
    "('EMULAB_FSIPS', '$FSNODE_IP,$EMULAB_VCOPS') ";

print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

212 213 214 215
#
# Create EMULAB_MCADDR and EMULAB_MCPORT variables
#

216 217
#
# Frisbee multicast info
218 219 220
# XXX assumptions, assumptions (as of 9/05).  We could allow up to a /8 network
# but we assign a unique port as well as address and a port is only 16 bits,
# so use a /16.
221 222 223
# XXX assumptions II (as of 2/08).  frisbeelauncher ticks up the MC address
# all the way to /8 (it wraps the port number as needed), so lets make it
# so here.
224 225
# XXX assumptions III (as of 11/11).  Frisbee master server running on
# subboss can open up the port range even wider, by default starting at 1025.
226 227 228
# XXX assumptions IV (as of 5/15).  Frisbee master server now constrains
# server/client to a configurable range.
# XXX assumptions V (as of 2/17).  Subbosses use the same port range as boss.
229 230
#
my @mcaddr = split /\./, $FRISBEE_MCASTADDR, 4;
231
$FRISBEE_MCASTADDR = $mcaddr[0] . ".0.0.0/8";
232 233 234 235
# XXX hack for subbosses
if ($subbosses > 0 && $mcaddr[0] != 239) {
    $FRISBEE_MCASTADDR .= ",239.0.0.0/8";
}
236 237 238
my $loport = ($FRISBEE_MCASTPORT == 0) ? 1025 : $FRISBEE_MCASTPORT;
my $hiport = ($FRISBEE_MCNUMPORT == 0) ? 65535 : $loport + $FRISBEE_MCNUMPORT - 1;
$FRISBEE_MCASTPORT = "$loport-$hiport";
239

240 241 242 243 244 245 246 247 248 249 250 251
$str = "replace into default_firewall_vars values ('EMULAB_MCADDR', '$FRISBEE_MCASTADDR')";
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

$str = "replace into default_firewall_vars values ('EMULAB_MCPORT', '$FRISBEE_MCASTPORT')";
print "$str\n"
    if (!$doit);
DBQueryFatal($str)
    if ($doit);

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
#
# Check for support of non-segmented control network.
#
# For this to work, all servers on the same subnet must have entries
# in the interfaces table with a valid MAC address.
#
my $nodenet = inet_aton($CONTROL_NETWORK) & inet_aton($CONTROL_NETMASK);
my $privnet = inet_aton($PRIVATE_NETWORK) & inet_aton($PRIVATE_NETMASK);
my $pubnet = inet_aton($PUBLIC_NETWORK) & inet_aton($PUBLIC_NETMASK);

my $segcnet = 1;
if ($nodenet eq $privnet && $privnet eq $pubnet) {
    print "You appear to be using a non-segmented control network.\n";
    $segcnet = 0;
}

foreach my $n (@servers) {
    my $res = DBQueryFatal("select node_id,IP,mac from interfaces ".
			  "where role='ctrl' and node_id='$n'");
    if ($res->numrows == 0) {
	if ($segcnet) {
	    print STDERR "NOTE: '$n' does not have an interfaces table entry,".
		" but this doesn't matter in your config.\n";
	} else {
	    print STDERR "WARNING: '$n' does not have an interfaces table entry,".
		" you will need to create one for the control net interface.\n";
	}
    }
}

282
exit(0);