diff options
author | hrs <hrs@FreeBSD.org> | 2011-06-05 12:27:34 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2011-06-05 12:27:34 +0000 |
commit | 8ff65f2104c6b6188f7a86fc8b074b5d9d8cf576 (patch) | |
tree | be9323d9ac7dde0b1af11cdbcfae206542a1c222 /usr.sbin | |
parent | ecae8238dfcc956729cb43702018343ad85e6ba4 (diff) | |
parent | 58bf7d3104c5e5f32bfd96ca36c8551c7d94fa53 (diff) | |
download | FreeBSD-src-8ff65f2104c6b6188f7a86fc8b074b5d9d8cf576.zip FreeBSD-src-8ff65f2104c6b6188f7a86fc8b074b5d9d8cf576.tar.gz |
Merge from HEAD@222712.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/bsdinstall/scripts/Makefile | 3 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/auto | 2 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/netconfig | 168 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/netconfig_ipv4 | 85 | ||||
-rwxr-xr-x | usr.sbin/bsdinstall/scripts/netconfig_ipv6 | 149 | ||||
-rw-r--r-- | usr.sbin/jail/Makefile | 3 | ||||
-rw-r--r-- | usr.sbin/jail/jail.c | 76 | ||||
-rw-r--r-- | usr.sbin/jls/Makefile | 9 | ||||
-rw-r--r-- | usr.sbin/jls/jls.c | 76 | ||||
-rw-r--r-- | usr.sbin/kbdmap/kbdmap.c | 2 | ||||
-rw-r--r-- | usr.sbin/mfiutil/mfi_evt.c | 8 | ||||
-rw-r--r-- | usr.sbin/mountd/mountd.c | 243 | ||||
-rwxr-xr-x | usr.sbin/pc-sysinstall/backend-query/enable-net.sh | 57 | ||||
-rwxr-xr-x | usr.sbin/pc-sysinstall/backend-query/test-netup.sh | 25 | ||||
-rwxr-xr-x | usr.sbin/pc-sysinstall/backend/functions-networking.sh | 195 | ||||
-rw-r--r-- | usr.sbin/rpc.lockd/lockd.c | 249 | ||||
-rw-r--r-- | usr.sbin/rpc.statd/statd.c | 240 | ||||
-rw-r--r-- | usr.sbin/rtsold/rtsol.c | 2 | ||||
-rw-r--r-- | usr.sbin/usbdump/usbdump.8 | 8 |
19 files changed, 1376 insertions, 224 deletions
diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile index 8ad6744..e32fda6 100644 --- a/usr.sbin/bsdinstall/scripts/Makefile +++ b/usr.sbin/bsdinstall/scripts/Makefile @@ -1,7 +1,8 @@ # $FreeBSD$ SCRIPTS= auto adduser checksum config hostname jail keymap mirrorselect \ - mount netconfig rootpass services time umount wlanconfig + mount netconfig netconfig_ipv4 netconfig_ipv6 rootpass services \ + time umount wlanconfig BINDIR= /usr/libexec/bsdinstall NO_MAN= true diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto index 6a0e9b5..bdc5fc4 100755 --- a/usr.sbin/bsdinstall/scripts/auto +++ b/usr.sbin/bsdinstall/scripts/auto @@ -199,7 +199,7 @@ finalconfig() { clear echo This shell is operating in a chroot in the new system. \ When finished making configuration changes, type \"exit\". - chroot "$BSDINSTALL_CHROOT" /bin/sh + chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1 # Don't hose local rc.conf changes cp $BSDINSTALL_CHROOT/etc/rc.conf $BSDINSTALL_TMPETC/rc.conf.manual finalconfig diff --git a/usr.sbin/bsdinstall/scripts/netconfig b/usr.sbin/bsdinstall/scripts/netconfig index 0374d12..b78e330 100755 --- a/usr.sbin/bsdinstall/scripts/netconfig +++ b/usr.sbin/bsdinstall/scripts/netconfig @@ -2,6 +2,11 @@ #- # Copyright (c) 2011 Nathan Whitehorn # All rights reserved. +# Copyright (c) 2011 The FreeBSD Foundation +# All rights reserved. +# +# Portions of this software were developed by Bjoern Zeeb +# under sponsorship from the FreeBSD Foundation. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -36,8 +41,6 @@ DIALOG_TAGS="" : ${DIALOG_ITEM_HELP=4} : ${DIALOG_ESC=255} -echo -n > $BSDINSTALL_TMPETC/rc.conf.net - for IF in `ifconfig -l`; do test "$IF" = "lo0" && continue (ifconfig -g wlan | egrep -wq $IF) && continue @@ -51,12 +54,14 @@ INTERFACE=`echo $DIALOG_TAGS | xargs dialog --backtitle 'FreeBSD Installer' --ti if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi exec 3>&- +: > $BSDINSTALL_TMPETC/._rc.conf.net + # Do a dirty check to see if this a wireless interface -- there should be a # better way IFCONFIG_PREFIX="" if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then NEXT_WLAN_IFACE=wlan0 # XXX - echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/rc.conf.net + echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/._rc.conf.net IFCONFIG_PREFIX="WPA " if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then ifconfig $NEXT_WLAN_IFACE create wlandev $INTERFACE @@ -66,56 +71,129 @@ if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then INTERFACE="$NEXT_WLAN_IFACE" fi -dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0 -if [ $? -eq $DIALOG_OK ]; then - echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/rc.conf.net +IPV6_AVAIL=0 +IPV4_AVAIL=0 +sysctl -N kern.features.inet6 > /dev/null 2>&1 +case $? in +0) IPV6_AVAIL=1 ;; +esac +sysctl -N kern.features.inet > /dev/null 2>&1 +case $? in +0) IPV4_AVAIL=1 ;; +esac - if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then - dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0 - dhclient $INTERFACE 2>> $BSDINSTALL_LOG - if [ $? -ne 0 ]; then - dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0 - exec $0 - fi +if [ ${IPV4_AVAIL} -eq 1 ]; then + dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ + --yesno 'Would you like to configure IPv4 for this interface?' 0 0 + if [ $? -eq $DIALOG_OK ]; then + bsdinstall netconfig_ipv4 ${INTERFACE} "${IFCONFIG_PREFIX}" || \ + exec $0 + else + IPV4_AVAIL=0 + fi +fi +# In case wlanconfig left an option and we do not support IPv4 we need to write +# it out on its own. We cannot write it out with IPv6 as that suffix. +if [ ${IPV4_AVAIL} -eq 0 -a -n ${IFCONFIG_PREFIX} ]; then + echo ifconfig_${INTERFACE}=\"${IFCONFIG_PREFIX}\" >> $BSDINSTALL_TMPETC/._rc.conf.net +fi +if [ ${IPV6_AVAIL} -eq 1 ]; then + dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ + --yesno 'Would you like to configure IPv6 for this interface?' 0 0 + if [ $? -eq $DIALOG_OK ]; then + bsdinstall netconfig_ipv6 ${INTERFACE} || exec $0 + else + IPV6_AVAIL=0 fi - exit 0 fi -IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'` -NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'` -ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'` +SEARCH="" +IP4_1="" +IP4_2="" +IP6_1="" +IP6_2="" +while read key value; do + case "${key}" in + search) SEARCH="${value}" ;; + nameserver) # is more trick as we have to distinguish v4 and v6 + case "${value}" in + [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*) + if [ -z "${IP4_1}" ] ; then + IP4_1="${value}" + elif [ -z "${IP4_2}" ]; then + IP4_2="${value}" + fi + ;; + [0-9A-Fa-f:]*:*) + if [ -z "${IP6_1}" ] ; then + IP6_1="${value}" + elif [ -z "${IP6_2}" ]; then + IP6_2="${value}" + fi + ;; + esac + ;; + # ignore others + esac +done < ${BSDINSTALL_TMPETC}/resolv.conf + +RESOLV="" +if [ ${IPV6_AVAIL} -eq 1 -a ${IPV4_AVAIL} -eq 1 ]; then + RESOLV=" + 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0 + 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2 + 'IPv6 DNS #1' 2 0 \"${IP6_1}\" 2 16 50 0 0 + 'IPv6 DNS #2' 3 0 \"${IP6_2}\" 3 16 50 0 0 + 'IPv4 DNS #1' 4 0 \"${IP4_1}\" 4 16 16 0 0 + 'IPv4 DNS #2' 5 0 \"${IP4_2}\" 5 16 16 0 0" +elif [ ${IPV6_AVAIL} -eq 1 ]; then + RESOLV=" + 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0 + 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2 + 'IPv6 DNS #1' 2 0 \"${IP6_1}\" 2 16 50 0 0 + 'IPv6 DNS #2' 3 0 \"${IP6_2}\" 3 16 50 0 0" +elif [ ${IPV4_AVAIL} -eq 1 ]; then + RESOLV=" + 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0 + 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2 + 'IPv4 DNS #1' 2 0 \"${IP4_1}\" 2 16 16 0 0 + 'IPv4 DNS #2' 3 0 \"${IP4_2}\" 3 16 16 0 0" +else + exit 0 +fi exec 3>&1 -IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \ - 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \ - 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \ - 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \ - \ - 'Nameserver' 5 0 "" 5 20 16 0 \ - 'Search Domain' 6 0 "" 6 20 20 0 \ +RESOLV=$(echo "${RESOLV}" | xargs dialog --backtitle 'FreeBSD Installer' \ + --title 'Network Configuration' \ + --mixedform 'Resovler Configuration' 0 0 0 \ 2>&1 1>&3) if [ $? -eq $DIALOG_CANCEL ]; then exec $0; fi exec 3>&- -echo $INTERFACE $IF_CONFIG | - awk -v prefix="$IFCONFIG_PREFIX" '{ - printf("ifconfig_%s=\"%s%s netmask %s\"\n", $1, prefix, $2, $3); - printf("defaultrouter=\"%s\"\n", $4); - }' >> $BSDINSTALL_TMPETC/rc.conf.net - -if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then - . $BSDINSTALL_TMPETC/rc.conf.net - ifconfig $INTERFACE `eval echo \\\$ifconfig_$INTERFACE` - route delete default - route add default $defaultrouter -fi - - -echo $IF_CONFIG | - awk '{ - if ($4 != "") - printf("nameserver %s\n", $4); - if ($5 != "") - printf("search %s\n", $5); - }' > $BSDINSTALL_TMPETC/resolv.conf +echo ${RESOLV} | tr ' ' '\n' | \ +awk ' +BEGIN { + search=-1; +} +{ + if (/^[[:space:]]+$/) { + next; + } + if (/^Nameserver$/) { + printf "\n"; + search=0; + next; + } + if (search == -1) { + printf "search "; + search=1; + } + if (search > 0) { + printf "%s%s", (search > 1) ? " " : "", $1; + search++; + next; + } + printf "nameserver %s\n", $1; +}' > ${BSDINSTALL_TMPETC}/resolv.conf +mv $BSDINSTALL_TMPETC/._rc.conf.net $BSDINSTALL_TMPETC/rc.conf.net diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv4 b/usr.sbin/bsdinstall/scripts/netconfig_ipv4 new file mode 100755 index 0000000..72dc0ee --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv4 @@ -0,0 +1,85 @@ +#!/bin/sh +#- +# Copyright (c) 2011 Nathan Whitehorn +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +: ${DIALOG_OK=0} +: ${DIALOG_CANCEL=1} +: ${DIALOG_HELP=2} +: ${DIALOG_EXTRA=3} +: ${DIALOG_ITEM_HELP=4} +: ${DIALOG_ESC=255} + +INTERFACE=$1 +IFCONFIG_PREFIX="$2" +case "${INTERFACE}" in +"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ + --msgbox 'No interface specified for IPv4 configuration.' 0 0 + exit 1 + ;; +esac + +dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0 +if [ $? -eq $DIALOG_OK ]; then + echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/._rc.conf.net + + if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0 + dhclient $INTERFACE 2>> $BSDINSTALL_LOG + if [ $? -ne 0 ]; then + dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0 + exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}" + fi + fi + exit 0 +fi + +IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'` +NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'` +ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'` + +exec 3>&1 +IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \ + 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \ + 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \ + 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \ +2>&1 1>&3) +if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi +exec 3>&- + +echo $INTERFACE $IF_CONFIG | + awk -v prefix="$IFCONFIG_PREFIX" '{ + printf("ifconfig_%s=\"%s inet %s netmask %s\"\n", $1, prefix, $2, $3); + printf("defaultrouter=\"%s\"\n", $4); + }' >> $BSDINSTALL_TMPETC/._rc.conf.net + +if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + . $BSDINSTALL_TMPETC/._rc.conf.net + ifconfig $INTERFACE inet `eval echo \\\$ifconfig_$INTERFACE` + route delete -inet default + route add -inet default $defaultrouter +fi + diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv6 b/usr.sbin/bsdinstall/scripts/netconfig_ipv6 new file mode 100755 index 0000000..70bd203 --- /dev/null +++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv6 @@ -0,0 +1,149 @@ +#!/bin/sh +#- +# Copyright (c) 2011 Nathan Whitehorn +# All rights reserved. +# Copyright (c) 2011 The FreeBSD Foundation +# All rights reserved. +# +# Portions of this software were developed by Bjoern Zeeb +# under sponsorship from the FreeBSD Foundation. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +# +# TODO: +# - Add -R /sbin/resolvconf to rtsol once support is in tree. +# - Add DHCPv6 support once FreeBSD ships with it. +# + +: ${DIALOG_OK=0} +: ${DIALOG_CANCEL=1} +: ${DIALOG_HELP=2} +: ${DIALOG_EXTRA=3} +: ${DIALOG_ITEM_HELP=4} +: ${DIALOG_ESC=255} + +INTERFACE=$1 +case "${INTERFACE}" in +"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ + --msgbox 'No interface specified for IPv6 configuration.' 0 0 + exit 1 + ;; +esac + +AGAIN="" +while : ; do + MSG="Would you like to try stateless address autoconfiguration (SLAAC)${AGAIN}?" + dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \ + --yesno "${MSG}" 0 0 + if [ $? -eq $DIALOG_OK ]; then + if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + dialog --backtitle 'FreeBSD Installer' \ + --infobox "Sending Router Solicitation ..." 0 0 + ifconfig ${INTERFACE} inet6 -ifdisabled accept_rtadv up + rtsol -F $INTERFACE 2>> $BSDINSTALL_LOG + if [ $? -ne 0 ]; then + dialog --backtitle 'FreeBSD Installer' --msgbox "SLAAC failed." 0 0 + AGAIN=" again" + continue + fi + fi + echo ifconfig_${INTERFACE}_ipv6=\"inet6 accept_rtadv\" >> $BSDINSTALL_TMPETC/._rc.conf.net + exit 0 + else + break + fi +done + +ROUTER6=`netstat -Wrn -f inet6 | awk '/default/ {printf("%s\n", $2);}'` +ADDRS=`ifconfig ${INTERFACE} inet6 | \ +awk -v dfr="${ROUTER6}" ' +BEGIN { + n=0; +} +{ + if (/inet6/) { + if (match($2, "^fe80:")) { next; }; + # For the moment ignore all but the first address; it might confuse the user. + if (n > 0) { next; }; + n++; + printf "\"IPv6 Address\" %d 0 \"%s/%s\" %d 16 50 0 0 ", n, $2, $4, n; + } +} +END { + if (n == 0) { + n++; + printf "\"IPv6 Address\" %d 0 \"\" %d 16 50 0 0 ", n, n; + } + n++; + # Nasty trick adding a (hidden, same y) read-only field as a marker + # to separate interface address(es) from the default router. + printf "\"Default Router\" %d 0 \"%s\" %d 16 50 0 2 ", n, "DefaultRouter", n; + printf "\"Default Router\" %d 0 \"%s\" %d 16 50 0 0 ", n, dfr, n; +}'` + +exec 3>&1 +IF_CONFIG=$(echo ${ADDRS} | xargs dialog --backtitle 'FreeBSD Installer' \ + --title 'Network Configuration' \ + --mixedform 'Static IPv6 Network Interface Configuration' 0 0 0 \ +2>&1 1>&3) +if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi +exec 3>&- + +echo ${IF_CONFIG} | tr ' ' '\n' | \ +awk -v iface="${INTERFACE}" ' +BEGIN { + dfr=0; + count=0; +} +{ + if (/^[[:space:]]+$/) { + next; + } + if (/DefaultRouter/) { + dfr=1; + next; + } + if (dfr == 1) { + printf("ipv6_defaultrouter=\"%s\"\n", $1); + next; + } + if (count > 0) { + # Ignore all but the first IP address for now. + next; + } + count++; + if (!match($1, "/")) { + sub("$", "/64", $1); + } + printf("ifconfig_%s_ipv6=\"inet6 %s\"\n", iface, $1); +}' >> $BSDINSTALL_TMPETC/._rc.conf.net + +if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then + . $BSDINSTALL_TMPETC/._rc.conf.net + ifconfig ${INTERFACE} `eval echo \\\$ifconfig_${INTERFACE}_ipv6` + route delete default + route add default ${ipv6_defaultrouter} +fi + diff --git a/usr.sbin/jail/Makefile b/usr.sbin/jail/Makefile index de35dcf..52d237b 100644 --- a/usr.sbin/jail/Makefile +++ b/usr.sbin/jail/Makefile @@ -10,5 +10,8 @@ LDADD= -ljail -lutil .if ${MK_INET6_SUPPORT} != "no" CFLAGS+= -DINET6 .endif +.if ${MK_INET_SUPPORT} != "no" +CFLAGS+= -DINET +.endif .include <bsd.prog.mk> diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c index 0722bfd..fc4f71c 100644 --- a/usr.sbin/jail/jail.c +++ b/usr.sbin/jail/jail.c @@ -54,12 +54,18 @@ static struct jailparam *params; static char **param_values; static int nparams; -static char *ip4_addr; #ifdef INET6 +static int ip6_ok; static char *ip6_addr; #endif +#ifdef INET +static int ip4_ok; +static char *ip4_addr; +#endif +#if defined(INET6) || defined(INET) static void add_ip_addr(char **addrp, char *newaddr); +#endif #ifdef INET6 static void add_ip_addr46(char *newaddr); #endif @@ -194,6 +200,13 @@ main(int argc, char **argv) if (uflag) GET_USER_INFO; +#ifdef INET6 + ip6_ok = feature_present("inet6"); +#endif +#ifdef INET + ip4_ok = feature_present("inet"); +#endif + if (jailname) set_param("name", jailname); if (securelevel) @@ -207,10 +220,12 @@ main(int argc, char **argv) break; } if (hflag) { +#ifdef INET if (!strncmp(argv[i], "ip4.addr=", 9)) { add_ip_addr(&ip4_addr, argv[i] + 9); break; } +#endif #ifdef INET6 if (!strncmp(argv[i], "ip6.addr=", 9)) { add_ip_addr(&ip6_addr, argv[i] + 9); @@ -231,12 +246,14 @@ main(int argc, char **argv) set_param("host.hostname", argv[1]); if (hflag) add_ip_addrinfo(0, argv[1]); +#if defined(INET6) || defined(INET) if (argv[2][0] != '\0') #ifdef INET6 add_ip_addr46(argv[2]); #else add_ip_addr(&ip4_addr, argv[2]); #endif +#endif cmdarg = 3; /* Emulate the defaults from security.jail.* sysctls */ sysvallen = sizeof(sysval); @@ -259,8 +276,10 @@ main(int argc, char **argv) } } } +#ifdef INET if (ip4_addr != NULL) set_param("ip4.addr", ip4_addr); +#endif #ifdef INET6 if (ip6_addr != NULL) set_param("ip6.addr", ip6_addr); @@ -297,14 +316,19 @@ main(int argc, char **argv) for (i = 0; i < nparams; i++) if (!strcmp(params[i].jp_name, "path")) break; -#ifdef INET6 +#if defined(INET6) && defined(INET) fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n", jid, i < nparams ? (char *)params[i].jp_value : argv[0], argv[1], ip4_addr ? ip4_addr : "", ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0] ? "," : "", ip6_addr ? ip6_addr : "", argv[3]); -#else +#elif defined(INET6) + fprintf(fp, "%d\t%s\t%s\t%s\t%s\n", + jid, i < nparams + ? (char *)params[i].jp_value : argv[0], + argv[1], ip6_addr ? ip6_addr : "", argv[3]); +#elif defined(INET) fprintf(fp, "%d\t%s\t%s\t%s\t%s\n", jid, i < nparams ? (char *)params[i].jp_value : argv[0], @@ -348,6 +372,7 @@ main(int argc, char **argv) err(1, "execvp: %s", argv[cmdarg]); } +#if defined(INET6) || defined(INET) static void add_ip_addr(char **addrp, char *value) { @@ -368,6 +393,7 @@ add_ip_addr(char **addrp, char *value) *addrp = addr; } } +#endif #ifdef INET6 static void @@ -391,23 +417,24 @@ static void add_ip_addrinfo(int ai_flags, char *value) { struct addrinfo hints, *ai0, *ai; - struct in_addr addr4; - size_t size; - int error, ip4ok; - int mib[4]; + int error; +#ifdef INET char avalue4[INET_ADDRSTRLEN]; + struct in_addr addr4; +#endif #ifdef INET6 - struct in6_addr addr6; - int ip6ok; char avalue6[INET6_ADDRSTRLEN]; + struct in6_addr addr6; #endif /* Look up the hostname (or get the address) */ memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; -#ifdef INET6 +#if defined(INET6) && defined(INET) hints.ai_family = PF_UNSPEC; -#else +#elif defined(INET6) + hints.ai_family = PF_INET6; +#elif defined(INET) hints.ai_family = PF_INET; #endif hints.ai_flags = ai_flags; @@ -415,32 +442,12 @@ add_ip_addrinfo(int ai_flags, char *value) if (error != 0) errx(1, "hostname %s: %s", value, gai_strerror(error)); - /* - * Silently ignore unsupported address families from DNS lookups. - * But if this is a numeric address, let the kernel give the error. - */ - if (ai_flags & AI_NUMERICHOST) - ip4ok = -#ifdef INET6 - ip6ok = -#endif - 1; - else { - size = 4; - ip4ok = (sysctlnametomib("security.jail.param.ip4", mib, - &size) == 0); -#ifdef INET6 - size = 4; - ip6ok = (sysctlnametomib("security.jail.param.ip6", mib, - &size) == 0); -#endif - } - /* Convert the addresses to ASCII so set_param can convert them back. */ for (ai = ai0; ai; ai = ai->ai_next) switch (ai->ai_family) { +#ifdef INET case AF_INET: - if (!ip4ok) + if (!ip4_ok && (ai_flags & AI_NUMERICHOST) == 0) break; memcpy(&addr4, &((struct sockaddr_in *) (void *)ai->ai_addr)->sin_addr, sizeof(addr4)); @@ -449,9 +456,10 @@ add_ip_addrinfo(int ai_flags, char *value) err(1, "inet_ntop"); add_ip_addr(&ip4_addr, avalue4); break; +#endif #ifdef INET6 case AF_INET6: - if (!ip6ok) + if (!ip6_ok && (ai_flags & AI_NUMERICHOST) == 0) break; memcpy(&addr6, &((struct sockaddr_in6 *) (void *)ai->ai_addr)->sin6_addr, sizeof(addr6)); diff --git a/usr.sbin/jls/Makefile b/usr.sbin/jls/Makefile index e1157af..b297cc4 100644 --- a/usr.sbin/jls/Makefile +++ b/usr.sbin/jls/Makefile @@ -1,8 +1,17 @@ # $FreeBSD$ +.include <bsd.own.mk> + PROG= jls MAN= jls.8 DPADD= ${LIBJAIL} LDADD= -ljail +.if ${MK_INET6_SUPPORT} != "no" +CFLAGS+= -DINET6 +.endif +.if ${MK_INET_SUPPORT} != "no" +CFLAGS+= -DINET +.endif + .include <bsd.prog.mk> diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c index 2c1655b..14aa6af 100644 --- a/usr.sbin/jls/jls.c +++ b/usr.sbin/jls/jls.c @@ -59,6 +59,12 @@ __FBSDID("$FreeBSD$"); static struct jailparam *params; static int *param_parent; static int nparams; +#ifdef INET6 +static int ip6_ok; +#endif +#ifdef INET +static int ip4_ok; +#endif static int add_param(const char *name, void *value, size_t valuelen, struct jailparam *source, unsigned flags); @@ -112,6 +118,13 @@ main(int argc, char **argv) errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]"); } +#ifdef INET6 + ip6_ok = feature_present("inet6"); +#endif +#ifdef INET + ip4_ok = feature_present("inet"); +#endif + /* Add the parameters to print. */ if (optind == argc) { if (pflags & (PRINT_HEADER | PRINT_NAMEVAL)) @@ -124,13 +137,24 @@ main(int argc, char **argv) add_param("name", NULL, (size_t)0, NULL, JP_USER); add_param("dying", NULL, (size_t)0, NULL, JP_USER); add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER); - add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER); - add_param("ip6.addr", NULL, (size_t)0, NULL, - JP_USER | JP_OPT); +#ifdef INET + if (ip4_ok) + add_param("ip4.addr", NULL, (size_t)0, NULL, + JP_USER); +#endif +#ifdef INET6 + if (ip6_ok) + add_param("ip6.addr", NULL, (size_t)0, NULL, + JP_USER | JP_OPT); +#endif } else { pflags |= PRINT_DEFAULT; add_param("jid", NULL, (size_t)0, NULL, JP_USER); - add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER); +#ifdef INET + if (ip4_ok) + add_param("ip4.addr", NULL, (size_t)0, NULL, + JP_USER); +#endif add_param("host.hostname", NULL, (size_t)0, NULL, JP_USER); add_param("path", NULL, (size_t)0, NULL, JP_USER); @@ -327,7 +351,7 @@ print_jail(int pflags, int jflags) { char *nname; char **param_values; - int i, ai, jid, count, spc; + int i, ai, jid, count, n, spc; char ipbuf[INET6_ADDRSTRLEN]; jid = jailparam_get(params, nparams, jflags); @@ -345,31 +369,45 @@ print_jail(int pflags, int jflags) *(int *)params[4].jp_value ? "DYING" : "ACTIVE", "", *(int *)params[5].jp_value); - count = params[6].jp_valuelen / sizeof(struct in_addr); - for (ai = 0; ai < count; ai++) - if (inet_ntop(AF_INET, - &((struct in_addr *)params[6].jp_value)[ai], - ipbuf, sizeof(ipbuf)) == NULL) - err(1, "inet_ntop"); - else - printf("%6s %-15.15s\n", "", ipbuf); - if (!strcmp(params[7].jp_name, "ip6.addr")) { - count = params[7].jp_valuelen / sizeof(struct in6_addr); + n = 6; +#ifdef INET + if (ip4_ok && !strcmp(params[n].jp_name, "ip.addr")) { + count = params[n].jp_valuelen / sizeof(struct in_addr); + for (ai = 0; ai < count; ai++) + if (inet_ntop(AF_INET, + &((struct in_addr *)params[n].jp_value)[ai], + ipbuf, sizeof(ipbuf)) == NULL) + err(1, "inet_ntop"); + else + printf("%6s %-15.15s\n", "", ipbuf); + n++; + } +#endif +#ifdef INET6 + if (ip6_ok && !strcmp(params[n].jp_name, "ip6.addr")) { + count = params[n].jp_valuelen / sizeof(struct in6_addr); for (ai = 0; ai < count; ai++) if (inet_ntop(AF_INET6, - &((struct in6_addr *)params[7].jp_value)[ai], + &((struct in6_addr *) + params[n].jp_value)[ai], ipbuf, sizeof(ipbuf)) == NULL) err(1, "inet_ntop"); else printf("%6s %s\n", "", ipbuf); + n++; } +#endif } else if (pflags & PRINT_DEFAULT) printf("%6d %-15.15s %-29.29s %.74s\n", *(int *)params[0].jp_value, - params[1].jp_valuelen == 0 ? "-" +#ifdef INET + (!ip4_ok || params[1].jp_valuelen == 0) ? "-" : inet_ntoa(*(struct in_addr *)params[1].jp_value), - (char *)params[2].jp_value, - (char *)params[3].jp_value); +#else + "-" +#endif + (char *)params[2-!ip4_ok].jp_value, + (char *)params[3-!ip4_ok].jp_value); else { param_values = alloca(nparams * sizeof(*param_values)); for (i = 0; i < nparams; i++) { diff --git a/usr.sbin/kbdmap/kbdmap.c b/usr.sbin/kbdmap/kbdmap.c index 93c5a08..c993389 100644 --- a/usr.sbin/kbdmap/kbdmap.c +++ b/usr.sbin/kbdmap/kbdmap.c @@ -226,10 +226,10 @@ get_font(void) } } } + fclose(fp); } else fprintf(stderr, "Could not open %s for reading\n", sysconfig); - fclose(fp); return fnt; } diff --git a/usr.sbin/mfiutil/mfi_evt.c b/usr.sbin/mfiutil/mfi_evt.c index b9288d8..a8a8775 100644 --- a/usr.sbin/mfiutil/mfi_evt.c +++ b/usr.sbin/mfiutil/mfi_evt.c @@ -362,8 +362,8 @@ mfi_decode_evt(int fd, struct mfi_evt_detail *detail, int verbose) { printf("%5d (%s/%s/%s) - ", detail->seq, format_timestamp(detail->time), - format_locale(detail->class.members.locale), - format_class(detail->class.members.class)); + format_locale(detail->evt_class.members.locale), + format_class(detail->evt_class.members.evt_class)); switch (detail->arg_type) { case MR_EVT_ARGS_NONE: break; @@ -557,7 +557,7 @@ show_events(int ac, char **av) num_events = 15; filter.members.reserved = 0; filter.members.locale = MFI_EVT_LOCALE_ALL; - filter.members.class = MFI_EVT_CLASS_WARNING; + filter.members.evt_class = MFI_EVT_CLASS_WARNING; start = info.boot_seq_num; stop = info.newest_seq_num; verbose = 0; @@ -567,7 +567,7 @@ show_events(int ac, char **av) while ((ch = getopt(ac, av, "c:l:n:v")) != -1) { switch (ch) { case 'c': - if (parse_class(optarg, &filter.members.class) < 0) { + if (parse_class(optarg, &filter.members.evt_class) < 0) { error = errno; warn("Error parsing event class"); return (error); diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index 65bf44f..01a27eb 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -158,6 +158,8 @@ struct fhreturn { int *fhr_secflavors; }; +#define GETPORT_MAXTRY 20 /* Max tries to get a port # */ + /* Global defs */ char *add_expdir(struct dirlist **, char *, int); void add_dlist(struct dirlist **, struct dirlist *, @@ -167,7 +169,9 @@ int check_dirpath(char *); int check_options(struct dirlist *); int checkmask(struct sockaddr *sa); int chk_host(struct dirlist *, struct sockaddr *, int *, int *); -void create_service(struct netconfig *nconf); +static int create_service(struct netconfig *nconf); +static void complete_service(struct netconfig *nconf, char *port_str); +static void clearout_service(void); void del_mlist(char *hostp, char *dirp); struct dirlist *dirp_search(struct dirlist *, char *); int do_mount(struct exportlist *, struct grouplist *, int, @@ -233,6 +237,10 @@ int got_sighup = 0; int xcreated = 0; char *svcport_str = NULL; +static int mallocd_svcport = 0; +static int *sock_fd; +static int sock_fdcnt; +static int sock_fdpos; int opt_flags; static int have_v6 = 1; @@ -281,6 +289,8 @@ main(int argc, char **argv) in_port_t svcport; int c, k, s; int maxrec = RPC_MAXDATASIZE; + int attempt_cnt, port_len, port_pos, ret; + char **port_list; /* Check that another mountd isn't already running. */ pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid); @@ -451,17 +461,97 @@ main(int argc, char **argv) hosts[nhosts - 1] = "127.0.0.1"; } + attempt_cnt = 1; + sock_fdcnt = 0; + sock_fd = NULL; + port_list = NULL; + port_len = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { if (nconf->nc_flag & NC_VISIBLE) { if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ + } else { + ret = create_service(nconf); + if (ret == 1) + /* Ignore this call */ + continue; + if (ret < 0) { + /* + * Failed to bind port, so close off + * all sockets created and try again + * if the port# was dynamically + * assigned via bind(2). + */ + clearout_service(); + if (mallocd_svcport != 0 && + attempt_cnt < GETPORT_MAXTRY) { + free(svcport_str); + svcport_str = NULL; + mallocd_svcport = 0; + } else { + errno = EADDRINUSE; + syslog(LOG_ERR, + "bindresvport_sa: %m"); + exit(1); + } + + /* Start over at the first service. */ + free(sock_fd); + sock_fdcnt = 0; + sock_fd = NULL; + nc_handle = setnetconfig(); + attempt_cnt++; + } else if (mallocd_svcport != 0 && + attempt_cnt == GETPORT_MAXTRY) { + /* + * For the last attempt, allow + * different port #s for each nconf + * by saving the svcport_str and + * setting it back to NULL. + */ + port_list = realloc(port_list, + (port_len + 1) * sizeof(char *)); + if (port_list == NULL) + out_of_mem(); + port_list[port_len++] = svcport_str; + svcport_str = NULL; + mallocd_svcport = 0; + } + } + } + } + + /* + * Successfully bound the ports, so call complete_service() to + * do the rest of the setup on the service(s). + */ + sock_fdpos = 0; + port_pos = 0; + nc_handle = setnetconfig(); + while ((nconf = getnetconfig(nc_handle))) { + if (nconf->nc_flag & NC_VISIBLE) { + if (have_v6 == 0 && strcmp(nconf->nc_protofmly, + "inet6") == 0) { + /* DO NOTHING */ + } else if (port_list != NULL) { + if (port_pos >= port_len) { + syslog(LOG_ERR, "too many port#s"); + exit(1); + } + complete_service(nconf, port_list[port_pos++]); } else - create_service(nconf); + complete_service(nconf, svcport_str); } } endnetconfig(nc_handle); + free(sock_fd); + if (port_list != NULL) { + for (port_pos = 0; port_pos < port_len; port_pos++) + free(port_list[port_pos]); + free(port_list); + } if (xcreated == 0) { syslog(LOG_ERR, "could not create any services"); @@ -491,30 +581,31 @@ main(int argc, char **argv) /* * This routine creates and binds sockets on the appropriate - * addresses. It gets called one time for each transport and - * registrates the service with rpcbind on that trasport. + * addresses. It gets called one time for each transport. + * It returns 0 upon success, 1 for ingore the call and -1 to indicate + * bind failed with EADDRINUSE. + * Any file descriptors that have been created are stored in sock_fd and + * the total count of them is maintained in sock_fdcnt. */ -void +static int create_service(struct netconfig *nconf) { struct addrinfo hints, *res = NULL; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; struct __rpc_sockinfo si; - struct netbuf servaddr; - SVCXPRT *transp = NULL; int aicode; int fd; int nhostsbak; int one = 1; int r; - int registered = 0; u_int32_t host_addr[4]; /* IPv4 or IPv6 */ + int mallocd_res; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) - return; /* not my type */ + return (1); /* not my type */ /* * XXX - using RPC library internal functions. @@ -522,7 +613,7 @@ create_service(struct netconfig *nconf) if (!__rpc_nconf2sockinfo(nconf, &si)) { syslog(LOG_ERR, "cannot get information for %s", nconf->nc_netid); - return; + return (1); } /* Get mountd's address on this transport */ @@ -538,6 +629,12 @@ create_service(struct netconfig *nconf) nhostsbak = nhosts; while (nhostsbak > 0) { --nhostsbak; + sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int)); + if (sock_fd == NULL) + out_of_mem(); + sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */ + mallocd_res = 0; + /* * XXX - using RPC library internal functions. */ @@ -549,14 +646,16 @@ create_service(struct netconfig *nconf) syslog(non_fatal ? LOG_DEBUG : LOG_ERR, "cannot create socket for %s", nconf->nc_netid); - return; + if (non_fatal != 0) + continue; + exit(1); } switch (hints.ai_family) { case AF_INET: if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) { - hints.ai_flags &= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET6 address. @@ -571,7 +670,7 @@ create_service(struct netconfig *nconf) case AF_INET6: if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) { - hints.ai_flags &= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET address. @@ -607,6 +706,7 @@ create_service(struct netconfig *nconf) res = malloc(sizeof(struct addrinfo)); if (res == NULL) out_of_mem(); + mallocd_res = 1; res->ai_flags = hints.ai_flags; res->ai_family = hints.ai_family; res->ai_protocol = hints.ai_protocol; @@ -620,7 +720,7 @@ create_service(struct netconfig *nconf) sin->sin_addr.s_addr = htonl(INADDR_ANY); res->ai_addr = (struct sockaddr*) sin; res->ai_addrlen = (socklen_t) - sizeof(res->ai_addr); + sizeof(struct sockaddr_in); break; case AF_INET6: sin6 = malloc(sizeof(struct sockaddr_in6)); @@ -631,10 +731,12 @@ create_service(struct netconfig *nconf) sin6->sin6_addr = in6addr_any; res->ai_addr = (struct sockaddr*) sin6; res->ai_addrlen = (socklen_t) - sizeof(res->ai_addr); - break; - default: + sizeof(struct sockaddr_in6); break; + default: + syslog(LOG_ERR, "bad addr fam %d", + res->ai_family); + exit(1); } } else { if ((aicode = getaddrinfo(NULL, svcport_str, @@ -643,6 +745,7 @@ create_service(struct netconfig *nconf) "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); + close(fd); continue; } } @@ -652,16 +755,91 @@ create_service(struct netconfig *nconf) syslog(LOG_ERR, "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); + close(fd); continue; } } + /* Store the fd. */ + sock_fd[sock_fdcnt - 1] = fd; + + /* Now, attempt the bind. */ r = bindresvport_sa(fd, res->ai_addr); if (r != 0) { + if (errno == EADDRINUSE && mallocd_svcport != 0) { + if (mallocd_res != 0) { + free(res->ai_addr); + free(res); + } else + freeaddrinfo(res); + return (-1); + } syslog(LOG_ERR, "bindresvport_sa: %m"); exit(1); } + if (svcport_str == NULL) { + svcport_str = malloc(NI_MAXSERV * sizeof(char)); + if (svcport_str == NULL) + out_of_mem(); + mallocd_svcport = 1; + + if (getnameinfo(res->ai_addr, + res->ai_addr->sa_len, NULL, NI_MAXHOST, + svcport_str, NI_MAXSERV * sizeof(char), + NI_NUMERICHOST | NI_NUMERICSERV)) + errx(1, "Cannot get port number"); + } + if (mallocd_res != 0) { + free(res->ai_addr); + free(res); + } else + freeaddrinfo(res); + res = NULL; + } + return (0); +} + +/* + * Called after all the create_service() calls have succeeded, to complete + * the setup and registration. + */ +static void +complete_service(struct netconfig *nconf, char *port_str) +{ + struct addrinfo hints, *res = NULL; + struct __rpc_sockinfo si; + struct netbuf servaddr; + SVCXPRT *transp = NULL; + int aicode, fd, nhostsbak; + int registered = 0; + + if ((nconf->nc_semantics != NC_TPI_CLTS) && + (nconf->nc_semantics != NC_TPI_COTS) && + (nconf->nc_semantics != NC_TPI_COTS_ORD)) + return; /* not my type */ + + /* + * XXX - using RPC library internal functions. + */ + if (!__rpc_nconf2sockinfo(nconf, &si)) { + syslog(LOG_ERR, "cannot get information for %s", + nconf->nc_netid); + return; + } + + nhostsbak = nhosts; + while (nhostsbak > 0) { + --nhostsbak; + if (sock_fdpos >= sock_fdcnt) { + /* Should never happen. */ + syslog(LOG_ERR, "Ran out of socket fd's"); + return; + } + fd = sock_fd[sock_fdpos++]; + if (fd < 0) + continue; + if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); @@ -696,19 +874,7 @@ create_service(struct netconfig *nconf) hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; - if (svcport_str == NULL) { - svcport_str = malloc(NI_MAXSERV * sizeof(char)); - if (svcport_str == NULL) - out_of_mem(); - - if (getnameinfo(res->ai_addr, - res->ai_addr->sa_len, NULL, NI_MAXHOST, - svcport_str, NI_MAXSERV * sizeof(char), - NI_NUMERICHOST | NI_NUMERICSERV)) - errx(1, "Cannot get port number"); - } - - if((aicode = getaddrinfo(NULL, svcport_str, &hints, + if ((aicode = getaddrinfo(NULL, port_str, &hints, &res)) != 0) { syslog(LOG_ERR, "cannot get local address: %s", gai_strerror(aicode)); @@ -728,6 +894,23 @@ create_service(struct netconfig *nconf) } /* end while */ } +/* + * Clear out sockets after a failure to bind one of them, so that the + * cycle of socket creation/binding can start anew. + */ +static void +clearout_service(void) +{ + int i; + + for (i = 0; i < sock_fdcnt; i++) { + if (sock_fd[i] >= 0) { + shutdown(sock_fd[i], SHUT_RDWR); + close(sock_fd[i]); + } + } +} + static void usage(void) { diff --git a/usr.sbin/pc-sysinstall/backend-query/enable-net.sh b/usr.sbin/pc-sysinstall/backend-query/enable-net.sh index 3c73550..8cd72a1 100755 --- a/usr.sbin/pc-sysinstall/backend-query/enable-net.sh +++ b/usr.sbin/pc-sysinstall/backend-query/enable-net.sh @@ -1,6 +1,11 @@ #!/bin/sh #- # Copyright (c) 2010 iXsystems, Inc. All rights reserved. +# Copyright (c) 2011 The FreeBSD Foundation +# All rights reserved. +# +# Portions of this software were developed by Bjoern Zeeb +# under sponsorship from the FreeBSD Foundation. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -40,23 +45,67 @@ NETMASK="$3" DNS="$4" GATEWAY="$5" MIRRORFETCH="$6" +IPV6="$7" +IPV6GATE="$8" +IPV6DNS="$9" if [ -z "${NIC}" ] then - echo "ERROR: Usage enable-net <nic> <ip> <netmask> <dns> <gateway>" + echo "ERROR: Usage enable-net <nic> <ip> <netmask> <dns> <gateway> <ipv6> " \ + "<ipv6gateway> <ipv6dns>" exit 150 fi if [ "$NIC" = "AUTO-DHCP" ] then enable_auto_dhcp +elif [ "$NIC" = "IPv6-SLAAC" ] +then + enable_auto_slaac + # In addition, if static values were defined, add them as well. + # We might not get DNS information from RAs, for example. + if [ -n "${IPV6}" ]; then + VAL="" + get_first_wired_nic + if [ -n "${VAL}" ]; then + ifconfig ${VAL} inet6 ${IPV6} alias + fi + fi + # Append only here. + if [ -n "${IPV6DNS}" ]; then + echo "nameserver ${IPV6DNS}" >>/etc/resolv.conf + fi + # Do not + if [ -n "${IPV6GATE}" ]; then + # Check if we have a default route already to not overwrite. + if ! route -n get -inet6 default > /dev/null 2>&1 ; then + route add -inet6 default ${IPV6GATE} + fi + fi else echo "Enabling NIC: $NIC" - ifconfig ${NIC} ${IP} ${NETMASK} + if [ -n "${IP}" ]; then + ifconfig ${NIC} inet ${IP} ${NETMASK} + fi + if [ -n "${IPV6}" ]; then + ifconfig ${NIC} inet6 ${IPV6} alias + fi - echo "nameserver ${DNS}" >/etc/resolv.conf + # Keep default from IPv4-only support times and clear the resolv.conf file. + : > /etc/resolv.conf + if [ -n "${DNS}" ]; then + echo "nameserver ${DNS}" >>/etc/resolv.conf + fi + if [ -n "${IPV6DNS}" ]; then + echo "nameserver ${IPV6DNS}" >>/etc/resolv.conf + fi - route add default ${GATE} + if [ -n "${GATE}" ]; then + route add -inet default ${GATE} + fi + if [ -n "${IPV6GATE}" ]; then + route add -inet6 default ${IPV6GATE} + fi fi case ${MIRRORFETCH} in diff --git a/usr.sbin/pc-sysinstall/backend-query/test-netup.sh b/usr.sbin/pc-sysinstall/backend-query/test-netup.sh index 4c8304e..e0a3eba 100755 --- a/usr.sbin/pc-sysinstall/backend-query/test-netup.sh +++ b/usr.sbin/pc-sysinstall/backend-query/test-netup.sh @@ -1,6 +1,11 @@ #!/bin/sh #- # Copyright (c) 2010 iXsystems, Inc. All rights reserved. +# Copyright (c) 2011 The FreeBSD Foundation +# All rights reserved. +# +# Portions of this software were developed by Bjoern Zeeb +# under sponsorship from the FreeBSD Foundation.# # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -26,8 +31,8 @@ # $FreeBSD$ -# Script which tests "fetch" when using a network connection, and saves -# if we are using direct connect, or need FTP passive mode +# Script which tries to ping "home" to see if Internet connectivity is +# available. ############################################################################# rm ${TMPDIR}/.testftp >/dev/null 2>/dev/null @@ -39,12 +44,26 @@ then exit 0 fi +ping6 -c 2 www.pcbsd.org >/dev/null 2>/dev/null +if [ "$?" = "0" ] +then + echo "ftp: Up" + exit 0 +fi + ping -c 2 www.freebsd.org >/dev/null 2>/dev/null if [ "$?" = "0" ] then echo "ftp: Up" exit 0 fi - + +ping6 -c 2 www.freebsd.org >/dev/null 2>/dev/null +if [ "$?" = "0" ] +then + echo "ftp: Up" + exit 0 +fi + echo "ftp: Down" exit 1 diff --git a/usr.sbin/pc-sysinstall/backend/functions-networking.sh b/usr.sbin/pc-sysinstall/backend/functions-networking.sh index d12a9cc..bdd5a1a 100755 --- a/usr.sbin/pc-sysinstall/backend/functions-networking.sh +++ b/usr.sbin/pc-sysinstall/backend/functions-networking.sh @@ -1,6 +1,11 @@ #!/bin/sh #- # Copyright (c) 2010 iXsystems, Inc. All rights reserved. +# Copyright (c) 2011 The FreeBSD Foundation +# All rights reserved. +# +# Portions of this software were developed by Bjoern Zeeb +# under sponsorship from the FreeBSD Foundation. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -119,6 +124,61 @@ save_auto_dhcp() enable_dhcp_all }; +# Function which simply enables iPv6 SLAAC on all detected nics +enable_slaac_all() +{ + rm ${TMPDIR}/.niclist >/dev/null 2>/dev/null + # start by getting a list of nics on this system + ${QUERYDIR}/detect-nics.sh > ${TMPDIR}/.niclist + if [ -e "${TMPDIR}/.niclist" ] + then + echo "# Auto-Enabled NICs from pc-sysinstall" >>${FSMNT}/etc/rc.conf + WLANCOUNT="0" + while read line + do + NIC="`echo $line | cut -d ':' -f 1`" + DESC="`echo $line | cut -d ':' -f 2`" + echo_log "Setting $NIC to acceptign RAs on the system." + check_is_wifi ${NIC} + if [ $? -eq 0 ] + then + # We have a wifi device, setup a wlan* entry for it + # Given we cannot have DHCP and SLAAC the same time currently + # it's save to just duplicate. + WLAN="wlan${WLANCOUNT}" + echo "wlans_${NIC}=\"${WLAN}\"" >>${FSMNT}/etc/rc.conf + #echo "ifconfig_${NIC}=\"up\"" >>${FSMNT}/etc/rc.conf + echo "ifconfig_${WLAN}=\"inet6 accept_rtadv\"" >>${FSMNT}/etc/rc.conf + CNIC="${WLAN}" + WLANCOUNT=$((WLANCOUNT+1)) + else + #echo "ifconfig_${NIC}=\"up\"" >>${FSMNT}/etc/rc.conf + echo "ifconfig_${NIC}_ipv6=\"inet6 accept_rtadv\"" >>${FSMNT}/etc/rc.conf + CNIC="${NIC}" + fi + + done < ${TMPDIR}/.niclist + fi + + # Given we cannot yet rely on RAs to provide DNS information as much + # as we can in the DHCP world, we should append a given nameserver. + : > ${FSMNT}/etc/resolv.conf + get_value_from_cfg netSaveIPv6NameServer + NAMESERVER="${VAL}" + if [ -n "${NAMESERVER}" ] + then + echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf + fi + +}; + + +# Function which detects available nics, and enables IPv6 SLAAC on them +save_auto_slaac() +{ + enable_slaac_all +}; + # Function which saves a manual nic setup to the installed system save_manual_nic() @@ -137,21 +197,41 @@ save_manual_nic() fi # If we get here, we have a manual setup, lets do so now + IFARGS="" + IF6ARGS="" # Set the manual IP - IFARGS="inet ${NETIP}" - - # Check if we have a netmask to set - get_value_from_cfg netSaveMask - NETMASK="${VAL}" - if [ -n "${NETMASK}" ] + if [ -n "${NETIP}" ] then - IFARGS="${IFARGS} netmask ${NETMASK}" + IFARGS="inet ${NETIP}" + + # Check if we have a netmask to set + get_value_from_cfg netSaveMask + NETMASK="${VAL}" + if [ -n "${NETMASK}" ] + then + IFARGS="${IFARGS} netmask ${NETMASK}" + fi fi + get_value_from_cfg netSaveIPv6 + NETIP6="${VAL}" + if [ -n "${NETIP6}" ] + then + # Make sure we have one inet6 prefix. + IF6ARGS=`echo "${NETIP6}" | awk '{ if ("^inet6 ") { print $0; } else + { printf "inet6 %s", $0; } }'` + fi echo "# Auto-Enabled NICs from pc-sysinstall" >>${FSMNT}/etc/rc.conf - echo "ifconfig_${NIC}=\"${IFARGS}\"" >>${FSMNT}/etc/rc.conf + if [ -n "${IFARGS}" ] + then + echo "ifconfig_${NIC}=\"${IFARGS}\"" >>${FSMNT}/etc/rc.conf + fi + if [ -n "${IF6ARGS}" ] + then + echo "ifconfig_${NIC}_ipv6=\"${IF6ARGS}\"" >>${FSMNT}/etc/rc.conf + fi # Check if we have a default router to set get_value_from_cfg netSaveDefaultRouter @@ -160,15 +240,28 @@ save_manual_nic() then echo "defaultrouter=\"${NETROUTE}\"" >>${FSMNT}/etc/rc.conf fi + get_value_from_cfg netSaveIPv6DefaultRouter + NETROUTE="${VAL}" + if [ -n "${NETROUTE}" ] + then + echo "ipv6_defaultrouter=\"${NETROUTE}\"" >>${FSMNT}/etc/rc.conf + fi # Check if we have a nameserver to enable + : > ${FSMNT}/etc/resolv.conf get_value_from_cfg netSaveNameServer NAMESERVER="${VAL}" if [ -n "${NAMESERVER}" ] then - echo "nameserver ${NAMESERVER}" >${FSMNT}/etc/resolv.conf + echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf fi - + get_value_from_cfg netSaveIPv6NameServer + NAMESERVER="${VAL}" + if [ -n "${NAMESERVER}" ] + then + echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf + fi + }; # Function which determines if a nic is active / up @@ -208,6 +301,31 @@ enable_auto_dhcp() }; +# Function which detects available nics, and runs rtsol on them. +enable_auto_slaac() +{ + + # start by getting a list of nics on this system + ${QUERYDIR}/detect-nics.sh > ${TMPDIR}/.niclist + ALLNICS="" + while read line + do + NIC="`echo $line | cut -d ':' -f 1`" + DESC="`echo $line | cut -d ':' -f 2`" + + is_nic_active "${NIC}" + if [ $? -eq 0 ] ; then + echo_log "Will try IPv6 SLAAC on $NIC $DESC" + ifconfig ${NIC} inet6 -ifdisabled accept_rtadv up + ALLNICS="${ALLNICS} ${NIC}" + fi + done < ${TMPDIR}/.niclist + + # XXX once we support it in-tree call /sbin/resovconf here. + echo_log "Running rtsol on ${ALLNICS}" + rtsol -F ${ALLNICS} >/dev/null 2>/dev/null +} + # Get the mac address of a target NIC get_nic_mac() { @@ -236,15 +354,20 @@ enable_manual_nic() # If we get here, we have a manual setup, lets do so now - # Set the manual IP - rc_halt "ifconfig ${NIC} ${NETIP}" + # IPv4: - # Check if we have a netmask to set - get_value_from_cfg netMask - NETMASK="${VAL}" - if [ -n "${NETMASK}" ] + # Set the manual IP + if [ -n "${NETIP}" ] then - rc_halt "ifconfig ${NIC} netmask ${NETMASK}" + # Check if we have a netmask to set + get_value_from_cfg netMask + NETMASK="${VAL}" + if [ -n "${NETMASK}" ] + then + rc_halt "ifconfig inet ${NIC} netmask ${NETMASK}" + else + rc_halt "ifconfig inet ${NIC} ${NETIP}" + fi fi # Check if we have a default router to set @@ -252,18 +375,42 @@ enable_manual_nic() NETROUTE="${VAL}" if [ -n "${NETROUTE}" ] then - rc_halt "route add default ${NETROUTE}" + rc_halt "route add -inet default ${NETROUTE}" + fi + + # IPv6: + + # Set static IPv6 address + get_value_from_cfg netIPv6 + NETIP="${VAL}" + if [ -n ${NETIP} ] + then + rc_halt "ifconfig inet6 ${NIC} ${NETIP} -ifdisabled up" + fi + + # Default router + get_value_from_cfg netIPv6DefaultRouter + NETROUTE="${VAL}" + if [ -n "${NETROUTE}" ] + then + rc_halt "route add -inet6 default ${NETROUTE}" fi # Check if we have a nameserver to enable + : >/etc/resolv.conf get_value_from_cfg netNameServer NAMESERVER="${VAL}" if [ -n "${NAMESERVER}" ] then - echo "nameserver ${NAMESERVER}" >/etc/resolv.conf + echo "nameserver ${NAMESERVER}" >>/etc/resolv.conf fi - - + get_value_from_cfg netIPv6NameServer + NAMESERVER="${VAL}" + if [ -n "${NAMESERVER}" ] + then + echo "nameserver ${NAMESERVER}" >>/etc/resolv.conf + fi + }; @@ -281,6 +428,9 @@ start_networking() if [ "$NETDEV" = "AUTO-DHCP" ] then enable_auto_dhcp + elif [ "$NETDEV" = "IPv6-SLAAC" ] + then + enable_auto_slaac else enable_manual_nic ${NETDEV} fi @@ -304,6 +454,9 @@ save_networking_install() if [ "$NETDEV" = "AUTO-DHCP" ] then save_auto_dhcp + elif [ "$NETDEV" = "IPv6-SLAAC" ] + then + save_auto_slaac else save_manual_nic ${NETDEV} fi diff --git a/usr.sbin/rpc.lockd/lockd.c b/usr.sbin/rpc.lockd/lockd.c index fb9e536..b3402ff 100644 --- a/usr.sbin/rpc.lockd/lockd.c +++ b/usr.sbin/rpc.lockd/lockd.c @@ -74,6 +74,8 @@ __RCSID("$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $"); #include "lockd.h" #include <rpcsvc/nlm_prot.h> +#define GETPORT_MAXTRY 20 /* Max tries to get a port # */ + int debug_level = 0; /* 0 = no debugging syslog() calls */ int _rpcsvcdirty = 0; @@ -84,13 +86,19 @@ int kernel_lockd_client; pid_t client_pid; struct mon mon_host; char **hosts, *svcport_str = NULL; +static int mallocd_svcport = 0; +static int *sock_fd; +static int sock_fdcnt; +static int sock_fdpos; int nhosts = 0; int xcreated = 0; char **addrs; /* actually (netid, uaddr) pairs */ int naddrs; /* count of how many (netid, uaddr) pairs */ char localhost[] = "localhost"; -void create_service(struct netconfig *nconf); +static int create_service(struct netconfig *nconf); +static void complete_service(struct netconfig *nconf, char *port_str); +static void clearout_service(void); void lookup_addresses(struct netconfig *nconf); void init_nsm(void); void nlm_prog_0(struct svc_req *, SVCXPRT *); @@ -119,6 +127,8 @@ main(int argc, char **argv) int have_v6 = 1; int maxrec = RPC_MAXDATASIZE; in_port_t svcport = 0; + int attempt_cnt, port_len, port_pos, ret; + char **port_list; while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) { switch (ch) { @@ -309,6 +319,11 @@ main(int argc, char **argv) } endnetconfig(nc_handle); } else { + attempt_cnt = 1; + sock_fdcnt = 0; + sock_fd = NULL; + port_list = NULL; + port_len = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ @@ -317,11 +332,96 @@ main(int argc, char **argv) if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { - create_service(nconf); + ret = create_service(nconf); + if (ret == 1) + /* Ignore this call */ + continue; + if (ret < 0) { + /* + * Failed to bind port, so close + * off all sockets created and + * try again if the port# was + * dynamically assigned via + * bind(2). + */ + clearout_service(); + if (mallocd_svcport != 0 && + attempt_cnt < + GETPORT_MAXTRY) { + free(svcport_str); + svcport_str = NULL; + mallocd_svcport = 0; + } else { + errno = EADDRINUSE; + syslog(LOG_ERR, + "bindresvport_sa: %m"); + exit(1); + } + + /* + * Start over at the first + * service. + */ + free(sock_fd); + sock_fdcnt = 0; + sock_fd = NULL; + nc_handle = setnetconfig(); + attempt_cnt++; + } else if (mallocd_svcport != 0 && + attempt_cnt == GETPORT_MAXTRY) { + /* + * For the last attempt, allow + * different port #s for each + * nconf by saving the + * svcport_str and setting it + * back to NULL. + */ + port_list = realloc(port_list, + (port_len + 1) * + sizeof(char *)); + if (port_list == NULL) + out_of_mem(); + port_list[port_len++] = + svcport_str; + svcport_str = NULL; + mallocd_svcport = 0; + } } } } + + /* + * Successfully bound the ports, so call complete_service() to + * do the rest of the setup on the service(s). + */ + sock_fdpos = 0; + port_pos = 0; + nc_handle = setnetconfig(); + while ((nconf = getnetconfig(nc_handle))) { + /* We want to listen only on udp6, tcp6, udp, tcp transports */ + if (nconf->nc_flag & NC_VISIBLE) { + /* Skip if there's no IPv6 support */ + if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { + /* DO NOTHING */ + } else if (port_list != NULL) { + if (port_pos >= port_len) { + syslog(LOG_ERR, + "too many port#s"); + exit(1); + } + complete_service(nconf, + port_list[port_pos++]); + } else + complete_service(nconf, svcport_str); + } + } endnetconfig(nc_handle); + free(sock_fd); + if (port_list != NULL) { + for (port_pos = 0; port_pos < port_len; port_pos++) + free(port_list[port_pos]); + free(port_list); + } } /* @@ -386,29 +486,30 @@ main(int argc, char **argv) /* * This routine creates and binds sockets on the appropriate - * addresses. It gets called one time for each transport and - * registrates the service with rpcbind on that trasport. + * addresses. It gets called one time for each transport. + * It returns 0 upon success, 1 for ingore the call and -1 to indicate + * bind failed with EADDRINUSE. + * Any file descriptors that have been created are stored in sock_fd and + * the total count of them is maintained in sock_fdcnt. */ -void +static int create_service(struct netconfig *nconf) { struct addrinfo hints, *res = NULL; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; struct __rpc_sockinfo si; - struct netbuf servaddr; - SVCXPRT *transp = NULL; int aicode; int fd; int nhostsbak; int r; - int registered = 0; u_int32_t host_addr[4]; /* IPv4 or IPv6 */ + int mallocd_res; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) - return; /* not my type */ + return (1); /* not my type */ /* * XXX - using RPC library internal functions. @@ -416,7 +517,7 @@ create_service(struct netconfig *nconf) if (!__rpc_nconf2sockinfo(nconf, &si)) { syslog(LOG_ERR, "cannot get information for %s", nconf->nc_netid); - return; + return (1); } /* Get rpc.statd's address on this transport */ @@ -432,6 +533,11 @@ create_service(struct netconfig *nconf) nhostsbak = nhosts; while (nhostsbak > 0) { --nhostsbak; + sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int)); + if (sock_fd == NULL) + out_of_mem(); + sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */ + mallocd_res = 0; /* * XXX - using RPC library internal functions. @@ -446,7 +552,7 @@ create_service(struct netconfig *nconf) case AF_INET: if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) { - hints.ai_flags &= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET6 address. @@ -461,7 +567,7 @@ create_service(struct netconfig *nconf) case AF_INET6: if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) { - hints.ai_flags &= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET address. @@ -485,6 +591,7 @@ create_service(struct netconfig *nconf) res = malloc(sizeof(struct addrinfo)); if (res == NULL) out_of_mem(); + mallocd_res = 1; res->ai_flags = hints.ai_flags; res->ai_family = hints.ai_family; res->ai_protocol = hints.ai_protocol; @@ -498,7 +605,7 @@ create_service(struct netconfig *nconf) sin->sin_addr.s_addr = htonl(INADDR_ANY); res->ai_addr = (struct sockaddr*) sin; res->ai_addrlen = (socklen_t) - sizeof(res->ai_addr); + sizeof(struct sockaddr_in); break; case AF_INET6: sin6 = malloc(sizeof(struct sockaddr_in6)); @@ -508,10 +615,14 @@ create_service(struct netconfig *nconf) sin6->sin6_port = htons(0); sin6->sin6_addr = in6addr_any; res->ai_addr = (struct sockaddr*) sin6; - res->ai_addrlen = (socklen_t) sizeof(res->ai_addr); + res->ai_addrlen = (socklen_t) + sizeof(struct sockaddr_in6); break; default: - break; + syslog(LOG_ERR, + "bad addr fam %d", + res->ai_family); + exit(1); } } else { if ((aicode = getaddrinfo(NULL, svcport_str, @@ -520,6 +631,7 @@ create_service(struct netconfig *nconf) "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); + close(fd); continue; } } @@ -529,16 +641,92 @@ create_service(struct netconfig *nconf) syslog(LOG_ERR, "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); + close(fd); continue; } } + + /* Store the fd. */ + sock_fd[sock_fdcnt - 1] = fd; + + /* Now, attempt the bind. */ r = bindresvport_sa(fd, res->ai_addr); if (r != 0) { + if (errno == EADDRINUSE && mallocd_svcport != 0) { + if (mallocd_res != 0) { + free(res->ai_addr); + free(res); + } else + freeaddrinfo(res); + return (-1); + } syslog(LOG_ERR, "bindresvport_sa: %m"); exit(1); } + if (svcport_str == NULL) { + svcport_str = malloc(NI_MAXSERV * sizeof(char)); + if (svcport_str == NULL) + out_of_mem(); + mallocd_svcport = 1; + + if (getnameinfo(res->ai_addr, + res->ai_addr->sa_len, NULL, NI_MAXHOST, + svcport_str, NI_MAXSERV * sizeof(char), + NI_NUMERICHOST | NI_NUMERICSERV)) + errx(1, "Cannot get port number"); + } + if (mallocd_res != 0) { + free(res->ai_addr); + free(res); + } else + freeaddrinfo(res); + res = NULL; + } + return (0); +} + +/* + * Called after all the create_service() calls have succeeded, to complete + * the setup and registration. + */ +static void +complete_service(struct netconfig *nconf, char *port_str) +{ + struct addrinfo hints, *res = NULL; + struct __rpc_sockinfo si; + struct netbuf servaddr; + SVCXPRT *transp = NULL; + int aicode, fd, nhostsbak; + int registered = 0; + + if ((nconf->nc_semantics != NC_TPI_CLTS) && + (nconf->nc_semantics != NC_TPI_COTS) && + (nconf->nc_semantics != NC_TPI_COTS_ORD)) + return; /* not my type */ + + /* + * XXX - using RPC library internal functions. + */ + if (!__rpc_nconf2sockinfo(nconf, &si)) { + syslog(LOG_ERR, "cannot get information for %s", + nconf->nc_netid); + return; + } + + nhostsbak = nhosts; + while (nhostsbak > 0) { + --nhostsbak; + if (sock_fdpos >= sock_fdcnt) { + /* Should never happen. */ + syslog(LOG_ERR, "Ran out of socket fd's"); + return; + } + fd = sock_fd[sock_fdpos++]; + if (fd < 0) + continue; + if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); @@ -582,19 +770,7 @@ create_service(struct netconfig *nconf) hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; - if (svcport_str == NULL) { - svcport_str = malloc(NI_MAXSERV * sizeof(char)); - if (svcport_str == NULL) - out_of_mem(); - - if (getnameinfo(res->ai_addr, - res->ai_addr->sa_len, NULL, NI_MAXHOST, - svcport_str, NI_MAXSERV * sizeof(char), - NI_NUMERICHOST | NI_NUMERICSERV)) - errx(1, "Cannot get port number"); - } - - if((aicode = getaddrinfo(NULL, svcport_str, &hints, + if ((aicode = getaddrinfo(NULL, port_str, &hints, &res)) != 0) { syslog(LOG_ERR, "cannot get local address: %s", gai_strerror(aicode)); @@ -617,6 +793,23 @@ create_service(struct netconfig *nconf) } /* + * Clear out sockets after a failure to bind one of them, so that the + * cycle of socket creation/binding can start anew. + */ +static void +clearout_service(void) +{ + int i; + + for (i = 0; i < sock_fdcnt; i++) { + if (sock_fd[i] >= 0) { + shutdown(sock_fd[i], SHUT_RDWR); + close(sock_fd[i]); + } + } +} + +/* * Look up addresses for the kernel to create transports for. */ void diff --git a/usr.sbin/rpc.statd/statd.c b/usr.sbin/rpc.statd/statd.c index b8b4311..ff537f8 100644 --- a/usr.sbin/rpc.statd/statd.c +++ b/usr.sbin/rpc.statd/statd.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include <err.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <rpc/rpc.h> @@ -55,13 +56,21 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include "statd.h" +#define GETPORT_MAXTRY 20 /* Max tries to get a port # */ + int debug = 0; /* Controls syslog() calls for debug messages */ char **hosts, *svcport_str = NULL; int nhosts = 0; int xcreated = 0; - -void create_service(struct netconfig *nconf); +static int mallocd_svcport = 0; +static int *sock_fd; +static int sock_fdcnt; +static int sock_fdpos; + +static int create_service(struct netconfig *nconf); +static void complete_service(struct netconfig *nconf, char *port_str); +static void clearout_service(void); static void handle_sigchld(int sig); void out_of_mem(void); @@ -78,6 +87,8 @@ main(int argc, char **argv) char *endptr, **hosts_bak; int have_v6 = 1; int maxrec = RPC_MAXDATASIZE; + int attempt_cnt, port_len, port_pos, ret; + char **port_list; while ((ch = getopt(argc, argv, "dh:p:")) != -1) switch (ch) { @@ -176,6 +187,11 @@ main(int argc, char **argv) hosts[nhosts - 1] = "127.0.0.1"; } + attempt_cnt = 1; + sock_fdcnt = 0; + sock_fd = NULL; + port_list = NULL; + port_len = 0; nc_handle = setnetconfig(); while ((nconf = getnetconfig(nc_handle))) { /* We want to listen only on udp6, tcp6, udp, tcp transports */ @@ -184,11 +200,87 @@ main(int argc, char **argv) if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { /* DO NOTHING */ } else { - create_service(nconf); + ret = create_service(nconf); + if (ret == 1) + /* Ignore this call */ + continue; + if (ret < 0) { + /* + * Failed to bind port, so close off + * all sockets created and try again + * if the port# was dynamically + * assigned via bind(2). + */ + clearout_service(); + if (mallocd_svcport != 0 && + attempt_cnt < GETPORT_MAXTRY) { + free(svcport_str); + svcport_str = NULL; + mallocd_svcport = 0; + } else { + errno = EADDRINUSE; + syslog(LOG_ERR, + "bindresvport_sa: %m"); + exit(1); + } + + /* Start over at the first service. */ + free(sock_fd); + sock_fdcnt = 0; + sock_fd = NULL; + nc_handle = setnetconfig(); + attempt_cnt++; + } else if (mallocd_svcport != 0 && + attempt_cnt == GETPORT_MAXTRY) { + /* + * For the last attempt, allow + * different port #s for each nconf + * by saving the svcport_str and + * setting it back to NULL. + */ + port_list = realloc(port_list, + (port_len + 1) * sizeof(char *)); + if (port_list == NULL) + out_of_mem(); + port_list[port_len++] = svcport_str; + svcport_str = NULL; + mallocd_svcport = 0; + } } } } + + /* + * Successfully bound the ports, so call complete_service() to + * do the rest of the setup on the service(s). + */ + sock_fdpos = 0; + port_pos = 0; + nc_handle = setnetconfig(); + while ((nconf = getnetconfig(nc_handle))) { + /* We want to listen only on udp6, tcp6, udp, tcp transports */ + if (nconf->nc_flag & NC_VISIBLE) { + /* Skip if there's no IPv6 support */ + if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) { + /* DO NOTHING */ + } else if (port_list != NULL) { + if (port_pos >= port_len) { + syslog(LOG_ERR, "too many port#s"); + exit(1); + } + complete_service(nconf, port_list[port_pos++]); + } else + complete_service(nconf, svcport_str); + } + } endnetconfig(nc_handle); + free(sock_fd); + if (port_list != NULL) { + for (port_pos = 0; port_pos < port_len; port_pos++) + free(port_list[port_pos]); + free(port_list); + } + init_file("/var/db/statd.status"); /* Note that it is NOT sensible to run this program from inetd - the */ @@ -215,29 +307,30 @@ main(int argc, char **argv) /* * This routine creates and binds sockets on the appropriate - * addresses. It gets called one time for each transport and - * registrates the service with rpcbind on that trasport. + * addresses. It gets called one time for each transport. + * It returns 0 upon success, 1 for ingore the call and -1 to indicate + * bind failed with EADDRINUSE. + * Any file descriptors that have been created are stored in sock_fd and + * the total count of them is maintained in sock_fdcnt. */ -void +static int create_service(struct netconfig *nconf) { struct addrinfo hints, *res = NULL; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; struct __rpc_sockinfo si; - struct netbuf servaddr; - SVCXPRT *transp = NULL; int aicode; int fd; int nhostsbak; int r; - int registered = 0; u_int32_t host_addr[4]; /* IPv4 or IPv6 */ + int mallocd_res; if ((nconf->nc_semantics != NC_TPI_CLTS) && (nconf->nc_semantics != NC_TPI_COTS) && (nconf->nc_semantics != NC_TPI_COTS_ORD)) - return; /* not my type */ + return (1); /* not my type */ /* * XXX - using RPC library internal functions. @@ -245,7 +338,7 @@ create_service(struct netconfig *nconf) if (!__rpc_nconf2sockinfo(nconf, &si)) { syslog(LOG_ERR, "cannot get information for %s", nconf->nc_netid); - return; + return (1); } /* Get rpc.statd's address on this transport */ @@ -261,6 +354,11 @@ create_service(struct netconfig *nconf) nhostsbak = nhosts; while (nhostsbak > 0) { --nhostsbak; + sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int)); + if (sock_fd == NULL) + out_of_mem(); + sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */ + mallocd_res = 0; /* * XXX - using RPC library internal functions. @@ -274,7 +372,7 @@ create_service(struct netconfig *nconf) case AF_INET: if (inet_pton(AF_INET, hosts[nhostsbak], host_addr) == 1) { - hints.ai_flags &= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET6 address. @@ -289,7 +387,7 @@ create_service(struct netconfig *nconf) case AF_INET6: if (inet_pton(AF_INET6, hosts[nhostsbak], host_addr) == 1) { - hints.ai_flags &= AI_NUMERICHOST; + hints.ai_flags |= AI_NUMERICHOST; } else { /* * Skip if we have an AF_INET address. @@ -313,6 +411,7 @@ create_service(struct netconfig *nconf) res = malloc(sizeof(struct addrinfo)); if (res == NULL) out_of_mem(); + mallocd_res = 1; res->ai_flags = hints.ai_flags; res->ai_family = hints.ai_family; res->ai_protocol = hints.ai_protocol; @@ -326,7 +425,7 @@ create_service(struct netconfig *nconf) sin->sin_addr.s_addr = htonl(INADDR_ANY); res->ai_addr = (struct sockaddr*) sin; res->ai_addrlen = (socklen_t) - sizeof(res->ai_addr); + sizeof(struct sockaddr_in); break; case AF_INET6: sin6 = malloc(sizeof(struct sockaddr_in6)); @@ -336,10 +435,13 @@ create_service(struct netconfig *nconf) sin6->sin6_port = htons(0); sin6->sin6_addr = in6addr_any; res->ai_addr = (struct sockaddr*) sin6; - res->ai_addrlen = (socklen_t) sizeof(res->ai_addr); + res->ai_addrlen = (socklen_t) + sizeof(struct sockaddr_in6); break; default: - break; + syslog(LOG_ERR, "bad addr fam %d", + res->ai_family); + exit(1); } } else { if ((aicode = getaddrinfo(NULL, svcport_str, @@ -348,6 +450,7 @@ create_service(struct netconfig *nconf) "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); + close(fd); continue; } } @@ -357,16 +460,91 @@ create_service(struct netconfig *nconf) syslog(LOG_ERR, "cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode)); + close(fd); continue; } } + /* Store the fd. */ + sock_fd[sock_fdcnt - 1] = fd; + + /* Now, attempt the bind. */ r = bindresvport_sa(fd, res->ai_addr); if (r != 0) { + if (errno == EADDRINUSE && mallocd_svcport != 0) { + if (mallocd_res != 0) { + free(res->ai_addr); + free(res); + } else + freeaddrinfo(res); + return (-1); + } syslog(LOG_ERR, "bindresvport_sa: %m"); exit(1); } + if (svcport_str == NULL) { + svcport_str = malloc(NI_MAXSERV * sizeof(char)); + if (svcport_str == NULL) + out_of_mem(); + mallocd_svcport = 1; + + if (getnameinfo(res->ai_addr, + res->ai_addr->sa_len, NULL, NI_MAXHOST, + svcport_str, NI_MAXSERV * sizeof(char), + NI_NUMERICHOST | NI_NUMERICSERV)) + errx(1, "Cannot get port number"); + } + if (mallocd_res != 0) { + free(res->ai_addr); + free(res); + } else + freeaddrinfo(res); + res = NULL; + } + return (0); +} + +/* + * Called after all the create_service() calls have succeeded, to complete + * the setup and registration. + */ +static void +complete_service(struct netconfig *nconf, char *port_str) +{ + struct addrinfo hints, *res = NULL; + struct __rpc_sockinfo si; + struct netbuf servaddr; + SVCXPRT *transp = NULL; + int aicode, fd, nhostsbak; + int registered = 0; + + if ((nconf->nc_semantics != NC_TPI_CLTS) && + (nconf->nc_semantics != NC_TPI_COTS) && + (nconf->nc_semantics != NC_TPI_COTS_ORD)) + return; /* not my type */ + + /* + * XXX - using RPC library internal functions. + */ + if (!__rpc_nconf2sockinfo(nconf, &si)) { + syslog(LOG_ERR, "cannot get information for %s", + nconf->nc_netid); + return; + } + + nhostsbak = nhosts; + while (nhostsbak > 0) { + --nhostsbak; + if (sock_fdpos >= sock_fdcnt) { + /* Should never happen. */ + syslog(LOG_ERR, "Ran out of socket fd's"); + return; + } + fd = sock_fd[sock_fdpos++]; + if (fd < 0) + continue; + if (nconf->nc_semantics != NC_TPI_CLTS) listen(fd, SOMAXCONN); @@ -397,19 +575,8 @@ create_service(struct netconfig *nconf) hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; - if (svcport_str == NULL) { - svcport_str = malloc(NI_MAXSERV * sizeof(char)); - if (svcport_str == NULL) - out_of_mem(); - - if (getnameinfo(res->ai_addr, - res->ai_addr->sa_len, NULL, NI_MAXHOST, - svcport_str, NI_MAXSERV * sizeof(char), - NI_NUMERICHOST | NI_NUMERICSERV)) - errx(1, "Cannot get port number"); - } - if((aicode = getaddrinfo(NULL, svcport_str, &hints, + if ((aicode = getaddrinfo(NULL, port_str, &hints, &res)) != 0) { syslog(LOG_ERR, "cannot get local address: %s", gai_strerror(aicode)); @@ -428,6 +595,23 @@ create_service(struct netconfig *nconf) } /* end while */ } +/* + * Clear out sockets after a failure to bind one of them, so that the + * cycle of socket creation/binding can start anew. + */ +static void +clearout_service(void) +{ + int i; + + for (i = 0; i < sock_fdcnt; i++) { + if (sock_fd[i] >= 0) { + shutdown(sock_fd[i], SHUT_RDWR); + close(sock_fd[i]); + } + } +} + static void usage() { diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c index 76ebe96..afa935e 100644 --- a/usr.sbin/rtsold/rtsol.c +++ b/usr.sbin/rtsold/rtsol.c @@ -247,7 +247,7 @@ rtsol_input(int s) struct nd_opt_rdnss *rdnss; struct nd_opt_dnssl *dnssl; size_t len; - char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1 + 1]; + char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1]; char dname[NI_MAXHOST]; struct timeval now; struct timeval lifetime; diff --git a/usr.sbin/usbdump/usbdump.8 b/usr.sbin/usbdump/usbdump.8 index a02f34e..104c3b3 100644 --- a/usr.sbin/usbdump/usbdump.8 +++ b/usr.sbin/usbdump/usbdump.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 4, 2010 +.Dd May 31, 2011 .Dt USBDUMP 8 .Os .Sh NAME @@ -63,16 +63,16 @@ Write the raw packets to .Ar file . .El .Sh EXAMPLES -Captures USB raw packets on usbus2: +Capture the USB raw packets on usbus2: .Pp .Dl "usbdump -i usbus2 -s 256 -v" .Pp -Dumps the USB raw packets of usbus2 into the file without packet +Dump the USB raw packets of usbus2 into the file without packet size limit: .Pp .Dl "usbdump -i usbus2 -s 0 -w /tmp/dump_pkts" .Pp -Read the USB raw packets from previous file: +Read and display the USB raw packets from previous file: .Pp .Dl "usbdump -r /tmp/dump_pkts -v" .Sh OUTPUT FORMAT |