1#!/bin/sh 2# 3# CDDL HEADER START 4# 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. 8# 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. 13# 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] 19# 20# CDDL HEADER END 21# 22# 23# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24# 25# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T. 26# All rights reserved. 27# 28 29# Print warnings to console 30warn_failed_ifs() { 31 echo "Failed to $1 interface(s):$2" >/dev/msglog 32} 33 34# 35# shcat file 36# Simulates cat in sh so it doesn't need to be on the root filesystem. 37# 38shcat() { 39 while [ $# -ge 1 ]; do 40 while read i; do 41 echo "$i" 42 done < $1 43 shift 44 done 45} 46 47# 48# inet_list list of IPv4 interfaces. 49# inet6_list list of IPv6 interfaces. 50# ipmp_list list of IPMP IPv4 interfaces. 51# ipmp6_list list of IPMP IPv6 interfaces. 52# inet_plumbed list of plumbed IPv4 interfaces. 53# inet6_plumbed list of plumbed IPv6 interfaces. 54# ipmp_created list of created IPMP IPv4 interfaces. 55# ipmp6_created list of created IPMP IPv6 interfaces. 56# inet_failed list of IPv4 interfaces that failed to plumb. 57# inet6_failed list of IPv6 interfaces that failed to plumb. 58# ipmp_failed list of IPMP IPv4 interfaces that failed to be created. 59# ipmp6_failed list of IPMP IPv6 interfaces that failed to be created. 60# 61unset inet_list inet_plumbed inet_failed \ 62 inet6_list inet6_plumbed inet6_failed \ 63 ipmp_list ipmp_created ipmp_failed \ 64 ipmp6_list ipmp6_created ipmp6_failed 65 66# 67# get_physical interface 68# 69# Return physical interface corresponding to the given interface. 70# 71get_physical() 72{ 73 ORIGIFS="$IFS" 74 IFS="${IFS}:" 75 set -- $1 76 IFS="$ORIGIFS" 77 78 echo $1 79} 80 81# 82# get_logical interface 83# 84# Return logical interface number. Zero will be returned 85# if there is no explicit logical number. 86# 87get_logical() 88{ 89 ORIGIFS="$IFS" 90 IFS="${IFS}:" 91 set -- $1 92 IFS="$ORIGIFS" 93 94 if [ -z "$2" ]; then 95 echo 0 96 else 97 echo $2 98 fi 99} 100 101# 102# if_comp if1 if2 103# 104# Compare interfaces. Do the physical interface names and logical interface 105# numbers match? 106# 107if_comp() 108{ 109 physical_comp $1 $2 && [ `get_logical $1` -eq `get_logical $2` ] 110} 111 112# 113# physical_comp if1 if2 114# 115# Do the two interfaces share a physical interface? 116# 117physical_comp() 118{ 119 [ "`get_physical $1`" = "`get_physical $2`" ] 120} 121 122# 123# in_list op item list 124# 125# Is "item" in the given list? Use "op" to do the test, applying it to 126# "item" and each member of the list in turn until it returns success. 127# 128in_list() 129{ 130 op=$1 131 item=$2 132 shift 2 133 134 while [ $# -gt 0 ]; do 135 $op $item $1 && return 0 136 shift 137 done 138 139 return 1 140} 141 142# 143# get_groupifname groupname 144# 145# Return the IPMP meta-interface name for the group, if it exists. 146# 147get_groupifname() 148{ 149 /sbin/ipmpstat -gP -o groupname,group | while IFS=: read name ifname; do 150 if [ "$name" = "$1" ]; then 151 echo "$ifname" 152 return 153 fi 154 done 155} 156 157# 158# create_ipmp ifname groupname type 159# 160# Helper function for create_groupifname() that returns zero if it's able 161# to create an IPMP interface of the specified type and place it in the 162# specified group, or non-zero otherwise. 163# 164create_ipmp() 165{ 166 /sbin/ifconfig $1 >/dev/null 2>&1 && return 1 167 /sbin/ifconfig $1 inet6 >/dev/null 2>&1 && return 1 168 /sbin/ifconfig $1 $3 ipmp group $2 2>/dev/null 169} 170 171# 172# create_groupifname groupname type 173# 174# Create an IPMP meta-interface name for the group. We only use this 175# function if all of the interfaces in the group failed at boot and there 176# were no /etc/hostname[6].<if> files for the IPMP meta-interface. 177# 178create_groupifname() 179{ 180 # 181 # This is a horrible way to count from 0 to 999, but in sh and 182 # without necessarily having /usr mounted, what else can we do? 183 # 184 for a in "" 1 2 3 4 5 6 7 8 9; do 185 for b in 0 1 2 3 4 5 6 7 8 9; do 186 for c in 0 1 2 3 4 5 6 7 8 9; do 187 # strip leading zeroes 188 [ "$a" = "" ] && [ "$b" = 0 ] && b="" 189 if create_ipmp ipmp$a$b$c $1 $2; then 190 echo ipmp$a$b$c 191 return 192 fi 193 done 194 done 195 done 196} 197 198# 199# get_hostname_ipmpinfo interface type 200# 201# Return all requested IPMP keywords from hostname file for a given interface. 202# 203# Example: 204# get_hostname_ipmpinfo hme0 inet keyword [ keyword ... ] 205# 206get_hostname_ipmpinfo() 207{ 208 case "$2" in 209 inet) file=/etc/hostname.$1 210 ;; 211 inet6) file=/etc/hostname6.$1 212 ;; 213 *) 214 return 215 ;; 216 esac 217 218 [ -r "$file" ] || return 219 220 type=$2 221 shift 2 222 223 # 224 # Read through the hostname file looking for the specified 225 # keywords. Since there may be several keywords that cancel 226 # each other out, the caller must post-process as appropriate. 227 # 228 while read line; do 229 [ -z "$line" ] && continue 230 /sbin/ifparse -s "$type" $line 231 done < "$file" | while read one two; do 232 for keyword in "$@"; do 233 [ "$one" = "$keyword" ] && echo "$one $two" 234 done 235 done 236} 237 238# 239# get_group_for_type interface type list 240# 241# Look through the set of hostname files associated with the same physical 242# interface as "interface", and determine which group they would configure. 243# Only hostname files associated with the physical interface or logical 244# interface zero are allowed to set the group. 245# 246get_group_for_type() 247{ 248 physical=`get_physical $1` 249 type=$2 250 group="" 251 252 # 253 # The last setting of the group is the one that counts, which is 254 # the reason for the second while loop. 255 # 256 shift 2 257 for ifname in "$@"; do 258 if if_comp "$physical" $ifname; then 259 get_hostname_ipmpinfo $ifname $type group 260 fi 261 done | while :; do 262 read keyword grname || { 263 echo "$group" 264 break 265 } 266 group="$grname" 267 done 268} 269 270# 271# get_group interface 272# 273# If there is both an inet and inet6 version of an interface, the group 274# could be set in either set of hostname files. Since inet6 is configured 275# after inet, if there's a setting in both files, inet6 wins. 276# 277get_group() 278{ 279 group=`get_group_for_type $1 inet6 $inet6_list` 280 [ -z "$group" ] && group=`get_group_for_type $1 inet $inet_list` 281 echo $group 282} 283 284# 285# Given the interface name and the address family (inet or inet6), determine 286# whether this is a VRRP VNIC. 287# 288# This is used to determine whether to bring the interface up 289# 290not_vrrp_interface() { 291 macaddrtype=`/sbin/dladm show-vnic $1 -o MACADDRTYPE -p 2>/dev/null` 292 293 case "$macaddrtype" in 294 'vrrp'*''$2'') vrrp=1 295 ;; 296 *) vrrp=0 297 ;; 298 esac 299 return $vrrp 300} 301 302# doDHCPhostname interface 303# Pass to this function the name of an interface. It will return 304# true if one should enable the use of DHCP client-side host name 305# requests on the interface, and false otherwise. 306# 307doDHCPhostname() 308{ 309 if [ -f /etc/dhcp.$1 ] && [ -f /etc/hostname.$1 ]; then 310 set -- `shcat /etc/hostname.$1` 311 [ $# -eq 2 -a "$1" = "inet" ] 312 return $? 313 fi 314 return 1 315} 316 317# 318# inet_process_hostname processor [ args ] 319# 320# Process an inet hostname file. The contents of the file 321# are taken from standard input. Each line is passed 322# on the command line to the "processor" command. 323# Command line arguments can be passed to the processor. 324# 325# Examples: 326# inet_process_hostname /sbin/ifconfig hme0 < /etc/hostname.hme0 327# 328# inet_process_hostname /sbin/ifparse -f < /etc/hostname.hme0 329# 330# If there is only line in an hostname file we assume it contains 331# the old style address which results in the interface being brought up 332# and the netmask and broadcast address being set ($inet_oneline_epilogue). 333# 334# Note that if the interface is a VRRP interface, do not bring the address 335# up ($inet_oneline_epilogue_no_up). 336# 337# If there are multiple lines we assume the file contains a list of 338# commands to the processor with neither the implied bringing up of the 339# interface nor the setting of the default netmask and broadcast address. 340# 341# Return non-zero if any command fails so that the caller may alert 342# users to errors in the configuration. 343# 344inet_oneline_epilogue_no_up="netmask + broadcast +" 345inet_oneline_epilogue="netmask + broadcast + up" 346 347inet_process_hostname() 348{ 349 if doDHCPhostname $2; then 350 : 351 else 352 # 353 # Redirecting input from a file results in a sub-shell being 354 # used, hence this outer loop surrounding the "multiple_lines" 355 # and "ifcmds" variables. 356 # 357 while :; do 358 multiple_lines=false 359 ifcmds="" 360 retval=0 361 362 while read one rest; do 363 if [ -n "$ifcmds" ]; then 364 # 365 # This handles the first N-1 366 # lines of a N-line hostname file. 367 # 368 $* $ifcmds || retval=$? 369 multiple_lines=true 370 fi 371 372 # 373 # Strip out the "ipmp" keyword if it's the 374 # first token, since it's used to control 375 # interface creation, not configuration. 376 # 377 [ "$one" = ipmp ] && one= 378 ifcmds="$one $rest" 379 done 380 381 # 382 # If the hostname file is empty or consists of only 383 # blank lines, break out of the outer loop without 384 # configuring the newly plumbed interface. 385 # 386 [ -z "$ifcmds" ] && return $retval 387 if [ $multiple_lines = false ]; then 388 # 389 # The traditional one-line hostname file. 390 # Note that we only bring it up if the 391 # interface is not a VRRP VNIC. 392 # 393 if not_vrrp_interface $2 $3; then 394 estr="$inet_oneline_epilogue" 395 else 396 estr="$inet_oneline_epilogue_no_up" 397 fi 398 ifcmds="$ifcmds $estr" 399 fi 400 401 # 402 # This handles either the single-line case or 403 # the last line of the N-line case. 404 # 405 $* $ifcmds || return $? 406 return $retval 407 done 408 fi 409} 410 411# 412# inet6_process_hostname processor [ args ] 413# 414# Process an inet6 hostname file. The contents of the file 415# are taken from standard input. Each line is passed 416# on the command line to the "processor" command. 417# Command line arguments can be passed to the processor. 418# 419# Examples: 420# inet6_process_hostname /sbin/ifconfig hme0 inet6 < /etc/hostname6.hme0 421# 422# inet6_process_hostname /sbin/ifparse -f inet6 < /etc/hostname6.hme0 423# 424# Return non-zero if any of the commands fail so that the caller may alert 425# users to errors in the configuration. 426# 427inet6_process_hostname() 428{ 429 retval=0 430 while read one rest; do 431 # 432 # See comment in inet_process_hostname for details. 433 # 434 [ "$one" = ipmp ] && one= 435 ifcmds="$one $rest" 436 437 if [ -n "$ifcmds" ]; then 438 $* $ifcmds || retval=$? 439 fi 440 done 441 return $retval 442} 443 444# 445# Process interfaces that failed to plumb. Find the IPMP meta-interface 446# that should host the addresses. For IPv6, only static addresses defined 447# in hostname6 files are moved, autoconfigured addresses are not moved. 448# 449# Example: 450# move_addresses inet6 451# 452move_addresses() 453{ 454 type="$1" 455 eval "failed=\"\$${type}_failed\"" 456 eval "list=\"\$${type}_list\"" 457 process_func="${type}_process_hostname" 458 processed="" 459 460 if [ "$type" = inet ]; then 461 typedesc="IPv4" 462 zaddr="0.0.0.0" 463 hostpfx="/etc/hostname" 464 else 465 typedesc="IPv6" 466 zaddr="::" 467 hostpfx="/etc/hostname6" 468 fi 469 470 echo "Moving addresses from missing ${typedesc} interface(s):\c" \ 471 >/dev/msglog 472 473 for ifname in $failed; do 474 in_list if_comp $ifname $processed && continue 475 476 group=`get_group $ifname` 477 if [ -z "$group" ]; then 478 in_list physical_comp $ifname $processed || { 479 echo " $ifname (not moved -- not" \ 480 "in an IPMP group)\c" >/dev/msglog 481 processed="$processed $ifname" 482 } 483 continue 484 fi 485 486 # 487 # Lookup the IPMP meta-interface name. If one doesn't exist, 488 # create it. 489 # 490 grifname=`get_groupifname $group` 491 [ -z "$grifname" ] && grifname=`create_groupifname $group $type` 492 493 # 494 # The hostname files are processed twice. In the first 495 # pass, we are looking for all commands that apply to the 496 # non-additional interface address. These may be 497 # scattered over several files. We won't know whether the 498 # address represents a failover address or not until we've 499 # read all the files associated with the interface. 500 # 501 # In the first pass through the hostname files, all 502 # additional logical interface commands are removed. The 503 # remaining commands are concatenated together and passed 504 # to ifparse to determine whether the non-additional 505 # logical interface address is a failover address. If it 506 # as a failover address, the address may not be the first 507 # item on the line, so we can't just substitute "addif" 508 # for "set". We prepend an "addif $zaddr" command, and 509 # let the embedded "set" command set the address later. 510 # 511 /sbin/ifparse -f $type ` 512 for item in $list; do 513 if_comp $ifname $item && $process_func \ 514 /sbin/ifparse $type < $hostpfx.$item 515 done | while read three four; do 516 [ "$three" != addif ] && echo "$three $four \c" 517 done` | while read one two; do 518 [ -z "$one" ] && continue 519 [ "$one $two" = "$inet_oneline_epilogue" ] && \ 520 continue 521 line="addif $zaddr $one $two" 522 /sbin/ifconfig $grifname $type $line >/dev/null 523 done 524 525 # 526 # In the second pass, look for the the "addif" commands 527 # that configure additional failover addresses. Addif 528 # commands are not valid in logical interface hostname 529 # files. 530 # 531 if [ "$ifname" = "`get_physical $ifname`" ]; then 532 $process_func /sbin/ifparse -f $type < $hostpfx.$ifname \ 533 | while read one two; do 534 [ "$one" = addif ] && \ 535 /sbin/ifconfig $grifname $type \ 536 addif $two >/dev/null 537 done 538 fi 539 540 in_list physical_comp $ifname $processed || { 541 processed="$processed $ifname" 542 echo " $ifname (moved to $grifname)\c" > /dev/msglog 543 } 544 done 545 echo "." >/dev/msglog 546} 547 548# 549# ipadm_from_gz_if ifname 550# 551# Return true if we are in a non-global zone and Layer-3 protection of 552# IP addresses is being enforced on the interface by the global zone 553# 554ipadm_from_gz_if() 555{ 556 pif=`/sbin/ipadm show-if -o persistent -p $1 2>/dev/null | egrep '4|6'` 557 if smf_is_globalzone || ![[ $pif == *4* || $pif == *6* ]]; then 558 return 1 559 else 560 # 561 # In the non-global zone, plumb the interface to show current 562 # flags and check if Layer-3 protection has been enforced by 563 # the global zone. Note that this function may return 564 # with a plumbed interface. Ideally, we would not have to 565 # plumb the interface to check l3protect, but since we 566 # the `allowed-ips' datalink property cannot currently be 567 # examined in any other way from the non-global zone, we 568 # resort to plumbing the interface 569 # 570 /sbin/ifconfig $1 plumb > /dev/null 2>&1 571 l3protect=`/sbin/ipadm show-if -o current -p $1|grep -c 'Z'` 572 if [ $l3protect = 0 ]; then 573 return 1 574 else 575 return 0 576 fi 577 fi 578} 579 580# 581# if_configure type class interface_list 582# 583# Configure all of the interfaces of type `type' (e.g., "inet6") in 584# `interface_list' according to their /etc/hostname[6].* files. `class' 585# describes the class of interface (e.g., "IPMP"), as a diagnostic aid. 586# For inet6 interfaces, the interface is also brought up. 587# 588if_configure() 589{ 590 fail= 591 type=$1 592 class=$2 593 process_func=${type}_process_hostname 594 shift 2 595 596 if [ "$type" = inet ]; then 597 desc="IPv4" 598 hostpfx="/etc/hostname" 599 else 600 desc="IPv6" 601 hostpfx="/etc/hostname6" 602 fi 603 [ -n "$class" ] && desc="$class $desc" 604 605 echo "configuring $desc interfaces:\c" 606 while [ $# -gt 0 ]; do 607 $process_func /sbin/ifconfig $1 $type < $hostpfx.$1 >/dev/null 608 if [ $? != 0 ]; then 609 ipadm_from_gz_if $1 610 if [ $? != 0 ]; then 611 fail="$fail $1" 612 fi 613 elif [ "$type" = inet6 ]; then 614 # 615 # only bring the interface up if it is not a 616 # VRRP VNIC 617 # 618 if not_vrrp_interface $1 $type; then 619 /sbin/ifconfig $1 inet6 up || fail="$fail $1" 620 fi 621 fi 622 echo " $1\c" 623 shift 624 done 625 echo "." 626 627 [ -n "$fail" ] && warn_failed_ifs "configure $desc" "$fail" 628} 629 630# 631# net_reconfigure is called from the network/physical service (by the 632# net-physical and net-nwam method scripts) to perform tasks that only 633# need to be done during a reconfigure boot. This needs to be 634# isolated in a function since network/physical has two instances 635# (default and nwam) that have distinct method scripts that each need 636# to do these things. 637# 638net_reconfigure () 639{ 640 # 641 # Is this a reconfigure boot? If not, then there's nothing 642 # for us to do. 643 # 644 reconfig=`svcprop -c -p system/reconfigure \ 645 system/svc/restarter:default 2>/dev/null` 646 if [ $? -ne 0 -o "$reconfig" = false ]; then 647 return 0 648 fi 649 650 # 651 # Ensure that the datalink-management service is running since 652 # manifest-import has not yet run for a first boot after 653 # upgrade. We wouldn't need to do that if manifest-import ran 654 # earlier in boot, since there is an explicit dependency 655 # between datalink-management and network/physical. 656 # 657 svcadm enable -ts network/datalink-management:default 658 659 # 660 # There is a bug in SMF which causes the svcadm command above 661 # to exit prematurely (with an error code of 3) before having 662 # waited for the service to come online after having enabled 663 # it. Until that bug is fixed, we need to have the following 664 # loop to explicitly wait for the service to come online. 665 # 666 i=0 667 while [ $i -lt 30 ]; do 668 i=`expr $i + 1` 669 sleep 1 670 state=`svcprop -p restarter/state \ 671 network/datalink-management:default 2>/dev/null` 672 if [ $? -ne 0 ]; then 673 continue 674 elif [ "$state" = "online" ]; then 675 break 676 fi 677 done 678 if [ "$state" != "online" ]; then 679 echo "The network/datalink-management service \c" 680 echo "did not come online." 681 return 1 682 fi 683 684 # 685 # Initialize the set of physical links, and validate and 686 # remove all the physical links which were removed during the 687 # system shutdown. 688 # 689 /sbin/dladm init-phys 690 return 0 691} 692 693# 694# Check for use of the default "Port VLAN Identifier" (PVID) -- VLAN 1. 695# If there is one for a given interface, then warn the user and force the 696# PVID to zero (if it's not already set). We do this by generating a list 697# of interfaces with VLAN 1 in use first, and then parsing out the 698# corresponding base datalink entries to check for ones without a 699# "default_tag" property. 700# 701update_pvid() 702{ 703 datalink=/etc/dladm/datalink.conf 704 705 ( 706 # Find datalinks using VLAN 1 explicitly 707 # configured by dladm 708 /usr/bin/nawk ' 709 /^#/ || NF < 2 { next } 710 { linkdata[$1]=$2; } 711 /;vid=int,1;/ { 712 sub(/.*;linkover=int,/, "", $2); 713 sub(/;.*/, "", $2); 714 link=linkdata[$2]; 715 sub(/name=string,/, "", link); 716 sub(/;.*/, "", link); 717 print link; 718 }' $datalink 719 ) | ( /usr/bin/sort -u; echo END; cat $datalink ) | /usr/bin/nawk ' 720 /^END$/ { state=1; } 721 state == 0 { usingpvid[++nusingpvid]=$1; next; } 722 /^#/ || NF < 2 { next; } 723 { 724 # If it is already present and has a tag set, 725 # then believe it. 726 if (!match($2, /;default_tag=/)) 727 next; 728 sub(/name=string,/, "", $2); 729 sub(/;.*/, "", $2); 730 for (i = 1; i <= nusingpvid; i++) { 731 if (usingpvid[i] == $2) 732 usingpvid[i]=""; 733 } 734 } 735 END { 736 for (i = 1; i <= nusingpvid; i++) { 737 if (usingpvid[i] != "") { 738 printf("Warning: default VLAN tag set to 0" \ 739 " on %s\n", usingpvid[i]); 740 cmd=sprintf("dladm set-linkprop -p " \ 741 "default_tag=0 %s\n", usingpvid[i]); 742 system(cmd); 743 } 744 } 745 }' 746} 747 748# 749# service_exists fmri 750# 751# returns success (0) if the service exists, 1 otherwise. 752# 753service_exists() 754{ 755 /usr/sbin/svccfg -s $1 listpg > /dev/null 2>&1 756 if [ $? -eq 0 ]; then 757 return 0; 758 fi 759 return 1; 760} 761 762# 763# service_is_enabled fmri 764# 765# returns success (0) if the service is enabled (permanently or 766# temporarily), 1 otherwise. 767# 768service_is_enabled() 769{ 770 # 771 # The -c option must be specified to use the composed view 772 # because the general/enabled property takes immediate effect. 773 # See Example 2 in svcprop(1). 774 # 775 # Look at the general_ovr/enabled (if it is present) first to 776 # determine the temporarily enabled state. 777 # 778 tstate=`/usr/bin/svcprop -c -p general_ovr/enabled $1 2>/dev/null` 779 if [ $? -eq 0 ]; then 780 [ "$tstate" = "true" ] && return 0 781 return 1 782 fi 783 784 state=`/usr/bin/svcprop -c -p general/enabled $1 2>/dev/null` 785 [ "$state" = "true" ] && return 0 786 return 1 787} 788 789# 790# is_valid_v4addr addr 791# 792# Returns 0 if a valid IPv4 address is given, 1 otherwise. 793# 794is_valid_v4addr() 795{ 796 echo $1 | /usr/xpg4/bin/awk 'NF != 1 { exit 1 } \ 797 $1 !~ /^((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}\ 798 (25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/ \ 799 { exit 1 }' 800 return $? 801} 802 803# 804# is_valid_v6addr addr 805# 806# Returns 0 if a valid IPv6 address is given, 1 otherwise. 807# 808is_valid_v6addr() 809{ 810 echo $1 | /usr/xpg4/bin/awk 'NF != 1 { exit 1 } \ 811 # 1:2:3:4:5:6:7:8 812 $1 !~ /^([a-fA-F0-9]{1,4}:){7}[a-fA-F0-9]{1,4}$/ && 813 # 1:2:3::6:7:8 814 $1 !~ /^([a-fA-F0-9]{1,4}:){0,6}:([a-fA-F0-9]{1,4}:){0,6}\ 815 [a-fA-F0-9]{1,4}$/ && 816 # 1:2:3:: 817 $1 !~ /^([a-fA-F0-9]{1,4}:){0,7}:$/ && 818 # ::7:8 819 $1 !~ /^:(:[a-fA-F0-9]{1,4}){0,6}:[a-fA-F0-9]{1,4}$/ && 820 # ::f:1.2.3.4 821 $1 !~ /^:(:[a-fA-F0-9]{1,4}){0,5}:\ 822 ((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}\ 823 (25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/ && 824 # a:b:c:d:e:f:1.2.3.4 825 $1 !~ /^([a-fA-F0-9]{1,4}:){6}\ 826 ((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}\ 827 (25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/ \ 828 { exit 1 }' 829 return $? 830} 831 832# 833# is_valid_addr addr 834# 835# Returns 0 if a valid IPv4 or IPv6 address is given, 1 otherwise. 836# 837is_valid_addr() 838{ 839 is_valid_v4addr $1 || is_valid_v6addr $1 840} 841 842# 843# nwam_get_loc_prop location property 844# 845# echoes the value of the property for the given location 846# return: 847# 0 => property is set 848# 1 => property is not set 849# 850nwam_get_loc_prop() 851{ 852 value=`/usr/sbin/nwamcfg "select loc $1; get -V $2" 2>/dev/null` 853 rtn=$? 854 echo $value 855 return $rtn 856} 857