From be8675fc88c8dabe5be3a35e8ebc18e130112a48 Mon Sep 17 00:00:00 2001 From: Jamie Cameron Date: Mon, 27 Jun 2011 23:20:10 -0400 Subject: [PATCH] Start of work on bridge support --- net/debian-linux-lib.pl | 28 +++++++++++++++++++++++- net/edit_bifc.cgi | 39 ++++++++++++++++++++++++++++++++-- net/lang/en | 11 ++++++++-- net/list_ifcs.cgi | 12 ++++++++--- net/redhat-linux-lib.pl | 31 +++++++++++++++++++++++++-- net/save_bifc.cgi | 47 +++++++++++++++++++++++++++-------------- 6 files changed, 142 insertions(+), 26 deletions(-) diff --git a/net/debian-linux-lib.pl b/net/debian-linux-lib.pl index c42e180f8..3d437fff1 100755 --- a/net/debian-linux-lib.pl +++ b/net/debian-linux-lib.pl @@ -37,6 +37,9 @@ foreach $iface (@ifaces) { else { $cfg->{'name'} = $cfg->{'fullname'}; } + if ($cfg->{'fullname'} =~ /^br(\d+)$/) { + $cfg->{'bridge'} = 1; + } if ($gconfig{'os_version'} >= 3 || scalar(@autos)) { $cfg->{'up'} = &indexof($name, @autos) >= 0; } @@ -77,6 +80,13 @@ foreach $iface (@ifaces) { $cfg->{'ether_type'} = $v[0]; $cfg->{'ether'} = $v[1]; } + elsif ($param eq 'bridge_ports') { + $cfg->{'bridgeto'} = $value; + } + elsif ($param eq 'pre-up' && + $value =~ /brctl\s+addif\s+br\d+\s+(\S+)/) { + $cfg->{'bridgeto'} = $1; + } else { $cfg->{$param} = $value; } @@ -147,7 +157,7 @@ if ($cfg->{'dhcp'} == 1) { elsif ($cfg->{'bootp'} == 1) { $method = 'bootp'; } -else { +elsif ($cfg->{'address'}) { $method = 'static'; push(@options, ['address', $cfg->{'address'}]); push(@options, ['netmask', $cfg->{'netmask'}]); @@ -164,6 +174,9 @@ else { push(@options, ['network', $network]); } } +else { + $method = 'manual'; + } my @autos = get_auto_defs(); my $amode = $gconfig{'os_version'} > 3 || scalar(@autos); if (!$cfg->{'up'} && !$amode) { push(@options, ['noauto', '']); } @@ -1023,5 +1036,18 @@ local ($iface) = @_; return !$iface || $iface->{'virtual'} eq ''; } +# Returns 1, as boot-time interfaces on Debian can exist without an IP (such as +# for bridging) +sub supports_no_address +{ +return 1; +} + +# Bridge interfaces can be created on debian +sub supports_bridges +{ +return 1; +} + 1; diff --git a/net/edit_bifc.cgi b/net/edit_bifc.cgi index 69a328052..1b0907005 100755 --- a/net/edit_bifc.cgi +++ b/net/edit_bifc.cgi @@ -16,6 +16,16 @@ elsif ($in{'new'} && $in{'vlan'}) { # New VLAN &ui_print_header(undef, $text{'vlan_create'}, ""); } +elsif ($in{'new'} && $in{'bridge'}) { + # New Bridge + &ui_print_header(undef, $text{'bridge_create'}, ""); + $bmax = -1; + foreach $b (@boot) { + if ($b->{'fullname'} =~ /^br(\d+)$/) { + $bmax = $1; + } + } + } elsif ($in{'new'}) { # New real or virtual interface &ui_print_header(undef, $text{'bifc_create'}, ""); @@ -47,6 +57,7 @@ print &ui_hidden("new", $in{'new'}); print &ui_hidden("idx", $in{'idx'}); print &ui_hidden("vlan", $in{'vlan'}); print &ui_hidden("bond", $in{'bond'}); +print &ui_hidden("bridge", $in{'bridge'}); print &ui_table_start($in{'virtual'} || $b && $b->{'virtual'} ne "" ? $text{'bifc_desc2'} : $text{'bifc_desc1'}, "width=100%", 4); @@ -69,6 +80,9 @@ elsif ($in{'new'}) { if ($in{'vlan'} == 1) { $namefield = "auto".&ui_hidden("name", "auto"); } + elsif ($in{'bridge'}) { + $namefield = "br".&ui_textbox("name", ($bmax+1), 3); + } else { $namefield = &ui_textbox("name", undef, 6); } @@ -94,6 +108,14 @@ print &ui_table_row($text{'ifcs_act'}, $upfield); $virtual = (!$b && $in{'virtual'}) || ($b && $b->{'virtual'} ne ""); $dhcp = &can_edit("dhcp") && !$virtual; $bootp = &can_edit("bootp") && !$virtual; +if (defined(&supports_no_address) && &supports_no_address()) { + # Having no address is allowed + $canno = 1; + } +elsif ($b && !$b->{'address'} && !$b->{'dhcp'} && !$b->{'bootp'}) { + # Has no address + $canno = 1; + } @opts = ( ); if ($dhcp) { push(@opts, [ "dhcp", $text{'ifcs_dhcp'} ]); @@ -101,6 +123,8 @@ if ($dhcp) { if ($bootp) { push(@opts, [ "bootp", $text{'ifcs_bootp'} ]); } +if ($canno) { + } @grid = ( $text{'ifcs_ip'}, &ui_textbox("address", $b ? $b->{'address'} : "", 15) ); if ($in{'virtual'} && $in{'new'} && $virtual_netmask) { @@ -129,6 +153,9 @@ elsif ($b && $b->{'broadcast'}) { push(@grid, $text{'ifcs_broad'}, "$b->{'broadcast'}"); } push(@opts, [ "address", $text{'ifcs_static2'}, &ui_grid_table(\@grid, 2) ]); +if ($canno) { + push(@opts, [ "none", $text{'ifcs_noaddress'} ]); + } # Show the IP field if (@opts > 1) { @@ -147,7 +174,7 @@ if (&supports_address6($b)) { # Multiple IPs allowed $table6 = &ui_columns_start([ $text{'ifcs_address6'}, $text{'ifcs_netmask6'} ], 50); - for($i=0; $i<=@{$b->{'address6'}}; $i++) { + for($i=0; $i<=($b ? scalar(@{$b->{'address6'}}) : 0); $i++) { $table6 .= &ui_columns_row([ &ui_textbox("address6_$i", $b->{'address6'}->[$i], 40), @@ -157,6 +184,7 @@ if (&supports_address6($b)) { $table6 .= &ui_columns_end(); print &ui_table_row($text{'ifcs_mode6'}, &ui_radio_table("mode6", + !$b ? "none" : $b->{'auto6'} ? "auto" : @{$b->{'address6'}} ? "address" : "none", [ [ "none", $text{'ifcs_none6'} ], @@ -238,7 +266,7 @@ if(($in{'vlan'}) or (&iface_type($b->{'name'}) =~ /^(.*) (VLAN)$/)) { } # Hardware address, if non-virtual -if (($in{'new'} && $in{'virtual'} eq "") || +if (($in{'new'} && $in{'virtual'} eq "" && !$in{'bridge'}) || (!$in{'new'} && $b->{'virtual'} eq "" && defined(&boot_iface_hardware) && &boot_iface_hardware($b->{'name'}))) { @@ -247,6 +275,13 @@ if (($in{'new'} && $in{'virtual'} eq "") || print &ui_table_row($text{'aifc_hard'}, $hardfield); } +# Real interface for bridge +if ($in{'bridge'} || $b && $b->{'bridge'}) { + @ethboot = grep { $_->{'fullname'} =~ /^eth(\d+)$/ } @boot; + print &ui_table_row($text{'bifc_bridgeto'}, + &ui_select("bridgeto", $b->{'bridgeto'}, \@ethboot)); + } + print &ui_table_end(); # Generate and show buttons at end of the form diff --git a/net/lang/en b/net/lang/en index aafccbc4d..65f47f047 100644 --- a/net/lang/en +++ b/net/lang/en @@ -24,6 +24,7 @@ ifcs_up=Up ifcs_down=Down ifcs_add=Add a new interface. ifcs_radd=Add a new address range. +ifcs_badd=Add a new bridge. ifcs_boot=Activated at Boot ifcs_act=Activate ifcs_bootp=From BOOTP @@ -42,6 +43,7 @@ ifcs_ecannot_this=You are not allowed to edit this network interface ifcs_range=Range $1 ifcs_static2=Static configuration ifcs_static3=IPv6 enabled +ifcs_noaddress=No address configured ifcs_mode=IPv4 address ifcs_mode6=IPv6 addresses ifcs_address6=IPv6 address @@ -100,9 +102,12 @@ bifc_err4=Failed to deactivate interface bifc_capply=Create and Apply bifc_eapply=You cannot activate an interface that uses DHCP or BOOTP bifc_edhcpmain=DHCP can only be enabled on the primary network interface +bifc_bridgeto=Connect bridge to interface +bifc_ebridgeto=An existing Ethernet interface must be selected for this bridge to use +bifc_ebridgeto2=The selected interface for the bridge must not have any address assigned bonding_add=Add a new bonding Interface. -bonding_create=Create Bootup Bonding Interface +bonding_create=Create Bonding Interface bonding_teamparts=Teaming Partner bonding_teammode=Teaming Mode bonding_miimon=Mii-Monitoring Interval @@ -112,7 +117,9 @@ bonding_downdelay=Downdelay vlan_add=Add Vlan Tagged Interface vlan_physical=Physical Device vlan_id=Vlan ID -vlan_create=Create a VLAN tagged interface +vlan_create=Create VLAN Interface + +bridge_create=Create Bridge Interface routes_title=Routing and Gateways routes_boot=Routing configuration activated at boot time diff --git a/net/list_ifcs.cgi b/net/list_ifcs.cgi index 222f66c6e..09ae544c0 100755 --- a/net/list_ifcs.cgi +++ b/net/list_ifcs.cgi @@ -115,15 +115,21 @@ print &ui_form_start("delete_bifcs.cgi", "post"); if ($allow_add) { push(@links, "$text{'ifcs_add'}"); if (defined(&supports_bonding) && &supports_bonding()) { - push(@links, "$text{'bonding_add'}"); + push(@links, "". + "$text{'bonding_add'}"); } if (defined(&supports_vlans) && &supports_vlans()) { - push(@links, "$text{'vlan_add'}"); + push(@links, "". + "$text{'vlan_add'}"); } } if ($allow_add && defined(&supports_ranges) && &supports_ranges()) { push(@links, "$text{'ifcs_radd'}"); } +if ($allow_add && defined(&supports_bridges) && &supports_bridges()) { + push(@links, "". + "$text{'ifcs_badd'}"); + } print &ui_links_row(\@links); @tds = ( "width=5 valign=top", "width=20% valign=top", "width=20% valign=top", "width=20% valign=top", "width=20% valign=top" ); @@ -202,7 +208,7 @@ foreach $a (@boot) { push(@cols, $a->{'bootp'} ? $text{'ifcs_bootp'} : $a->{'dhcp'} ? $text{'ifcs_dhcp'} : $a->{'address'} ? &html_escape($a->{'address'}) : - $text{'ifcs_auto'}); + $text{'ifcs_noaddress'}); push(@cols, $a->{'netmask'} ? &html_escape($a->{'netmask'}) : $text{'ifcs_auto'}); if (&supports_address6()) { diff --git a/net/redhat-linux-lib.pl b/net/redhat-linux-lib.pl index a156917a2..92e2b0e2e 100755 --- a/net/redhat-linux-lib.pl +++ b/net/redhat-linux-lib.pl @@ -60,7 +60,8 @@ do 'linux-lib.pl'; # Returns a list of interfaces brought up at boot time sub boot_interfaces { -local(@rv, $f); +local (@rv, $f); +local %bridge_map; opendir(CONF, &translate_filename($net_scripts_dir)); while($f = readdir(CONF)) { local (%conf, $b); @@ -89,7 +90,8 @@ while($f = readdir(CONF)) { $b->{'virtual'} = $2; } else { $b->{'name'} = $b->{'fullname'}; } - $b->{'up'} = defined($conf{'ONPARENT'}) && $b->{'virtual'} ne '' ? + $b->{'up'} = defined($conf{'ONPARENT'}) && + $b->{'virtual'} ne '' ? ($conf{'ONPARENT'} eq 'yes') : ($conf{'ONBOOT'} eq 'yes'); $b->{'address'} = $conf{'IPADDR'}; @@ -122,10 +124,19 @@ while($f = readdir(CONF)) { $b->{'desc'} = $conf{'NAME'}; $b->{'index'} = scalar(@rv); $b->{'file'} = "$net_scripts_dir/$f"; + if ($conf{'BRIDGE'}) { + $bridge_map{$conf{'BRIDGE'}} = $b->{'fullname}; + } push(@rv, $b); } } closedir(CONF); +foreach my $b (@rv) { + if ($b->{'fullname'} =~ /^br\d+$/) { + $b->{'bridge'} = 1; + $b->{'bridgeto'} = $bridge_map{$b->{'fullname'}}; + } + } return @rv; } @@ -192,6 +203,9 @@ else { $conf{'IPV6ADDR'} = shift(@ip6s); $conf{'IPV6ADDR_SECONDARIES'} = join(" ", @ip6s); } + if ($_[0]->{'fullname'} =~ /^br(\d+)$/) { + $conf{'TYPE'} = 'Bridge'; + } } $conf{'NAME'} = $_[0]->{'desc'}; &write_env_file("$net_scripts_dir/ifcfg-$name", \%conf); @@ -868,5 +882,18 @@ local ($iface) = @_; return !$iface || $iface->{'virtual'} eq ''; } +# Returns 1, as boot-time interfaces on Redhat can exist without an IP (such as +# for bridging) +sub supports_no_address +{ +return 1; +} + +# Bridge interfaces can be created on redhat +sub supports_bridges +{ +return 1; +} + 1; diff --git a/net/save_bifc.cgi b/net/save_bifc.cgi index f9a3578dd..fcab1f98b 100755 --- a/net/save_bifc.cgi +++ b/net/save_bifc.cgi @@ -45,6 +45,7 @@ else { if (defined($oldb->{'virtual'})); $b->{'code'} = $oldb->{'code'}; $b->{'fullname'} = $oldb->{'fullname'}; + $b->{'bridge'} = $oldb->{'bridge'}; } elsif (defined($in{'virtual'})) { # creating a virtual interface @@ -78,37 +79,40 @@ else { $b->{'name'} = $1; $b->{'virtual'} = $3; $b->{'fullname'} = $b->{'name'}.":".$b->{'virtual'}; - &can_create_iface() || &error($text{'ifcs_ecannot'}); - &can_iface($b) || &error($text{'ifcs_ecannot'}); + } + elsif ($in{'bridge'}) { + # Creating a bridge interface + $in{'name'} =~ /^\d+$/ || &error($text{'bifc_ebridge'}); + $b->{'name'} = $b->{'fullname'} = "br".$in{'name'}; } elsif ($in{'name'} =~/^[a-z]+\d*(\.\d+)?$/) { # creating a real interface - foreach $eb (@boot) { - if ($eb->{'fullname'} eq $in{'name'}) { - &error(&text('bifc_edup', $in{'name'})); - } - } $b->{'name'} = $in{'name'}; $b->{'fullname'} = $in{'name'}; - &can_create_iface() || &error($text{'ifcs_ecannot'}); - &can_iface($b) || &error($text{'ifcs_ecannot'}); + $b->{'bridge'} = 1; } elsif ($in{'name'} eq 'auto') { # creating a vlan interface - foreach $eb (@boot) { - if ($eb->{'fullname'} eq $in{'name'}) { - &error(&text('bifc_edup', $in{'name'})); - } - } $b->{'name'} = $in{'name'}; $b->{'fullname'} = $in{'name'}; - &can_create_iface() || &error($text{'ifcs_ecannot'}); - &can_iface($b) || &error($text{'ifcs_ecannot'}); } else { &error($text{'bifc_ename'}); } + if ($in{'new'}) { + # Check permissions + &can_create_iface() || &error($text{'ifcs_ecannot'}); + &can_iface($b) || &error($text{'ifcs_ecannot'}); + + # Check for clash + foreach $eb (@boot) { + if ($eb->{'fullname'} eq $b->{'fullname'}) { + &error(&text('bifc_edup', $in{'name'})); + } + } + } + # Check for address clash $allow_clash = defined(&allow_interface_clash) ? &allow_interface_clash($b, 1) : 1; @@ -273,6 +277,17 @@ else { } } + # Save bridge settings + if ($b->{'bridge'}) { + $in{'bridgeto'} =~ /^eth\d+$/ || + &error($text{'bifc_ebridgeto'}); + ($bt) = grep { $_->{'fullname'} eq $in{'bridgeto'} } @boot; + $bt || &error($text{'bifc_ebridgeto'}); + ($bt->{'address'} || $bt->{'dhcp'} || $bt->{'bootp'}) && + &error($text{'bifc_ebridgeto2'}); + $b->{'bridgeto'} = $in{'bridgeto'}; + } + # Save the interface with its final name $b->{'fullname'} = $b->{'name'}. ( $b->{'virtual'} eq '' ? '' : ':'.$b->{'virtual'});