5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
23 # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
25 # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.
26 # All rights reserved.
29 NET_INADDR_ANY
="0.0.0.0"
30 NET_IN6ADDR_ANY_INIT
="::0"
32 # Print warnings to console
34 echo "Failed to $1 interface(s):$2" >/dev
/msglog
39 # Simulates cat in sh so it doesn't need to be on the root filesystem.
42 while [ $# -ge 1 ]; do
55 echo "$message" | smf_console
56 if [ $err -ne 0 ]; then
57 echo "Error code = $err" | smf_console
62 # inet_list list of IPv4 interfaces.
63 # inet6_list list of IPv6 interfaces.
64 # ipmp_list list of IPMP IPv4 interfaces.
65 # ipmp6_list list of IPMP IPv6 interfaces.
66 # inet_plumbed list of plumbed IPv4 interfaces.
67 # inet6_plumbed list of plumbed IPv6 interfaces.
68 # ipmp_created list of created IPMP IPv4 interfaces.
69 # ipmp6_created list of created IPMP IPv6 interfaces.
70 # inet_failed list of IPv4 interfaces that failed to plumb.
71 # inet6_failed list of IPv6 interfaces that failed to plumb.
72 # ipmp_failed list of IPMP IPv4 interfaces that failed to be created.
73 # ipmp6_failed list of IPMP IPv6 interfaces that failed to be created.
75 unset inet_list inet_plumbed inet_failed \
76 inet6_list inet6_plumbed inet6_failed \
77 ipmp_list ipmp_created ipmp_failed \
78 ipmp6_list ipmp6_created ipmp6_failed
81 # get_physical interface
83 # Return physical interface corresponding to the given interface.
96 # get_logical interface
98 # Return logical interface number. Zero will be returned
99 # if there is no explicit logical number.
118 # Compare interfaces. Do the physical interface names and logical interface
123 physical_comp
$1 $2 && [ `get_logical $1` -eq `get_logical $2` ]
127 # physical_comp if1 if2
129 # Do the two interfaces share a physical interface?
133 [ "`get_physical $1`" = "`get_physical $2`" ]
137 # in_list op item list
139 # Is "item" in the given list? Use "op" to do the test, applying it to
140 # "item" and each member of the list in turn until it returns success.
148 while [ $# -gt 0 ]; do
149 $op $item $1 && return 0
157 # get_groupifname groupname
159 # Return the IPMP meta-interface name for the group, if it exists.
163 /sbin
/ipmpstat
-gP -o groupname
,group |
while IFS
=: read name ifname
; do
164 if [ "$name" = "$1" ]; then
172 # create_ipmp ifname groupname type
174 # Helper function for create_groupifname() that returns zero if it's able
175 # to create an IPMP interface of the specified type and place it in the
176 # specified group, or non-zero otherwise.
180 /sbin
/ifconfig
$1 >/dev
/null
2>&1 && return 1
181 /sbin
/ifconfig
$1 inet6
>/dev
/null
2>&1 && return 1
182 /sbin
/ifconfig
$1 $3 ipmp group
$2 2>/dev
/null
186 # create_groupifname groupname type
188 # Create an IPMP meta-interface name for the group. We only use this
189 # function if all of the interfaces in the group failed at boot and there
190 # were no /etc/hostname[6].<if> files for the IPMP meta-interface.
195 # This is a horrible way to count from 0 to 999, but in sh and
196 # without necessarily having /usr mounted, what else can we do?
198 for a
in "" 1 2 3 4 5 6 7 8 9; do
199 for b
in 0 1 2 3 4 5 6 7 8 9; do
200 for c
in 0 1 2 3 4 5 6 7 8 9; do
201 # strip leading zeroes
202 [ "$a" = "" ] && [ "$b" = 0 ] && b
=""
203 if create_ipmp ipmp
$a$b$c $1 $2; then
213 # get_hostname_ipmpinfo interface type
215 # Return all requested IPMP keywords from hostname file for a given interface.
218 # get_hostname_ipmpinfo hme0 inet keyword [ keyword ... ]
220 get_hostname_ipmpinfo
()
223 inet
) file=/etc
/hostname.
$1
225 inet6
) file=/etc
/hostname6.
$1
232 [ -r "$file" ] ||
return
238 # Read through the hostname file looking for the specified
239 # keywords. Since there may be several keywords that cancel
240 # each other out, the caller must post-process as appropriate.
243 [ -z "$line" ] && continue
244 /sbin
/ifparse
-s "$type" $line
245 done < "$file" |
while read one two
; do
246 for keyword
in "$@"; do
247 [ "$one" = "$keyword" ] && echo "$one $two"
253 # get_group_for_type interface type list
255 # Look through the set of hostname files associated with the same physical
256 # interface as "interface", and determine which group they would configure.
257 # Only hostname files associated with the physical interface or logical
258 # interface zero are allowed to set the group.
262 physical
=`get_physical $1`
267 # The last setting of the group is the one that counts, which is
268 # the reason for the second while loop.
271 for ifname
in "$@"; do
272 if if_comp
"$physical" $ifname; then
273 get_hostname_ipmpinfo
$ifname $type group
276 read keyword grname ||
{
285 # get_group interface
287 # If there is both an inet and inet6 version of an interface, the group
288 # could be set in either set of hostname files. Since inet6 is configured
289 # after inet, if there's a setting in both files, inet6 wins.
293 group
=`get_group_for_type $1 inet6 $inet6_list`
294 [ -z "$group" ] && group
=`get_group_for_type $1 inet $inet_list`
299 # Given the interface name and the address family (inet or inet6), determine
300 # whether this is a VRRP VNIC.
302 # This is used to determine whether to bring the interface up
304 not_vrrp_interface
() {
305 macaddrtype
=`/sbin/dladm show-vnic $1 -o MACADDRTYPE -p 2>/dev/null`
307 case "$macaddrtype" in
308 'vrrp'*''$2'') vrrp
=1
316 # doDHCPhostname interface
317 # Pass to this function the name of an interface. It will return
318 # true if one should enable the use of DHCP client-side host name
319 # requests on the interface, and false otherwise.
323 if [ -f /etc
/dhcp.
$1 ] && [ -f /etc
/hostname.
$1 ]; then
324 set -- `shcat /etc/hostname.$1`
325 [ $# -eq 2 -a "$1" = "inet" ]
332 # inet_process_hostname processor [ args ]
334 # Process an inet hostname file. The contents of the file
335 # are taken from standard input. Each line is passed
336 # on the command line to the "processor" command.
337 # Command line arguments can be passed to the processor.
340 # inet_process_hostname /sbin/ifconfig hme0 < /etc/hostname.hme0
342 # inet_process_hostname /sbin/ifparse -f < /etc/hostname.hme0
344 # If there is only line in an hostname file we assume it contains
345 # the old style address which results in the interface being brought up
346 # and the netmask and broadcast address being set ($inet_oneline_epilogue).
348 # Note that if the interface is a VRRP interface, do not bring the address
349 # up ($inet_oneline_epilogue_no_up).
351 # If there are multiple lines we assume the file contains a list of
352 # commands to the processor with neither the implied bringing up of the
353 # interface nor the setting of the default netmask and broadcast address.
355 # Return non-zero if any command fails so that the caller may alert
356 # users to errors in the configuration.
358 inet_oneline_epilogue_no_up
="netmask + broadcast +"
359 inet_oneline_epilogue
="netmask + broadcast + up"
361 inet_process_hostname
()
363 if doDHCPhostname
$2; then
367 # Redirecting input from a file results in a sub-shell being
368 # used, hence this outer loop surrounding the "multiple_lines"
369 # and "ifcmds" variables.
376 while read one rest
; do
377 if [ -n "$ifcmds" ]; then
379 # This handles the first N-1
380 # lines of a N-line hostname file.
382 $
* $ifcmds || retval
=$?
387 # Strip out the "ipmp" keyword if it's the
388 # first token, since it's used to control
389 # interface creation, not configuration.
391 [ "$one" = ipmp
] && one
=
396 # If the hostname file is empty or consists of only
397 # blank lines, break out of the outer loop without
398 # configuring the newly plumbed interface.
400 [ -z "$ifcmds" ] && return $retval
401 if [ $multiple_lines = false
]; then
403 # The traditional one-line hostname file.
404 # Note that we only bring it up if the
405 # interface is not a VRRP VNIC.
407 if not_vrrp_interface
$2 $3; then
408 estr
="$inet_oneline_epilogue"
410 estr
="$inet_oneline_epilogue_no_up"
412 ifcmds
="$ifcmds $estr"
416 # This handles either the single-line case or
417 # the last line of the N-line case.
419 $
* $ifcmds ||
return $?
426 # inet6_process_hostname processor [ args ]
428 # Process an inet6 hostname file. The contents of the file
429 # are taken from standard input. Each line is passed
430 # on the command line to the "processor" command.
431 # Command line arguments can be passed to the processor.
434 # inet6_process_hostname /sbin/ifconfig hme0 inet6 < /etc/hostname6.hme0
436 # inet6_process_hostname /sbin/ifparse -f inet6 < /etc/hostname6.hme0
438 # Return non-zero if any of the commands fail so that the caller may alert
439 # users to errors in the configuration.
441 inet6_process_hostname
()
444 while read one rest
; do
446 # See comment in inet_process_hostname for details.
448 [ "$one" = ipmp
] && one
=
451 if [ -n "$ifcmds" ]; then
452 $
* $ifcmds || retval
=$?
459 # Process interfaces that failed to plumb. Find the IPMP meta-interface
460 # that should host the addresses. For IPv6, only static addresses defined
461 # in hostname6 files are moved, autoconfigured addresses are not moved.
464 # move_addresses inet6
469 eval "failed=\"\$${type}_failed\""
470 eval "list=\"\$${type}_list\""
471 process_func
="${type}_process_hostname"
474 if [ "$type" = inet
]; then
477 hostpfx
="/etc/hostname"
481 hostpfx
="/etc/hostname6"
484 echo "Moving addresses from missing ${typedesc} interface(s):\c" \
487 for ifname
in $failed; do
488 in_list if_comp
$ifname $processed && continue
490 group
=`get_group $ifname`
491 if [ -z "$group" ]; then
492 in_list physical_comp
$ifname $processed ||
{
493 echo " $ifname (not moved -- not" \
494 "in an IPMP group)\c" >/dev
/msglog
495 processed
="$processed $ifname"
501 # Lookup the IPMP meta-interface name. If one doesn't exist,
504 grifname
=`get_groupifname $group`
505 [ -z "$grifname" ] && grifname
=`create_groupifname $group $type`
508 # The hostname files are processed twice. In the first
509 # pass, we are looking for all commands that apply to the
510 # non-additional interface address. These may be
511 # scattered over several files. We won't know whether the
512 # address represents a failover address or not until we've
513 # read all the files associated with the interface.
515 # In the first pass through the hostname files, all
516 # additional logical interface commands are removed. The
517 # remaining commands are concatenated together and passed
518 # to ifparse to determine whether the non-additional
519 # logical interface address is a failover address. If it
520 # as a failover address, the address may not be the first
521 # item on the line, so we can't just substitute "addif"
522 # for "set". We prepend an "addif $zaddr" command, and
523 # let the embedded "set" command set the address later.
525 /sbin
/ifparse
-f $type `
526 for item in $list; do
527 if_comp $ifname $item && $process_func \
528 /sbin/ifparse $type < $hostpfx.$item
529 done | while read three four; do
530 [ "$three" != addif ] && echo "$three $four \c"
531 done` |
while read one two
; do
532 [ -z "$one" ] && continue
533 [ "$one $two" = "$inet_oneline_epilogue" ] && \
535 line
="addif $zaddr $one $two"
536 /sbin
/ifconfig
$grifname $type $line >/dev
/null
540 # In the second pass, look for the the "addif" commands
541 # that configure additional failover addresses. Addif
542 # commands are not valid in logical interface hostname
545 if [ "$ifname" = "`get_physical $ifname`" ]; then
546 $process_func /sbin
/ifparse
-f $type < $hostpfx.
$ifname \
547 |
while read one two
; do
548 [ "$one" = addif
] && \
549 /sbin
/ifconfig
$grifname $type \
550 addif
$two >/dev
/null
554 in_list physical_comp
$ifname $processed ||
{
555 processed
="$processed $ifname"
556 echo " $ifname (moved to $grifname)\c" > /dev
/msglog
559 echo "." >/dev
/msglog
563 # ipadm_from_gz_if ifname
565 # Return true if we are in a non-global zone and Layer-3 protection of
566 # IP addresses is being enforced on the interface by the global zone
570 pif
=`/sbin/ipadm show-if -o persistent -p $1 2>/dev/null | egrep '4|6'`
571 if smf_is_globalzone ||
![[ $pif == *4* ||
$pif == *6* ]]; then
575 # In the non-global zone, plumb the interface to show current
576 # flags and check if Layer-3 protection has been enforced by
577 # the global zone. Note that this function may return
578 # with a plumbed interface. Ideally, we would not have to
579 # plumb the interface to check l3protect, but since we
580 # the `allowed-ips' datalink property cannot currently be
581 # examined in any other way from the non-global zone, we
582 # resort to plumbing the interface
584 /sbin
/ifconfig
$1 plumb
> /dev
/null
2>&1
585 l3protect
=`/sbin/ipadm show-if -o current -p $1|grep -c 'Z'`
586 if [ $l3protect = 0 ]; then
595 # if_configure type class interface_list
597 # Configure all of the interfaces of type `type' (e.g., "inet6") in
598 # `interface_list' according to their /etc/hostname[6].* files. `class'
599 # describes the class of interface (e.g., "IPMP"), as a diagnostic aid.
600 # For inet6 interfaces, the interface is also brought up.
607 process_func
=${type}_process_hostname
610 if [ "$type" = inet
]; then
612 hostpfx
="/etc/hostname"
615 hostpfx
="/etc/hostname6"
617 [ -n "$class" ] && desc
="$class $desc"
619 echo "configuring $desc interfaces:\c"
620 while [ $# -gt 0 ]; do
621 $process_func /sbin
/ifconfig
$1 $type < $hostpfx.
$1 >/dev
/null
627 elif [ "$type" = inet6
]; then
629 # only bring the interface up if it is not a
632 if not_vrrp_interface
$1 $type; then
633 /sbin
/ifconfig
$1 inet6 up || fail
="$fail $1"
641 [ -n "$fail" ] && warn_failed_ifs
"configure $desc" "$fail"
645 # net_reconfigure is called from the network/physical service (by the
646 # net-physical and net-nwam method scripts) to perform tasks that only
647 # need to be done during a reconfigure boot. This needs to be
648 # isolated in a function since network/physical has two instances
649 # (default and nwam) that have distinct method scripts that each need
650 # to do these things.
655 # Is this a reconfigure boot? If not, then there's nothing
658 reconfig
=`svcprop -c -p system/reconfigure \
659 system/svc/restarter:default 2>/dev/null`
660 if [ $?
-ne 0 -o "$reconfig" = false
]; then
665 # Ensure that the datalink-management service is running since
666 # manifest-import has not yet run for a first boot after
667 # upgrade. We wouldn't need to do that if manifest-import ran
668 # earlier in boot, since there is an explicit dependency
669 # between datalink-management and network/physical.
671 svcadm
enable -ts network
/datalink-management
:default
674 # There is a bug in SMF which causes the svcadm command above
675 # to exit prematurely (with an error code of 3) before having
676 # waited for the service to come online after having enabled
677 # it. Until that bug is fixed, we need to have the following
678 # loop to explicitly wait for the service to come online.
681 while [ $i -lt 30 ]; do
684 state
=`svcprop -p restarter/state \
685 network/datalink-management:default 2>/dev/null`
686 if [ $?
-ne 0 ]; then
688 elif [ "$state" = "online" ]; then
692 if [ "$state" != "online" ]; then
693 echo "The network/datalink-management service \c"
694 echo "did not come online."
699 # Initialize the set of physical links, and validate and
700 # remove all the physical links which were removed during the
703 /sbin
/dladm init-phys
708 # Check for use of the default "Port VLAN Identifier" (PVID) -- VLAN 1.
709 # If there is one for a given interface, then warn the user and force the
710 # PVID to zero (if it's not already set). We do this by generating a list
711 # of interfaces with VLAN 1 in use first, and then parsing out the
712 # corresponding base datalink entries to check for ones without a
713 # "default_tag" property.
717 datalink
=/etc
/dladm
/datalink.conf
720 # Find datalinks using VLAN 1 explicitly
721 # configured by dladm
723 /^#/ || NF < 2 { next }
726 sub(/.*;linkover=int,/, "", $2);
729 sub(/name=string,/, "", link);
730 sub(/;.*/, "", link);
733 ) |
( /usr
/bin
/sort -u; echo END
; cat $datalink ) |
/usr
/bin
/nawk
'
735 state == 0 { usingpvid[++nusingpvid]=$1; next; }
736 /^#/ || NF < 2 { next; }
738 # If it is already present and has a tag set,
740 if (!match($2, /;default_tag=/))
742 sub(/name=string,/, "", $2);
744 for (i = 1; i <= nusingpvid; i++) {
745 if (usingpvid[i] == $2)
750 for (i = 1; i <= nusingpvid; i++) {
751 if (usingpvid[i] != "") {
752 printf("Warning: default VLAN tag set to 0" \
753 " on %s\n", usingpvid[i]);
754 cmd=sprintf("dladm set-linkprop -p " \
755 "default_tag=0 %s\n", usingpvid[i]);
763 # service_exists fmri
765 # returns success (0) if the service exists, 1 otherwise.
769 /usr
/sbin
/svccfg
-s $1 listpg
> /dev
/null
2>&1
770 if [ $?
-eq 0 ]; then
777 # service_is_enabled fmri
779 # returns success (0) if the service is enabled (permanently or
780 # temporarily), 1 otherwise.
785 # The -c option must be specified to use the composed view
786 # because the general/enabled property takes immediate effect.
787 # See Example 2 in svcprop(1).
789 # Look at the general_ovr/enabled (if it is present) first to
790 # determine the temporarily enabled state.
792 tstate
=`/usr/bin/svcprop -c -p general_ovr/enabled $1 2>/dev/null`
793 if [ $?
-eq 0 ]; then
794 [ "$tstate" = "true" ] && return 0
798 state
=`/usr/bin/svcprop -c -p general/enabled $1 2>/dev/null`
799 [ "$state" = "true" ] && return 0
804 # is_valid_v4addr addr
806 # Returns 0 if a valid IPv4 address is given, 1 otherwise.
810 echo $1 |
/usr
/xpg
4/bin
/awk 'NF != 1 { exit 1 } \
811 $1 !~ /^((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}\
812 (25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/ \
818 # is_valid_v6addr addr
820 # Returns 0 if a valid IPv6 address is given, 1 otherwise.
824 echo $1 |
/usr
/xpg
4/bin
/awk 'NF != 1 { exit 1 } \
826 $1 !~ /^([a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/ &&
828 $1 !~ /^([a-fA-F0-9]{1,4}:){0,6}:([a-fA-F0-9]{1,4}:){0,6}\
829 [a-fA-F0-9]{1,4}$/ &&
831 $1 !~ /^([a-fA-F0-9]{1,4}:){0,7}:$/ &&
833 $1 !~ /^:(:[a-fA-F0-9]{1,4}){0,6}:[a-fA-F0-9]{1,4}$/ &&
835 $1 !~ /^:(:[a-fA-F0-9]{1,4}){0,5}:\
836 ((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}\
837 (25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/ &&
838 # a:b:c:d:e:f:1.2.3.4
839 $1 !~ /^([a-fA-F0-9]{1,4}:){6}\
840 ((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}\
841 (25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/ \
849 # Returns 0 if a valid IPv4 or IPv6 address is given, 1 otherwise.
853 is_valid_v4addr
$1 || is_valid_v6addr
$1
857 # nwam_get_loc_prop location property
859 # echoes the value of the property for the given location
861 # 0 => property is set
862 # 1 => property is not set
866 value
=`/usr/sbin/nwamcfg "select loc $1; get -V $2" 2>/dev/null`
873 # nwam_get_loc_list_prop location property
875 # echoes a space-separated list of the property values for the given location
877 # 0 => property is set
878 # 1 => property is not set
880 nwam_get_loc_list_prop
()
882 clist
=`/usr/sbin/nwamcfg "select loc $1; get -V $2" 2>/dev/null`
885 # nwamcfg gives us a comma-separated list;
886 # need to convert commas to spaces.
888 slist
=`echo $clist | sed -e s/","/" "/g`