etc/network.subr: enhance wlan initialization
[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 $
9c600e7d
MD
26#
27
28#
29# Subroutines commonly used from network startup scripts.
e4b0f1d1 30# Requires that /etc/rc.subr be loaded first.
9c600e7d
MD
31#
32
33# ifconfig_up if
34# Evaluate ifconfig(8) arguments for interface $if and
35# run ifconfig(8) with those arguments. It returns 0 if
36# arguments were found and executed or 1 if the interface
f26c267a
SW
37# had no arguments. Pseudo arguments DHCP and WPA are handled
38# here.
9c600e7d
MD
39#
40ifconfig_up()
41{
e4b0f1d1 42 local _cfg ifconfig_args
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}
5ad36ff1 48 ifconfig $1 up
f26c267a 49 _cfg=0
9c600e7d 50 fi
f26c267a
SW
51
52 if wpaif $1; then
5ad36ff1 53 ifconfig $1 up
f26c267a 54 /etc/rc.d/wpa_supplicant start $1
e9136cbf
AL
55 # NOTE: wpa_supplicant(8) needs to control the interface's
56 # state in order to perform the SSID scan. But
57 # dhcpcd(8), which may be started by the "dhcp_client"
58 # below, can race against wpa_supplicant(8) and modify
59 # the interface's state, breaking the SSID scan and
60 # preventing the SSID association.
61 # Insert a small delay here to workaround the issue.
62 sleep 1
f26c267a
SW
63 _cfg=0 # XXX: not sure this should count
64 fi
65
66 if dhcpif $1; then
817cf585 67 /etc/rc.d/dhcp_client start $1
f26c267a
SW
68 _cfg=0
69 fi
70
71 return $_cfg
9c600e7d
MD
72}
73
74# ifconfig_down if
75# Remove all inet entries from the $if interface. It returns
76# 0 if inet entries were found and removed. It returns 1 if
77# no entries were found or they could not be removed.
78#
79ifconfig_down()
80{
e4b0f1d1
AL
81 local _cfg _ifs oldifs _inet inetList
82
9c600e7d
MD
83 [ -z "$1" ] && return 1
84 _ifs="^"
f26c267a 85 _cfg=1
9c600e7d
MD
86
87 inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`"
88
89 oldifs="$IFS"
90 IFS="$_ifs"
91 for _inet in $inetList ; do
92 # get rid of extraneous line
93 [ -z "$_inet" ] && break
94
95 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
96
97 IFS="$oldifs"
98 ifconfig $1 ${_inet} delete
99 IFS="$_ifs"
f26c267a 100 _cfg=0
9c600e7d
MD
101 done
102 IFS="$oldifs"
103
f26c267a
SW
104 if wpaif $1; then
105 /etc/rc.d/wpa_supplicant stop $1
106 fi
107
108 if dhcpif $1; then
817cf585 109 /etc/rc.d/dhcp_client stop $1
f26c267a
SW
110 _cfg=0
111 fi
112
5ad36ff1
AL
113 if ifexists $1; then
114 ifconfig $1 down
115 _cfg=0
116 fi
117
f26c267a
SW
118 return $_cfg
119}
120
d86e211f
AH
121# get_if_var if var [default]
122# Return the value of the pseudo-hash corresponding to $if where
123# $var is a string containg the sub-string "IF" which will be
124# replaced with $if after the characters defined in _punct are
125# replaced with '_'. If the variable is unset, replace it with
126# $default if given.
e4b0f1d1 127#
d86e211f
AH
128get_if_var()
129{
130 local _if _punct_c _punct _var _default prefix suffix
131
132 if [ $# -ne 2 -a $# -ne 3 ]; then
133 err 3 'USAGE: get_if_var name var [default]'
134 fi
135
136 _if=$1
137 _punct=". - / +"
138 for _punct_c in $_punct; do
139 _if=`ltr ${_if} ${_punct_c} '_'`
140 done
141 _var=$2
142 _default=$3
143
144 prefix=${_var%%IF*}
145 suffix=${_var##*IF}
146 eval echo \${${prefix}${_if}${suffix}-${_default}}
147}
148
8cd2e074 149# _ifconfig_getargs if [af]
f26c267a 150# Echos the arguments for the supplied interface to stdout.
e4b0f1d1
AL
151# Returns 1 if no interface is specified.
152# In general, the ifconfig_getargs() below should be used outside
153# this file.
154#
f26c267a
SW
155_ifconfig_getargs()
156{
e4b0f1d1
AL
157 local _if _ifn _af _args
158
f26c267a 159 _ifn=$1
8cd2e074
AL
160 _af=${2:+${2}_}
161
f26c267a
SW
162 if [ -z "$_ifn" ]; then
163 return 1
164 fi
165
8cd2e074 166 _args=`get_if_var $_ifn ${_af}ifconfig_IF`
f26c267a
SW
167 if [ -z "$_args" -a -n "${pccard_ifconfig}" ]; then
168 for _if in ${removable_interfaces} ; do
169 if [ "$_if" = "$_ifn" ] ; then
170 _args=${pccard_ifconfig}
171 break
172 fi
173 done
174 fi
175
176 echo $_args
177}
178
8cd2e074 179# ifconfig_getargs if [af]
e4b0f1d1 180# Takes the result from _ifconfig_getargs() and removes pseudo
f26c267a 181# args such as DHCP and WPA.
e4b0f1d1 182#
f26c267a
SW
183ifconfig_getargs()
184{
e4b0f1d1
AL
185 local _tmpargs _arg _args is_optarg
186
8cd2e074 187 _tmpargs=`_ifconfig_getargs $1 $2`
f26c267a
SW
188 if [ $? -eq 1 ]; then
189 return 1
190 fi
191 _args=
192
1f03f592 193 is_optarg=no
f26c267a 194 for _arg in $_tmpargs; do
1f03f592
SW
195 if [ "$is_optarg" = "no" ]; then
196 case $_arg in
197 [Dd][Hh][Cc][Pp])
198 ;;
199 [Ww][Pp][Aa])
200 ;;
201 *)
202 _args="$_args $_arg"
203 case $_arg in
204 authmode)
205 is_optarg=yes
206 ;;
207 esac
208 ;;
209 esac
210 else
f26c267a 211 _args="$_args $_arg"
1f03f592
SW
212 is_optarg=no
213 fi
f26c267a
SW
214 done
215
216 echo $_args
217}
218
da4dd514
AL
219# ipv6if if
220# Returns 0 if the interface should be configured for IPv6 and
221# 1 otherwise.
e4b0f1d1 222#
da4dd514
AL
223ipv6if()
224{
225 local _if _tmpargs
226 _if=$1
227
228 # lo0 is always IPv6-enabled
e4b0f1d1 229 if [ "$_if" = "lo0" ]; then
da4dd514 230 return 0
e4b0f1d1 231 fi
da4dd514
AL
232
233 case ${ipv6_enable} in
234 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
235 return 1
236 ;;
237 esac
238
239 case "${ipv6_network_interfaces}" in
240 $_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
241 # True if $ipv6_ifconfig_IF is defined.
242 _tmpargs=`_ifconfig_getargs $_if ipv6`
243 if [ -n "${_tmpargs}" ]; then
244 return 0
245 fi
246
247 # True if $ipv6_prefix_IF is defined.
248 _tmpargs=`get_if_var $_if ipv6_prefix_IF`
249 if [ -n "${_tmpargs}" ]; then
250 return 0
251 fi
252
253 ;;
254 esac
255
256 return 1
257}
258
329743de
AL
259# dhcpif if [ipv4|ipv6]
260# Returns 0 if the interface needs DHCP for IPv4/IPv6 and 1 otherwise.
261# If the second argument is "ipv4" (or "ipv6"), then only IPv4 (or
262# IPv6) is checked, otherwise both are checked.
e4b0f1d1 263#
f26c267a
SW
264dhcpif()
265{
329743de
AL
266 local _tmpargs _arg _if _af
267 _if=$1
268 _af=$2
269
270 if [ -z "$_af" -o "$_af" = "ipv4" ]; then
271 _tmpargs=`_ifconfig_getargs $_if`
272 for _arg in $_tmpargs; do
273 case $_arg in
274 [Dd][Hh][Cc][Pp])
275 return 0
276 ;;
277 esac
278 done
279 fi
280
281 if [ -z "$_af" -o "$_af" = "ipv6" ] && ipv6if $_if; then
282 _tmpargs=`_ifconfig_getargs $_if ipv6`
283 for _arg in $_tmpargs; do
284 case $_arg in
285 [Dd][Hh][Cc][Pp])
286 return 0
287 ;;
288 esac
289 done
290 fi
291
f26c267a
SW
292 return 1
293}
294
295# wpaif if
296# Returns 0 if the interface is a WPA interface and 1 otherwise.
e4b0f1d1 297#
f26c267a
SW
298wpaif()
299{
e4b0f1d1
AL
300 local _tmpargs _arg is_optarg
301
f26c267a 302 _tmpargs=`_ifconfig_getargs $1`
1f03f592 303 is_optarg=no
f26c267a 304 for _arg in $_tmpargs; do
1f03f592
SW
305 if [ "$is_optarg" = "no" ]; then
306 case $_arg in
307 [Ww][Pp][Aa])
308 return 0
309 ;;
310 authmode)
311 is_optarg=yes
312 ;;
313 esac
314 else
315 is_optarg=no
316 fi
f26c267a 317 done
e4b0f1d1 318
f26c267a 319 return 1
9c600e7d
MD
320}
321
cc419283
AL
322# ifexists if
323# Returns 0 if the interface exists and 1 otherwise.
e4b0f1d1 324#
cc419283
AL
325ifexists()
326{
327 [ -z "$1" ] && return 1
e4b0f1d1 328 ifconfig -n $1 >/dev/null 2>&1
cc419283
AL
329}
330
3b4e0f2a
AL
331# ifalias_common if action [ipv6]
332# Helper function for ifalias_up() and ifalias_down().
333# The $action argument can be either "alias" (to add an
334# alias) or "-alias" (to remove an alias).
335# Returns 0 if at least one alias was added/removed or
9c600e7d
MD
336# 1 if there were none.
337#
3b4e0f2a 338ifalias_common()
9c600e7d 339{
3b4e0f2a
AL
340 local _if _action _af _af2 _ret _var _args _alias
341 _if=$1
342 _action=$2
343 _af=$3
e4b0f1d1 344
9c600e7d 345 _ret=1
3b4e0f2a 346 _alias=0
9c600e7d 347 while : ; do
3b4e0f2a
AL
348 if [ "${_af}" = "ipv6" ]; then
349 _af2="inet6"
350 _var="ipv6_ifconfig_IF_alias${_alias}"
9c600e7d 351 else
3b4e0f2a
AL
352 _af2="inet"
353 _var="ifconfig_IF_alias${_alias}"
354 fi
355 _args=`get_if_var $_if $_var`
356 _args="${_args#${_af2} }"
357 if [ -z "${_args}" ]; then
9c600e7d
MD
358 break
359 fi
3b4e0f2a
AL
360 ifconfig $_if $_af2 $_args $_action
361 _alias=$((${_alias} + 1))
362 _ret=0
9c600e7d
MD
363 done
364 return $_ret
365}
366
3b4e0f2a
AL
367# ifalias_up if [ipv6]
368# Configure IPv4 aliases for network interface $if or
369# IPv6 aliases if the second argument is "ipv6".
370# It returns 0 if at least one alias was configured or
371# 1 if there were none.
372#
373ifalias_up()
374{
375 ifalias_common $1 alias $2
376}
377
378# ifalias_down if [ipv6]
379# Remove IPv4 aliases for network interface $if or
380# IPv6 aliases if the second argument is "ipv6".
9c600e7d
MD
381# It returns 0 if at least one alias was removed or
382# 1 if there were none.
383#
384ifalias_down()
385{
3b4e0f2a 386 ifalias_common $1 -alias $2
9c600e7d
MD
387}
388
389# ifscript_up if
390# Evaluate a startup script for the $if interface.
391# It returns 0 if a script was found and processed or
392# 1 if no script was found.
393#
394ifscript_up()
395{
396 if [ -r /etc/start_if.$1 ]; then
397 . /etc/start_if.$1
398 return 0
399 fi
400 return 1
401}
402
403# ifscript_down if
404# Evaluate a shutdown script for the $if interface.
405# It returns 0 if a script was found and processed or
406# 1 if no script was found.
407#
408ifscript_down()
409{
410 if [ -r /etc/stop_if.$1 ]; then
411 . /etc/stop_if.$1
412 return 0
413 fi
414 return 1
415}
416
69dc5784
DF
417# wlan_get_unused
418# walk through net.wlan and find unused device that can be created
419#
420wlan_get_unused()
421{
422 local idx
423
424 idx=0
425
426 while : ; do
427 if ! ${SYSCTL_N} -q net.wlan.${idx}.%parent >/dev/null; then
428 echo "wlan${idx}"
429 break
430 fi
431 idx=$((${idx} + 1))
432 done
433}
434
435# wlan_is_parent
436# check if given interface is parent for any existing wlan device
437#
438wlan_is_parent()
439{
440 sysctl -q net.wlan | grep -q "%parent: ${1}"
441}
442
3928a593
AL
443# wlan_up
444# Create IEEE 802.11 interfaces.
445#
446wlan_up()
447{
448 local _prefix _list parent child child_wlans create_args debug_flags
449 _prefix=
450 _list=
451
69dc5784
DF
452 local _rcconf _auto
453 _rcconf=""
454 _auto=""
455
4c258131
DF
456 local wlan_devices
457 if [ -n "$1" ]; then
458 wlan_devices="$1"
459 else
460 wlan_devices="`${SYSCTL_N} -q net.wlan.devices`"
461 fi
462
69dc5784
DF
463 # Order detected devices so that interfaces configured via rc.conf are
464 # created first, and then all other devices are automatically assigned
4c258131 465 for parent in ${wlan_devices}; do
69dc5784
DF
466 child_wlans=`get_if_var $parent wlans_IF`
467 if [ -n "${child_wlans}" ]; then
468 _rcconf="${_rcconf} ${parent}"
469 else
470 _auto="${_auto} ${parent}"
471 fi
472 done
473
474 for parent in ${_rcconf} ${_auto}; do
475 if wlan_is_parent $parent; then
476 continue
477 fi
3928a593
AL
478 # Parse wlans_$parent="$child ..."
479 child_wlans=`get_if_var $parent wlans_IF`
69dc5784
DF
480 # Or find first unused wlan device to create
481 if [ -z "${child_wlans}" ]; then
482 child_wlans=`wlan_get_unused`
483 fi
3928a593
AL
484 for child in ${child_wlans}; do
485 if ifexists $child; then
486 continue
487 fi
488
489 create_args="wlandev $parent `get_if_var $child create_args_IF`"
490 debug_flags="`get_if_var $child wlandebug_IF`"
491 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
492 ifconfig $child create ${create_args}
493 else
494 ifconfig wlan create ${create_args} name $child
495 fi
496 if [ $? -eq 0 ]; then
497 _list="${_list}${_prefix}${child}"
498 [ -z "$_prefix" ] && _prefix=' '
499 fi
500 if [ -n "${debug_flags}" ]; then
501 wlandebug -i $child ${debug_flags}
502 fi
503 done
504 done
505
506 if [ -n "${_list}" ]; then
507 echo "Created wlan interfaces: ${_list}"
508 fi
509 debug "Created wlan interfaces: ${_list}"
510}
511
512# wlan_down
513# Destroy IEEE 802.11 interfaces.
514#
515wlan_down()
516{
517 local _prefix _list parent child child_wlans
518 _prefix=
519 _list=
520
4c258131
DF
521 local wlan_devices
522 if [ -n "$1" ]; then
523 wlan_devices="$1"
524 else
525 wlan_devices="`${SYSCTL_N} -q net.wlan.devices`"
526 fi
527
528 for parent in ${wlan_devices}; do
3928a593
AL
529 child_wlans=`get_if_var $parent wlans_IF`
530 for child in ${child_wlans}; do
531 if ! ifexists $child; then
532 continue
533 fi
534
535 ifconfig -n $child destroy
536 if [ $? -eq 0 ]; then
537 _list="${_list}${_prefix}${child}"
538 [ -z "$_prefix" ] && _prefix=' '
539 fi
540 done
541 done
542
543 if [ -n "${_list}" ]; then
544 echo "Destroyed wlan interfaces: ${_list}"
545 fi
546 debug "Destroyed wlan interfaces: ${_list}"
547}
548
e4b0f1d1
AL
549# clone_up
550# Create cloneable interfaces.
9c600e7d
MD
551#
552clone_up()
553{
e4b0f1d1 554 local _prefix _list ifn
9c600e7d
MD
555 _prefix=
556 _list=
e4b0f1d1 557
9c600e7d
MD
558 for ifn in ${cloned_interfaces}; do
559 ifconfig ${ifn} create
560 if [ $? -eq 0 ]; then
561 _list="${_list}${_prefix}${ifn}"
562 [ -z "$_prefix" ] && _prefix=' '
563 fi
564 done
e4b0f1d1
AL
565 if [ -n "${_list}" ]; then
566 echo "Created clone interfaces: ${_list}"
567 fi
568 debug "Created clone interfaces: ${_list}"
9c600e7d
MD
569}
570
e4b0f1d1
AL
571# clone_down
572# Destroy cloned interfaces.
9c600e7d
MD
573#
574clone_down()
575{
e4b0f1d1 576 local _prefix _list ifn
9c600e7d
MD
577 _prefix=
578 _list=
e4b0f1d1 579
9c600e7d
MD
580 for ifn in ${cloned_interfaces}; do
581 ifconfig ${ifn} destroy
582 if [ $? -eq 0 ]; then
583 _list="${_list}${_prefix}${ifn}"
584 [ -z "$_prefix" ] && _prefix=' '
585 fi
586 done
e4b0f1d1
AL
587 if [ -n "${_list}" ]; then
588 echo "Destroyed clone interfaces: ${_list}"
589 fi
590 debug "Destroyed clone interfaces: ${_list}"
9c600e7d
MD
591}
592
e4b0f1d1
AL
593# gif_up
594# Create IPv6<-->IPv4 tunnels
595#
9c600e7d 596gif_up() {
e4b0f1d1
AL
597 local _if _peers
598
9c600e7d
MD
599 case ${gif_interfaces} in
600 [Nn][Oo] | '')
e4b0f1d1 601 return
9c600e7d
MD
602 ;;
603 esac
e4b0f1d1
AL
604
605 for _if in ${gif_interfaces}; do
606 eval _peers=\$gifconfig_${_if}
607 case ${_peers} in
608 '')
609 continue
610 ;;
611 *)
612 ifconfig $_if create >/dev/null 2>&1
613 ifconfig $_if tunnel ${_peers}
614 ifconfig $_if up
615 ;;
616 esac
617 done
9c600e7d
MD
618}
619
f26c267a
SW
620# ifnet_rename
621# Rename all requested interfaces.
622#
623ifnet_rename()
624{
e4b0f1d1 625 local _ifn_list _if _ifname
f26c267a 626
e4b0f1d1 627 _ifn_list=$(ifconfig -l)
f26c267a 628 [ -z "$_ifn_list" ] && return 0
e4b0f1d1 629
f26c267a 630 for _if in ${_ifn_list} ; do
a939f930 631 _ifname=`get_if_var $_if ifconfig_IF_name`
e4b0f1d1 632 if [ -n "$_ifname" ]; then
f26c267a
SW
633 ifconfig $_if name $_ifname
634 fi
635 done
636 return 0
637}
638
0e387345
AL
639# list_net_interfaces
640# List all network interfaces.
acba6ed7
SS
641# Note that the list will include cloned interfaces if applicable.
642# Cloned interfaces must already exist to have a chance to appear
643# in the list if ${network_interfaces} is set to `auto'.
9c600e7d
MD
644#
645list_net_interfaces()
646{
0e387345
AL
647 local _tmplist _autolist _lo _if
648
9c600e7d
MD
649 case ${network_interfaces} in
650 [Aa][Uu][Tt][Oo])
3928a593 651 _autolist=$(ifconfig -l)
667713fe
HT
652 _lo=
653 for _if in ${_autolist} ; do
654 if [ "$_if" = "lo0" ]; then
655 _lo="lo0"
656 else
657 _tmplist="${_tmplist} ${_if}"
658 fi
659 done
660 _tmplist="${_lo} ${_tmplist}"
9c600e7d
MD
661 ;;
662 *)
acba6ed7 663 _tmplist="${network_interfaces} ${cloned_interfaces}"
9c600e7d
MD
664 ;;
665 esac
9c600e7d 666
0e387345 667 echo $_tmplist
9c600e7d
MD
668}
669
670hexdigit()
671{
672 if [ $1 -lt 10 ]; then
673 echo $1
674 else
675 case $1 in
676 10) echo a ;;
677 11) echo b ;;
678 12) echo c ;;
679 13) echo d ;;
680 14) echo e ;;
681 15) echo f ;;
682 esac
683 fi
684}
685
686hexprint()
687{
e4b0f1d1 688 local val str dig
9c600e7d
MD
689 val=$1
690 str=''
691
692 dig=`hexdigit $((${val} & 15))`
693 str=${dig}${str}
694 val=$((${val} >> 4))
695 while [ ${val} -gt 0 ]; do
696 dig=`hexdigit $((${val} & 15))`
697 str=${dig}${str}
698 val=$((${val} >> 4))
699 done
700
701 echo ${str}
702}
703
8716355d
DF
704is_wired_interface()
705{
706 local media
707
708 case `ifconfig $1 2>/dev/null` in
709 *media:?Ethernet*) media=Ethernet ;;
710 esac
711
712 test "$media" = "Ethernet"
713}
714
715is_ndis_interface()
716{
717 case `sysctl -n net.wlan.${1#wlan}.%parent 2>/dev/null` in
718 ndis*) true ;;
719 *) false ;;
720 esac
721}
e4b0f1d1
AL
722
723#
724# IPv6-specific setup subroutines
725#
726
9c600e7d
MD
727# Setup the interfaces for IPv6
728network6_interface_setup()
729{
e4b0f1d1
AL
730 local interfaces rtsol_interfaces ipv6_ifconfig
731 local rtsol_available rtsol_interface
3b4e0f2a 732 local prefix laddr hostid address
e4b0f1d1
AL
733 local _if j
734
9c600e7d
MD
735 interfaces=$*
736 rtsol_interfaces=''
737 case ${ipv6_gateway_enable} in
738 [Yy][Ee][Ss])
739 rtsol_available=no
740 ;;
741 *)
742 rtsol_available=yes
743 ;;
744 esac
e4b0f1d1 745 for _if in $interfaces; do
9c600e7d 746 rtsol_interface=yes
e4b0f1d1 747 prefix=`get_if_var $_if ipv6_prefix_IF`
9c600e7d
MD
748 if [ -n "${prefix}" ]; then
749 rtsol_available=no
750 rtsol_interface=no
e4b0f1d1 751 laddr=`network6_getladdr $_if`
9c600e7d
MD
752 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
753 for j in ${prefix}; do
754 address=$j\:${hostid}
e4b0f1d1 755 ifconfig $_if inet6 ${address} prefixlen 64 alias
9c600e7d
MD
756
757 case ${ipv6_gateway_enable} in
758 [Yy][Ee][Ss])
759 # subnet-router anycast address
760 # (rfc2373)
e4b0f1d1 761 ifconfig $_if inet6 $j:: prefixlen 64 \
9c600e7d
MD
762 alias anycast
763 ;;
764 esac
765 done
766 fi
e4b0f1d1 767 ipv6_ifconfig=`ifconfig_getargs $_if ipv6`
203bea78 768 ipv6_ifconfig="${ipv6_ifconfig#inet6 }"
9c600e7d
MD
769 if [ -n "${ipv6_ifconfig}" ]; then
770 rtsol_available=no
771 rtsol_interface=no
e4b0f1d1 772 ifconfig $_if inet6 ${ipv6_ifconfig} alias
9c600e7d
MD
773 fi
774
e4b0f1d1
AL
775 if [ "${rtsol_available}" = "yes" -a \
776 "${rtsol_interface}" = "yes" ]; then
9c600e7d 777 case ${i} in
06937ef9 778 lo0|gif[0-9]*|stf[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
9c600e7d
MD
779 ;;
780 *)
e4b0f1d1 781 rtsol_interfaces="${rtsol_interfaces} ${_if}"
9c600e7d
MD
782 ;;
783 esac
784 else
e4b0f1d1 785 ifconfig $_if inet6
9c600e7d
MD
786 fi
787 done
788
e4b0f1d1 789 if [ "${rtsol_available}" = "yes" -a -n "${rtsol_interfaces}" ]; then
9c600e7d
MD
790 # Act as endhost - automatically configured.
791 # You can configure only single interface, as
792 # specification assumes that autoconfigured host has
793 # single interface only.
b0a4258d 794 ${SYSCTL_W} net.inet6.ip6.accept_rtadv=1
9c600e7d
MD
795 set ${rtsol_interfaces}
796 ifconfig $1 up
e4b0f1d1 797 echo "Auto configuring interface $1 ..."
9c600e7d
MD
798 rtsol $1
799 fi
800
e4b0f1d1 801 for _if in $interfaces; do
3b4e0f2a 802 ifalias_up $_if ipv6
9c600e7d
MD
803 done
804}
805
806# Setup IPv6 to IPv4 mapping
807network6_stf_setup()
808{
e4b0f1d1
AL
809 local stf_prefixlen stf_interface_ipv6_ifid
810 local hexfrag1 hexfrag2 ipv4_in_hexformat laddr
811 local _if OIFS
812
9c600e7d
MD
813 case ${stf_interface_ipv4addr} in
814 [Nn][Oo] | '')
815 ;;
816 *)
817 # assign IPv6 addr and interface route for 6to4 interface
818 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
819 OIFS="$IFS"
820 IFS=".$IFS"
821 set ${stf_interface_ipv4addr}
822 IFS="$OIFS"
823 hexfrag1=`hexprint $(($1*256 + $2))`
824 hexfrag2=`hexprint $(($3*256 + $4))`
825 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
826 case ${stf_interface_ipv6_ifid} in
827 [Aa][Uu][Tt][Oo] | '')
e4b0f1d1
AL
828 for _if in ${ipv6_network_interfaces}; do
829 laddr=`network6_getladdr $_if`
9c600e7d
MD
830 case ${laddr} in
831 '')
832 ;;
833 *)
834 break
835 ;;
836 esac
837 done
838 stf_interface_ipv6_ifid=`expr "${laddr}" : \
839 'fe80::\(.*\)%\(.*\)'`
840 case ${stf_interface_ipv6_ifid} in
841 '')
842 stf_interface_ipv6_ifid=0:0:0:1
843 ;;
844 esac
845 ;;
846 esac
847 ifconfig stf0 create >/dev/null 2>&1
848 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
849 prefixlen ${stf_prefixlen}
850 # disallow packets to malicious 6to4 prefix
851 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
852 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
853 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
854 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
855 ;;
856 esac
857}
858
859# Setup static routes
860network6_static_routes_setup()
861{
e4b0f1d1
AL
862 local _rt
863
9c600e7d
MD
864 # Set up any static routes.
865 case ${ipv6_defaultrouter} in
866 [Nn][Oo] | '')
867 ;;
868 *)
869 ipv6_static_routes="default ${ipv6_static_routes}"
870 ipv6_route_default="default ${ipv6_defaultrouter}"
871 ;;
872 esac
873 case ${ipv6_static_routes} in
874 [Nn][Oo] | '')
875 ;;
876 *)
e4b0f1d1
AL
877 for _rt in ${ipv6_static_routes}; do
878 eval ipv6_route_args=\$ipv6_route_${_rt}
9c600e7d
MD
879 route add -inet6 ${ipv6_route_args}
880 done
881 ;;
882 esac
883}
884
9c600e7d
MD
885# Install the "default interface" to kernel, which will be used
886# as the default route when there's no router.
887network6_default_interface_setup()
888{
e4b0f1d1
AL
889 local _if laddr
890
9c600e7d
MD
891 # Choose IPv6 default interface if it is not clearly specified.
892 case ${ipv6_default_interface} in
893 '')
e4b0f1d1
AL
894 for _if in ${ipv6_network_interfaces}; do
895 if [ "${_if}" = "lo0" ]; then
9c600e7d 896 continue
e4b0f1d1
AL
897 fi
898
899 laddr=`network6_getladdr $_if exclude_tentative`
9c600e7d
MD
900 case ${laddr} in
901 '')
902 ;;
903 *)
e4b0f1d1 904 ipv6_default_interface=$_if
9c600e7d
MD
905 break
906 ;;
907 esac
908 done
909 ;;
910 esac
911
912 # Disallow unicast packets without outgoing scope identifiers,
913 # or route such packets to a "default" interface, if it is specified.
914 route add -inet6 fe80:: -prefixlen 10 ::1 -reject
915 case ${ipv6_default_interface} in
916 [Nn][Oo] | '')
917 route add -inet6 ff02:: -prefixlen 16 ::1 -reject
918 ;;
919 *)
920 laddr=`network6_getladdr ${ipv6_default_interface}`
921 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
922 -cloning
923
924 # Disable installing the default interface with the
925 # case net.inet6.ip6.forwarding=0 and
926 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict
927 # between the default router list and the manual
928 # configured default route.
929 case ${ipv6_gateway_enable} in
930 [Yy][Ee][Ss])
931 ;;
932 *)
b0a4258d 933 if [ `${SYSCTL_N} net.inet6.ip6.accept_rtadv` -eq 1 ]
9c600e7d
MD
934 then
935 ndp -I ${ipv6_default_interface}
936 fi
937 ;;
938 esac
939 ;;
940 esac
941}
942
943network6_getladdr()
944{
e4b0f1d1
AL
945 local proto addr rest
946
9c600e7d
MD
947 ifconfig $1 2>/dev/null | while read proto addr rest; do
948 case ${proto} in
949 inet6)
950 case ${addr} in
951 fe80::*)
952 if [ -z "$2" ]; then
953 echo ${addr}
954 return
955 fi
956 case ${rest} in
957 *tentative*)
958 continue
959 ;;
960 *)
961 echo ${addr}
962 return
963 esac
964 esac
965 esac
966 done
967}