Start of work on bridge support
authorJamie Cameron <jcameron@webmin.com>
Tue, 28 Jun 2011 03:20:10 +0000 (23:20 -0400)
committerJamie Cameron <jcameron@webmin.com>
Tue, 28 Jun 2011 03:20:10 +0000 (23:20 -0400)
net/debian-linux-lib.pl
net/edit_bifc.cgi
net/lang/en
net/list_ifcs.cgi
net/redhat-linux-lib.pl
net/save_bifc.cgi

index c42e180..3d437ff 100755 (executable)
@@ -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;
 
index 69a3280..1b09070 100755 (executable)
@@ -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'}, "<tt>$b->{'broadcast'}</tt>");
        }
 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
index aafccbc..65f47f0 100644 (file)
@@ -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 <i>boot time</i>
index 222f66c..09ae544 100755 (executable)
@@ -115,15 +115,21 @@ print &ui_form_start("delete_bifcs.cgi", "post");
 if ($allow_add) {
        push(@links, "<a href='edit_bifc.cgi?new=1'>$text{'ifcs_add'}</a>");
        if (defined(&supports_bonding) && &supports_bonding()) {
-               push(@links, "<a href='edit_bifc.cgi?new=1&bond=1'>$text{'bonding_add'}</a>");
+               push(@links, "<a href='edit_bifc.cgi?new=1&bond=1'>".
+                            "$text{'bonding_add'}</a>");
        }
        if (defined(&supports_vlans) && &supports_vlans()) {
-               push(@links, "<a href='edit_bifc.cgi?new=1&vlan=1'>$text{'vlan_add'}</a>");
+               push(@links, "<a href='edit_bifc.cgi?new=1&vlan=1'>".
+                            "$text{'vlan_add'}</a>");
        }
        }
 if ($allow_add && defined(&supports_ranges) && &supports_ranges()) {
        push(@links, "<a href='edit_range.cgi?new=1'>$text{'ifcs_radd'}</a>");
        }
+if ($allow_add && defined(&supports_bridges) && &supports_bridges()) {
+       push(@links, "<a href='edit_bifcs.cgi?new=1&bridge=1'>".
+                    "$text{'ifcs_badd'}</a>");
+       }
 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()) {
index a156917..92e2b0e 100755 (executable)
@@ -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;
 
index f9a3578..fcab1f9 100755 (executable)
@@ -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'});