2 # Networking functions for FreeBSD
5 # Returns a list of currently ifconfig'd interfaces
8 local(@rv, @lines, $l);
9 &open_execute_command(IFC, "ifconfig -A", 1, 1);
12 if (/^\S+:/) { push(@lines, $_); }
13 else { $lines[$#lines] .= $_; }
19 $ifc{'name'} = $ifc{'fullname'} = $1;
20 if ($l =~ /^(\S+):(\d+):\s/) { $ifc{'virtual'} = $2; }
21 if ($l =~ s/inet\s+(\S+)\s+netmask\s+(\S+)\s+broadcast\s+(\S+)//) {
23 $ifc{'netmask'} = &parse_hex($2);
24 $ifc{'broadcast'} = $3;
26 elsif ($l =~ s/inet\s+(\S+)\s+netmask\s+(\S+)//) {
28 $ifc{'netmask'} = &parse_hex($2);
31 if ($l =~ /ether\s+(\S+)/) { $ifc{'ether'} = $1; }
32 if ($l =~ /mtu\s+(\S+)/) { $ifc{'mtu'} = $1; }
33 $ifc{'up'}++ if ($l =~ /\<UP/);
34 $ifc{'edit'} = &iface_type($ifc{'name'}) =~ /ethernet|loopback/i;
35 $ifc{'index'} = scalar(@rv);
37 $ifc{'ether'} = join(":", map { sprintf "%2.2d", $_ }
38 split(/:/, $ifc{'ether'}));
42 # Add aliases as virtual interfaces
44 while($l =~ s/inet\s+(\S+)\s+netmask\s+(\S+)\s+broadcast\s+(\S+)//) {
46 $vifc{'address'} = $1;
47 $vifc{'netmask'} = &parse_hex($2);
48 $vifc{'broadcast'} = $3;
50 $vifc{'edit'} = $ifc{'edit'};
51 $vifc{'virtual'} = $v++;
52 $vifc{'fullname'} = $vifc{'name'}.':'.$vifc{'virtual'};
53 $vifc{'index'} = scalar(@rv);
60 # activate_interface(&details)
61 # Create or modify an interface
62 sub activate_interface
65 map { $act{$_->{'fullname'}} = $_ } &active_interfaces();
66 local $old = $act{$_[0]->{'fullname'}};
67 $act{$_[0]->{'fullname'}} = $_[0];
68 &interface_sync(\%act, $_[0]->{'name'});
71 # deactivate_interface(&details)
72 # Deactive an interface
73 sub deactivate_interface
76 local @act = &active_interfaces();
77 if ($_[0]->{'virtual'} eq '') {
78 @act = grep { $_->{'name'} ne $_[0]->{'name'} } @act;
81 @act = grep { $_->{'fullname'} ne $_[0]->{'fullname'} } @act;
83 map { $act{$_->{'fullname'}} = $_ } @act;
84 &interface_sync(\%act, $_[0]->{'name'});
87 # interface_sync(interfaces, name)
90 while(&backquote_command("ifconfig $_[1]") =~ /\s+inet\s+/) {
91 &system_logged("ifconfig $_[1] delete >/dev/null 2>&1");
93 foreach $a (sort { $a->{'fullname'} cmp $b->{'fullname'} }
94 grep { $_->{'name'} eq $_[1] } values(%{$_[0]})) {
95 local $cmd = "ifconfig $a->{'name'}";
96 if ($a->{'virtual'} ne '') {
97 $cmd .= " alias $a->{'address'}";
100 $cmd .= " $a->{'address'}";
102 if ($a->{'netmask'}) { $cmd .= " netmask $a->{'netmask'}"; }
103 if ($a->{'broadcast'}) { $cmd .= " broadcast $a->{'broadcast'}"; }
104 if ($a->{'mtu'}) { $cmd .= " mtu $a->{'mtu'}"; }
105 $msg .= "running $cmd<br>\n";
106 local $out = &backquote_logged("$cmd 2>&1");
107 if ($? && $out !~ /file exists/i) {
110 if ($a->{'virtual'} eq '') {
111 if ($a->{'up'}) { $out = &backquote_command("ifconfig $a->{'name'} up 2>&1"); }
112 else { $out = &backquote_logged("ifconfig $a->{'name'} down 2>&1"); }
113 &error($out) if ($?);
120 # Returns a list of interfaces brought up at boot time
124 local @if_list = split(" ",
125 &backquote_command("echo -n /etc/hostname.*[!~]"));
127 if ( $if_list[0] eq "/etc/hostname.*[!~]" )
130 foreach $r (@if_list) {
132 local $alias_cnt = 0;
134 ($if = $r) =~ s/\/etc\/hostname\.//;
136 &open_readfile( IF_FILE, $r)
137 or die "Could not open: $r";
142 if( ! /^inet .*|^dhcp/ )
146 %ifc = ( 'name' => $if,
153 %ifc = ( 'name' => $if,
154 'virtual' => $alias_cnt,
155 'fullname' => "$if:$alias_cnt" );
159 # Non-virtual interface
160 %ifc = ( 'name' => $if,
166 $ifc{'address'} = $_[1] if( $_[1] ne 'NONE' );
167 $ifc{'netmask'} = $_[2] if( $_[2] ne 'NONE' );
168 $ifc{'broadcast'} = $_[3] if( $_[3] ne 'NONE' );
171 $ifc{'index'} = scalar(@rv);
180 # save_interface(&details)
181 # Create or update a boot-time interface
184 local ($str, $lines, $found = 0);
185 local $if = $_[0]->{'name'};
186 local $alias_nr = $_[0]->{'virtual'};
188 &lock_file("/etc/hostname.$if");
189 if ( $_[0]->{'dhcp'} ){
190 &open_tempfile( IF_FILE, ">/etc/hostname.".$if );
191 &print_tempfile(IF_FILE, "dhcp\n");
192 &close_tempfile( IF_FILE );
193 &unlock_file("/etc/hostname.$if");
197 if ( $alias_nr eq '' ) {
202 $str = "inet alias ";
206 $str .= $_[0]->{'address'};
207 $str .= " $_[0]->{'netmask'}" if ($_[0]->{'netmask'});
208 $str .= " $_[0]->{'broadcast'}" if ($_[0]->{'broadcast'});
210 $_ = &backquote_command("echo -n /etc/hostname.*");
212 if( /hostname.$if/ ) {
213 $lines = &read_file_lines( "/etc/hostname.".$if );
214 foreach $l (@$lines) {
216 if( ! /^inet |^dhcp/ )
218 if( $alias_nr == 0 ) {
225 if( $alias_nr == 1 ) {
233 push @$lines, ($str);
238 &open_tempfile( IF_FILE, ">/etc/hostname.".$if );
239 &print_tempfile(IF_FILE, $str, "\n");
240 &close_tempfile( IF_FILE );
242 &unlock_file("/etc/hostname.$if");
246 # delete_interface(&details)
247 # Delete a boot-time interface
250 local ($cnt = 0, $lines, $found = 0);
251 local $if = $_[0]->{'name'};
252 local $addr = $_[0]->{'address'};
254 $_ = &backquote_command("echo -n /etc/hostname.*");
256 &lock_file("/etc/hostname.$if");
257 if( /hostname.$if/ ) {
258 $lines = &read_file_lines( "/etc/hostname.".$if );
259 foreach $l (@$lines) {
268 { splice @$lines, $cnt-1, 1; }
271 # check if we deleted the only entry in the file
272 # if so delete the file (otherwise dhcp will be used for the interface)
274 &unlink_logged("/etc/hostname.".$if);
277 &unlock_file("/etc/hostname.$if");
281 # Returns a human-readable interface type name
284 return $_[0] =~ /^tun/ ? "Loopback tunnel" :
285 $_[0] =~ /^sl/ ? "SLIP" :
286 $_[0] =~ /^ppp/ ? "PPP" :
287 $_[0] =~ /^lo/ ? "Loopback" :
288 $_[0] =~ /^ar/ ? "Arnet" :
289 $_[0] =~ /^(aue|cue|kue)/ ? "USB ethernet" :
290 $_[0] =~ /^(sk|ti|wx)/ ? "Gigabit ethernet" :
291 $_[0] =~ /^(al|ax|be|mx|qe|qec|rl|sf|sis|ste|tx|wb)/ ? "Fast ethernet" :
292 $_[0] =~ /^(ae|cs|dc|de|ec|ed|eg|el|en|ep|es|ex|fxp|hme|ie|il|ix|iy|le|mc|ne|np|qn|sm|sn|tl|vr|vx|we|xe|xl|ze|zp)/ ? "Ethernet" : $text{'ifcs_unknown'};
295 # iface_hardware(name)
296 # Does some interface have an editable hardware address
303 # Can some boot-time interface parameter be edited?
306 return $_[0] =~ /netmask|broadcast|dhcp/;
309 # valid_boot_address(address)
310 # Is some address valid for a bootup interface
311 sub valid_boot_address
313 return &check_ipaddress($_[0]);
317 # Returns a hashtable containing keys nameserver, domain, search & order
321 &open_readfile(RESOLV, "/etc/resolv.conf");
325 if (/nameserver\s+(.*)/) {
326 push(@{$dns->{'nameserver'}}, split(/\s+/, $1));
328 elsif (/search\s+(.*)/) {
329 $dns->{'domain'} = [ split(/\s+/, $1) ];
331 elsif (/lookup\s+(.*)/) {
332 $dns->{'order'} = [ split(/\s+/, $1) ];
337 $dns->{'files'} = [ "/etc/resolv.conf" ];
341 # save_dns_config(&config)
342 # Writes out the resolv.conf file
345 &lock_file("/etc/resolv.conf");
346 &open_readfile(RESOLV, "/etc/resolv.conf");
347 local @resolv = <RESOLV>;
349 &open_tempfile(RESOLV, ">/etc/resolv.conf");
350 foreach (@{$_[0]->{'nameserver'}}) {
351 &print_tempfile(RESOLV, "nameserver $_\n");
353 if ($_[0]->{'domain'}) {
354 &print_tempfile(RESOLV, "search ",join(" ", @{$_[0]->{'domain'}}),"\n");
357 &print_tempfile(RESOLV, $_) if (!/^\s*(nameserver|search|lookup)\s+/);
359 &print_tempfile(RESOLV, "lookup ");
360 foreach (@{$_[0]->{'order'}}) {
361 &print_tempfile(RESOLV, $_," ");
363 &print_tempfile(RESOLV, "\n");
364 &close_tempfile(RESOLV);
365 &unlock_file("/etc/resolv.conf");
369 $max_dns_servers = 3;
372 # Returns HTML for selecting the name resolution order
375 return &common_order_input("order", $_[0]->{'order'},
376 [ [ "file", "Hosts" ], [ "bind", "DNS" ], [ "yp", "NIS" ] ]);
380 # Parses the form created by order_input()
384 for($i=0; defined($in{"order_$i"}); $i++) {
385 push(@order, $in{"order_$i"}) if ($in{"order_$i"});
387 $_[0]->{'order'} = \@order;
393 local $hn = &read_file_contents("/etc/myname");
398 return &get_system_hostname();
401 # save_hostname(name)
404 &system_logged("hostname $_[0] >/dev/null 2>&1");
405 &open_lock_tempfile(MYNAME, ">/etc/myname");
406 &print_tempfile(MYNAME, $_[0],"\n");
407 &close_tempfile(MYNAME);
408 undef(@main::get_system_hostname); # clear cache
412 local ($l, $lines, $found = 0);
416 $lines = read_file_lines($_[0]);
417 foreach $l (@$lines) {
425 push @$lines, ($news);
433 &open_readfile(DEFR, "/etc/mygate");
440 read_file("/etc/sysctl.conf", \%sysctl);
441 $gw = "$sysctl{'net.inet.ip.forwarding'}";
443 $gw = "0" if( $gw eq '' );
446 read_file("/etc/rc.conf",\%rc);
447 $rd = $rc{'routed_flags'};
449 $rd = "NO" if( $rd eq '' );
452 sub routing_config_files
454 return ( "/etc/mygate", "/etc/sysctl.conf", "/etc/rc.conf" );
462 print &ui_table_row($text{'routes_default'},
463 &ui_opt_textbox("defr", $defr eq 'NO' ? '' : $defr, 20,
464 $text{'routes_none'}));
467 print &ui_table_row($text{'routes_forward'},
468 &ui_radio("gw", $gw || 0, [ [ 1, $text{'yes'} ],
469 [ 0, $text{'no'} ] ]));
471 # Run route discovery
472 print &ui_table_row($text{'routes_routed'},
473 &ui_radio("rd", $rd || '-q', [ [ '-q', $text{'yes'} ],
474 [ 'NO', $text{'no'} ] ]));
479 $in{'defr_def'} || &check_ipaddress($in{'defr'}) ||
480 &error(&text('routes_edefault', $in{'defr'}));
484 &lock_file("/etc/mygate");
485 if ( $in{'defr_def'} && -f "/etc/mygate" ) {
486 &unlink_file("/etc/mygate");
489 if( $in{'defr'} ne $defr ) {
490 &open_tempfile(MYGATE, ">/etc/mygate");
491 &print_tempfile(MYGATE, $in{'defr'},"\n");
492 &close_tempfile(MYDATE);
495 &unlock_file("/etc/mygate");
497 if( $in{'gw'} ne $gw ) {
498 &set_line( "/etc/sysctl.conf", "^net.inet.ip.forwarding", "net.inet.ip.forwarding=$in{'gw'}" );
501 if( $in{'rd'} ne $rd ) {
502 &set_line( "/etc/rc.conf", "^routed_flags", "routed_flags=$in{'rd'}" );
506 sub os_feedback_files
508 return ( split(" ", `echo -n /etc/hostname.*[!~]`),
509 "/etc/resolv.conf", "/etc/myname", "/etc/mygate", "/etc/rc.conf",
510 "/etc/sysctl.conf" );
513 # supports_address6([&iface])
514 # Returns 1 if managing IPv6 interfaces is supported
515 sub supports_address6