1 # Networking functions for Gentoo 2006+
5 $gentoo_net_config = "/etc/conf.d/net";
6 $min_virtual_number = 1;
9 # Parses the Gentoo net config file into an array of named sections
15 open(CONF, $gentoo_net_config);
19 if (/^\s*(\S+)\s*=\s*\((.*)/) {
20 # Start of some section, which may span several lines
21 $sect = { 'name' => $1,
25 if ($v =~ /^(.*)\)/) {
27 $sect->{'values'} = [ &split_gentoo_values("$1") ];
28 $sect->{'eline'} = $lnum;
33 $sect->{'values'} = [ &split_gentoo_values($v) ];
36 elsif (/^\s*\)/ && $sect) {
38 $sect->{'eline'} = $lnum;
41 elsif (/^\s*(".*")\s*\)/ && $sect) {
42 # End of a section, but with some values before it
43 push(@{$sect->{'values'}}, &split_gentoo_values("$1"));
44 $sect->{'eline'} = $lnum;
47 elsif (/^\s*(".*")/ && $sect) {
48 # Values within a section
49 push(@{$sect->{'values'}}, &split_gentoo_values("$1"));
57 # save_gentoo_net(&old, &new)
58 # Update or create a Gentoo net config file section
61 local ($old, $new) = @_;
64 push(@lines, $new->{'name'}."=(");
65 foreach my $v (@{$new->{'values'}}) {
66 push(@lines," \"$v\"");
70 local $lref = &read_file_lines($gentoo_net_config);
73 splice(@$lref, $old->{'line'}, $old->{'eline'}-$old->{'line'}+1,
75 $new->{'eline'} = $new->{'line'}+scalar(@lines)-1;
77 elsif ($old && !$new) {
79 splice(@$lref, $old->{'line'}, $old->{'eline'}-$old->{'line'}+1);
81 elsif (!$old && $new) {
83 $new->{'line'} = scalar(@$lref);
84 $new->{'eline'} = $new->{'line'}+scalar(@lines)-1;
87 &flush_file_lines($gentoo_net_config);
90 # split_gentoo_values(string)
91 # Splits a string like "foo bar" "smeg spod" into an array
92 sub split_gentoo_values
96 while($str =~ /^\s*"([^"]+)",?(.*)/) {
104 # Returns a list of interfaces brought up at boot time
108 foreach my $g (&parse_gentoo_net()) {
109 if ($g->{'name'} =~ /^config_(\S+)/) {
112 foreach my $v (@{$g->{'values'}}) {
113 # An interface definition
114 local $iface = { 'name' => $gn,
117 'index' => scalar(@rv) };
119 $iface->{'fullname'} = $gn;
122 $iface->{'fullname'} = $gn.":".$n;
123 $iface->{'virtual'} = $n;
125 local @w = split(/\s+/, $v);
126 if ($w[0] eq "dhcp") {
127 $iface->{'dhcp'} = 1;
129 elsif ($w[0] eq "noop") {
130 # Skipped, but still uses a up a number
134 if (&check_ipaddress($w[0])) {
135 $iface->{'address'} = $w[0];
137 elsif ($w[0] =~ /^([0-9\.]+)\/(\d+)$/) {
138 $iface->{'address'} = $1;
139 $iface->{'netmask'} = &prefix_to_mask($2);
141 for($i=1; $i<@w; $i++) {
142 if ($w[$i] eq "netmask") {
143 $iface->{'netmask'} = $w[++$i];
145 elsif ($w[$i] eq "broadcast") {
146 $iface->{'broadcast'} = $w[++$i];
148 elsif ($w[$i] eq "mtu") {
149 $iface->{'mtu'} = $w[++$i];
152 if ($iface->{'address'} && $iface->{'netmask'}) {
153 $iface->{'broadcast'} ||= &compute_broadcast(
154 $iface->{'address'}, $iface->{'netmask'});
156 $iface->{'gentoo'} = $g;
161 elsif ($g->{'name'} =~ /^routes_(\S+)/) {
162 # A route definition for an interface
163 local ($iface) = grep { $_->{'fullname'} eq $1 } @rv;
164 local $spec = $g->{'values'}->[0];
166 if ($spec =~ /default\s+via\s+([0-9\.]+)/ ||
167 $spec =~ /default\s+([0-9\.]+)/) {
168 $iface->{'gateway'} = $1;
169 $iface->{'gentoogw'} = $g;
178 # save_interface(&details)
179 # Create or update a boot-time interface
183 &lock_file($gentoo_net_config);
185 # Build the interface line
187 if ($iface->{'dhcp'}) {
191 push(@w, $iface->{'address'});
192 if ($iface->{'netmask'}) {
193 push(@w, "netmask", $iface->{'netmask'});
195 if ($iface->{'broadcast'}) {
196 push(@w, "broadcast", $iface->{'broadcast'});
198 if ($iface->{'mtu'}) {
199 push(@w, "mtu", $iface->{'mtu'});
203 # Find the current block for this interface
204 local @gentoo = &parse_gentoo_net();
205 local ($g) = grep { $_->{'name'} eq 'config_'.$iface->{'name'} } @gentoo;
207 # Found it .. append or replace
208 while (!$g->{'values'}->[$iface->{'virtual'}]) {
209 push(@{$g->{'values'}}, "noop");
211 $g->{'values'}->[$iface->{'virtual'}] = join(" ", @w);
212 &save_gentoo_net($g, $g);
216 $g = { 'name' => $iface->{'name'},
217 'values' => [ join(" ", @w) ] };
218 &save_gentoo_net(undef, $g);
220 &unlock_file($gentoo_net_config);
223 # delete_interface(&details)
224 # Delete a boot-time interface
229 # Find the current block for this interface
230 &lock_file($gentoo_net_config);
231 local @gentoo = &parse_gentoo_net();
232 local ($g) = grep { $_->{'name'} eq 'config_'.$iface->{'name'} } @gentoo;
234 # Found it .. take out the interface
235 if ($iface->{'virtual'} == scalar(@{$g->{'values'}})-1) {
237 pop(@{$g->{'values'}});
240 $g->{'values'}->[$iface->{'virtual'}] = 'noop';
242 &save_gentoo_net($g, $g);
244 &unlock_file($gentoo_net_config);
248 # Can some boot-time interface parameter be edited?
251 return $_[0] ne 'up' && $_[0] ne 'bootp';
254 # valid_boot_address(address)
255 # Is some address valid for a bootup interface
256 sub valid_boot_address
258 return &check_ipaddress($_[0]);
265 &read_env_file("/etc/conf.d/hostname", \%host);
266 if ($host{'HOSTNAME'}) {
267 return $host{'HOSTNAME'};
269 return &get_system_hostname(1);
272 # save_hostname(name)
276 &read_env_file("/etc/conf.d/hostname", \%host);
277 $host{'HOSTNAME'} = $_[0];
278 &write_env_file("/etc/conf.d/hostname", \%host);
279 &system_logged("hostname $_[0] >/dev/null 2>&1");
283 # Prints HTML for editing routing settings
286 local ($gw, $dev) = &get_default_gateway();
287 local @ifaces = grep { $_->{'virtual'} eq '' } &boot_interfaces();
288 print &ui_table_row($text{'routes_def'},
289 &ui_radio("route_def", $gw ? 0 : 1,
290 [ [ 1, $text{'routes_nogw'}."<br>" ],
291 [ 0, &text('routes_ggw',
292 &ui_textbox("gw", $gw, 20),
293 &ui_select("dev", $dev,
294 [ map { $_->{'name'} } @ifaces ])) ] ]));
298 # Applies settings from routing_input form
301 if ($in{'route_def'}) {
302 &set_default_gateway();
305 &check_ipaddress($in{'gw'}) ||
306 &error(&text('routes_edefault', $in{'gw'}));
307 &set_default_gateway($in{'gw'}, $in{'dev'});
312 # Apply the interface and routing settings
315 opendir(DIR, "/etc/init.d");
316 foreach my $f (readdir(DIR)) {
317 if ($f =~ /^net.(\S+)/ && $1 ne "lo") {
318 &system_logged("cd / ; /etc/init.d/$f restart >/dev/null 2>&1 </dev/null");
324 # get_default_gateway()
325 # Returns the default gateway IP (if one is set) and device (if set) boot time
327 sub get_default_gateway
329 local @ifaces = &boot_interfaces();
330 local ($iface) = grep { $_->{'gateway'} } @ifaces;
332 return ( $iface->{'gateway'}, $iface->{'name'} );
339 # set_default_gateway(gateway, device)
340 # Sets the default gateway to the given IP accessible via the given device,
341 # in the boot time settings.
342 sub set_default_gateway
344 local ($gw, $dev) = @_;
345 &lock_file($gentoo_net_config);
346 local @ifaces = &boot_interfaces();
347 local ($iface) = grep { $_->{'gateway'} } @ifaces;
349 # Change existing default route
350 $g = $iface->{'gentoogw'};
351 $g->{'name'} = 'routes_'.$dev;
352 $g->{'values'}->[0] = "default via $gw";
353 &save_gentoo_net($g, $g);
355 elsif ($iface && !$gw) {
356 # Deleting existing default route
357 $g = $iface->{'gentoogw'};
358 &save_gentoo_net($g, undef);
360 elsif (!$iface && $gw) {
361 # Adding new default route
362 $g = { 'name' => 'routes_'.$dev,
363 'values' => [ "default via $gw" ] };
364 &save_gentoo_net(undef, $g);
366 &unlock_file($gentoo_net_config);
369 # supports_address6([&iface])
370 # Returns 1 if managing IPv6 interfaces is supported
371 sub supports_address6