Updated to latest master (change of amd64 tag to x86_64).
[dragonfly.git] / etc / network.subr
CommitLineData
9c600e7d
MD
1#
2# Copyright (c) 2003 The FreeBSD Project. All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions
6# are met:
7# 1. Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9# 2. Redistributions in binary form must reproduce the above copyright
10# notice, this list of conditions and the following disclaimer in the
11# documentation and/or other materials provided with the distribution.
12#
13# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
14# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
17# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23# SUCH DAMAGE.
24#
f26c267a 25# $FreeBSD: src/etc/network.subr,v 1.163 2005/06/30 04:52:47 brooks Exp $
667713fe 26# $DragonFly: src/etc/network.subr,v 1.7 2008/03/15 10:13:37 hasso Exp $
9c600e7d
MD
27#
28
29#
30# Subroutines commonly used from network startup scripts.
31# Requires that rc.conf be loaded first.
32#
33
34# ifconfig_up if
35# Evaluate ifconfig(8) arguments for interface $if and
36# run ifconfig(8) with those arguments. It returns 0 if
37# arguments were found and executed or 1 if the interface
f26c267a
SW
38# had no arguments. Pseudo arguments DHCP and WPA are handled
39# here.
9c600e7d
MD
40#
41ifconfig_up()
42{
f26c267a
SW
43 _cfg=1
44
45 ifconfig_args=`ifconfig_getargs $1`
9c600e7d
MD
46 if [ -n "${ifconfig_args}" ]; then
47 ifconfig $1 ${ifconfig_args}
f26c267a 48 _cfg=0
9c600e7d 49 fi
f26c267a
SW
50
51 if wpaif $1; then
52 /etc/rc.d/wpa_supplicant start $1
53 _cfg=0 # XXX: not sure this should count
54 fi
55
56 if dhcpif $1; then
57 /etc/rc.d/dhclient start $1
58 _cfg=0
59 fi
60
61 return $_cfg
9c600e7d
MD
62}
63
64# ifconfig_down if
65# Remove all inet entries from the $if interface. It returns
66# 0 if inet entries were found and removed. It returns 1 if
67# no entries were found or they could not be removed.
68#
69ifconfig_down()
70{
71 [ -z "$1" ] && return 1
72 _ifs="^"
f26c267a 73 _cfg=1
9c600e7d
MD
74
75 inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`"
76
77 oldifs="$IFS"
78 IFS="$_ifs"
79 for _inet in $inetList ; do
80 # get rid of extraneous line
81 [ -z "$_inet" ] && break
82
83 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
84
85 IFS="$oldifs"
86 ifconfig $1 ${_inet} delete
87 IFS="$_ifs"
f26c267a 88 _cfg=0
9c600e7d
MD
89 done
90 IFS="$oldifs"
91
f26c267a
SW
92 if wpaif $1; then
93 /etc/rc.d/wpa_supplicant stop $1
94 fi
95
96 if dhcpif $1; then
97 /etc/rc.d/dhclient stop $1
98 _cfg=0
99 fi
100
101 return $_cfg
102}
103
104# _ifconfig_getargs if
105# Echos the arguments for the supplied interface to stdout.
106# returns 1 if empty. In general, ifconfig_getargs should be used
107# outside this file.
108_ifconfig_getargs()
109{
110 _ifn=$1
111 if [ -z "$_ifn" ]; then
112 return 1
113 fi
114
115 eval _args=\$ifconfig_$1
116 if [ -z "$_args" -a -n "${pccard_ifconfig}" ]; then
117 for _if in ${removable_interfaces} ; do
118 if [ "$_if" = "$_ifn" ] ; then
119 _args=${pccard_ifconfig}
120 break
121 fi
122 done
123 fi
124
125 echo $_args
126}
127
128# ifconfig_getargs if
129# Takes the result from _ifconfig_getargs and removes pseudo
130# args such as DHCP and WPA.
131ifconfig_getargs()
132{
133 _tmpargs=`_ifconfig_getargs $1`
134 if [ $? -eq 1 ]; then
135 return 1
136 fi
137 _args=
138
1f03f592 139 is_optarg=no
f26c267a 140 for _arg in $_tmpargs; do
1f03f592
SW
141 if [ "$is_optarg" = "no" ]; then
142 case $_arg in
143 [Dd][Hh][Cc][Pp])
144 ;;
145 [Ww][Pp][Aa])
146 ;;
147 *)
148 _args="$_args $_arg"
149 case $_arg in
150 authmode)
151 is_optarg=yes
152 ;;
153 esac
154 ;;
155 esac
156 else
f26c267a 157 _args="$_args $_arg"
1f03f592
SW
158 is_optarg=no
159 fi
f26c267a
SW
160 done
161
162 echo $_args
163}
164
165# dhcpif if
166# Returns 0 if the interface is a DHCP interface and 1 otherwise.
167dhcpif()
168{
169 _tmpargs=`_ifconfig_getargs $1`
170 for _arg in $_tmpargs; do
171 case $_arg in
172 [Dd][Hh][Cc][Pp])
173 return 0
174 ;;
175 esac
176 done
177 return 1
178}
179
180# wpaif if
181# Returns 0 if the interface is a WPA interface and 1 otherwise.
182wpaif()
183{
184 _tmpargs=`_ifconfig_getargs $1`
1f03f592 185 is_optarg=no
f26c267a 186 for _arg in $_tmpargs; do
1f03f592
SW
187 if [ "$is_optarg" = "no" ]; then
188 case $_arg in
189 [Ww][Pp][Aa])
190 return 0
191 ;;
192 authmode)
193 is_optarg=yes
194 ;;
195 esac
196 else
197 is_optarg=no
198 fi
f26c267a
SW
199 done
200 return 1
9c600e7d
MD
201}
202
203# ifalias_up if
204# Configure aliases for network interface $if.
205# It returns 0 if at least one alias was configured or
206# 1 if there were none.
207#
208ifalias_up()
209{
210 _ret=1
211 alias=0
212 while : ; do
213 eval ifconfig_args=\$ifconfig_$1_alias${alias}
214 if [ -n "${ifconfig_args}" ]; then
215 ifconfig $1 ${ifconfig_args} alias
216 alias=$((${alias} + 1))
217 _ret=0
218 else
219 break
220 fi
221 done
222 return $_ret
223}
224
225#ifalias_down if
226# Remove aliases for network interface $if.
227# It returns 0 if at least one alias was removed or
228# 1 if there were none.
229#
230ifalias_down()
231{
232 _ret=1
233 alias=0
234 while : ; do
235 eval ifconfig_args=\$ifconfig_$1_alias${alias}
236 if [ -n "${ifconfig_args}" ]; then
237 ifconfig $1 ${ifconfig_args} -alias
238 alias=$((${alias} + 1))
239 _ret=0
240 else
241 break
242 fi
243 done
244 return $_ret
245}
246
247# ifscript_up if
248# Evaluate a startup script for the $if interface.
249# It returns 0 if a script was found and processed or
250# 1 if no script was found.
251#
252ifscript_up()
253{
254 if [ -r /etc/start_if.$1 ]; then
255 . /etc/start_if.$1
256 return 0
257 fi
258 return 1
259}
260
261# ifscript_down if
262# Evaluate a shutdown script for the $if interface.
263# It returns 0 if a script was found and processed or
264# 1 if no script was found.
265#
266ifscript_down()
267{
268 if [ -r /etc/stop_if.$1 ]; then
269 . /etc/stop_if.$1
270 return 0
271 fi
272 return 1
273}
274
275# Create cloneable interfaces.
276#
277clone_up()
278{
279 _prefix=
280 _list=
281 for ifn in ${cloned_interfaces}; do
282 ifconfig ${ifn} create
283 if [ $? -eq 0 ]; then
284 _list="${_list}${_prefix}${ifn}"
285 [ -z "$_prefix" ] && _prefix=' '
286 fi
287 done
288 debug "Cloned: ${_list}"
289}
290
291# Destroy cloned interfaces. Destroyed interfaces are echoed
292# to standard output.
293#
294clone_down()
295{
296 _prefix=
297 _list=
298 for ifn in ${cloned_interfaces}; do
299 ifconfig ${ifn} destroy
300 if [ $? -eq 0 ]; then
301 _list="${_list}${_prefix}${ifn}"
302 [ -z "$_prefix" ] && _prefix=' '
303 fi
304 done
305 debug "Destroyed clones: ${_list}"
306}
307
308gif_up() {
309 case ${gif_interfaces} in
310 [Nn][Oo] | '')
311 ;;
312 *)
313 for i in ${gif_interfaces}; do
314 eval peers=\$gifconfig_$i
315 case ${peers} in
316 '')
317 continue
318 ;;
319 *)
320 ifconfig $i create >/dev/null 2>&1
321 ifconfig $i tunnel ${peers}
322 ifconfig $i up
323 ;;
324 esac
325 done
326 ;;
327 esac
328}
329
330#
331# ipx_up ifn
332# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
333# arguments were found and configured; returns 1 otherwise.
334#
335ipx_up()
336{
337 ifn="$1"
338 eval ifconfig_args=\$ifconfig_${ifn}_ipx
339 if [ -n "${ifconfig_args}" ]; then
340 ifconfig ${ifn} ${ifconfig_args}
341 return 0
342 fi
343 return 1
344}
345
346# ipx_down ifn
347# Remove IPX addresses for interface $ifn. Returns 0 if IPX
348# addresses were found and unconfigured. It returns 1, otherwise.
349#
350ipx_down()
351{
352 [ -z "$1" ] && return 1
353 _ifs="^"
354 _ret=1
355
356 ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
357
358 oldifs="$IFS"
359 IFS="$_ifs"
360 for _ipx in $ipxList ; do
361 # get rid of extraneous line
362 [ -z "$_ipx" ] && break
363
364 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
365
366 IFS="$oldifs"
367 ifconfig $1 ${_ipx} delete
368 IFS="$_ifs"
369 _ret=0
370 done
371 IFS="$oldifs"
372
373 return $_ret
374}
375
f26c267a
SW
376# ifnet_rename
377# Rename all requested interfaces.
378#
379ifnet_rename()
380{
381
382 _ifn_list="`ifconfig -l`"
383 [ -z "$_ifn_list" ] && return 0
384 for _if in ${_ifn_list} ; do
385 eval _ifname=\$ifconfig_${_if}_name
386 if [ ! -z "$_ifname" ]; then
387 ifconfig $_if name $_ifname
388 fi
389 done
390 return 0
391}
392
9c600e7d
MD
393#
394# list_net_interfaces type
395# List all network interfaces. The type of interface returned
396# can be controlled by the type argument. The type
397# argument can be any of the following:
398# nodhcp - all interfaces, excluding DHCP configured interfaces
399# dhcp - list only DHCP configured interfaces
400# If no argument is specified all network interfaces are output.
acba6ed7
SS
401# Note that the list will include cloned interfaces if applicable.
402# Cloned interfaces must already exist to have a chance to appear
403# in the list if ${network_interfaces} is set to `auto'.
9c600e7d
MD
404#
405list_net_interfaces()
406{
407 type=$1
408
fc8d011c
MD
409 # Get a list of ALL the interfaces. NOTE: cloned interfaces
410 # have already been configured so they should show up in the
411 # ifconfig -l output.
9c600e7d
MD
412 #
413 case ${network_interfaces} in
414 [Aa][Uu][Tt][Oo])
667713fe
HT
415 _autolist="`ifconfig -l`"
416 _lo=
417 for _if in ${_autolist} ; do
418 if [ "$_if" = "lo0" ]; then
419 _lo="lo0"
420 else
421 _tmplist="${_tmplist} ${_if}"
422 fi
423 done
424 _tmplist="${_lo} ${_tmplist}"
9c600e7d
MD
425 ;;
426 *)
acba6ed7 427 _tmplist="${network_interfaces} ${cloned_interfaces}"
9c600e7d
MD
428 ;;
429 esac
9c600e7d
MD
430
431 if [ -z "$type" ]; then
432 echo $_tmplist
433 return 0
434 fi
435
f26c267a 436 # Separate out dhcp and non-dhcp interfaces
9c600e7d
MD
437 #
438 _aprefix=
acba6ed7 439 _bprefix=
9c600e7d
MD
440 for _if in ${_tmplist} ; do
441 eval _ifarg="\$ifconfig_${_if}"
442 case "$_ifarg" in
443 [Dd][Hh][Cc][Pp])
444 _dhcplist="${_dhcplist}${_aprefix}${_if}"
445 [ -z "$_aprefix" ] && _aprefix=' '
446 ;;
447 ''|*)
448 _nodhcplist="${_nodhcplist}${_bprefix}${_if}"
449 [ -z "$_bprefix" ] && _bprefix=' '
450 ;;
451 esac
452 done
453
454 case "$type" in
455 nodhcp)
456 echo $_nodhcplist
457 ;;
458 dhcp)
459 echo $_dhcplist
460 ;;
461 esac
a7d4c818 462 return 0
9c600e7d
MD
463}
464
465hexdigit()
466{
467 if [ $1 -lt 10 ]; then
468 echo $1
469 else
470 case $1 in
471 10) echo a ;;
472 11) echo b ;;
473 12) echo c ;;
474 13) echo d ;;
475 14) echo e ;;
476 15) echo f ;;
477 esac
478 fi
479}
480
481hexprint()
482{
483 val=$1
484 str=''
485
486 dig=`hexdigit $((${val} & 15))`
487 str=${dig}${str}
488 val=$((${val} >> 4))
489 while [ ${val} -gt 0 ]; do
490 dig=`hexdigit $((${val} & 15))`
491 str=${dig}${str}
492 val=$((${val} >> 4))
493 done
494
495 echo ${str}
496}
497
498# Setup the interfaces for IPv6
499network6_interface_setup()
500{
501 interfaces=$*
502 rtsol_interfaces=''
503 case ${ipv6_gateway_enable} in
504 [Yy][Ee][Ss])
505 rtsol_available=no
506 ;;
507 *)
508 rtsol_available=yes
509 ;;
510 esac
511 for i in $interfaces; do
512 rtsol_interface=yes
513 eval prefix=\$ipv6_prefix_$i
514 if [ -n "${prefix}" ]; then
515 rtsol_available=no
516 rtsol_interface=no
517 laddr=`network6_getladdr $i`
518 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
519 for j in ${prefix}; do
520 address=$j\:${hostid}
521 ifconfig $i inet6 ${address} prefixlen 64 alias
522
523 case ${ipv6_gateway_enable} in
524 [Yy][Ee][Ss])
525 # subnet-router anycast address
526 # (rfc2373)
527 ifconfig $i inet6 $j:: prefixlen 64 \
528 alias anycast
529 ;;
530 esac
531 done
532 fi
533 eval ipv6_ifconfig=\$ipv6_ifconfig_$i
534 if [ -n "${ipv6_ifconfig}" ]; then
535 rtsol_available=no
536 rtsol_interface=no
537 ifconfig $i inet6 ${ipv6_ifconfig} alias
538 fi
539
540 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
541 then
542 case ${i} in
543 lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
544 ;;
545 *)
546 rtsol_interfaces="${rtsol_interfaces} ${i}"
547 ;;
548 esac
549 else
550 ifconfig $i inet6
551 fi
552 done
553
554 if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
555 # Act as endhost - automatically configured.
556 # You can configure only single interface, as
557 # specification assumes that autoconfigured host has
558 # single interface only.
559 sysctl net.inet6.ip6.accept_rtadv=1
560 set ${rtsol_interfaces}
561 ifconfig $1 up
562 rtsol $1
563 fi
564
565 for i in $interfaces; do
566 alias=0
567 while : ; do
568 eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias}
569 if [ -z "${ipv6_ifconfig}" ]; then
570 break;
571 fi
572 ifconfig $i inet6 ${ipv6_ifconfig} alias
573 alias=$((${alias} + 1))
574 done
575 done
576}
577
578# Setup IPv6 to IPv4 mapping
579network6_stf_setup()
580{
581 case ${stf_interface_ipv4addr} in
582 [Nn][Oo] | '')
583 ;;
584 *)
585 # assign IPv6 addr and interface route for 6to4 interface
586 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
587 OIFS="$IFS"
588 IFS=".$IFS"
589 set ${stf_interface_ipv4addr}
590 IFS="$OIFS"
591 hexfrag1=`hexprint $(($1*256 + $2))`
592 hexfrag2=`hexprint $(($3*256 + $4))`
593 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
594 case ${stf_interface_ipv6_ifid} in
595 [Aa][Uu][Tt][Oo] | '')
596 for i in ${ipv6_network_interfaces}; do
597 laddr=`network6_getladdr ${i}`
598 case ${laddr} in
599 '')
600 ;;
601 *)
602 break
603 ;;
604 esac
605 done
606 stf_interface_ipv6_ifid=`expr "${laddr}" : \
607 'fe80::\(.*\)%\(.*\)'`
608 case ${stf_interface_ipv6_ifid} in
609 '')
610 stf_interface_ipv6_ifid=0:0:0:1
611 ;;
612 esac
613 ;;
614 esac
615 ifconfig stf0 create >/dev/null 2>&1
616 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
617 prefixlen ${stf_prefixlen}
618 # disallow packets to malicious 6to4 prefix
619 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
620 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
621 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
622 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
623 ;;
624 esac
625}
626
627# Setup static routes
628network6_static_routes_setup()
629{
630 # Set up any static routes.
631 case ${ipv6_defaultrouter} in
632 [Nn][Oo] | '')
633 ;;
634 *)
635 ipv6_static_routes="default ${ipv6_static_routes}"
636 ipv6_route_default="default ${ipv6_defaultrouter}"
637 ;;
638 esac
639 case ${ipv6_static_routes} in
640 [Nn][Oo] | '')
641 ;;
642 *)
643 for i in ${ipv6_static_routes}; do
644 eval ipv6_route_args=\$ipv6_route_${i}
645 route add -inet6 ${ipv6_route_args}
646 done
647 ;;
648 esac
649}
650
651# Setup faith
652network6_faith_setup()
653{
654 case ${ipv6_faith_prefix} in
655 [Nn][Oo] | '')
656 ;;
657 *)
658 sysctl net.inet6.ip6.keepfaith=1
659 ifconfig faith0 create >/dev/null 2>&1
660 ifconfig faith0 up
661 for prefix in ${ipv6_faith_prefix}; do
662 prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
663 case ${prefixlen} in
664 '')
665 prefixlen=96
666 ;;
667 *)
668 prefix=`expr "${prefix}" : \
669 "\(.*\)/${prefixlen}"`
670 ;;
671 esac
672 route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
673 route change -inet6 ${prefix} -prefixlen ${prefixlen} \
674 -ifp faith0
675 done
676 ;;
677 esac
678}
679
680# Install the "default interface" to kernel, which will be used
681# as the default route when there's no router.
682network6_default_interface_setup()
683{
684 # Choose IPv6 default interface if it is not clearly specified.
685 case ${ipv6_default_interface} in
686 '')
687 for i in ${ipv6_network_interfaces}; do
688 case $i in
689 lo0|faith[0-9]*)
690 continue
691 ;;
692 esac
693 laddr=`network6_getladdr $i exclude_tentative`
694 case ${laddr} in
695 '')
696 ;;
697 *)
698 ipv6_default_interface=$i
699 break
700 ;;
701 esac
702 done
703 ;;
704 esac
705
706 # Disallow unicast packets without outgoing scope identifiers,
707 # or route such packets to a "default" interface, if it is specified.
708 route add -inet6 fe80:: -prefixlen 10 ::1 -reject
709 case ${ipv6_default_interface} in
710 [Nn][Oo] | '')
711 route add -inet6 ff02:: -prefixlen 16 ::1 -reject
712 ;;
713 *)
714 laddr=`network6_getladdr ${ipv6_default_interface}`
715 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
716 -cloning
717
718 # Disable installing the default interface with the
719 # case net.inet6.ip6.forwarding=0 and
720 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict
721 # between the default router list and the manual
722 # configured default route.
723 case ${ipv6_gateway_enable} in
724 [Yy][Ee][Ss])
725 ;;
726 *)
727 if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
728 then
729 ndp -I ${ipv6_default_interface}
730 fi
731 ;;
732 esac
733 ;;
734 esac
735}
736
737network6_getladdr()
738{
739 ifconfig $1 2>/dev/null | while read proto addr rest; do
740 case ${proto} in
741 inet6)
742 case ${addr} in
743 fe80::*)
744 if [ -z "$2" ]; then
745 echo ${addr}
746 return
747 fi
748 case ${rest} in
749 *tentative*)
750 continue
751 ;;
752 *)
753 echo ${addr}
754 return
755 esac
756 esac
757 esac
758 done
759}