xref: /dragonfly/etc/network.subr (revision ae75c143462d5e92cbae686b9ad9b86ce29d38cd)
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#
25# $FreeBSD: src/etc/network.subr,v 1.163 2005/06/30 04:52:47 brooks Exp $
26#
27
28#
29# Subroutines commonly used from network startup scripts.
30# Requires that /etc/rc.subr be loaded first.
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
37#         had no arguments.  Pseudo arguments DHCP and WPA are handled
38#         here.
39#
40ifconfig_up()
41{
42          local _cfg ifconfig_args
43          _cfg=1
44
45          ifconfig_args=`ifconfig_getargs $1`
46          if [ -n "${ifconfig_args}" ]; then
47                    ifconfig $1 ${ifconfig_args}
48                    ifconfig $1 up
49                    _cfg=0
50          fi
51
52          if wpaif $1; then
53                    ifconfig $1 up
54                    /etc/rc.d/wpa_supplicant start $1
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
63                    _cfg=0              # XXX: not sure this should count
64          fi
65
66          if dhcpif $1; then
67                    /etc/rc.d/dhcp_client start $1
68                    _cfg=0
69          fi
70
71          return $_cfg
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{
81          local _cfg _ifs oldifs _inet inetList
82
83          [ -z "$1" ] && return 1
84          _ifs="^"
85          _cfg=1
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"
100                    _cfg=0
101          done
102          IFS="$oldifs"
103
104          if wpaif $1; then
105                    /etc/rc.d/wpa_supplicant stop $1
106          fi
107
108          if dhcpif $1; then
109                    /etc/rc.d/dhcp_client stop $1
110                    _cfg=0
111          fi
112
113          if ifexists $1; then
114                    ifconfig $1 down
115                    _cfg=0
116          fi
117
118          return $_cfg
119}
120
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.
127#
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
149# _ifconfig_getargs if [af]
150#         Echos the arguments for the supplied interface to stdout.
151#         Returns 1 if no interface is specified.
152#         In general, the ifconfig_getargs() below should be used outside
153#         this file.
154#
155_ifconfig_getargs()
156{
157          local _if _ifn _af _args
158
159          _ifn=$1
160          _af=${2:+${2}_}
161
162          if [ -z "$_ifn" ]; then
163                    return 1
164          fi
165
166          _args=`get_if_var $_ifn ${_af}ifconfig_IF`
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
179# ifconfig_getargs if [af]
180#         Takes the result from _ifconfig_getargs() and removes pseudo
181#         args such as DHCP and WPA.
182#
183ifconfig_getargs()
184{
185          local _tmpargs _arg _args is_optarg
186
187          _tmpargs=`_ifconfig_getargs $1 $2`
188          if [ $? -eq 1 ]; then
189                    return 1
190          fi
191          _args=
192
193          is_optarg=no
194          for _arg in $_tmpargs; do
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
211                              _args="$_args $_arg"
212                              is_optarg=no
213                    fi
214          done
215
216          echo $_args
217}
218
219# ipv6if if
220#         Returns 0 if the interface should be configured for IPv6 and
221#         1 otherwise.
222#
223ipv6if()
224{
225          local _if _tmpargs
226          _if=$1
227
228          # lo0 is always IPv6-enabled
229          if [ "$_if" = "lo0" ]; then
230                    return 0
231          fi
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
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.
263#
264dhcpif()
265{
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
292          return 1
293}
294
295# wpaif if
296#         Returns 0 if the interface is a WPA interface and 1 otherwise.
297#
298wpaif()
299{
300          local _tmpargs _arg is_optarg
301
302          _tmpargs=`_ifconfig_getargs $1`
303          is_optarg=no
304          for _arg in $_tmpargs; do
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
317          done
318
319          return 1
320}
321
322# ifexists if
323#         Returns 0 if the interface exists and 1 otherwise.
324#
325ifexists()
326{
327          [ -z "$1" ] && return 1
328          ifconfig -n $1 >/dev/null 2>&1
329}
330
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
336#         1 if there were none.
337#
338ifalias_common()
339{
340          local _if _action _af _af2 _ret _var _args _alias
341          _if=$1
342          _action=$2
343          _af=$3
344
345          _ret=1
346          _alias=0
347          while : ; do
348                    if [ "${_af}" = "ipv6" ]; then
349                              _af2="inet6"
350                              _var="ipv6_ifconfig_IF_alias${_alias}"
351                    else
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
358                              break
359                    fi
360                    ifconfig $_if $_af2 $_args $_action
361                    _alias=$((${_alias} + 1))
362                    _ret=0
363          done
364          return $_ret
365}
366
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".
381#         It returns 0 if at least one alias was removed or
382#         1 if there were none.
383#
384ifalias_down()
385{
386          ifalias_common $1 -alias $2
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
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
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
452          local _rcconf _auto
453          _rcconf=""
454          _auto=""
455
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
463          # Order detected devices so that interfaces configured via rc.conf are
464          # created first, and then all other devices are automatically assigned
465          for parent in ${wlan_devices}; do
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
478                    # Parse wlans_$parent="$child ..."
479                    child_wlans=`get_if_var $parent wlans_IF`
480                    # Or find first unused wlan device to create
481                    if [ -z "${child_wlans}" ]; then
482                              child_wlans=`wlan_get_unused`
483                    fi
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
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
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
549# clone_up
550#         Create cloneable interfaces.
551#
552clone_up()
553{
554          local _prefix _list ifn
555          _prefix=
556          _list=
557
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
565          if [ -n "${_list}" ]; then
566                    echo "Created clone interfaces: ${_list}"
567          fi
568          debug "Created clone interfaces: ${_list}"
569}
570
571# clone_down
572#         Destroy cloned interfaces.
573#
574clone_down()
575{
576          local _prefix _list ifn
577          _prefix=
578          _list=
579
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
587          if [ -n "${_list}" ]; then
588                    echo "Destroyed clone interfaces: ${_list}"
589          fi
590          debug "Destroyed clone interfaces: ${_list}"
591}
592
593# gif_up
594#         Create IPv6<-->IPv4 tunnels
595#
596gif_up() {
597          local _if _peers
598
599          case ${gif_interfaces} in
600          [Nn][Oo] | '')
601                    return
602                    ;;
603          esac
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
618}
619
620# ifnet_rename
621#         Rename all requested interfaces.
622#
623ifnet_rename()
624{
625          local _ifn_list _if _ifname
626
627          _ifn_list=$(ifconfig -l)
628          [ -z "$_ifn_list" ] && return 0
629
630          for _if in ${_ifn_list} ; do
631                    _ifname=`get_if_var $_if ifconfig_IF_name`
632                    if [ -n "$_ifname" ]; then
633                              ifconfig $_if name $_ifname
634                    fi
635          done
636          return 0
637}
638
639# list_net_interfaces
640#         List all network interfaces.
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'.
644#
645list_net_interfaces()
646{
647          local _tmplist _autolist _lo _if
648
649          case ${network_interfaces} in
650          [Aa][Uu][Tt][Oo])
651                    _autolist=$(ifconfig -l)
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}"
661                    ;;
662          *)
663                    _tmplist="${network_interfaces} ${cloned_interfaces}"
664                    ;;
665          esac
666
667          echo $_tmplist
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{
688          local val str dig
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
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
715#
716# IPv6-specific setup subroutines
717#
718
719# Setup the interfaces for IPv6
720network6_interface_setup()
721{
722          local interfaces rtsol_interfaces ipv6_ifconfig
723          local rtsol_available rtsol_interface
724          local prefix laddr hostid address
725          local _if j
726
727          interfaces=$*
728          rtsol_interfaces=''
729          case ${ipv6_gateway_enable} in
730          [Yy][Ee][Ss])
731                    rtsol_available=no
732                    ;;
733          *)
734                    rtsol_available=yes
735                    ;;
736          esac
737          for _if in $interfaces; do
738                    rtsol_interface=yes
739                    prefix=`get_if_var $_if ipv6_prefix_IF`
740                    if [ -n "${prefix}" ]; then
741                              rtsol_available=no
742                              rtsol_interface=no
743                              laddr=`network6_getladdr $_if`
744                              hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
745                              for j in ${prefix}; do
746                                        address=$j\:${hostid}
747                                        ifconfig $_if inet6 ${address} prefixlen 64 alias
748
749                                        case ${ipv6_gateway_enable} in
750                                        [Yy][Ee][Ss])
751                                                  # subnet-router anycast address
752                                                  # (rfc2373)
753                                                  ifconfig $_if inet6 $j:: prefixlen 64 \
754                                                            alias anycast
755                                                  ;;
756                                        esac
757                              done
758                    fi
759                    ipv6_ifconfig=`ifconfig_getargs $_if ipv6`
760                    ipv6_ifconfig="${ipv6_ifconfig#inet6 }"
761                    if [ -n "${ipv6_ifconfig}" ]; then
762                              rtsol_available=no
763                              rtsol_interface=no
764                              ifconfig $_if inet6 ${ipv6_ifconfig} alias
765                    fi
766
767                    if [ "${rtsol_available}" = "yes" -a \
768                         "${rtsol_interface}" = "yes" ]; then
769                              case ${i} in
770                              lo0|gif[0-9]*|stf[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
771                                        ;;
772                              *)
773                                        rtsol_interfaces="${rtsol_interfaces} ${_if}"
774                                        ;;
775                              esac
776                    else
777                              ifconfig $_if inet6
778                    fi
779          done
780
781          if [ "${rtsol_available}" = "yes" -a -n "${rtsol_interfaces}" ]; then
782                    # Act as endhost - automatically configured.
783                    # You can configure only single interface, as
784                    # specification assumes that autoconfigured host has
785                    # single interface only.
786                    ${SYSCTL_W} net.inet6.ip6.accept_rtadv=1
787                    set ${rtsol_interfaces}
788                    ifconfig $1 up
789                    echo "Auto configuring interface $1 ..."
790                    rtsol $1
791          fi
792
793          for _if in $interfaces; do
794                    ifalias_up $_if ipv6
795          done
796}
797
798# Setup IPv6 to IPv4 mapping
799network6_stf_setup()
800{
801          local stf_prefixlen stf_interface_ipv6_ifid
802          local hexfrag1 hexfrag2 ipv4_in_hexformat laddr
803          local _if OIFS
804
805          case ${stf_interface_ipv4addr} in
806          [Nn][Oo] | '')
807                    ;;
808          *)
809                    # assign IPv6 addr and interface route for 6to4 interface
810                    stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
811                    OIFS="$IFS"
812                    IFS=".$IFS"
813                    set ${stf_interface_ipv4addr}
814                    IFS="$OIFS"
815                    hexfrag1=`hexprint $(($1*256 + $2))`
816                    hexfrag2=`hexprint $(($3*256 + $4))`
817                    ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
818                    case ${stf_interface_ipv6_ifid} in
819                    [Aa][Uu][Tt][Oo] | '')
820                              for _if in ${ipv6_network_interfaces}; do
821                                        laddr=`network6_getladdr $_if`
822                                        case ${laddr} in
823                                        '')
824                                                  ;;
825                                        *)
826                                                  break
827                                                  ;;
828                                        esac
829                              done
830                              stf_interface_ipv6_ifid=`expr "${laddr}" : \
831                                                                  'fe80::\(.*\)%\(.*\)'`
832                              case ${stf_interface_ipv6_ifid} in
833                              '')
834                                        stf_interface_ipv6_ifid=0:0:0:1
835                                        ;;
836                              esac
837                              ;;
838                    esac
839                    ifconfig stf0 create >/dev/null 2>&1
840                    ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
841                              prefixlen ${stf_prefixlen}
842                    # disallow packets to malicious 6to4 prefix
843                    route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
844                    route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
845                    route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
846                    route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
847                    ;;
848          esac
849}
850
851# Setup static routes
852network6_static_routes_setup()
853{
854          local _rt
855
856          # Set up any static routes.
857          case ${ipv6_defaultrouter} in
858          [Nn][Oo] | '')
859                    ;;
860          *)
861                    ipv6_static_routes="default ${ipv6_static_routes}"
862                    ipv6_route_default="default ${ipv6_defaultrouter}"
863                    ;;
864          esac
865          case ${ipv6_static_routes} in
866          [Nn][Oo] | '')
867                    ;;
868          *)
869                    for _rt in ${ipv6_static_routes}; do
870                              eval ipv6_route_args=\$ipv6_route_${_rt}
871                              route add -inet6 ${ipv6_route_args}
872                    done
873                    ;;
874          esac
875}
876
877# Install the "default interface" to kernel, which will be used
878# as the default route when there's no router.
879network6_default_interface_setup()
880{
881          local _if laddr
882
883          # Choose IPv6 default interface if it is not clearly specified.
884          case ${ipv6_default_interface} in
885          '')
886                    for _if in ${ipv6_network_interfaces}; do
887                              if [ "${_if}" = "lo0" ]; then
888                                        continue
889                              fi
890
891                              laddr=`network6_getladdr $_if exclude_tentative`
892                              case ${laddr} in
893                              '')
894                                        ;;
895                              *)
896                                        ipv6_default_interface=$_if
897                                        break
898                                        ;;
899                              esac
900                    done
901                    ;;
902          esac
903
904          # Disallow unicast packets without outgoing scope identifiers,
905          # or route such packets to a "default" interface, if it is specified.
906          route add -inet6 fe80:: -prefixlen 10 ::1 -reject
907          case ${ipv6_default_interface} in
908          [Nn][Oo] | '')
909                    route add -inet6 ff02:: -prefixlen 16 ::1 -reject
910                    ;;
911          *)
912                    laddr=`network6_getladdr ${ipv6_default_interface}`
913                    route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
914                              -cloning
915
916                    # Disable installing the default interface with the
917                    # case net.inet6.ip6.forwarding=0 and
918                    # net.inet6.ip6.accept_rtadv=0, due to avoid conflict
919                    # between the default router list and the manual
920                    # configured default route.
921                    case ${ipv6_gateway_enable} in
922                    [Yy][Ee][Ss])
923                              ;;
924                    *)
925                              if [ `${SYSCTL_N} net.inet6.ip6.accept_rtadv` -eq 1 ]
926                              then
927                                        ndp -I ${ipv6_default_interface}
928                              fi
929                              ;;
930                    esac
931                    ;;
932          esac
933}
934
935network6_getladdr()
936{
937          local proto addr rest
938
939          ifconfig $1 2>/dev/null | while read proto addr rest; do
940                    case ${proto} in
941                    inet6)
942                              case ${addr} in
943                              fe80::*)
944                                        if [ -z "$2" ]; then
945                                                  echo ${addr}
946                                                  return
947                                        fi
948                                        case ${rest} in
949                                        *tentative*)
950                                                  continue
951                                                  ;;
952                                        *)
953                                                  echo ${addr}
954                                                  return
955                                        esac
956                              esac
957                    esac
958          done
959}
960