Index: head/etc/host.conf =================================================================== --- head/etc/host.conf (revision 65531) +++ head/etc/host.conf (nonexistent) @@ -1,7 +0,0 @@ -# $FreeBSD$ -# First try the /etc/hosts file -hosts -# Now try the nameserver next. -bind -# If you have YP/NIS configured, uncomment the next line -# nis Property changes on: head/etc/host.conf ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/etc/Makefile =================================================================== --- head/etc/Makefile (revision 65531) +++ head/etc/Makefile (revision 65532) @@ -1,191 +1,191 @@ # from: @(#)Makefile 5.11 (Berkeley) 5/21/91 # $FreeBSD$ SUBDIR= sendmail BIN1= amd.map apmd.conf auth.conf \ crontab csh.cshrc csh.login csh.logout \ dhclient.conf dm.conf fbtab ftpusers gettytab group \ - hosts hosts.allow host.conf hosts.equiv hosts.lpd \ + hosts hosts.allow hosts.equiv hosts.lpd \ inetd.conf login.access login.conf \ motd modems networks newsyslog.conf \ pam.conf phones pim6dd.conf pim6sd.conf \ printcap profile protocols \ rc rc.atm rc.devfs rc.diskless1 rc.diskless2 rc.firewall rc.isdn \ rc.network rc.network6 rc.pccard rc.serial rc.shutdown rc.sysctl \ remote rpc security services shells syslog.conf usbd.conf \ etc.${MACHINE_ARCH}/disktab \ etc.${MACHINE_ARCH}/rc.${MACHINE_ARCH} \ etc.${MACHINE_ARCH}/ttys \ ${.CURDIR}/../gnu/usr.bin/man/manpath/manpath.config \ ${.CURDIR}/../usr.bin/mail/misc/mail.rc \ ${.CURDIR}/../usr.bin/locate/locate/locate.rc .if exists(${.CURDIR}/../crypto) && !defined(NO_OPENSSH) SSH= ${.CURDIR}/../crypto/openssh/ssh_config \ ${.CURDIR}/../crypto/openssh/sshd_config .endif .if exists(${.CURDIR}/../crypto) && !defined(NO_OPENSSL) SSL= ${.CURDIR}/../crypto/openssl/apps/openssl.cnf .endif # -rwxr-xr-x root.wheel, for the new cron root.wheel BIN2= netstart pccard_ether rc.suspend rc.resume MTREE= BSD.include.dist BSD.local.dist BSD.root.dist BSD.usr.dist \ BSD.var.dist BSD.x11.dist BSD.x11-4.dist NAMEDB= PROTO.localhost.rev named.conf named.root make-localhost PPPCNF= ppp.deny ppp.shells.sample PPPCF2= ppp.conf ETCMAIL=Makefile README mailer.conf access.sample virtusertable.sample \ mailertable.sample aliases # Special top level files for FreeBSD COPYRIGHT= COPYRIGHT FREEBSD= FREEBSD+= ${COPYRIGHT} etc: distribute: cd ${.CURDIR} ; ${MAKE} distribution DESTDIR=${DISTDIR}/bin .if defined(OBJFORMAT) echo OBJFORMAT=${OBJFORMAT} > ${DISTDIR}/bin/etc/objformat .endif @echo distribution: (cd ${.CURDIR}; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 ${BIN1} ${DESTDIR}/etc; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 755 ${BIN2} ${DESTDIR}/etc; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 defaults/rc.conf ${DESTDIR}/etc/defaults/; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 defaults/make.conf ${DESTDIR}/etc/defaults/; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 defaults/pccard.conf ${DESTDIR}/etc/defaults/; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 defaults/periodic.conf ${DESTDIR}/etc/defaults/; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 600 /dev/null \ ${DESTDIR}/var/log/cron; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 600 \ master.passwd ${DESTDIR}/etc; \ ( cd ${.CURDIR}/periodic; ${MAKE} install ); \ ( cd ${.CURDIR}/../gnu/usr.bin/send-pr; ${MAKE} etc-gnats-freefall ); \ ( cd ${.CURDIR}/../gnu/libexec/uucp/sample; ${MAKE} install ); \ ( cd ${.CURDIR}/../share/termcap; ${MAKE} etc-termcap ); \ ( cd ${.CURDIR}/../usr.sbin/rmt; ${MAKE} etc-rmt ); \ ( cd ${.CURDIR}/sendmail; ${MAKE} etc-sendmail.cf ); \ ( cd ${.CURDIR}/isdn; ${MAKE} install ); \ pwd_mkdb -p -d ${DESTDIR}/etc ${DESTDIR}/etc/master.passwd; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 555 \ MAKEDEV.local MAKEDEV ${DESTDIR}/dev ) .if exists(${.CURDIR}/../crypto) && !defined(NO_OPENSSH) (cd ${.CURDIR}; ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 ${SSH} \ ${DESTDIR}/etc/ssh ) .endif .if exists(${.CURDIR}/../crypto) && !defined(NO_OPENSSL) (cd ${.CURDIR}; ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 ${SSL} \ ${DESTDIR}/etc/ssl ) .endif .if !defined(NO_MAKEDEV) (cd ${DESTDIR}/dev; sh MAKEDEV all) .endif (cd ${.CURDIR}/root; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 dot.cshrc \ ${DESTDIR}/root/.cshrc; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 dot.klogin \ ${DESTDIR}/root/.klogin; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 dot.login \ ${DESTDIR}/root/.login; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 dot.profile \ ${DESTDIR}/root/.profile; \ rm -f ${DESTDIR}/.cshrc ${DESTDIR}/.profile; \ ln ${DESTDIR}/root/.cshrc ${DESTDIR}/.cshrc; \ ln ${DESTDIR}/root/.profile ${DESTDIR}/.profile) cd ${.CURDIR}/mtree; ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \ ${MTREE} ${DESTDIR}/etc/mtree cd ${.CURDIR}/namedb; ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \ ${NAMEDB} ${DESTDIR}/etc/namedb cd ${.CURDIR}/ppp; ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \ ${PPPCNF} ${DESTDIR}/etc/ppp cd ${.CURDIR}/ppp; ${INSTALL} -c -o root -g ${BINGRP} -m 600 \ ${PPPCF2} ${DESTDIR}/etc/ppp cd ${.CURDIR}/mail; ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \ ${ETCMAIL} ${DESTDIR}/etc/mail @if [ -d ${DESTDIR}/etc/mail -a -f ${DESTDIR}/etc/mail/aliases -a \ ! -f ${DESTDIR}/etc/aliases ]; then \ set -x; \ ln -s mail/aliases ${DESTDIR}/etc/aliases; \ fi ${INSTALL} -c -o ${BINOWN} -g operator -m 664 /dev/null \ ${DESTDIR}/etc/dumpdates ${INSTALL} -c -o nobody -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/db/locate.database ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/log/lpd-errs ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/log/maillog ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/log/lastlog ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/log/messages ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 600 /dev/null \ ${DESTDIR}/var/log/security ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 600 /dev/null \ ${DESTDIR}/var/log/slip.log ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 600 /dev/null \ ${DESTDIR}/var/log/ppp.log ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/log/wtmp ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ ${DESTDIR}/var/run/utmp ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 ${.CURDIR}/minfree \ ${DESTDIR}/var/crash (cd ${.CURDIR}/..; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ${FREEBSD} \ ${DESTDIR}/) .if !defined(NOMAN) (cd ${.CURDIR}/../share/man; ${MAKE} makedb; ) .endif distrib-dirs: mtree -deU -f ${.CURDIR}/mtree/BSD.root.dist -p ${DESTDIR}/ mtree -deU -f ${.CURDIR}/mtree/BSD.var.dist -p ${DESTDIR}/var mtree -deU -f ${.CURDIR}/mtree/BSD.usr.dist -p ${DESTDIR}/usr mtree -deU -f ${.CURDIR}/mtree/BSD.include.dist \ -p ${DESTDIR}/usr/include mtree -deU -f ${.CURDIR}/mtree/BSD.include.dist \ -p ${DESTDIR}/usr/libdata/perl/5.6.0/mach cd ${DESTDIR}/; rm -f ${DESTDIR}/sys; ln -s usr/src/sys sys cd ${DESTDIR}/usr/share/locale; \ set - `cat ${.CURDIR}/locale.alias`; \ while [ $$# -gt 0 ] ; \ do \ rm -rf "$$1"; \ ln -s "$$2" "$$1"; \ shift; shift; \ done cd ${DESTDIR}/usr/share/nls; \ set - `cat ${.CURDIR}/locale.alias`; \ while [ $$# -gt 0 ] ; \ do \ rm -rf "$$1"; \ ln -s "$$2" "$$1"; \ shift; shift; \ done; \ rm -rf POSIX; \ ln -s C POSIX etc-examples: (cd ${.CURDIR}; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ${BIN1} ${BIN2} \ ${DESTDIR}/usr/share/examples/etc; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 defaults/rc.conf \ ${DESTDIR}/usr/share/examples/etc/defaults; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 defaults/make.conf \ ${DESTDIR}/usr/share/examples/etc/defaults; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 defaults/pccard.conf \ ${DESTDIR}/usr/share/examples/etc/defaults; \ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 defaults/periodic.conf \ ${DESTDIR}/usr/share/examples/etc/defaults) .include Index: head/etc/hosts =================================================================== --- head/etc/hosts (revision 65531) +++ head/etc/hosts (revision 65532) @@ -1,29 +1,29 @@ # $FreeBSD$ # # Host Database # This file should contain the addresses and aliases # for local hosts that share this file. # In the presence of the domain name service or NIS, this file may -# not be consulted at all; see /etc/host.conf for the resolution order. +# not be consulted at all; see /etc/nsswitch.conf for the resolution order. # # ::1 localhost localhost.my.domain myname.my.domain 127.0.0.1 localhost localhost.my.domain myname.my.domain # # Imaginary network. #10.0.0.2 myname.my.domain myname #10.0.0.3 myfriend.my.domain myfriend # # According to RFC 1918, you can use the following IP networks for # private nets which will never be connected to the Internet: # # 10.0.0.0 - 10.255.255.255 # 172.16.0.0 - 172.31.255.255 # 192.168.0.0 - 192.168.255.255 # # In case you want to be able to connect to the Internet, you need # real official assigned numbers. PLEASE PLEASE PLEASE do not try # to invent your own network numbers but instead get one from your # network provider (if any) or from the Internet Registry (ftp to # rs.internic.net, directory `/templates'). # Index: head/etc/network.subr =================================================================== --- head/etc/network.subr (revision 65531) +++ head/etc/network.subr (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/etc/rc.d/netoptions =================================================================== --- head/etc/rc.d/netoptions (revision 65531) +++ head/etc/rc.d/netoptions (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/etc/rc.d/network1 =================================================================== --- head/etc/rc.d/network1 (revision 65531) +++ head/etc/rc.d/network1 (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/etc/rc.d/network2 =================================================================== --- head/etc/rc.d/network2 (revision 65531) +++ head/etc/rc.d/network2 (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/etc/rc.d/network3 =================================================================== --- head/etc/rc.d/network3 (revision 65531) +++ head/etc/rc.d/network3 (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/etc/rc.d/routing =================================================================== --- head/etc/rc.d/routing (revision 65531) +++ head/etc/rc.d/routing (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/etc/rc.network =================================================================== --- head/etc/rc.network (revision 65531) +++ head/etc/rc.network (revision 65532) @@ -1,683 +1,712 @@ #!/bin/sh - # # $FreeBSD$ # From: @(#)netstart 5.9 (Berkeley) 3/30/91 # Note that almost all of the user-configurable behavior is no longer in # this file, but rather in /etc/defaults/rc.conf. Please check that file # first before contemplating any changes here. If you do need to change # this file for some reason, we would like to know about it. # First pass startup stuff. # network_pass1() { echo -n 'Doing initial network setup:' + # Convert host.conf to nsswitch.conf if necessary + if [ -f "/etc/host.conf" ]; then + echo "" + echo "Warning: /etc/host.conf is no longer used" + if [ -f "/etc/nsswitch.conf" ]; then + echo " /etc/nsswitch.conf will be used instead" + else + echo " /etc/nsswitch.conf will be created for you" + convert_host_conf /etc/host.conf /etc/nsswitch.conf + fi + fi + # Set the host name if it is not already set # if [ -z "`hostname -s`" ]; then hostname ${hostname} echo -n ' hostname' fi # Set the domainname if we're using NIS # case ${nisdomainname} in [Nn][Oo] | '') ;; *) domainname ${nisdomainname} echo -n ' domain' ;; esac echo '.' # Initial ATM interface configuration # case ${atm_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.atm ]; then . /etc/rc.atm atm_pass1 fi ;; esac # Special options for sppp(4) interfaces go here. These need # to go _before_ the general ifconfig section, since in the case # of hardwired (no link1 flag) but required authentication, you # cannot pass auth parameters down to the already running interface. # for ifn in ${sppp_interfaces}; do eval spppcontrol_args=\$spppconfig_${ifn} if [ -n "${spppcontrol_args}" ]; then # The auth secrets might contain spaces; in order # to retain the quotation, we need to eval them # here. eval spppcontrol ${ifn} ${spppcontrol_args} fi done # Set up all the network interfaces, calling startup scripts if needed # case ${network_interfaces} in [Aa][Uu][Tt][Oo]) network_interfaces="`ifconfig -l`" ;; esac dhcp_interfaces="" for ifn in ${network_interfaces}; do if [ -r /etc/start_if.${ifn} ]; then . /etc/start_if.${ifn} eval showstat_$ifn=1 fi # Do the primary ifconfig if specified # eval ifconfig_args=\$ifconfig_${ifn} case ${ifconfig_args} in '') ;; [Dd][Hh][Cc][Pp]) # DHCP inits are done all in one go below dhcp_interfaces="$dhcp_interfaces $ifn" eval showstat_$ifn=1 ;; *) ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 ;; esac done if [ ! -z "${dhcp_interfaces}" ]; then ${dhcp_program:-/sbin/dhclient} ${dhcp_flags} ${dhcp_interfaces} fi for ifn in ${network_interfaces}; do # Check to see if aliases need to be added # alias=0 while : ; do eval ifconfig_args=\$ifconfig_${ifn}_alias${alias} if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} alias eval showstat_$ifn=1 alias=`expr ${alias} + 1` else break; fi done # Do ipx address if specified # eval ifconfig_args=\$ifconfig_${ifn}_ipx if [ -n "${ifconfig_args}" ]; then ifconfig ${ifn} ${ifconfig_args} eval showstat_$ifn=1 fi done for ifn in ${network_interfaces}; do eval showstat=\$showstat_${ifn} if [ ! -z ${showstat} ]; then ifconfig ${ifn} fi done # ISDN subsystem startup # case ${isdn_enable} in [Yy][Ee][Ss]) if [ -r /etc/rc.isdn ]; then . /etc/rc.isdn fi ;; esac # Start user ppp if required. This must happen before natd. # case ${ppp_enable} in [Yy][Ee][Ss]) # Establish ppp mode. # if [ "${ppp_mode}" != "ddial" -a "${ppp_mode}" != "direct" \ -a "${ppp_mode}" != "dedicated" \ -a "${ppp_mode}" != "background" ]; then ppp_mode="auto" fi ppp_command="/usr/sbin/ppp -quiet -${ppp_mode}" # Switch on NAT mode? # case ${ppp_nat} in [Yy][Ee][Ss]) ppp_command="${ppp_command} -nat" ;; esac ppp_command="${ppp_command} ${ppp_profile}" echo -n "Starting ppp as \"${ppp_user}\"" su ${ppp_user} -c "exec ${ppp_command}" ;; esac # Initialize IP filtering using ipfw # if /sbin/ipfw -q flush > /dev/null 2>&1; then firewall_in_kernel=1 else firewall_in_kernel=0 fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ "${firewall_in_kernel}" -eq 0 ] && kldload ipfw; then firewall_in_kernel=1 echo "Kernel firewall module loaded." elif [ "${firewall_in_kernel}" -eq 0 ]; then echo "Warning: firewall kernel module failed to load." fi ;; esac # Load the filters if required # case ${firewall_in_kernel} in 1) if [ -z "${firewall_script}" ]; then firewall_script=/etc/rc.firewall fi case ${firewall_enable} in [Yy][Ee][Ss]) if [ -r "${firewall_script}" ]; then . "${firewall_script}" echo -n 'Firewall rules loaded, starting divert daemons:' # Network Address Translation daemon # case ${natd_enable} in [Yy][Ee][Ss]) if [ -n "${natd_interface}" ]; then if echo ${natd_interface} | \ grep -q -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then natd_ifarg="-a ${natd_interface}" else natd_ifarg="-n ${natd_interface}" fi echo -n ' natd'; ${natd_program:-/sbin/natd} ${natd_flags} ${natd_ifarg} fi ;; esac echo '.' elif [ "`ipfw l 65535`" = "65535 deny ip from any to any" ]; then echo -n "Warning: kernel has firewall functionality, " echo "but firewall rules are not enabled." echo " All ip services are disabled." fi case ${firewall_logging} in [Yy][Ee][Ss] | '') echo 'Firewall logging=YES' sysctl -w net.inet.ip.fw.verbose=1 >/dev/null ;; *) ;; esac ;; esac ;; esac # Additional ATM interface configuration # if [ -n "${atm_pass1_done}" ]; then atm_pass2 fi # Configure routing # case ${defaultrouter} in [Nn][Oo] | '') ;; *) static_routes="default ${static_routes}" route_default="default ${defaultrouter}" ;; esac # Set up any static routes. This should be done before router discovery. # if [ -n "${static_routes}" ]; then for i in ${static_routes}; do eval route_args=\$route_${i} route add ${route_args} done fi echo -n 'Additional routing options:' case ${tcp_extensions} in [Yy][Ee][Ss] | '') ;; *) echo -n ' tcp extensions=NO' sysctl -w net.inet.tcp.rfc1323=0 >/dev/null ;; esac case ${icmp_bmcastecho} in [Yy][Ee][Ss]) echo -n ' broadcast ping responses=YES' sysctl -w net.inet.icmp.bmcastecho=1 >/dev/null ;; esac case ${icmp_drop_redirect} in [Yy][Ee][Ss]) echo -n ' ignore ICMP redirect=YES' sysctl -w net.inet.icmp.drop_redirect=1 >/dev/null ;; esac case ${icmp_log_redirect} in [Yy][Ee][Ss]) echo -n ' log ICMP redirect=YES' sysctl -w net.inet.icmp.log_redirect=1 >/dev/null ;; esac case ${gateway_enable} in [Yy][Ee][Ss]) echo -n ' IP gateway=YES' sysctl -w net.inet.ip.forwarding=1 >/dev/null ;; esac case ${forward_sourceroute} in [Yy][Ee][Ss]) echo -n ' do source routing=YES' sysctl -w net.inet.ip.sourceroute=1 >/dev/null ;; esac case ${accept_sourceroute} in [Yy][Ee][Ss]) echo -n ' accept source routing=YES' sysctl -w net.inet.ip.accept_sourceroute=1 >/dev/null ;; esac case ${tcp_keepalive} in [Yy][Ee][Ss]) echo -n ' TCP keepalive=YES' sysctl -w net.inet.tcp.always_keepalive=1 >/dev/null ;; esac case ${tcp_restrict_rst} in [Yy][Ee][Ss]) echo -n ' restrict TCP reset=YES' sysctl -w net.inet.tcp.restrict_rst=1 >/dev/null ;; esac case ${tcp_drop_synfin} in [Yy][Ee][Ss]) echo -n ' drop SYN+FIN packets=YES' sysctl -w net.inet.tcp.drop_synfin=1 >/dev/null ;; esac case ${ipxgateway_enable} in [Yy][Ee][Ss]) echo -n ' IPX gateway=YES' sysctl -w net.ipx.ipx.ipxforwarding=1 >/dev/null ;; esac case ${arpproxy_all} in [Yy][Ee][Ss]) echo -n ' ARP proxyall=YES' sysctl -w net.link.ether.inet.proxyall=1 >/dev/null ;; esac case ${ip_portrange_first} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_first=$ip_portrange_first' sysctl -w net.inet.ip.portrange.first=$ip_portrange_first >/dev/null ;; esac case ${ip_portrange_last} in [Nn][Oo] | '') ;; *) echo -n ' ip_portrange_last=$ip_portrange_last' sysctl -w net.inet.ip.portrange.last=$ip_portrange_last >/dev/null ;; esac echo '.' case ${ipsec_enable} in [Yy][Ee][Ss]) if [ -f ${ipsec_file} ]; then echo ' ipsec: enabled' setkey -f ${ipsec_file} else echo ' ipsec: file not found' fi ;; esac echo -n 'routing daemons:' case ${router_enable} in [Yy][Ee][Ss]) echo -n " ${router}"; ${router} ${router_flags} ;; esac case ${ipxrouted_enable} in [Yy][Ee][Ss]) echo -n ' IPXrouted' IPXrouted ${ipxrouted_flags} > /dev/null 2>&1 ;; esac case ${mrouted_enable} in [Yy][Ee][Ss]) echo -n ' mrouted'; mrouted ${mrouted_flags} ;; esac case ${rarpd_enable} in [Yy][Ee][Ss]) echo -n ' rarpd'; rarpd ${rarpd_flags} ;; esac echo '.' # Let future generations know we made it. # network_pass1_done=YES } network_pass2() { echo -n 'Doing additional network setup:' case ${named_enable} in [Yy][Ee][Ss]) echo -n ' named'; ${named_program:-named} ${named_flags} ;; esac case ${ntpdate_enable} in [Yy][Ee][Ss]) echo -n ' ntpdate' ${ntpdate_program:-ntpdate} ${ntpdate_flags} >/dev/null 2>&1 ;; esac case ${xntpd_enable} in [Yy][Ee][Ss]) echo -n ' ntpd'; ${xntpd_program:-ntpd} ${xntpd_flags} ;; esac case ${timed_enable} in [Yy][Ee][Ss]) echo -n ' timed'; timed ${timed_flags} ;; esac case ${portmap_enable} in [Yy][Ee][Ss]) echo -n ' portmap'; ${portmap_program:-/usr/sbin/portmap} ${portmap_flags} ;; esac # Start ypserv if we're an NIS server. # Run rpc.ypxfrd and rpc.yppasswdd only on the NIS master server. # case ${nis_server_enable} in [Yy][Ee][Ss]) echo -n ' ypserv'; ypserv ${nis_server_flags} case ${nis_ypxfrd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypxfrd' rpc.ypxfrd ${nis_ypxfrd_flags} ;; esac case ${nis_yppasswdd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.yppasswdd' rpc.yppasswdd ${nis_yppasswdd_flags} ;; esac ;; esac # Start ypbind if we're an NIS client # case ${nis_client_enable} in [Yy][Ee][Ss]) echo -n ' ypbind'; ypbind ${nis_client_flags} case ${nis_ypset_enable} in [Yy][Ee][Ss]) echo -n ' ypset'; ypset ${nis_ypset_flags} ;; esac ;; esac # Start keyserv if we are running Secure RPC # case ${keyserv_enable} in [Yy][Ee][Ss]) echo -n ' keyserv'; keyserv ${keyserv_flags} ;; esac # Start ypupdated if we are running Secure RPC and we are NIS master # case ${rpc_ypupdated_enable} in [Yy][Ee][Ss]) echo -n ' rpc.ypupdated'; rpc.ypupdated ;; esac # Start ATM daemons if [ -n "${atm_pass2_done}" ]; then atm_pass3 fi echo '.' network_pass2_done=YES } network_pass3() { echo -n 'Starting final network daemons:' case ${nfs_server_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="${mountd_flags} -n" ;; esac mountd ${mountd_flags} case ${nfs_reserved_port_only} in [Yy][Ee][Ss]) echo -n ' NFS on reserved port only=YES' sysctl -w vfs.nfs.nfs_privport=1 >/dev/null ;; esac echo -n ' nfsd'; nfsd ${nfs_server_flags} if [ -n "${nfs_bufpackets}" ]; then sysctl -w vfs.nfs.bufpackets=${nfs_bufpackets} \ > /dev/null fi case ${rpc_lockd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.lockd'; rpc.lockd ;; esac case ${rpc_statd_enable} in [Yy][Ee][Ss]) echo -n ' rpc.statd'; rpc.statd ;; esac fi ;; *) case ${single_mountd_enable} in [Yy][Ee][Ss]) if [ -r /etc/exports ]; then echo -n ' mountd' case ${weak_mountd_authentication} in [Yy][Ee][Ss]) mountd_flags="-n" ;; esac mountd ${mountd_flags} fi ;; esac ;; esac case ${nfs_client_enable} in [Yy][Ee][Ss]) echo -n ' nfsiod'; nfsiod ${nfs_client_flags} if [ -n "${nfs_access_cache}" ]; then echo -n " NFS access cache time=${nfs_access_cache}" sysctl -w vfs.nfs.access_cache_timeout=${nfs_access_cache} \ >/dev/null fi ;; esac # If /var/db/mounttab exists, some nfs-server has not been # sucessfully notified about a previous client shutdown. # If there is no /var/db/mounttab, we do nothing. if [ -f /var/db/mounttab ]; then rpc.umntall -k fi case ${amd_enable} in [Yy][Ee][Ss]) echo -n ' amd' case ${amd_map_program} in [Nn][Oo] | '') ;; *) amd_flags="${amd_flags} `eval ${amd_map_program}`" ;; esac if [ -n "${amd_flags}" ]; then amd -p ${amd_flags} > /var/run/amd.pid 2> /dev/null else amd 2> /dev/null fi ;; esac case ${rwhod_enable} in [Yy][Ee][Ss]) echo -n ' rwhod'; rwhod ${rwhod_flags} ;; esac # Kerberos runs ONLY on the Kerberos server machine case ${kerberos_server_enable} in [Yy][Ee][Ss]) case ${kerberos_stash} in [Yy][Ee][Ss]) stash_flag=-n ;; *) stash_flag= ;; esac echo -n ' kerberos' kerberos ${stash_flag} >> /var/log/kerberos.log & case ${kadmind_server_enable} in [Yy][Ee][Ss]) echo -n ' kadmind' (sleep 20; kadmind ${stash_flag} >/dev/null 2>&1 &) & ;; esac unset stash_flag ;; esac case ${pppoed_enable} in [Yy][Ee][Ss]) if [ -n "${pppoed_provider}" ]; then pppoed_flags="${pppoed_flags} -p ${pppoed_provider}" fi echo -n ' pppoed'; /usr/libexec/pppoed ${pppoed_flags} ${pppoed_interface} ;; esac case ${sshd_enable} in [Yy][Ee][Ss]) if [ ! -f /etc/ssh/ssh_host_key ]; then echo ' creating ssh RSA host key'; /usr/bin/ssh-keygen -N "" -f /etc/ssh/ssh_host_key fi if [ ! -f /etc/ssh/ssh_host_dsa_key ]; then echo ' creating ssh DSA host key'; /usr/bin/ssh-keygen -d -N "" -f /etc/ssh/ssh_host_dsa_key fi ;; esac echo '.' network_pass3_done=YES } network_pass4() { echo -n 'Additional TCP options:' case ${log_in_vain} in [Nn][Oo] | '') ;; *) echo -n ' log_in_vain=YES' sysctl -w net.inet.tcp.log_in_vain=1 >/dev/null sysctl -w net.inet.udp.log_in_vain=1 >/dev/null ;; esac echo '.' network_pass4_done=YES } + +convert_host_conf() { + host_conf=$1; shift; + nsswitch_conf=$1; shift; + awk ' \ + /^[:blank:]*#/ { next } \ + /(hosts|local|file)/ { nsswitch[c] = "files"; c++; next } \ + /(dns|bind)/ { nsswitch[c] = "dns"; c++; next } \ + /nis/ { nsswitch[c] = "nis"; c++; next } \ + { printf "Warning: unrecognized line [%s]", $0 > "/dev/stderr" } \ + END { \ + printf "hosts: "; \ + for (i in nsswitch) printf "%s ", nsswitch[i]; \ + printf "\n"; \ + }' < $host_conf > $nsswitch_conf +} + Index: head/include/Makefile =================================================================== --- head/include/Makefile (revision 65531) +++ head/include/Makefile (revision 65532) @@ -1,140 +1,141 @@ # @(#)Makefile 8.2 (Berkeley) 1/4/94 # $FreeBSD$ # # Doing a make install builds /usr/include # # The ``rm -rf''s used below are safe because rm doesn't follow symbolic # links. CLEANFILES= osreldate.h version vers.c SUBDIR= rpcsvc FILES= a.out.h ar.h assert.h bitstring.h ctype.h db.h dirent.h disktab.h \ dlfcn.h elf.h err.h fnmatch.h fstab.h \ - fts.h glob.h grp.h strhash.h histedit.h ieeefp.h ifaddrs.h iso646.h \ + fts.h glob.h grp.h strhash.h \ + hesiod.h histedit.h ieeefp.h ifaddrs.h iso646.h \ libgen.h limits.h link.h locale.h malloc.h memory.h mpool.h \ ndbm.h netdb.h nl_types.h nlist.h objformat.h \ paths.h pthread.h pthread_np.h pwd.h \ ranlib.h regex.h regexp.h resolv.h rune.h runetype.h \ search.h setjmp.h sgtty.h \ signal.h stab.h stddef.h stdio.h stdlib.h string.h stringlist.h \ strings.h struct.h sysexits.h tar.h time.h timers.h \ ttyent.h unistd.h utime.h utmp.h vis.h .if defined(WANT_CSRG_LIBM) FILES+= math.h .endif ARPAFILES= ftp.h inet.h nameser.h nameser_compat.h telnet.h tftp.h PROTOFILES= dumprestore.h routed.h rwhod.h talkd.h timed.h RPCFILES= auth.h auth_unix.h clnt.h pmap_clnt.h pmap_prot.h pmap_rmt.h \ rpc.h rpc_com.h rpc_msg.h svc.h svc_auth.h types.h xdr.h \ auth_des.h des.h des_crypt.h MFILES= float.h floatingpoint.h stdarg.h varargs.h # posix4/aio.h conflicts with dysons and isn't installed: PFILES= mqueue.h sched.h semaphore.h # aio.h # Only for default SHARED=copies case SFILES= soundcard.h joystick.h LFILES= aio.h errno.h fcntl.h inttypes.h linker_set.h poll.h syslog.h \ termios.h ucontext.h LDIRS= cam msdosfs net netatalk netatm netgraph netinet netinet6 \ netipx netkey netncp netns nfs ntfs nwfs pccard posix4 sys vm LNOHEADERDIRS= isofs ufs dev LSUBDIRS= isofs/cd9660 ufs/ffs ufs/mfs ufs/ufs cam/scsi dev/ppbus dev/usb # For SHARED=symlinks, cam is a symlink, so cam/scsi is taken care of LSYMSUBDIRS= isofs/cd9660 ufs/ffs ufs/mfs ufs/ufs dev/ppbus dev/usb # Define SHARED to indicate whether you want symbolic links to the system # source (``symlinks''), or a separate copy (``copies''). ``symlinks'' is # probably only useful for developers and should be avoided if you do not # wish to tie your /usr/include and /usr/src together. #SHARED= symlinks SHARED?= copies all: osreldate.h osreldate.h: ${.CURDIR}/../sys/conf/newvers.sh \ ${.CURDIR}/../sys/sys/param.h @${ECHO} creating osreldate.h from newvers.sh setvar PARAMFILE ${.CURDIR}/../sys/sys/param.h; \ . ${.CURDIR}/../sys/conf/newvers.sh; \ echo "$$COPYRIGHT" > osreldate.h; \ echo \#'undef __FreeBSD_version' >> osreldate.h; \ echo \#'define __FreeBSD_version' $$RELDATE >> osreldate.h beforeinstall: ${SHARED} @rm -f ${DESTDIR}/usr/include/timepps.h cd ${.CURDIR}; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ ${FILES} ${DESTDIR}/usr/include cd ${.CURDIR}/arpa; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ ${ARPAFILES} ${DESTDIR}/usr/include/arpa cd ${.CURDIR}/protocols; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ ${PROTOFILES} ${DESTDIR}/usr/include/protocols cd ${.CURDIR}/rpc; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ ${RPCFILES} ${DESTDIR}/usr/include/rpc ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ ${.OBJDIR}/osreldate.h \ ${DESTDIR}/usr/include .for i in ${LFILES} ln -sf sys/$i ${DESTDIR}/usr/include/$i .endfor .for i in ${MFILES} ln -sf machine/$i ${DESTDIR}/usr/include/$i .endfor .for i in ${PFILES} ln -sf posix4/$i ${DESTDIR}/usr/include/$i .endfor copies: .for i in ${LDIRS} ${LSYMSUBDIRS} machine if [ -h ${DESTDIR}/usr/include/$i ]; then \ rm -f ${DESTDIR}/usr/include/$i; \ fi .endfor .for i in ${LNOHEADERDIRS} rm -rf ${DESTDIR}/usr/include/$i .endfor mtree -deU -f ${.CURDIR}/../etc/mtree/BSD.include.dist \ -p ${DESTDIR}/usr/include .for i in ${LDIRS} ${LSUBDIRS} cd ${.CURDIR}/../sys; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \ ${DESTDIR}/usr/include/$i .endfor .if exists(${.CURDIR}/../sys/${MACHINE_ARCH}/include) cd ${.CURDIR}/../sys/${MACHINE_ARCH}/include; \ ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 *.h \ ${DESTDIR}/usr/include/machine .endif .for i in ${SFILES} ln -sf ../sys/$i ${DESTDIR}/usr/include/machine/$i .endfor symlinks: @${ECHO} "Setting up symlinks to kernel source tree..." .for i in ${LDIRS} rm -rf ${DESTDIR}/usr/include/$i ln -s ../../sys/$i ${DESTDIR}/usr/include/$i .endfor .for i in ${LNOHEADERDIRS} rm -rf ${DESTDIR}/usr/include/$i mkdir ${DESTDIR}/usr/include/$i .endfor .for i in ${LSYMSUBDIRS} ln -s ../../../sys/$i ${DESTDIR}/usr/include/$i .endfor rm -rf ${DESTDIR}/usr/include/machine ln -s ../../sys/${MACHINE_ARCH}/include ${DESTDIR}/usr/include/machine .include Index: head/include/hesiod.h =================================================================== --- head/include/hesiod.h (nonexistent) +++ head/include/hesiod.h (revision 65532) @@ -0,0 +1,98 @@ +/* $NetBSD: hesiod.h,v 1.3 1999/01/24 23:53:18 lukem Exp $ */ +/* $FreeBSD$ */ + + +/*- + * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef _HESIOD_H_ +#define _HESIOD_H_ + + /* Application-visible indication that we have the new interfaces */ + +#define HESIOD_INTERFACES + + /* Configuration information. */ + +#ifndef _PATH_HESIOD_CONF /* Configuration file. */ +#define _PATH_HESIOD_CONF "/etc/hesiod.conf" +#endif + +#define DEF_RHS "" /* Defaults if HESIOD_CONF */ +#define DEF_LHS "" /* file is not present. */ + + /* Error codes (for backwards compatibility) */ + +#define HES_ER_UNINIT -1 /* uninitialized */ +#define HES_ER_OK 0 /* no error */ +#define HES_ER_NOTFOUND 1 /* Hesiod name not found by server */ +#define HES_ER_CONFIG 2 /* local problem (no config file?) */ +#define HES_ER_NET 3 /* network problem */ + + /* Declaration of routines */ + +#include + +__BEGIN_DECLS +int hesiod_init __P((void **)); +char **hesiod_resolve __P((void *, const char *, const char *)); +void hesiod_free_list __P((void *, char **)); +char *hesiod_to_bind __P((void *, const char *, const char *)); +void hesiod_end __P((void *)); + + /* backwards compatibility */ +int hes_init __P((void)); +char *hes_to_bind __P((const char *, const char *)); +char **hes_resolve __P((const char *, const char *)); +int hes_error __P((void)); +void hes_free __P((char **)); +__END_DECLS + +#endif /* ! _HESIOD_H_ */ Property changes on: head/include/hesiod.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/include/netdb.h =================================================================== --- head/include/netdb.h (revision 65531) +++ head/include/netdb.h (revision 65532) @@ -1,259 +1,249 @@ /*- * Copyright (c) 1980, 1983, 1988, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ /* * @(#)netdb.h 8.1 (Berkeley) 6/2/93 * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $ * $FreeBSD$ */ #ifndef _NETDB_H_ #define _NETDB_H_ #include #include #ifndef _PATH_HEQUIV # define _PATH_HEQUIV "/etc/hosts.equiv" #endif #define _PATH_HOSTS "/etc/hosts" #define _PATH_NETWORKS "/etc/networks" #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" extern int h_errno; /* * Structures returned by network data base library. All addresses are * supplied in host order, and returned in network order (suitable for * use in system calls). */ struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ #define h_addr h_addr_list[0] /* address, for backward compatibility */ }; /* * Assumption here is that a network number * fits in an unsigned long -- probably a poor one. */ struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ unsigned long n_net; /* network # */ }; struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port # */ char *s_proto; /* protocol to use */ }; struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ }; struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; /* * Error return codes from gethostbyname() and gethostbyaddr() * (left in extern int h_errno). */ #define NETDB_INTERNAL -1 /* see errno */ #define NETDB_SUCCESS 0 /* no problem */ #define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ #define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */ #define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ #define NO_DATA 4 /* Valid name, no data record of requested type */ #define NO_ADDRESS NO_DATA /* no address, look for MX record */ /* * Error return codes from getaddrinfo() */ #define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ #define EAI_AGAIN 2 /* temporary failure in name resolution */ #define EAI_BADFLAGS 3 /* invalid value for ai_flags */ #define EAI_FAIL 4 /* non-recoverable failure in name resolution */ #define EAI_FAMILY 5 /* ai_family not supported */ #define EAI_MEMORY 6 /* memory allocation failure */ #define EAI_NODATA 7 /* no address associated with hostname */ #define EAI_NONAME 8 /* hostname nor servname provided, or not known */ #define EAI_SERVICE 9 /* servname not supported for ai_socktype */ #define EAI_SOCKTYPE 10 /* ai_socktype not supported */ #define EAI_SYSTEM 11 /* system error returned in errno */ #define EAI_BADHINTS 12 #define EAI_PROTOCOL 13 #define EAI_RESNULL 14 #define EAI_MAX 15 /* * Flag values for getaddrinfo() */ #define AI_PASSIVE 0x00000001 /* get address to use bind() */ #define AI_CANONNAME 0x00000002 /* fill ai_canonname */ #define AI_NUMERICHOST 0x00000004 /* prevent name resolution */ /* valid flags for addrinfo */ #define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ #define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */ #define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */ /* special recommended flags for getipnodebyname */ #define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG) /* * Constants for getnameinfo() */ #define NI_MAXHOST 1025 #define NI_MAXSERV 32 /* * Flag values for getnameinfo() */ #define NI_NOFQDN 0x00000001 #define NI_NUMERICHOST 0x00000002 #define NI_NAMEREQD 0x00000004 #define NI_NUMERICSERV 0x00000008 #define NI_DGRAM 0x00000010 #define NI_WITHSCOPEID 0x00000020 /* * Scope delimit character */ #define SCOPE_DELIMITER '%' __BEGIN_DECLS void endhostent __P((void)); void endnetent __P((void)); void endprotoent __P((void)); void endservent __P((void)); void freehostent __P((struct hostent *)); struct hostent *gethostbyaddr __P((const char *, int, int)); struct hostent *gethostbyname __P((const char *)); struct hostent *gethostbyname2 __P((const char *, int)); struct hostent *gethostent __P((void)); struct hostent *getipnodebyaddr __P((const void *, size_t, int, int *)); struct hostent *getipnodebyname __P((const char *, int, int, int *)); struct netent *getnetbyaddr __P((unsigned long, int)); struct netent *getnetbyname __P((const char *)); struct netent *getnetent __P((void)); struct protoent *getprotobyname __P((const char *)); struct protoent *getprotobynumber __P((int)); struct protoent *getprotoent __P((void)); struct servent *getservbyname __P((const char *, const char *)); struct servent *getservbyport __P((int, const char *)); struct servent *getservent __P((void)); void herror __P((const char *)); __const char *hstrerror __P((int)); void sethostent __P((int)); /* void sethostfile __P((const char *)); */ void setnetent __P((int)); void setprotoent __P((int)); int getaddrinfo __P((const char *, const char *, const struct addrinfo *, struct addrinfo **)); int getnameinfo __P((const struct sockaddr *, size_t, char *, size_t, char *, size_t, int)); void freeaddrinfo __P((struct addrinfo *)); char *gai_strerror __P((int)); void setservent __P((int)); /* * PRIVATE functions specific to the FreeBSD implementation */ /* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */ void _sethosthtent __P((int)); void _endhosthtent __P((void)); void _sethostdnsent __P((int)); void _endhostdnsent __P((void)); void _setnethtent __P((int)); void _endnethtent __P((void)); void _setnetdnsent __P((int)); void _endnetdnsent __P((void)); -struct hostent * _gethostbyhtname __P((const char *, int)); -struct hostent * _gethostbydnsname __P((const char *, int)); struct hostent * _gethostbynisname __P((const char *, int)); -struct hostent * _gethostbyhtaddr __P((const char *, int, int)); -struct hostent * _gethostbydnsaddr __P((const char *, int, int)); struct hostent * _gethostbynisaddr __P((const char *, int, int)); -struct netent * _getnetbyhtname __P((const char *)); -struct netent * _getnetbydnsname __P((const char *)); -struct netent * _getnetbynisname __P((const char *)); -struct netent * _getnetbyhtaddr __P((unsigned long, int)); -struct netent * _getnetbydnsaddr __P((unsigned long, int)); -struct netent * _getnetbynisaddr __P((unsigned long, int)); void _map_v4v6_address __P((const char *src, char *dst)); void _map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len)); __END_DECLS #endif /* !_NETDB_H_ */ Index: head/include/nsswitch.h =================================================================== --- head/include/nsswitch.h (nonexistent) +++ head/include/nsswitch.h (revision 65532) @@ -0,0 +1,188 @@ +/* $NetBSD: nsswitch.h,v 1.6 1999/01/26 01:04:07 lukem Exp $ */ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _NSSWITCH_H +#define _NSSWITCH_H 1 + +#include + +#if __STDC__ +#include +#else +#include +#endif + +#ifndef _PATH_NS_CONF +#define _PATH_NS_CONF "/etc/nsswitch.conf" +#endif + +#define NS_CONTINUE 0 +#define NS_RETURN 1 + +#define NS_SUCCESS (1<<0) /* entry was found */ +#define NS_UNAVAIL (1<<1) /* source not responding, or corrupt */ +#define NS_NOTFOUND (1<<2) /* source responded 'no such entry' */ +#define NS_TRYAGAIN (1<<3) /* source busy, may respond to retrys */ +#define NS_STATUSMASK 0x000000ff /* bitmask to get the status flags */ + +/* + * currently implemented sources + */ +#define NSSRC_FILES "files" /* local files */ +#define NSSRC_DNS "dns" /* DNS; IN for hosts, HS for others */ +#define NSSRC_NIS "nis" /* YP/NIS */ +#define NSSRC_COMPAT "compat" /* passwd,group in YP compat mode */ + +/* + * currently implemented databases + */ +#define NSDB_HOSTS "hosts" +#define NSDB_GROUP "group" +#define NSDB_GROUP_COMPAT "group_compat" +#define NSDB_NETGROUP "netgroup" +#define NSDB_NETWORKS "networks" +#define NSDB_PASSWD "passwd" +#define NSDB_PASSWD_COMPAT "passwd_compat" +#define NSDB_SHELLS "shells" + +/* + * suggested databases to implement + */ +#define NSDB_ALIASES "aliases" +#define NSDB_AUTH "auth" +#define NSDB_AUTOMOUNT "automount" +#define NSDB_BOOTPARAMS "bootparams" +#define NSDB_ETHERS "ethers" +#define NSDB_EXPORTS "exports" +#define NSDB_NETMASKS "netmasks" +#define NSDB_PHONES "phones" +#define NSDB_PRINTCAP "printcap" +#define NSDB_PROTOCOLS "protocols" +#define NSDB_REMOTE "remote" +#define NSDB_RPC "rpc" +#define NSDB_SENDMAILVARS "sendmailvars" +#define NSDB_SERVICES "services" +#define NSDB_TERMCAP "termcap" +#define NSDB_TTYS "ttys" + +/* + * ns_dtab - `nsswitch dispatch table' + * contains an entry for each source and the appropriate function to call + */ +typedef struct { + const char *src; + int (*callback)(void *retval, void *cb_data, va_list ap); + void *cb_data; +} ns_dtab; + +/* + * macros to help build an ns_dtab[] + */ +#define NS_FILES_CB(F,C) { NSSRC_FILES, F, C }, +#define NS_COMPAT_CB(F,C) { NSSRC_COMPAT, F, C }, + +#ifdef HESIOD +# define NS_DNS_CB(F,C) { NSSRC_DNS, F, C }, +#else +# define NS_DNS_CB(F,C) +#endif + +#ifdef YP +# define NS_NIS_CB(F,C) { NSSRC_NIS, F, C }, +#else +# define NS_NIS_CB(F,C) +#endif + +/* + * ns_src - `nsswitch source' + * used by the nsparser routines to store a mapping between a source + * and its dispatch control flags for a given database. + */ +typedef struct { + const char *name; + u_int32_t flags; +} ns_src; + + +/* + * default sourcelist (if nsswitch.conf is missing, corrupt, + * or the requested database doesn't have an entry. + */ +extern const ns_src __nsdefaultsrc[]; + + +#ifdef _NS_PRIVATE + +/* + * private data structures for back-end nsswitch implementation + */ + +/* + * ns_dbt - `nsswitch database thang' + * for each database in /etc/nsswitch.conf there is a ns_dbt, with its + * name and a list of ns_src's containing the source information. + */ +typedef struct { + const char *name; /* name of database */ + ns_src *srclist; /* list of sources */ + int srclistsize; /* size of srclist */ +} ns_dbt; + +#endif /* _NS_PRIVATE */ + + +#include + +__BEGIN_DECLS +extern int nsdispatch __P((void *, const ns_dtab [], const char *, + const char *, const ns_src [], ...)); + +#ifdef _NS_PRIVATE +extern void _nsdbtaddsrc __P((ns_dbt *, const ns_src *)); +extern void _nsdbtdump __P((const ns_dbt *)); +extern const ns_dbt *_nsdbtget __P((const char *)); +extern void _nsdbtput __P((const ns_dbt *)); +extern void _nsyyerror __P((const char *)); +extern int _nsyylex __P((void)); +extern int _nsyylineno; +#endif /* _NS_PRIVATE */ + +__END_DECLS + +#endif /* !_NSSWITCH_H */ Property changes on: head/include/nsswitch.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libc/Makefile.inc =================================================================== --- head/lib/libc/Makefile.inc (revision 65531) +++ head/lib/libc/Makefile.inc (revision 65532) @@ -1,56 +1,59 @@ # $FreeBSD$ # # This file contains make rules that are shared by libc and libc_r. # # Define (empty) variables so that make doesn't give substitution # errors if the included makefiles don't change these: MDSRCS= MISRCS= MDASM= MIASM= NOASM= # # If there is a machine dependent makefile, use it: # .if exists(${.CURDIR}/../libc/${MACHINE_ARCH}/Makefile.inc) .include "${.CURDIR}/../libc/${MACHINE_ARCH}/Makefile.inc" .endif .include "${.CURDIR}/../libc/db/Makefile.inc" .include "${.CURDIR}/../libc/compat-43/Makefile.inc" .include "${.CURDIR}/../libc/gen/Makefile.inc" .include "${.CURDIR}/../libc/gmon/Makefile.inc" .include "${.CURDIR}/../libc/locale/Makefile.inc" .include "${.CURDIR}/../libc/net/Makefile.inc" .include "${.CURDIR}/../libc/nls/Makefile.inc" .if !defined(NO_QUAD) .include "${.CURDIR}/../libc/quad/Makefile.inc" .endif .include "${.CURDIR}/../libc/regex/Makefile.inc" .include "${.CURDIR}/../libc/stdio/Makefile.inc" .include "${.CURDIR}/../libc/stdlib/Makefile.inc" .include "${.CURDIR}/../libc/stdtime/Makefile.inc" .include "${.CURDIR}/../libc/string/Makefile.inc" .include "${.CURDIR}/../libc/sys/Makefile.inc" .include "${.CURDIR}/../libc/rpc/Makefile.inc" .include "${.CURDIR}/../libc/xdr/Makefile.inc" .if !defined(NO_YP_LIBC) CFLAGS+= -DYP .include "${.CURDIR}/../libc/yp/Makefile.inc" .endif +.if !defined(NO_HESIOD_LIBC) +CFLAGS+= -DHESIOD +.endif # If there are no machine dependent sources, append all the # machine-independent sources: .if empty(MDSRCS) SRCS+= ${MISRCS} .else # Append machine-dependent sources, then append machine-independent sources # for which there is no machine-dependent variant. SRCS+= ${MDSRCS} .for _src in ${MISRCS} .if ${MDSRCS:R:M${_src:R}} == "" SRCS+= ${_src} .endif .endfor .endif Index: head/lib/libc/gen/Makefile.inc =================================================================== --- head/lib/libc/gen/Makefile.inc (revision 65531) +++ head/lib/libc/gen/Makefile.inc (revision 65532) @@ -1,128 +1,128 @@ # @(#)Makefile.inc 8.6 (Berkeley) 5/4/95 # $FreeBSD$ # machine-independent gen sources .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/gen ${.CURDIR}/../libc/gen SRCS+= _rand48.c _spinlock_stub.c alarm.c arc4random.c assert.c \ basename.c \ clock.c closedir.c confstr.c \ crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \ dlfcn.c drand48.c erand48.c err.c errlst.c \ exec.c fnmatch.c fstab.c ftok.c fts.c getbootfile.c getbsize.c \ getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \ gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \ getobjformat.c getosreldate.c getpagesize.c \ getpass.c getpwent.c getttyent.c \ getusershell.c getvfsbyname.c getvfsent.c glob.c \ initgroups.c isatty.c jrand48.c lcong48.c \ lockf.c lrand48.c mrand48.c msgctl.c \ msgget.c msgrcv.c msgsnd.c nice.c \ nlist.c nrand48.c ntp_gettime.c opendir.c \ - pause.c popen.c psignal.c pwcache.c raise.c readdir.c rewinddir.c \ + pause.c popen.c psignal.c pw_scan.c pwcache.c raise.c readdir.c rewinddir.c \ posixshm.c \ scandir.c seed48.c seekdir.c semconfig.c semctl.c semget.c semop.c \ setdomainname.c sethostname.c setjmperr.c setmode.c setproctitle.c \ shmat.c shmctl.c shmdt.c shmget.c siginterrupt.c siglist.c signal.c \ sigsetops.c sleep.c srand48.c stringlist.c strtofflags.c \ sysconf.c sysctl.c sysctlbyname.c \ syslog.c telldir.c termios.c time.c times.c timezone.c ttyname.c \ ttyslot.c ualarm.c uname.c unvis.c usleep.c utime.c valloc.c vis.c \ wait.c wait3.c waitpid.c # machine-dependent gen sources .include "${.CURDIR}/../libc/${MACHINE_ARCH}/gen/Makefile.inc" .if ${LIB} == "c" MAN3+= alarm.3 arc4random.3 clock.3 \ basename.3 \ confstr.3 ctermid.3 daemon.3 \ devname.3 directory.3 dirname.3 dladdr.3 dllockinit.3 dlopen.3 \ err.3 exec.3 fnmatch.3 frexp.3 ftok.3 fts.3 \ getbootfile.3 getbsize.3 getcap.3 getcwd.3 \ getdiskbyname.3 getdomainname.3 getfsent.3 \ getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \ getmntinfo.3 getnetgrent.3 getobjformat.3 \ getpagesize.3 getpass.3 getpwent.3 \ getttyent.3 getusershell.3 getvfsbyname.3 getvfsent.3 \ glob.3 initgroups.3 isinf.3 \ ldexp.3 lockf.3 modf.3 msgctl.3 msgget.3 msgrcv.3 msgsnd.3 \ nice.3 nlist.3 pause.3 popen.3 psignal.3 pwcache.3 \ raise.3 rand48.3 rfork_thread.3 \ scandir.3 setjmp.3 setmode.3 setproctitle.3 shm_open.3 \ siginterrupt.3 signal.3 sigsetops.3 sleep.3 stringlist.3 \ strtofflags.3 sysconf.3 sysctl.3 syslog.3 tcgetpgrp.3 \ tcsendbreak.3 tcsetattr.3 tcsetpgrp.3 time.3 times.3 timezone.3 \ ttyname.3 tzset.3 ualarm.3 uname.3 unvis.3 usleep.3 utime.3 \ valloc.3 vis.3 MLINKS+=arc4random.3 arc4random_addrandom.3 arc4random.3 arc4random_stir.3 MLINKS+=crypt.3 des_cipher.3 crypt.3 des_setkey.3 crypt.3 encrypt.3 \ crypt.3 setkey.3 MLINKS+=ctermid.3 ctermid_r.3 MLINKS+=directory.3 closedir.3 directory.3 dirfd.3 directory.3 opendir.3 \ directory.3 readdir.3 directory.3 rewinddir.3 directory.3 seekdir.3 \ directory.3 telldir.3 MLINKS+=dlopen.3 dlclose.3 dlopen.3 dlerror.3 dlopen.3 dlsym.3 MLINKS+=err.3 err_set_exit.3 err.3 err_set_file.3 err.3 errc.3 err.3 errx.3 \ err.3 verr.3 err.3 verrc.3 err.3 verrx.3 err.3 vwarn.3 err.3 vwarnc.3 \ err.3 vwarnx.3 err.3 warnc.3 err.3 warn.3 err.3 warnx.3 MLINKS+=exec.3 execl.3 exec.3 execle.3 exec.3 execlp.3 exec.3 exect.3 \ exec.3 execv.3 exec.3 execvp.3 MLINKS+=fts.3 fts_children.3 fts.3 fts_close.3 fts.3 fts_open.3 \ fts.3 fts_read.3 fts.3 fts_set.3 MLINKS+=getcap.3 cgetcap.3 getcap.3 cgetclose.3 getcap.3 cgetent.3 \ getcap.3 cgetfirst.3 getcap.3 cgetmatch.3 getcap.3 cgetnext.3 \ getcap.3 cgetnum.3 getcap.3 cgetset.3 getcap.3 cgetstr.3 \ getcap.3 cgetustr.3 MLINKS+=getcwd.3 getwd.3 MLINKS+=getdomainname.3 setdomainname.3 MLINKS+=getfsent.3 endfsent.3 getfsent.3 getfsfile.3 getfsent.3 getfsspec.3 \ getfsent.3 getfstype.3 getfsent.3 setfsent.3 MLINKS+=getgrent.3 endgrent.3 getgrent.3 getgrgid.3 getgrent.3 getgrnam.3 \ getgrent.3 setgrent.3 getgrent.3 setgroupent.3 MLINKS+=gethostname.3 sethostname.3 MLINKS+=getnetgrent.3 endnetgrent.3 getnetgrent.3 innetgr.3 \ getnetgrent.3 setnetgrent.3 MLINKS+=getpwent.3 endpwent.3 getpwent.3 getpwnam.3 getpwent.3 getpwuid.3 \ getpwent.3 setpassent.3 getpwent.3 setpwent.3 getpwent.3 setpwfile.3 MLINKS+=getttyent.3 endttyent.3 getttyent.3 getttynam.3 \ getttyent.3 isdialuptty.3 getttyent.3 isnettty.3 \ getttyent.3 setttyent.3 MLINKS+=getusershell.3 endusershell.3 getusershell.3 setusershell.3 MLINKS+=getvfsent.3 endvfsent.3 getvfsent.3 getvfsbytype.3 \ getvfsent.3 setvfsent.3 getvfsent.3 vfsisloadable.3 \ getvfsent.3 vfsload.3 MLINKS+=glob.3 globfree.3 MLINKS+=isinf.3 isnan.3 isinf.3 isnanf.3 MLINKS+=popen.3 pclose.3 MLINKS+=psignal.3 sys_siglist.3 psignal.3 sys_signame.3 MLINKS+=psignal.3 strsignal.3 psignal.3 sys_siglist.3 psignal.3 sys_signame.3 MLINKS+=pwcache.3 group_from_gid.3 pwcache.3 user_from_uid.3 MLINKS+=rand48.3 _rand48.3 rand48.3 drand48.3 rand48.3 erand48.3 \ rand48.3 jrand48.3 rand48.3 lcong48.3 rand48.3 lrand48.3 \ rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 seed48.3 \ rand48.3 srand48.3 MLINKS+=scandir.3 alphasort.3 MLINKS+=strtofflags.3 fflagstostr.3 MLINKS+=setjmp.3 _longjmp.3 setjmp.3 _setjmp.3 setjmp.3 longjmp.3 \ setjmp.3 longjmperr.3 setjmp.3 longjmperror.3 \ setjmp.3 siglongjmp.3 setjmp.3 sigsetjmp.3 MLINKS+=setmode.3 getmode.3 MLINKS+=shm_open.3 shm_unlink.3 MLINKS+=sigsetops.3 sigaddset.3 sigsetops.3 sigdelset.3 \ sigsetops.3 sigemptyset.3 sigsetops.3 sigfillset.3 \ sigsetops.3 sigismember.3 MLINKS+=sysctl.3 sysctlbyname.3 MLINKS+=syslog.3 closelog.3 syslog.3 openlog.3 syslog.3 setlogmask.3 \ syslog.3 vsyslog.3 MLINKS+=tcsendbreak.3 tcdrain.3 tcsendbreak.3 tcflow.3 tcsendbreak.3 tcflush.3 MLINKS+=tcsetattr.3 cfgetispeed.3 tcsetattr.3 cfgetospeed.3 \ tcsetattr.3 cfmakeraw.3 tcsetattr.3 cfsetispeed.3 \ tcsetattr.3 cfsetospeed.3 tcsetattr.3 cfsetspeed.3 \ tcsetattr.3 tcgetattr.3 MLINKS+=ttyname.3 isatty.3 ttyname.3 ttyslot.3 MLINKS+=tzset.3 tzsetwall.3 MLINKS+=unvis.3 strunvis.3 unvis.3 strunvisx.3 MLINKS+=vis.3 strvis.3 vis.3 strvisx.3 .endif Index: head/lib/libc/gen/getgrent.3 =================================================================== --- head/lib/libc/gen/getgrent.3 (revision 65531) +++ head/lib/libc/gen/getgrent.3 (revision 65532) @@ -1,208 +1,204 @@ .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)getgrent.3 8.2 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" .Dd September 29, 1994 .Dt GETGRENT 3 .Os .Sh NAME .Nm getgrent , .Nm getgrnam , .Nm getgrgid , .Nm setgroupent , .\" .Nm setgrfile , .Nm setgrent , .Nm endgrent .Nd group database operations .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Fd #include .Ft struct group * .Fn getgrent void .Ft struct group * .Fn getgrnam "const char *name" .Ft struct group * .Fn getgrgid "gid_t gid" .Ft int .Fn setgroupent "int stayopen" .\" .Ft void .\" .Fn setgrfile "const char *name" .Ft int .Fn setgrent void .Ft void .Fn endgrent void .Sh DESCRIPTION These functions operate on the group database file .Pa /etc/group which is described in .Xr group 5 . Each line of the database is defined by the structure .Ar group found in the include file .Aq Pa grp.h : .Bd -literal -offset indent struct group { char *gr_name; /* group name */ char *gr_passwd; /* group password */ int gr_gid; /* group id */ char **gr_mem; /* group members */ }; .Ed .Pp The functions .Fn getgrnam and .Fn getgrgid search the group database for the given group name pointed to by .Ar name or the group id pointed to by .Ar gid , respectively, returning the first one encountered. Identical group names or group gids may result in undefined behavior. .Pp The .Fn getgrent function sequentially reads the group database and is intended for programs that wish to step through the complete list of groups. .Pp All three routines will open the group file for reading, if necessary. .Pp The .Fn setgroupent function opens the file, or rewinds it if it is already open. If .Fa stayopen is non-zero, file descriptors are left open, significantly speeding functions subsequent calls. This functionality is unnecessary for .Fn getgrent as it doesn't close its file descriptors by default. It should also be noted that it is dangerous for long-running programs to use this functionality as the group file may be updated. .Pp The .Fn setgrent function is identical to .Fn setgroupent with an argument of zero. .Pp The .Fn endgrent function closes any open files. -.Sh YP/NIS INTERACTION -When the -.Xr yp 4 -group database is enabled, the -.Fn getgrnam -and -.Fn getgrgid -functions use the YP maps -.Dq Li group.byname -and -.Dq Li group.bygid , -respectively, if the requested group is not found in the local -.Pa /etc/group -file. The -.Fn getgrent -function will step through the YP map -.Dq Li group.byname -if the entire map is enabled as described in -.Xr group 5 . .Sh RETURN VALUES The functions .Fn getgrent , .Fn getgrnam , and .Fn getgrgid , return a pointer to the group entry if successful; if end-of-file is reached or an error occurs a null pointer is returned. The functions .Fn setgroupent and .Fn setgrent return the value 1 if successful, otherwise the value 0 is returned. The functions .Fn endgrent and .Fn setgrfile have no return value. .Sh FILES .Bl -tag -width /etc/group -compact .It Pa /etc/group group database file .El .Sh SEE ALSO .Xr getpwent 3 , .Xr yp 4 , -.Xr group 5 +.Xr group 5 , +.Xr nsswitch.conf 5 .Sh HISTORY The functions .Fn endgrent , .Fn getgrent , .Fn getgrnam , .Fn getgrgid , and .Fn setgrent appeared in .At v7 . The functions .Fn setgrfile and .Fn setgroupent appeared in .Bx 4.3 Reno . .Sh COMPATIBILITY The historic function .Fn setgrfile , which allowed the specification of alternate password databases, has been deprecated and is no longer available. .Sh BUGS The functions .Fn getgrent , .Fn getgrnam , .Fn getgrgid , .Fn setgroupent and .Fn setgrent leave their results in an internal static object and return a pointer to that object. Subsequent calls to the same function will modify the same object. +.Pp +The functions +.Fn getgrent , +.Fn endgrent , +.Fn setgroupent , +and +.Fn setgrent +are fairly useless in a networked environment and should be +avoided, if possible. +.Fn getgrent +makes no attempt to suppress duplicate information if multiple +sources are specified in +.Xr nsswitch.conf 5 . + Index: head/lib/libc/gen/getgrent.c =================================================================== --- head/lib/libc/gen/getgrent.c (revision 65531) +++ head/lib/libc/gen/getgrent.c (revision 65532) @@ -1,553 +1,706 @@ +/* $NetBSD: getgrent.c,v 1.34.2.1 1999/04/27 14:10:58 perry Exp $ */ + /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. + * Portions Copyright (c) 1994, Jason Downs. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ +#include #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; +static char rcsid[] = + "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include + +#include +#include +#include +#include #include #include #include -#include +#include -static FILE *_gr_fp; -static struct group _gr_group; -static int _gr_stayopen; -static int grscan(), start_gr(); +#ifdef HESIOD +#include +#include +#endif #ifdef YP #include #include #include -static int _gr_stepping_yp; -static int _gr_yp_enabled; -static int _getypgroup(struct group *, const char *, char *); -static int _nextypgroup(struct group *); #endif +#if defined(YP) || defined(HESIOD) +#define _GROUP_COMPAT +#endif + +static FILE *_gr_fp; +static struct group _gr_group; +static int _gr_stayopen; +static int _gr_filesdone; + +static void grcleanup __P((void)); +static int grscan __P((int, gid_t, const char *)); +static char *getline __P((void)); +static int copyline __P((const char*)); +static int matchline __P((int, gid_t, const char *)); +static int start_gr __P((void)); + + + + /* initial size for malloc and increase steps for realloc */ #define MAXGRP 64 #define MAXLINELENGTH 256 -static char **members; /* list of group members */ -static int maxgrp; /* current length of **mebers */ -static char *line; /* temp buffer for group line */ -static int maxlinelength; /* current length of *line */ +#ifdef HESIOD +#if MAXLINELENGTH < NS_MAXLABEL + 1 +#error "MAXLINELENGTH must be at least NS_MAXLABEL + 1" +#endif +#endif -/* - * Lines longer than MAXLINELENGTHLIMIT will be count as an error. +static char **members; /* list of group members */ +static int maxgrp; /* current length of **members */ +static char *line; /* buffer for group line */ +static int maxlinelength; /* current length of *line */ + +/* + * Lines longer than MAXLINELENGTHLIMIT will be counted as an error. * <= 0 disable check for maximum line length * 256K is enough for 64,000 uids */ #define MAXLINELENGTHLIMIT (256 * 1024) -#define GROUP_IGNORE_COMMENTS 1 /* allow comments in /etc/group */ -struct group * -getgrent() -{ - if (!_gr_fp && !start_gr()) { - return NULL; - } - #ifdef YP - if (_gr_stepping_yp) { - if (_nextypgroup(&_gr_group)) - return(&_gr_group); - } -tryagain: +static char *__ypcurrent, *__ypdomain; +static int __ypcurrentlen; +static int _gr_ypdone; #endif - if (!grscan(0, 0, NULL)) - return(NULL); -#ifdef YP - if(_gr_group.gr_name[0] == '+' && _gr_group.gr_name[1]) { - _getypgroup(&_gr_group, &_gr_group.gr_name[1], - "group.byname"); - } else if(_gr_group.gr_name[0] == '+') { - if (!_nextypgroup(&_gr_group)) - goto tryagain; - else - return(&_gr_group); - } +#ifdef HESIOD +static int _gr_hesnum; #endif - return(&_gr_group); + +#ifdef _GROUP_COMPAT +enum _grmode { GRMODE_NONE, GRMODE_FULL, GRMODE_NAME }; +static enum _grmode __grmode; +#endif + +struct group * +getgrent() +{ + if ((!_gr_fp && !start_gr()) || !grscan(0, 0, NULL)) + return (NULL); + return &_gr_group; } struct group * getgrnam(name) const char *name; { int rval; if (!start_gr()) - return(NULL); -#ifdef YP - tryagain: -#endif + return NULL; rval = grscan(1, 0, name); -#ifdef YP - if(rval == -1 && (_gr_yp_enabled < 0 || (_gr_yp_enabled && - _gr_group.gr_name[0] == '+'))) { - if (!(rval = _getypgroup(&_gr_group, name, "group.byname"))) - goto tryagain; - } -#endif if (!_gr_stayopen) endgrent(); - return(rval ? &_gr_group : NULL); + return (rval) ? &_gr_group : NULL; } struct group * -#ifdef __STDC__ -getgrgid(gid_t gid) -#else getgrgid(gid) gid_t gid; -#endif { int rval; if (!start_gr()) - return(NULL); -#ifdef YP - tryagain: -#endif + return NULL; rval = grscan(1, gid, NULL); -#ifdef YP - if(rval == -1 && _gr_yp_enabled) { - char buf[16]; - snprintf(buf, sizeof buf, "%d", (unsigned)gid); - if (!(rval = _getypgroup(&_gr_group, buf, "group.bygid"))) - goto tryagain; - } -#endif if (!_gr_stayopen) endgrent(); - return(rval ? &_gr_group : NULL); + return (rval) ? &_gr_group : NULL; } -static int -start_gr() +void +grcleanup() { - if (_gr_fp) { - rewind(_gr_fp); - return(1); - } - _gr_fp = fopen(_PATH_GROUP, "r"); - if(!_gr_fp) return 0; + _gr_filesdone = 0; #ifdef YP - /* - * This is a disgusting hack, used to determine when YP is enabled. - * This would be easier if we had a group database to go along with - * the password database. - */ - { - char *line; - size_t linelen; - _gr_yp_enabled = 0; - while((line = fgetln(_gr_fp, &linelen)) != NULL) { - if(line[0] == '+') { - if(line[1] && line[1] != ':' && !_gr_yp_enabled) { - _gr_yp_enabled = 1; - } else { - _gr_yp_enabled = -1; - break; - } - } - } - rewind(_gr_fp); - } + if (__ypcurrent) + free(__ypcurrent); + __ypcurrent = NULL; + _gr_ypdone = 0; #endif +#ifdef HESIOD + _gr_hesnum = 0; +#endif +#ifdef _GROUP_COMPAT + __grmode = GRMODE_NONE; +#endif +} +static int +start_gr() +{ + grcleanup(); if (maxlinelength == 0) { - if ((line = (char *)malloc(sizeof(char) * - MAXLINELENGTH)) == NULL) - return(0); - maxlinelength += MAXLINELENGTH; + if ((line = (char *)malloc(MAXLINELENGTH)) == NULL) + return 0; + maxlinelength = MAXLINELENGTH; } - if (maxgrp == 0) { - if ((members = (char **)malloc(sizeof(char **) * + if ((members = (char **) malloc(sizeof(char**) * MAXGRP)) == NULL) - return(0); - maxgrp += MAXGRP; + return 0; + maxgrp = MAXGRP; } - - return 1; + if (_gr_fp) { + rewind(_gr_fp); + return 1; + } + return (_gr_fp = fopen(_PATH_GROUP, "r")) ? 1 : 0; } int -setgrent() +setgrent(void) { - return(setgroupent(0)); + return setgroupent(0); } int setgroupent(stayopen) int stayopen; { if (!start_gr()) - return(0); + return 0; _gr_stayopen = stayopen; -#ifdef YP - _gr_stepping_yp = 0; -#endif - return(1); + return 1; } void endgrent() { -#ifdef YP - _gr_stepping_yp = 0; -#endif + grcleanup(); if (_gr_fp) { (void)fclose(_gr_fp); _gr_fp = NULL; } } + +static int _local_grscan __P((void *, void *, va_list)); + +/*ARGSUSED*/ static int -grscan(search, gid, name) - register int search, gid; - register char *name; +_local_grscan(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - register char *cp, **m; - char *bp; + int search = va_arg(ap, int); + gid_t gid = va_arg(ap, gid_t); + const char *name = va_arg(ap, const char *); - -#ifdef YP - int _ypfound; -#endif + if (_gr_filesdone) + return NS_NOTFOUND; for (;;) { -#ifdef YP - _ypfound = 0; -#endif - if (fgets(line, maxlinelength, _gr_fp) == NULL) - return(0); + if (getline() == NULL) { + if (!search) + _gr_filesdone = 1; + return NS_NOTFOUND; + } + if (matchline(search, gid, name)) + return NS_SUCCESS; + } + /* NOTREACHED */ +} - if (!index(line, '\n')) { - do { - if (feof(_gr_fp)) - return(0); - - /* don't allocate infinite memory */ - if (MAXLINELENGTHLIMIT > 0 && - maxlinelength >= MAXLINELENGTHLIMIT) - return(0); +#ifdef HESIOD +static int _dns_grscan __P((void *, void *, va_list)); - if ((line = (char *)reallocf(line, - sizeof(char) * - (maxlinelength + MAXLINELENGTH))) == NULL) - return(0); - - if (fgets(line + maxlinelength - 1, - MAXLINELENGTH + 1, _gr_fp) == NULL) - return(0); +/*ARGSUSED*/ +static int +_dns_grscan(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + int search = va_arg(ap, int); + gid_t gid = va_arg(ap, gid_t); + const char *name = va_arg(ap, const char *); - maxlinelength += MAXLINELENGTH; - } while (!index(line + maxlinelength - - MAXLINELENGTH - 1, '\n')); + char **hp; + void *context; + int r; + size_t sz; + + r = NS_UNAVAIL; + if (!search && _gr_hesnum == -1) + return NS_NOTFOUND; + if (hesiod_init(&context) == -1) + return (r); + + for (;;) { + if (search) { + if (name) + strlcpy(line, name, maxlinelength); + else + snprintf(line, maxlinelength, "%u", + (unsigned int)gid); + } else { + snprintf(line, maxlinelength, "group-%u", _gr_hesnum); + _gr_hesnum++; } -#ifdef GROUP_IGNORE_COMMENTS - /* - * Ignore comments: ^[ \t]*# - */ - for (cp = line; *cp != '\0'; cp++) - if (*cp != ' ' && *cp != '\t') - break; - if (*cp == '#' || *cp == '\0') - continue; + hp = hesiod_resolve(context, line, "group"); + if (hp == NULL) { + if (errno == ENOENT) { + if (!search) + _gr_hesnum = -1; + r = NS_NOTFOUND; + } + break; + } + + /* only check first elem */ + if (copyline(hp[0]) == 0) + return NS_UNAVAIL; + hesiod_free_list(context, hp); + if (matchline(search, gid, name)) { + r = NS_SUCCESS; + break; + } else if (search) { + r = NS_NOTFOUND; + break; + } + } + hesiod_end(context); + return (r); +} #endif - bp = line; +#ifdef YP +static int _nis_grscan __P((void *, void *, va_list)); - if ((_gr_group.gr_name = strsep(&bp, ":\n")) == NULL) +/*ARGSUSED*/ +static int +_nis_grscan(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + int search = va_arg(ap, int); + gid_t gid = va_arg(ap, gid_t); + const char *name = va_arg(ap, const char *); + + char *key, *data; + int keylen, datalen; + int r; + size_t sz; + + if(__ypdomain == NULL) { + switch (yp_get_default_domain(&__ypdomain)) { + case 0: break; -#ifdef YP - /* - * XXX We need to be careful to avoid proceeding - * past this point under certain circumstances or - * we risk dereferencing null pointers down below. - */ - if (_gr_group.gr_name[0] == '+') { - if (strlen(_gr_group.gr_name) == 1) { - switch(search) { - case 0: - return(1); - case 1: - return(-1); - default: - return(0); - } - } else { - cp = &_gr_group.gr_name[1]; - if (search && name != NULL) - if (strcmp(cp, name)) - continue; - if (!_getypgroup(&_gr_group, cp, - "group.byname")) - continue; - if (search && name == NULL) - if (gid != _gr_group.gr_gid) - continue; - /* We're going to override -- tell the world. */ - _ypfound++; - } + case YPERR_RESRC: + return NS_TRYAGAIN; + default: + return NS_UNAVAIL; } -#else - if (_gr_group.gr_name[0] == '+') - continue; -#endif /* YP */ - if (search && name) { - if(strcmp(_gr_group.gr_name, name)) { - continue; - } + } + + if (search) { /* specific group or gid */ + if (name) + strlcpy(line, name, maxlinelength); + else + snprintf(line, maxlinelength, "%u", (unsigned int)gid); + data = NULL; + r = yp_match(__ypdomain, + (name) ? "group.byname" : "group.bygid", + line, (int)strlen(line), &data, &datalen); + switch (r) { + case 0: + break; + case YPERR_KEY: + if (data) + free(data); + return NS_NOTFOUND; + default: + if (data) + free(data); + return NS_UNAVAIL; } -#ifdef YP - if ((cp = strsep(&bp, ":\n")) == NULL) - if (_ypfound) - return(1); - else + data[datalen] = '\0'; /* clear trailing \n */ + if (copyline(data) == 0) + return NS_UNAVAIL; + free(data); + if (matchline(search, gid, name)) + return NS_SUCCESS; + else + return NS_NOTFOUND; + } + + /* ! search */ + if (_gr_ypdone) + return NS_NOTFOUND; + for (;;) { + data = NULL; + if(__ypcurrent) { + key = NULL; + r = yp_next(__ypdomain, "group.byname", + __ypcurrent, __ypcurrentlen, + &key, &keylen, &data, &datalen); + free(__ypcurrent); + switch (r) { + case 0: break; - if (strlen(cp) || !_ypfound) - _gr_group.gr_passwd = cp; -#else - if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL) - break; + case YPERR_NOMORE: + __ypcurrent = NULL; + if (key) + free(key); + if (data) + free(data); + _gr_ypdone = 1; + return NS_NOTFOUND; + default: + if (key) + free(key); + if (data) + free(data); + return NS_UNAVAIL; + } + __ypcurrent = key; + __ypcurrentlen = keylen; + } else { + if (yp_first(__ypdomain, "group.byname", + &__ypcurrent, &__ypcurrentlen, + &data, &datalen)) { + if (data); + free(data); + return NS_UNAVAIL; + } + } + data[datalen] = '\0'; /* clear trailing \n */ + if (copyline(data) == 0) + return NS_UNAVAIL; + free(data); + if (matchline(search, gid, name)) + return NS_SUCCESS; + } + /* NOTREACHED */ +} #endif - if (!(cp = strsep(&bp, ":\n"))) -#ifdef YP - if (_ypfound) - return(1); - else + +#ifdef _GROUP_COMPAT +/* + * log an error if "files" or "compat" is specified in group_compat database + */ +static int _bad_grscan __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_bad_grscan(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + static int warned; + + if (!warned) { + syslog(LOG_ERR, + "nsswitch.conf group_compat database can't use '%s'", + (char *)cb_data); + } + warned = 1; + return NS_UNAVAIL; +} + +/* + * when a name lookup in compat mode is required, look it up in group_compat + * nsswitch database. only Hesiod and NIS is supported - it doesn't make + * sense to lookup compat names from 'files' or 'compat' + */ + +static int __grscancompat __P((int, gid_t, const char *)); + +static int +__grscancompat(search, gid, name) + int search; + gid_t gid; + const char *name; +{ + static const ns_dtab dtab[] = { + NS_FILES_CB(_bad_grscan, "files") + NS_DNS_CB(_dns_grscan, NULL) + NS_NIS_CB(_nis_grscan, NULL) + NS_COMPAT_CB(_bad_grscan, "compat") + { 0 } + }; + static const ns_src defaultnis[] = { + { NSSRC_NIS, NS_SUCCESS }, + { 0 } + }; + + return (nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "grscancompat", + defaultnis, search, gid, name)); +} #endif - continue; -#ifdef YP - /* - * Hurm. Should we be doing this? We allow UIDs to - * be overridden -- what about GIDs? - */ - if (!_ypfound) -#endif - _gr_group.gr_gid = atoi(cp); - if (search && name == NULL && _gr_group.gr_gid != gid) - continue; - cp = NULL; - if (bp == NULL) /* !!! Must check for this! */ - break; -#ifdef YP - if ((cp = strsep(&bp, ":\n")) == NULL) - break; - if (!strlen(cp) && _ypfound) - return(1); - else - members[0] = NULL; - bp = cp; - cp = NULL; + +static int _compat_grscan __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_compat_grscan(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + int search = va_arg(ap, int); + gid_t gid = va_arg(ap, gid_t); + const char *name = va_arg(ap, const char *); + +#ifdef _GROUP_COMPAT + static char *grname = NULL; #endif - for (m = members; ; bp++) { - if (m == (members + maxgrp - 1)) { - if ((members = (char **) - reallocf(members, - sizeof(char **) * - (maxgrp + MAXGRP))) == NULL) - return(0); - m = members + maxgrp - 1; - maxgrp += MAXGRP; - } - if (*bp == ',') { - if (cp) { - *bp = '\0'; - *m++ = cp; - cp = NULL; + + for (;;) { +#ifdef _GROUP_COMPAT + if(__grmode != GRMODE_NONE) { + int r; + + switch(__grmode) { + case GRMODE_FULL: + r = __grscancompat(search, gid, name); + if (r == NS_SUCCESS) + return r; + __grmode = GRMODE_NONE; + break; + case GRMODE_NAME: + if(grname == (char *)NULL) { + __grmode = GRMODE_NONE; + break; } - } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { - if (cp) { - *bp = '\0'; - *m++ = cp; + r = __grscancompat(1, 0, grname); + free(grname); + grname = (char *)NULL; + if (r != NS_SUCCESS) + break; + if (!search) + return NS_SUCCESS; + if (name) { + if (! strcmp(_gr_group.gr_name, name)) + return NS_SUCCESS; + } else { + if (_gr_group.gr_gid == gid) + return NS_SUCCESS; } break; - } else if (cp == NULL) - cp = bp; - + case GRMODE_NONE: + abort(); + } + continue; } - _gr_group.gr_mem = members; - *m = NULL; - return(1); +#endif /* _GROUP_COMPAT */ + + if (getline() == NULL) + return NS_NOTFOUND; + +#ifdef _GROUP_COMPAT + if (line[0] == '+') { + char *tptr, *bp; + + switch(line[1]) { + case ':': + case '\0': + case '\n': + __grmode = GRMODE_FULL; + break; + default: + __grmode = GRMODE_NAME; + bp = line; + tptr = strsep(&bp, ":\n"); + grname = strdup(tptr + 1); + break; + } + continue; + } +#endif /* _GROUP_COMPAT */ + if (matchline(search, gid, name)) + return NS_SUCCESS; } /* NOTREACHED */ - return (0); } -#ifdef YP - static int -_gr_breakout_yp(struct group *gr, char *result) +grscan(search, gid, name) + int search; + gid_t gid; + const char *name; { - char *s, *cp; - char **m; + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_grscan, NULL) + NS_DNS_CB(_dns_grscan, NULL) + NS_NIS_CB(_nis_grscan, NULL) + NS_COMPAT_CB(_compat_grscan, NULL) + { 0 } + }; + static const ns_src compatsrc[] = { + { NSSRC_COMPAT, NS_SUCCESS }, + { 0 } + }; - /* - * XXX If 's' ends up being a NULL pointer, punt on this group. - * It means the NIS group entry is badly formatted and should - * be skipped. - */ - if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ - gr->gr_name = s; + r = nsdispatch(NULL, dtab, NSDB_GROUP, "grscan", compatsrc, + search, gid, name); + return (r == NS_SUCCESS) ? 1 : 0; +} - if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ - gr->gr_passwd = s; +static int +matchline(search, gid, name) + int search; + gid_t gid; + const char *name; +{ + unsigned long id; + char **m; + char *cp, *bp, *ep; - if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ - gr->gr_gid = atoi(s); - - if ((s = result) == NULL) return 0; - cp = 0; - - for (m = members; ; s++) { - if (m == members + maxgrp - 1) { - if ((members = (char **)reallocf(members, - sizeof(char **) * (maxgrp + MAXGRP))) == NULL) - return(0); - m = members + maxgrp - 1; + if (line[0] == '+') + return 0; /* sanity check to prevent recursion */ + bp = line; + _gr_group.gr_name = strsep(&bp, ":\n"); + if (search && name && strcmp(_gr_group.gr_name, name)) + return 0; + _gr_group.gr_passwd = strsep(&bp, ":\n"); + if (!(cp = strsep(&bp, ":\n"))) + return 0; + id = strtoul(cp, &ep, 10); + if (*ep != '\0') + return 0; + _gr_group.gr_gid = (gid_t)id; + if (search && name == NULL && _gr_group.gr_gid != gid) + return 0; + cp = NULL; + if (bp == NULL) + return 0; + for (_gr_group.gr_mem = m = members;; bp++) { + if (m == &members[maxgrp - 1]) { + members = (char **) reallocf(members, sizeof(char **) * + (maxgrp + MAXGRP)); + if (members == NULL) + return 0; + _gr_group.gr_mem = members; + m = &members[maxgrp - 1]; maxgrp += MAXGRP; } - if (*s == ',') { + if (*bp == ',') { if (cp) { - *s = '\0'; + *bp = '\0'; *m++ = cp; cp = NULL; } - } else if (*s == '\0' || *s == '\n' || *s == ' ') { + } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { if (cp) { - *s = '\0'; + *bp = '\0'; *m++ = cp; } break; - } else if (cp == NULL) { - cp = s; - } - } - _gr_group.gr_mem = members; + } else if (cp == NULL) + cp = bp; + } *m = NULL; - - return 1; + return 1; } -static char *_gr_yp_domain; - -static int -_getypgroup(struct group *gr, const char *name, char *map) +static char * +getline(void) { - char *result, *s; - static char resultbuf[YPMAXRECORD + 2]; - int resultlen; + const char *cp; - if(!_gr_yp_domain) { - if(yp_get_default_domain(&_gr_yp_domain)) - return 0; + tryagain: + if (fgets(line, maxlinelength, _gr_fp) == NULL) + return NULL; + if (index(line, '\n') == NULL) { + do { + if (feof(_gr_fp)) + return NULL; + if (MAXLINELENGTHLIMIT > 0 && + maxlinelength >= MAXLINELENGTHLIMIT) + return NULL; + line = (char *)reallocf(line, maxlinelength + + MAXLINELENGTH); + if (line == NULL) + return NULL; + if (fgets(line + maxlinelength - 1, + MAXLINELENGTH + 1, _gr_fp) == NULL) + return NULL; + maxlinelength += MAXLINELENGTH; + } while (index(line + maxlinelength - MAXLINELENGTH - 1, + '\n') == NULL); } - if(yp_match(_gr_yp_domain, map, name, strlen(name), - &result, &resultlen)) - return 0; - s = strchr(result, '\n'); - if(s) *s = '\0'; + /* + * Ignore comments: ^[ \t]*# + */ + for (cp = line; *cp != '\0'; cp++) + if (*cp != ' ' && *cp != '\t') + break; + if (*cp == '#' || *cp == '\0') + goto tryagain; - if(resultlen >= sizeof resultbuf) return 0; - strncpy(resultbuf, result, resultlen); - resultbuf[resultlen] = '\0'; - free(result); - return(_gr_breakout_yp(gr, resultbuf)); - + if (cp != line) /* skip white space at beginning of line */ + bcopy(cp, line, strlen(cp)); + + return line; } - static int -_nextypgroup(struct group *gr) +copyline(const char *src) { - static char *key; - static int keylen; - char *lastkey, *result; - static char resultbuf[YPMAXRECORD + 2]; - int resultlen; - int rv; + size_t sz; - if(!_gr_yp_domain) { - if(yp_get_default_domain(&_gr_yp_domain)) - return 0; - } - - if(!_gr_stepping_yp) { - if(key) free(key); - rv = yp_first(_gr_yp_domain, "group.byname", - &key, &keylen, &result, &resultlen); - if(rv) { + sz = strlen(src); + if (sz > maxlinelength - 1) { + sz = ((sz/MAXLINELENGTH)+1) * MAXLINELENGTH; + if ((line = (char *) reallocf(line, sz)) == NULL) return 0; - } - _gr_stepping_yp = 1; - goto unpack; - } else { -tryagain: - lastkey = key; - rv = yp_next(_gr_yp_domain, "group.byname", key, keylen, - &key, &keylen, &result, &resultlen); - free(lastkey); -unpack: - if(rv) { - _gr_stepping_yp = 0; - return 0; - } - - if(resultlen > sizeof(resultbuf)) { - free(result); - goto tryagain; - } - - strncpy(resultbuf, result, resultlen); - resultbuf[resultlen] = '\0'; - free(result); - if((result = strchr(resultbuf, '\n')) != NULL) - *result = '\0'; - if (_gr_breakout_yp(gr, resultbuf)) - return(1); - else - goto tryagain; + maxlinelength = sz; } + strlcpy(line, src, maxlinelength); + return 1; } -#endif /* YP */ Index: head/lib/libc/gen/getpwent.3 =================================================================== --- head/lib/libc/gen/getpwent.3 (revision 65531) +++ head/lib/libc/gen/getpwent.3 (revision 65532) @@ -1,222 +1,218 @@ .\" Copyright (c) 1988, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)getpwent.3 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" .Dd September 20, 1994 .Dt GETPWENT 3 .Os .Sh NAME .Nm getpwent , .Nm getpwnam , .Nm getpwuid , .Nm setpassent , .Nm setpwent , .Nm endpwent .Nd password database operations .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Fd #include .Ft struct passwd * .Fn getpwent void .Ft struct passwd * .Fn getpwnam "const char *login" .Ft struct passwd * .Fn getpwuid "uid_t uid" .Ft int .Fn setpassent "int stayopen" .Ft void .Fn setpwent void .Ft void .Fn endpwent void .Sh DESCRIPTION These functions operate on the password database file which is described in .Xr passwd 5 . Each entry in the database is defined by the structure .Ar passwd found in the include file .Aq Pa pwd.h : .Bd -literal -offset indent struct passwd { char *pw_name; /* user name */ char *pw_passwd; /* encrypted password */ uid_t pw_uid; /* user uid */ gid_t pw_gid; /* user gid */ time_t pw_change; /* password change time */ char *pw_class; /* user access class */ char *pw_gecos; /* Honeywell login info */ char *pw_dir; /* home directory */ char *pw_shell; /* default shell */ time_t pw_expire; /* account expiration */ int pw_fields; /* internal: fields filled in */ }; .Ed .Pp The functions .Fn getpwnam and .Fn getpwuid search the password database for the given login name or user uid, respectively, always returning the first one encountered. .Pp The .Fn getpwent function sequentially reads the password database and is intended for programs that wish to process the complete list of users. .Pp The .Fn setpassent function accomplishes two purposes. First, it causes .Fn getpwent to ``rewind'' to the beginning of the database. Additionally, if .Fa stayopen is non-zero, file descriptors are left open, significantly speeding up subsequent accesses for all of the routines. (This latter functionality is unnecessary for .Fn getpwent as it doesn't close its file descriptors by default.) .Pp It is dangerous for long-running programs to keep the file descriptors open as the database will become out of date if it is updated while the program is running. .Pp The .Fn setpwent function is identical to .Fn setpassent with an argument of zero. .Pp The .Fn endpwent function closes any open files. .Pp These routines have been written to ``shadow'' the password file, e.g. allow only certain programs to have access to the encrypted password. If the process which calls them has an effective uid of 0, the encrypted password will be returned, otherwise, the password field of the returned structure will point to the string .Ql * . -.Sh YP/NIS INTERACTION -When the -.Xr yp 4 -password database is enabled, the -.Fn getpwnam -and -.Fn getpwuid -functions use the YP maps -.Dq Li passwd.byname -and -.Dq Li passwd.byuid , -respectively, if the requested password entry is not found in the -local database. The -.Fn getpwent -function will step through the YP map -.Dq Li passwd.byname -if the entire map is enabled as described in -.Xr passwd 5 . .Sh RETURN VALUES The functions .Fn getpwent , .Fn getpwnam , and .Fn getpwuid , return a valid pointer to a passwd structure on success and a null pointer if end-of-file is reached or an error occurs. The .Fn setpassent function returns 0 on failure and 1 on success. The .Fn endpwent and .Fn setpwent functions have no return value. .Sh FILES .Bl -tag -width /etc/master.passwd -compact .It Pa /etc/pwd.db The insecure password database file .It Pa /etc/spwd.db The secure password database file .It Pa /etc/master.passwd The current password file .It Pa /etc/passwd A Version 7 format password file .El .Sh SEE ALSO .Xr getlogin 2 , .Xr getgrent 3 , .Xr yp 4 , +.Xr nsswitch.conf 5 , .Xr passwd 5 , .Xr pwd_mkdb 8 , .Xr vipw 8 .Sh HISTORY The .Fn getpwent , .Fn getpwnam , .Fn getpwuid , .Fn setpwent, and .Fn endpwent functions appeared in .At v7 . The .Fn setpassent function appeared in .Bx 4.3 Reno . .Sh COMPATIBILITY The historic function .Xr setpwfile 3 , which allowed the specification of alternate password databases, has been deprecated and is no longer available. .Sh BUGS The functions .Fn getpwent , .Fn getpwnam , and .Fn getpwuid , leave their results in an internal static object and return a pointer to that object. Subsequent calls to the same function will modify the same object. +.Pp +The functions +.Fn getpwent , +.Fn endpwent , +.Fn setpassent , +and +.Fn setpwent +are fairly useless in a networked environment and should be +avoided, if possible. +.Fn getpwent +makes no attempt to suppress duplicate information if multiple +sources are specified in +.Xr nsswitch.conf 5 Index: head/lib/libc/gen/getpwent.c =================================================================== --- head/lib/libc/gen/getpwent.c (revision 65531) +++ head/lib/libc/gen/getpwent.c (revision 65532) @@ -1,860 +1,1175 @@ +/* $NetBSD: getpwent.c,v 1.40.2.2 1999/04/27 22:09:45 perry Exp $ */ + /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. + * Portions Copyright (c) 1994, 1995, Jason Downs. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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$ */ +#include #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95"; +static const char *rcsid[] = + "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ -#include #include #include #include #include #include #include #include #include #include #include #include -#include +#include +#ifdef HESIOD +#include +#endif +#ifdef YP +#include +#include +#include +#include +#include +#endif -extern void setnetgrent __P(( char * )); -extern int getnetgrent __P(( char **, char **, char ** )); -extern int innetgr __P(( const char *, const char *, const char *, const char * )); +extern void setnetgrent __P((char *)); +extern int getnetgrent __P((char **, char **, char **)); +extern int innetgr __P((const char *, const char *, const char *, const char *)); +#include "pw_scan.h" + +#if defined(YP) || defined(HESIOD) +#define _PASSWD_COMPAT +#endif + /* * The lookup techniques and data extraction code here must be kept * in sync with that in `pwd_mkdb'. */ static struct passwd _pw_passwd; /* password structure */ static DB *_pw_db; /* password database */ -static int _pw_keynum; /* key counter */ +static int _pw_keynum; /* key counter. no more records if -1 */ static int _pw_stayopen; /* keep fd's open */ -#ifdef YP -#include -#include -#include +static int _pw_flags; /* password flags */ -static struct passwd _pw_copy; -static DBT empty = { NULL, 0 }; -static DB *_ypcache = (DB *)NULL; -static int _yp_exclusions = 0; -static int _yp_enabled = -1; -static int _pw_stepping_yp; /* set true when stepping thru map */ -static char _ypnam[YPMAXRECORD]; -#define YP_HAVE_MASTER 2 -#define YP_HAVE_ADJUNCT 1 -#define YP_HAVE_NONE 0 -static int _gotmaster; -static char *_pw_yp_domain; -static inline int unwind __P(( char * )); -static void _ypinitdb __P(( void )); -static int _havemaster __P((char *)); -static int _getyppass __P((struct passwd *, const char *, const char * )); -static int _nextyppass __P((struct passwd *)); -static inline int lookup __P((const char *)); -static inline void store __P((const char *)); -static inline int ingr __P((const char *, const char*)); -static inline int verf __P((const char *)); -static char * _get_adjunct_pw __P((const char *)); -#endif -static int __hashpw(DBT *); -static int __initdb(void); +static int __hashpw __P((DBT *)); +static int __initdb __P((void)); -struct passwd * -getpwent() -{ - DBT key; - char bf[sizeof(_pw_keynum) + 1]; - int rv; +static const ns_src compatsrc[] = { + { NSSRC_COMPAT, NS_SUCCESS }, + { 0 } +}; - if (!_pw_db && !__initdb()) - return((struct passwd *)NULL); - #ifdef YP - if(_pw_stepping_yp) { - _pw_passwd = _pw_copy; - if (unwind((char *)&_ypnam)) - return(&_pw_passwd); - } +static char *__ypcurrent, *__ypdomain; +static int __ypcurrentlen; +static int _pw_ypdone; /* non-zero if no more yp records */ #endif -tryagain: - ++_pw_keynum; - bf[0] = _PW_KEYBYNUM; - bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); - key.data = (u_char *)bf; - key.size = sizeof(_pw_keynum) + 1; - rv = __hashpw(&key); - if(!rv) return (struct passwd *)NULL; -#ifdef YP - if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { - if (_yp_enabled == -1) - _ypinitdb(); - bzero((char *)&_ypnam, sizeof(_ypnam)); - bcopy(_pw_passwd.pw_name, _ypnam, - strlen(_pw_passwd.pw_name)); - _pw_copy = _pw_passwd; - if (unwind((char *)&_ypnam) == 0) - goto tryagain; - else - return(&_pw_passwd); - } -#else - /* Ignore YP password file entries when YP is disabled. */ - if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') { - goto tryagain; - } +#ifdef HESIOD +static int _pw_hesnum; /* hes counter. no more records if -1 */ #endif - return(&_pw_passwd); -} -struct passwd * -getpwnam(name) +#ifdef _PASSWD_COMPAT +enum _pwmode { PWMODE_NONE, PWMODE_FULL, PWMODE_USER, PWMODE_NETGRP }; +static enum _pwmode __pwmode; + +enum _ypmap { YPMAP_NONE, YPMAP_ADJUNCT, YPMAP_MASTER }; + +static struct passwd *__pwproto = (struct passwd *)NULL; +static int __pwproto_flags; +static char line[1024]; +static long prbuf[1024 / sizeof(long)]; +static DB *__pwexclude = (DB *)NULL; + +static int __pwexclude_add __P((const char *)); +static int __pwexclude_is __P((const char *)); +static void __pwproto_set __P((void)); +static int __ypmaptype __P((void)); +static int __pwparse __P((struct passwd *, char *)); + + /* macros for deciding which YP maps to use. */ +#define PASSWD_BYNAME (__ypmaptype() == YPMAP_MASTER \ + ? "master.passwd.byname" : "passwd.byname") +#define PASSWD_BYUID (__ypmaptype() == YPMAP_MASTER \ + ? "master.passwd.byuid" : "passwd.byuid") + +/* + * add a name to the compat mode exclude list + */ +static int +__pwexclude_add(name) const char *name; { DBT key; - int len, rval; - char bf[UT_NAMESIZE + 2]; + DBT data; - if (!_pw_db && !__initdb()) - return((struct passwd *)NULL); + /* initialize the exclusion table if needed. */ + if(__pwexclude == (DB *)NULL) { + __pwexclude = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); + if(__pwexclude == (DB *)NULL) + return 1; + } - bf[0] = _PW_KEYBYNAME; - len = strlen(name); - if (len > UT_NAMESIZE) - return(NULL); - bcopy(name, bf + 1, len); - key.data = (u_char *)bf; - key.size = len + 1; - rval = __hashpw(&key); + /* set up the key */ + key.size = strlen(name); + /* LINTED key does not get modified */ + key.data = (char *)name; -#ifdef YP - if (!rval) { - if (_yp_enabled == -1) - _ypinitdb(); - if (_yp_enabled) - rval = _getyppass(&_pw_passwd, name, "passwd.byname"); - } -#endif - /* - * Prevent login attempts when YP is not enabled but YP entries - * are in /etc/master.passwd. - */ - if (rval && (_pw_passwd.pw_name[0] == '+'|| - _pw_passwd.pw_name[0] == '-')) rval = 0; + /* data is nothing. */ + data.data = NULL; + data.size = 0; - if (!_pw_stayopen) - endpwent(); - return(rval ? &_pw_passwd : (struct passwd *)NULL); + /* store it */ + if((__pwexclude->put)(__pwexclude, &key, &data, 0) == -1) + return 1; + + return 0; } -struct passwd * -getpwuid(uid) - uid_t uid; +/* + * test if a name is on the compat mode exclude list + */ +static int +__pwexclude_is(name) + const char *name; { DBT key; - int keyuid, rval; - char bf[sizeof(keyuid) + 1]; + DBT data; - if (!_pw_db && !__initdb()) - return((struct passwd *)NULL); + if(__pwexclude == (DB *)NULL) + return 0; /* nothing excluded */ - bf[0] = _PW_KEYBYUID; - keyuid = uid; - bcopy(&keyuid, bf + 1, sizeof(keyuid)); - key.data = (u_char *)bf; - key.size = sizeof(keyuid) + 1; - rval = __hashpw(&key); + /* set up the key */ + key.size = strlen(name); + /* LINTED key does not get modified */ + key.data = (char *)name; -#ifdef YP - if (!rval) { - if (_yp_enabled == -1) - _ypinitdb(); - if (_yp_enabled) { - char ypbuf[16]; /* big enough for 32-bit uids */ - snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); - rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); - } - } -#endif - /* - * Prevent login attempts when YP is not enabled but YP entries - * are in /etc/master.passwd. - */ - if (rval && (_pw_passwd.pw_name[0] == '+'|| - _pw_passwd.pw_name[0] == '-')) rval = 0; - - if (!_pw_stayopen) - endpwent(); - return(rval ? &_pw_passwd : (struct passwd *)NULL); + if((__pwexclude->get)(__pwexclude, &key, &data, 0) == 0) + return 1; /* excluded */ + + return 0; } -int -setpassent(stayopen) - int stayopen; +/* + * setup the compat mode prototype template + */ +static void +__pwproto_set() { - _pw_keynum = 0; -#ifdef YP - _pw_stepping_yp = 0; - if (stayopen) - setgroupent(1); -#endif - _pw_stayopen = stayopen; - return(1); -} + char *ptr; + struct passwd *pw = &_pw_passwd; -void -setpwent() -{ - (void)setpassent(0); + /* make this the new prototype */ + ptr = (char *)(void *)prbuf; + + /* first allocate the struct. */ + __pwproto = (struct passwd *)(void *)ptr; + ptr += sizeof(struct passwd); + + /* name */ + if(pw->pw_name && (pw->pw_name)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_name, strlen(pw->pw_name) + 1); + __pwproto->pw_name = ptr; + ptr += (strlen(pw->pw_name) + 1); + } else + __pwproto->pw_name = (char *)NULL; + + /* password */ + if(pw->pw_passwd && (pw->pw_passwd)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_passwd, strlen(pw->pw_passwd) + 1); + __pwproto->pw_passwd = ptr; + ptr += (strlen(pw->pw_passwd) + 1); + } else + __pwproto->pw_passwd = (char *)NULL; + + /* uid */ + __pwproto->pw_uid = pw->pw_uid; + + /* gid */ + __pwproto->pw_gid = pw->pw_gid; + + /* change (ignored anyway) */ + __pwproto->pw_change = pw->pw_change; + + /* class (ignored anyway) */ + __pwproto->pw_class = ""; + + /* gecos */ + if(pw->pw_gecos && (pw->pw_gecos)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_gecos, strlen(pw->pw_gecos) + 1); + __pwproto->pw_gecos = ptr; + ptr += (strlen(pw->pw_gecos) + 1); + } else + __pwproto->pw_gecos = (char *)NULL; + + /* dir */ + if(pw->pw_dir && (pw->pw_dir)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_dir, strlen(pw->pw_dir) + 1); + __pwproto->pw_dir = ptr; + ptr += (strlen(pw->pw_dir) + 1); + } else + __pwproto->pw_dir = (char *)NULL; + + /* shell */ + if(pw->pw_shell && (pw->pw_shell)[0]) { + ptr = (char *)ALIGN((u_long)ptr); + memmove(ptr, pw->pw_shell, strlen(pw->pw_shell) + 1); + __pwproto->pw_shell = ptr; + ptr += (strlen(pw->pw_shell) + 1); + } else + __pwproto->pw_shell = (char *)NULL; + + /* expire (ignored anyway) */ + __pwproto->pw_expire = pw->pw_expire; + + /* flags */ + __pwproto_flags = _pw_flags; } -void -endpwent() +static int +__ypmaptype() { - _pw_keynum = 0; -#ifdef YP - _pw_stepping_yp = 0; -#endif - if (_pw_db) { - (void)(_pw_db->close)(_pw_db); - _pw_db = (DB *)NULL; + static int maptype = -1; + int order, r; + + if (maptype != -1) + return (maptype); + + maptype = YPMAP_NONE; + if (geteuid() != 0) + return (maptype); + + if (!__ypdomain) { + if( _yp_check(&__ypdomain) == 0) + return (maptype); } -#ifdef YP - if (_ypcache) { - (void)(_ypcache->close)(_ypcache); - _ypcache = (DB *)NULL; - _yp_exclusions = 0; + + r = yp_order(__ypdomain, "master.passwd.byname", &order); + if (r == 0) { + maptype = YPMAP_MASTER; + return (maptype); } - /* Fix for PR #12008 */ - _yp_enabled = -1; -#endif -} -static int -__initdb() -{ - static int warned; - char *p; + /* + * NIS+ in YP compat mode doesn't support + * YPPROC_ORDER -- no point in continuing. + */ + if (r == YPERR_YPERR) + return (maptype); - p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; - _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); - if (_pw_db) - return(1); - if (!warned++) - syslog(LOG_ERR, "%s: %m", p); - return(0); + /* master.passwd doesn't exist -- try passwd.adjunct */ + if (r == YPERR_MAP) { + r = yp_order(__ypdomain, "passwd.adjunct.byname", &order); + if (r == 0) + maptype = YPMAP_ADJUNCT; + return (maptype); + } + + return (maptype); } +/* + * parse a passwd file line (from NIS or HESIOD). + * assumed to be `old-style' if maptype != YPMAP_MASTER. + */ static int -__hashpw(key) - DBT *key; +__pwparse(pw, s) + struct passwd *pw; + char *s; { - register char *p, *t; - static u_int max; - static char *line; - DBT data; + static char adjunctpw[YPMAXRECORD + 2]; + int flags, maptype; - if ((_pw_db->get)(_pw_db, key, &data, 0)) - return(0); - p = (char *)data.data; + maptype = __ypmaptype(); + flags = 0; + if (maptype == YPMAP_MASTER) + flags |= _PWSCAN_MASTER; + if (! __pw_scan(s, pw, flags)) + return 1; - /* Increase buffer size for long lines if necessary. */ - if (data.size > max) { - max = data.size + 1024; - if (!(line = reallocf(line, max))) - return(0); + /* now let the prototype override, if set. */ + if(__pwproto != (struct passwd *)NULL) { +#ifdef PW_OVERRIDE_PASSWD + if(__pwproto_flags & _PWF_PASSWD) + pw->pw_passwd = __pwproto->pw_passwd; +#endif + if(__pwproto_flags & _PWF_UID) + pw->pw_uid = __pwproto->pw_uid; + if(__pwproto_flags & _PWF_GID) + pw->pw_gid = __pwproto->pw_gid; + if(__pwproto_flags & _PWF_GECOS) + pw->pw_gecos = __pwproto->pw_gecos; + if(__pwproto_flags & _PWF_DIR) + pw->pw_dir = __pwproto->pw_dir; + if(__pwproto_flags & _PWF_SHELL) + pw->pw_shell = __pwproto->pw_shell; } + if ((maptype == YPMAP_ADJUNCT) && + (strstr(pw->pw_passwd, "##") != NULL)) { + char *data, *bp; + int datalen; - /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ - t = line; -#define EXPAND(e) e = t; while ( (*t++ = *p++) ); -#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v - EXPAND(_pw_passwd.pw_name); - EXPAND(_pw_passwd.pw_passwd); - SCALAR(_pw_passwd.pw_uid); - SCALAR(_pw_passwd.pw_gid); - SCALAR(_pw_passwd.pw_change); - EXPAND(_pw_passwd.pw_class); - EXPAND(_pw_passwd.pw_gecos); - EXPAND(_pw_passwd.pw_dir); - EXPAND(_pw_passwd.pw_shell); - SCALAR(_pw_passwd.pw_expire); - bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); - p += sizeof _pw_passwd.pw_fields; - return(1); -} + if (yp_match(__ypdomain, "passwd.adjunct.byname", pw->pw_name, + (int)strlen(pw->pw_name), &data, &datalen) == 0) { + if (datalen > sizeof(adjunctpw) - 1) + datalen = sizeof(adjunctpw) - 1; + strncpy(adjunctpw, data, (size_t)datalen); -#ifdef YP - -static void -_ypinitdb() -{ - DBT key, data; - char buf[] = { _PW_KEYYPENABLED }; - key.data = buf; - key.size = 1; - _yp_enabled = 0; - if ((_pw_db->get)(_pw_db, &key, &data, 0) == 0) { - _yp_enabled = (int)*((char *)data.data) - 2; - /* Don't even bother with this if we aren't root. */ - if (!geteuid()) { - if (!_pw_yp_domain) - if (yp_get_default_domain(&_pw_yp_domain)) - return; - _gotmaster = _havemaster(_pw_yp_domain); - } else _gotmaster = YP_HAVE_NONE; - /* - * Create a DB hash database in memory. Bet you didn't know you - * could do a dbopen() with a NULL filename, did you. - */ - if (_ypcache == (DB *)NULL) - _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL); + /* skip name to get password */ + if ((bp = strsep(&data, ":")) != NULL && + (bp = strsep(&data, ":")) != NULL) + pw->pw_passwd = bp; + } } + return 0; } +#endif /* _PASSWD_COMPAT */ /* - * See if a user is in the blackballed list. + * local files implementation of getpw*() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline int -lookup(name) - const char *name; +static int _local_getpw __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_local_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - DBT key; + DBT key; + char bf[/*CONSTCOND*/ MAX(MAXLOGNAME, sizeof(_pw_keynum)) + 1]; + uid_t uid; + int search, len, rval; + const char *name; - if (!_yp_exclusions) - return(0); + if (!_pw_db && !__initdb()) + return NS_UNAVAIL; - key.data = (char *)name; - key.size = strlen(name); - - if ((_ypcache->get)(_ypcache, &key, &empty, 0)) { - return(0); + search = va_arg(ap, int); + bf[0] = search; + switch (search) { + case _PW_KEYBYNUM: + if (_pw_keynum == -1) + return NS_NOTFOUND; /* no more local records */ + ++_pw_keynum; + memmove(bf + 1, &_pw_keynum, sizeof(_pw_keynum)); + key.size = sizeof(_pw_keynum) + 1; + break; + case _PW_KEYBYNAME: + name = va_arg(ap, const char *); + len = strlen(name); + memmove(bf + 1, name, (size_t)MIN(len, MAXLOGNAME)); + key.size = len + 1; + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + memmove(bf + 1, &uid, sizeof(len)); + key.size = sizeof(uid) + 1; + break; + default: + abort(); } - return(1); + key.data = (u_char *)bf; + rval = __hashpw(&key); + if (rval == NS_NOTFOUND && search == _PW_KEYBYNUM) + _pw_keynum = -1; /* flag `no more local records' */ + + if (!_pw_stayopen && (search != _PW_KEYBYNUM)) { + (void)(_pw_db->close)(_pw_db); + _pw_db = (DB *)NULL; + } + return (rval); } +#ifdef HESIOD /* - * Store a blackballed user in an in-core hash database. + * hesiod implementation of getpw*() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline void -store(key) - const char *key; +static int _dns_getpw __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_dns_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - DBT lkey; -/* - if (lookup(key)) - return; -*/ + const char *name; + uid_t uid; + int search; - _yp_exclusions = 1; + const char *map; + char **hp; + void *context; + int r; - lkey.data = (char *)key; - lkey.size = strlen(key); + search = va_arg(ap, int); + nextdnsbynum: + switch (search) { + case _PW_KEYBYNUM: + if (_pw_hesnum == -1) + return NS_NOTFOUND; /* no more hesiod records */ + snprintf(line, sizeof(line) - 1, "passwd-%u", _pw_hesnum); + _pw_hesnum++; + map = "passwd"; + break; + case _PW_KEYBYNAME: + name = va_arg(ap, const char *); + strncpy(line, name, sizeof(line)); + map = "passwd"; + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + snprintf(line, sizeof(line), "%u", (unsigned int)uid); + map = "uid"; /* XXX this is `passwd' on ultrix */ + break; + default: + abort(); + } + line[sizeof(line) - 1] = '\0'; - (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE); + r = NS_UNAVAIL; + if (hesiod_init(&context) == -1) + return (r); + + hp = hesiod_resolve(context, line, map); + if (hp == NULL) { + if (errno == ENOENT) { + /* flag `no more hesiod records' */ + if (search == _PW_KEYBYNUM) + _pw_hesnum = -1; + r = NS_NOTFOUND; + } + goto cleanup_dns_getpw; + } + + strncpy(line, hp[0], sizeof(line)); /* only check first elem */ + line[sizeof(line) - 1] = '\0'; + hesiod_free_list(context, hp); + if (__pwparse(&_pw_passwd, line)) { + if (search == _PW_KEYBYNUM) + goto nextdnsbynum; /* skip dogdy entries */ + r = NS_UNAVAIL; + } else + r = NS_SUCCESS; + cleanup_dns_getpw: + hesiod_end(context); + return (r); } +#endif +#ifdef YP /* - * Parse the + entries in the password database and do appropriate - * NIS lookups. While ugly to look at, this is optimized to do only - * as many lookups as are absolutely necessary in any given case. - * Basically, the getpwent() function will feed us + and - lines - * as they appear in the database. For + lines, we do netgroup/group - * and user lookups to find all usernames that match the rule and - * extract them from the NIS passwd maps. For - lines, we save the - * matching names in a database and a) exlude them, and b) make sure - * we don't consider them when processing other + lines that appear - * later. + * nis implementation of getpw*() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline int -unwind(grp) - char *grp; +static int _nis_getpw __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_nis_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - char *user, *host, *domain; - static int latch = 0; - static struct group *gr = NULL; - int rv = 0; + const char *name; + uid_t uid; + int search; + char *key, *data; + char *map; + int keylen, datalen, r, rval; - if (grp[0] == '+') { - if (strlen(grp) == 1) { - return(_nextyppass(&_pw_passwd)); + if(__ypdomain == NULL) { + if(_yp_check(&__ypdomain) == 0) + return NS_UNAVAIL; + } + + map = PASSWD_BYNAME; + search = va_arg(ap, int); + switch (search) { + case _PW_KEYBYNUM: + break; + case _PW_KEYBYNAME: + name = va_arg(ap, const char *); + strncpy(line, name, sizeof(line)); + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + snprintf(line, sizeof(line), "%u", (unsigned int)uid); + map = PASSWD_BYUID; + break; + default: + abort(); + } + line[sizeof(line) - 1] = '\0'; + rval = NS_UNAVAIL; + if (search != _PW_KEYBYNUM) { + data = NULL; + r = yp_match(__ypdomain, map, line, (int)strlen(line), + &data, &datalen); + if (r == YPERR_KEY) + rval = NS_NOTFOUND; + if (r != 0) { + if (data) + free(data); + return (rval); } - if (grp[1] == '@') { - _pw_stepping_yp = 1; -grpagain: - if (gr != NULL) { - if (*gr->gr_mem != NULL) { - if (lookup(*gr->gr_mem)) { - gr->gr_mem++; - goto grpagain; - } - rv = _getyppass(&_pw_passwd, - *gr->gr_mem, - "passwd.byname"); - gr->gr_mem++; - return(rv); - } else { - latch = 0; - _pw_stepping_yp = 0; - gr = NULL; - return(0); - } + data[datalen] = '\0'; /* clear trailing \n */ + strncpy(line, data, sizeof(line)); + line[sizeof(line) - 1] = '\0'; + free(data); + if (__pwparse(&_pw_passwd, line)) + return NS_UNAVAIL; + return NS_SUCCESS; + } + + if (_pw_ypdone) + return NS_NOTFOUND; + for (;;) { + data = key = NULL; + if (__ypcurrent) { + r = yp_next(__ypdomain, map, + __ypcurrent, __ypcurrentlen, + &key, &keylen, &data, &datalen); + free(__ypcurrent); + switch (r) { + case 0: + __ypcurrent = key; + __ypcurrentlen = keylen; + break; + case YPERR_NOMORE: + __ypcurrent = NULL; + /* flag `no more yp records' */ + _pw_ypdone = 1; + rval = NS_NOTFOUND; } - if (!latch) { - setnetgrent(grp+2); - latch++; - } -again: - if (getnetgrent(&host, &user, &domain) == 0) { - if ((gr = getgrnam(grp+2)) != NULL) - goto grpagain; - latch = 0; - _pw_stepping_yp = 0; - return(0); - } else { - if (lookup(user)) - goto again; - if (_getyppass(&_pw_passwd, user, - "passwd.byname")) - return(1); - else - goto again; - } } else { - if (lookup(grp+1)) - return(0); - return(_getyppass(&_pw_passwd, grp+1, "passwd.byname")); + r = yp_first(__ypdomain, map, &__ypcurrent, + &__ypcurrentlen, &data, &datalen); } - } else { - if (grp[1] == '@') { - setnetgrent(grp+2); - rv = 0; - while(getnetgrent(&host, &user, &domain) != 0) { - store(user); - rv++; - } - if (!rv && (gr = getgrnam(grp+2)) != NULL) { - while(*gr->gr_mem) { - store(*gr->gr_mem); - gr->gr_mem++; - } - } - } else { - store(grp+1); + if (r != 0) { + if (key) + free(key); + if (data) + free(data); + return (rval); } + data[datalen] = '\0'; /* clear trailing \n */ + strncpy(line, data, sizeof(line)); + line[sizeof(line) - 1] = '\0'; + free(data); + if (! __pwparse(&_pw_passwd, line)) + return NS_SUCCESS; } - return(0); -} + /* NOTREACHED */ +} /* _nis_getpw */ +#endif +#ifdef _PASSWD_COMPAT /* - * See if a user is a member of a particular group. + * See if the compat token is in the database. Only works if pwd_mkdb knows + * about the token. */ -static inline int -ingr(grp, name) - const char *grp; - const char *name; +static int __has_compatpw __P((void)); + +static int +__has_compatpw() { - register struct group *gr; + DBT key, data; + DBT pkey, pdata; + char bf[MAXLOGNAME]; + u_char cyp[] = { _PW_KEYYPENABLED }; - if ((gr = getgrnam(grp)) == NULL) - return(0); + /*LINTED*/ + key.data = cyp; + key.size = 1; - while(*gr->gr_mem) { - if (!strcmp(*gr->gr_mem, name)) - return(1); - gr->gr_mem++; + /* Pre-token database support. */ + bf[0] = _PW_KEYBYNAME; + bf[1] = '+'; + pkey.data = (u_char *)bf; + pkey.size = 2; + + if ((_pw_db->get)(_pw_db, &key, &data, 0) + && (_pw_db->get)(_pw_db, &pkey, &pdata, 0)) + return 0; /* No compat token */ + return 1; +} + +/* + * log an error if "files" or "compat" is specified in passwd_compat database + */ +static int _bad_getpw __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_bad_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + static int warned; + if (!warned) { + syslog(LOG_ERR, + "nsswitch.conf passwd_compat database can't use '%s'", + (char *)cb_data); } + warned = 1; + return NS_UNAVAIL; +} - return(0); +/* + * when a name lookup in compat mode is required (e.g., '+name', or a name in + * '+@netgroup'), look it up in the 'passwd_compat' nsswitch database. + * only Hesiod and NIS is supported - it doesn't make sense to lookup + * compat names from 'files' or 'compat'. + */ +static int __getpwcompat __P((int, uid_t, const char *)); + +static int +__getpwcompat(type, uid, name) + int type; + uid_t uid; + const char *name; +{ + static const ns_dtab dtab[] = { + NS_FILES_CB(_bad_getpw, "files") + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_bad_getpw, "compat") + { 0 } + }; + static const ns_src defaultnis[] = { + { NSSRC_NIS, NS_SUCCESS }, + { 0 } + }; + + switch (type) { + case _PW_KEYBYNUM: + return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "getpwcompat", + defaultnis, type); + case _PW_KEYBYNAME: + return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "getpwcompat", + defaultnis, type, name); + case _PW_KEYBYUID: + return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "getpwcompat", + defaultnis, type, uid); + default: + abort(); + /*NOTREACHED*/ + } } +#endif /* _PASSWD_COMPAT */ /* - * Check a user against the +@netgroup/-@netgroup lines listed in - * the local password database. Also checks +user/-user lines. - * If no netgroup exists that matches +@netgroup/-@netgroup, - * try searching regular groups with the same name. + * compat implementation of getpwent() + * varargs (ignored): + * type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] */ -static inline int -verf(name) - const char *name; +static int _compat_getpwent __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_compat_getpwent(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - DBT key; - char bf[sizeof(_pw_keynum) + 1]; - int keynum = 0; + DBT key; + int rval; + char bf[sizeof(_pw_keynum) + 1]; +#ifdef _PASSWD_COMPAT + static char *name = NULL; + char *user, *host, *dom; + int has_compatpw; +#endif + if (!_pw_db && !__initdb()) + return NS_UNAVAIL; + +#ifdef _PASSWD_COMPAT + has_compatpw = __has_compatpw(); + again: - ++keynum; - bf[0] = _PW_KEYYPBYNUM; - bcopy((char *)&keynum, bf + 1, sizeof(keynum)); - key.data = (u_char *)bf; - key.size = sizeof(keynum) + 1; - if (!__hashpw(&key)) { - /* Try again using old format */ - bf[0] = _PW_KEYBYNUM; - bcopy((char *)&keynum, bf + 1, sizeof(keynum)); - key.data = (u_char *)bf; - if (!__hashpw(&key)) - return(0); - } - if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-')) - goto again; - if (_pw_passwd.pw_name[0] == '+') { - if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */ - return(1); - if (_pw_passwd.pw_name[1] == '@') { - if ((innetgr(_pw_passwd.pw_name+2, NULL, name, - _pw_yp_domain) || - ingr(_pw_passwd.pw_name+2, name)) && !lookup(name)) - return(1); - else - goto again; - } else { - if (!strcmp(name, _pw_passwd.pw_name+1) && - !lookup(name)) - return(1); - else - goto again; + if (has_compatpw && (__pwmode != PWMODE_NONE)) { + int r; + + switch (__pwmode) { + case PWMODE_FULL: + r = __getpwcompat(_PW_KEYBYNUM, 0, NULL); + if (r == NS_SUCCESS) + return r; + __pwmode = PWMODE_NONE; + break; + + case PWMODE_NETGRP: + r = getnetgrent(&host, &user, &dom); + if (r == 0) { /* end of group */ + endnetgrent(); + __pwmode = PWMODE_NONE; + break; + } + if (!user || !*user) + break; + r = __getpwcompat(_PW_KEYBYNAME, 0, user); + if (r == NS_SUCCESS) + return r; + break; + + case PWMODE_USER: + if (name == NULL) { + __pwmode = PWMODE_NONE; + break; + } + r = __getpwcompat(_PW_KEYBYNAME, 0, name); + free(name); + name = NULL; + if (r == NS_SUCCESS) + return r; + break; + + case PWMODE_NONE: + abort(); } + goto again; } - if (_pw_passwd.pw_name[0] == '-') { - /* Note that a minus wildcard is a no-op. */ - if (_pw_passwd.pw_name[1] == '@') { - if (innetgr(_pw_passwd.pw_name+2, NULL, name, - _pw_yp_domain) || - ingr(_pw_passwd.pw_name+2, name)) { - store(name); - return(0); - } else +#endif + + if (_pw_keynum == -1) + return NS_NOTFOUND; /* no more local records */ + ++_pw_keynum; + bf[0] = _PW_KEYBYNUM; + memmove(bf + 1, &_pw_keynum, sizeof(_pw_keynum)); + key.data = (u_char *)bf; + key.size = sizeof(_pw_keynum) + 1; + rval = __hashpw(&key); + if (rval == NS_NOTFOUND) + _pw_keynum = -1; /* flag `no more local records' */ + else if (rval == NS_SUCCESS) { +#ifdef _PASSWD_COMPAT + /* if we don't have YP at all, don't bother. */ + if (has_compatpw) { + if(_pw_passwd.pw_name[0] == '+') { + /* set the mode */ + switch(_pw_passwd.pw_name[1]) { + case '\0': + __pwmode = PWMODE_FULL; + break; + case '@': + __pwmode = PWMODE_NETGRP; + setnetgrent(_pw_passwd.pw_name + 2); + break; + default: + __pwmode = PWMODE_USER; + name = strdup(_pw_passwd.pw_name + 1); + break; + } + + /* save the prototype */ + __pwproto_set(); goto again; - } else { - if (!strcmp(name, _pw_passwd.pw_name+1)) { - store(name); - return(0); - } else + } else if(_pw_passwd.pw_name[0] == '-') { + /* an attempted exclusion */ + switch(_pw_passwd.pw_name[1]) { + case '\0': + break; + case '@': + setnetgrent(_pw_passwd.pw_name + 2); + while(getnetgrent(&host, &user, &dom)) { + if(user && *user) + __pwexclude_add(user); + } + endnetgrent(); + break; + default: + __pwexclude_add(_pw_passwd.pw_name + 1); + break; + } goto again; + } } - +#endif } - return(0); + return (rval); } -static char * -_get_adjunct_pw(name) - const char *name; -{ - static char adjunctbuf[YPMAXRECORD+2]; - int rval; - char *result; - int resultlen; - char *map = "passwd.adjunct.byname"; - char *s; +/* + * compat implementation of getpwnam() and getpwuid() + * varargs: type, [ uid (type == _PW_KEYBYUID) | name (type == _PW_KEYBYNAME) ] + */ +static int _compat_getpw __P((void *, void *, va_list)); - if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name), - &result, &resultlen))) - return(NULL); - - strncpy(adjunctbuf, result, resultlen); - adjunctbuf[resultlen] = '\0'; - free(result); - result = (char *)&adjunctbuf; - - /* Don't care about the name. */ - if ((s = strsep(&result, ":")) == NULL) - return (NULL); /* name */ - if ((s = strsep(&result, ":")) == NULL) - return (NULL); /* password */ - - return(s); -} - static int -_pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master) +_compat_getpw(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - char *s, *result; - static char resbuf[YPMAXRECORD+2]; +#ifdef _PASSWD_COMPAT + DBT key; + int search, rval, r, s, keynum; + uid_t uid; + char bf[sizeof(keynum) + 1]; + char *name, *host, *user, *dom; +#endif - /* - * Be triple, ultra super-duper paranoid: reject entries - * that start with a + or -. yp_mkdb and /var/yp/Makefile - * are _both_ supposed to strip these out, but you never - * know. - */ - if (*res == '+' || *res == '-') - return 0; + if (!_pw_db && !__initdb()) + return NS_UNAVAIL; - /* - * The NIS protocol definition limits the size of an NIS - * record to YPMAXRECORD bytes. We need to do a copy to - * a static buffer here since the memory pointed to by - * res will be free()ed when this function returns. - */ - strncpy((char *)&resbuf, res, resultlen); - resbuf[resultlen] = '\0'; - result = (char *)&resbuf; + /* + * If there isn't a compat token in the database, use files. + */ +#ifdef _PASSWD_COMPAT + if (! __has_compatpw()) +#endif + return (_local_getpw(rv, cb_data, ap)); - /* - * XXX Sanity check: make sure all fields are valid (no NULLs). - * If we find a badly formatted entry, we punt. - */ - if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ - /* - * We don't care what pw_fields says: we _always_ want the - * username returned to us by NIS. - */ - pw->pw_name = s; - pw->pw_fields |= _PWF_NAME; - - if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ - if(!(pw->pw_fields & _PWF_PASSWD)) { - /* SunOS passwd.adjunct hack */ - if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) { - char *realpw; - realpw = _get_adjunct_pw(pw->pw_name); - if (realpw == NULL) - pw->pw_passwd = s; - else - pw->pw_passwd = realpw; - } else { - pw->pw_passwd = s; - } - pw->pw_fields |= _PWF_PASSWD; +#ifdef _PASSWD_COMPAT + search = va_arg(ap, int); + uid = 0; + name = NULL; + rval = NS_NOTFOUND; + switch (search) { + case _PW_KEYBYNAME: + name = va_arg(ap, char *); + break; + case _PW_KEYBYUID: + uid = va_arg(ap, uid_t); + break; + default: + abort(); } - if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */ - if(!(pw->pw_fields & _PWF_UID)) { - pw->pw_uid = atoi(s); - pw->pw_fields |= _PWF_UID; - } + for (s = -1, keynum = 1 ; ; keynum++) { + bf[0] = _PW_KEYBYNUM; + memmove(bf + 1, &keynum, sizeof(keynum)); + key.data = (u_char *)bf; + key.size = sizeof(keynum) + 1; + if(__hashpw(&key) != NS_SUCCESS) + break; + switch(_pw_passwd.pw_name[0]) { + case '+': + /* save the prototype */ + __pwproto_set(); - if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ - if(!(pw->pw_fields & _PWF_GID)) { - pw->pw_gid = atoi(s); - pw->pw_fields |= _PWF_GID; - } + switch(_pw_passwd.pw_name[1]) { + case '\0': + r = __getpwcompat(search, uid, name); + if (r != NS_SUCCESS) + continue; + break; + case '@': +pwnam_netgrp: +#if 0 /* XXX: is this a hangover from pre-nsswitch? */ + if(__ypcurrent) { + free(__ypcurrent); + __ypcurrent = NULL; + } +#endif + if (s == -1) /* first time */ + setnetgrent(_pw_passwd.pw_name + 2); + s = getnetgrent(&host, &user, &dom); + if (s == 0) { /* end of group */ + endnetgrent(); + s = -1; + continue; + } + if (!user || !*user) + goto pwnam_netgrp; - if (master == YP_HAVE_MASTER) { - if ((s = strsep(&result, ":")) == NULL) return 0; /* class */ - if(!(pw->pw_fields & _PWF_CLASS)) { - pw->pw_class = s; - pw->pw_fields |= _PWF_CLASS; - } + r = __getpwcompat(_PW_KEYBYNAME, 0, user); - if ((s = strsep(&result, ":")) == NULL) return 0; /* change */ - if(!(pw->pw_fields & _PWF_CHANGE)) { - pw->pw_change = atol(s); - pw->pw_fields |= _PWF_CHANGE; - } + if (r == NS_UNAVAIL) + return r; + if (r == NS_NOTFOUND) { + /* + * just because this user is bad + * it doesn't mean they all are. + */ + goto pwnam_netgrp; + } + break; + default: + user = _pw_passwd.pw_name + 1; + r = __getpwcompat(_PW_KEYBYNAME, 0, user); - if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */ - if(!(pw->pw_fields & _PWF_EXPIRE)) { - pw->pw_expire = atol(s); - pw->pw_fields |= _PWF_EXPIRE; + if (r == NS_UNAVAIL) + return r; + if (r == NS_NOTFOUND) + continue; + break; + } + if(__pwexclude_is(_pw_passwd.pw_name)) { + if(s == 1) /* inside netgroup */ + goto pwnam_netgrp; + continue; + } + break; + case '-': + /* attempted exclusion */ + switch(_pw_passwd.pw_name[1]) { + case '\0': + break; + case '@': + setnetgrent(_pw_passwd.pw_name + 2); + while(getnetgrent(&host, &user, &dom)) { + if(user && *user) + __pwexclude_add(user); + } + endnetgrent(); + break; + default: + __pwexclude_add(_pw_passwd.pw_name + 1); + break; + } + break; } + if ((search == _PW_KEYBYNAME && + strcmp(_pw_passwd.pw_name, name) == 0) + || (search == _PW_KEYBYUID && _pw_passwd.pw_uid == uid)) { + rval = NS_SUCCESS; + break; + } + if(s == 1) /* inside netgroup */ + goto pwnam_netgrp; + continue; } + __pwproto = (struct passwd *)NULL; - if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */ - if(!(pw->pw_fields & _PWF_GECOS)) { - pw->pw_gecos = s; - pw->pw_fields |= _PWF_GECOS; + if (!_pw_stayopen) { + (void)(_pw_db->close)(_pw_db); + _pw_db = (DB *)NULL; } - - if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */ - if(!(pw->pw_fields & _PWF_DIR)) { - pw->pw_dir = s; - pw->pw_fields |= _PWF_DIR; + if(__pwexclude != (DB *)NULL) { + (void)(__pwexclude->close)(__pwexclude); + __pwexclude = (DB *)NULL; } + return rval; +#endif /* _PASSWD_COMPAT */ +} - if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */ - if(!(pw->pw_fields & _PWF_SHELL)) { - pw->pw_shell = s; - pw->pw_fields |= _PWF_SHELL; - } +struct passwd * +getpwent() +{ + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_getpw, NULL) + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_compat_getpwent, NULL) + { 0 } + }; - /* Be consistent. */ - if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0'; - - return 1; + r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwent", compatsrc, + _PW_KEYBYNUM); + if (r != NS_SUCCESS) + return (struct passwd *)NULL; + return &_pw_passwd; } -static int -_havemaster(char *_yp_domain) +struct passwd * +getpwnam(name) + const char *name; { - int order; - int rval; + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_getpw, NULL) + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_compat_getpw, NULL) + { 0 } + }; - if (!(rval = yp_order(_yp_domain, "master.passwd.byname", &order))) - return(YP_HAVE_MASTER); + if (name == NULL || name[0] == '\0') + return (struct passwd *)NULL; - /* - * NIS+ in YP compat mode doesn't support - * YPPROC_ORDER -- no point in continuing. - */ - if (rval == YPERR_YPERR) - return(YP_HAVE_NONE); + r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwnam", compatsrc, + _PW_KEYBYNAME, name); + return (r == NS_SUCCESS ? &_pw_passwd : (struct passwd *)NULL); +} - /* master.passwd doesn't exist -- try passwd.adjunct */ - if (rval == YPERR_MAP) { - rval = yp_order(_yp_domain, "passwd.adjunct.byname", &order); - if (!rval) - return(YP_HAVE_ADJUNCT); - } +struct passwd * +getpwuid(uid) + uid_t uid; +{ + int r; + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_getpw, NULL) + NS_DNS_CB(_dns_getpw, NULL) + NS_NIS_CB(_nis_getpw, NULL) + NS_COMPAT_CB(_compat_getpw, NULL) + { 0 } + }; - return (YP_HAVE_NONE); + r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwuid", compatsrc, + _PW_KEYBYUID, uid); + return (r == NS_SUCCESS ? &_pw_passwd : (struct passwd *)NULL); } -static int -_getyppass(struct passwd *pw, const char *name, const char *map) +int +setpassent(stayopen) + int stayopen; { - char *result, *s; - int resultlen; - int rv; - char mastermap[YPMAXRECORD]; - - if(!_pw_yp_domain) { - if(yp_get_default_domain(&_pw_yp_domain)) - return 0; + _pw_keynum = 0; + _pw_stayopen = stayopen; +#ifdef YP + __pwmode = PWMODE_NONE; + if(__ypcurrent) + free(__ypcurrent); + __ypcurrent = NULL; + _pw_ypdone = 0; +#endif +#ifdef HESIOD + _pw_hesnum = 0; +#endif +#ifdef _PASSWD_COMPAT + if(__pwexclude != (DB *)NULL) { + (void)(__pwexclude->close)(__pwexclude); + __pwexclude = (DB *)NULL; } + __pwproto = (struct passwd *)NULL; +#endif + return 1; +} - if (_gotmaster == YP_HAVE_MASTER) - snprintf(mastermap, sizeof(mastermap), "master.%s", map); - else - snprintf(mastermap, sizeof(mastermap), "%s", map); +void +setpwent() +{ + (void) setpassent(0); +} - if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name), - &result, &resultlen)) { - if (_gotmaster != YP_HAVE_MASTER) - return 0; - snprintf(mastermap, sizeof(mastermap), "%s", map); - if (yp_match(_pw_yp_domain, (char *)&mastermap, - name, strlen(name), &result, &resultlen)) - return 0; - _gotmaster = YP_HAVE_NONE; +void +endpwent() +{ + _pw_keynum = 0; + if (_pw_db) { + (void)(_pw_db->close)(_pw_db); + _pw_db = (DB *)NULL; } +#ifdef _PASSWD_COMPAT + __pwmode = PWMODE_NONE; +#endif +#ifdef YP + if(__ypcurrent) + free(__ypcurrent); + __ypcurrent = NULL; + _pw_ypdone = 0; +#endif +#ifdef HESIOD + _pw_hesnum = 0; +#endif +#ifdef _PASSWD_COMPAT + if(__pwexclude != (DB *)NULL) { + (void)(__pwexclude->close)(__pwexclude); + __pwexclude = (DB *)NULL; + } + __pwproto = (struct passwd *)NULL; +#endif +} - if (!_pw_stepping_yp) { - s = strchr(result, ':'); - if (s) { - *s = '\0'; - } else { - /* Must be a malformed entry if no colons. */ - free(result); - return(0); - } +static int +__initdb() +{ + static int warned; + char *p; - if (!verf(result)) { - *s = ':'; - free(result); - return(0); - } - - *s = ':'; /* Put back the colon we previously replaced with a NUL. */ +#ifdef _PASSWD_COMPAT + __pwmode = PWMODE_NONE; +#endif + if (geteuid() == 0) { + _pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (_pw_db) + return(1); } - - rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster); - free(result); - return(rv); + _pw_db = dbopen((p = _PATH_MP_DB), O_RDONLY, 0, DB_HASH, NULL); + if (_pw_db) + return 1; + if (!warned) + syslog(LOG_ERR, "%s: %m", p); + warned = 1; + return 0; } static int -_nextyppass(struct passwd *pw) +__hashpw(key) + DBT *key; { - static char *key; - static int keylen; - char *lastkey, *result, *s; - int resultlen; - int rv; - char *map = "passwd.byname"; + char *p, *t; + static u_int max; + static char *buf; + DBT data; - if(!_pw_yp_domain) { - if(yp_get_default_domain(&_pw_yp_domain)) - return 0; + switch ((_pw_db->get)(_pw_db, key, &data, 0)) { + case 0: + break; /* found */ + case 1: + return NS_NOTFOUND; + case -1: + return NS_UNAVAIL; /* error in db routines */ + default: + abort(); } - if (_gotmaster == YP_HAVE_MASTER) - map = "master.passwd.byname"; + p = (char *)data.data; + if (data.size > max && !(buf = realloc(buf, (max += 1024)))) + return NS_UNAVAIL; - if(!_pw_stepping_yp) { - if(key) free(key); - rv = yp_first(_pw_yp_domain, map, - &key, &keylen, &result, &resultlen); - if(rv) { - return 0; - } - _pw_stepping_yp = 1; - goto unpack; - } else { -tryagain: - lastkey = key; - rv = yp_next(_pw_yp_domain, map, key, keylen, - &key, &keylen, &result, &resultlen); - free(lastkey); -unpack: - if(rv) { - _pw_stepping_yp = 0; - return 0; - } + /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ + t = buf; +#define EXPAND(e) e = t; while ((*t++ = *p++)); +#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v + EXPAND(_pw_passwd.pw_name); + EXPAND(_pw_passwd.pw_passwd); + SCALAR(_pw_passwd.pw_uid); + SCALAR(_pw_passwd.pw_gid); + SCALAR(_pw_passwd.pw_change); + EXPAND(_pw_passwd.pw_class); + EXPAND(_pw_passwd.pw_gecos); + EXPAND(_pw_passwd.pw_dir); + EXPAND(_pw_passwd.pw_shell); + SCALAR(_pw_passwd.pw_expire); + SCALAR(_pw_passwd.pw_fields); - s = strchr(result, ':'); - if (s) { - *s = '\0'; - } else { - /* Must be a malformed entry if no colons. */ - free(result); - goto tryagain; - } - - if (lookup(result)) { - *s = ':'; - free(result); - goto tryagain; - } - - *s = ':'; /* Put back the colon we previously replaced with a NUL. */ - if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) { - free(result); - return(1); - } else { - free(result); - goto tryagain; - } - } + return NS_SUCCESS; } - -#endif /* YP */ Index: head/lib/libc/gen/getusershell.3 =================================================================== --- head/lib/libc/gen/getusershell.3 (revision 65531) +++ head/lib/libc/gen/getusershell.3 (revision 65532) @@ -1,102 +1,102 @@ +.\" $NetBSD: getusershell.3,v 1.6 1999/03/22 19:44:42 garbled Exp $ +.\" $FreeBSD$ +.\" .\" Copyright (c) 1985, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" @(#)getusershell.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd January 16, 1999 .Dt GETUSERSHELL 3 -.Os BSD 4.3 +.Os .Sh NAME .Nm getusershell , .Nm setusershell , .Nm endusershell -.Nd get legal user shells +.Nd get valid user shells .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Ft char * .Fn getusershell void .Ft void .Fn setusershell void .Ft void .Fn endusershell void .Sh DESCRIPTION The .Fn getusershell function -returns a pointer to a legal user shell as defined by the -system manager in the file -.Pa /etc/shells . -If -.Pa /etc/shells -is unreadable or does not exist, +returns a pointer to a valid user shell as defined by the +system manager in the shells database as described in +.Xr shells 5 . +If the shells database is not available, .Fn getusershell behaves as if .Pa /bin/sh and .Pa /bin/csh -were listed in the file. +were listed. .Pp The .Fn getusershell function reads the next line (opening the file if necessary); .Fn setusershell rewinds the file; .Fn endusershell closes it. .Sh FILES .Bl -tag -width /etc/shells -compact .It Pa /etc/shells .El .Sh DIAGNOSTICS The routine .Fn getusershell returns a null pointer (0) on .Dv EOF . .Sh SEE ALSO +.Xr nsswitch.conf 5 , .Xr shells 5 .Sh HISTORY The .Fn getusershell function appeared in .Bx 4.3 . .Sh BUGS The .Fn getusershell function leaves its result in an internal static object and returns -a pointer to that object. -Subsequent calls to +a pointer to that object. Subsequent calls to .Fn getusershell will modify the same object. Index: head/lib/libc/gen/getusershell.c =================================================================== --- head/lib/libc/gen/getusershell.c (revision 65531) +++ head/lib/libc/gen/getusershell.c (revision 65532) @@ -1,139 +1,278 @@ +/* $NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $ */ + /* * Copyright (c) 1985, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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$ */ +#include #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = + "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include -#include -#include + #include +#include +#include +#include +#include #include +#include +#include #include -#include +#ifdef HESIOD +#include +#endif +#ifdef YP +#include +#include +#include +#endif + /* * Local shells should NOT be added here. They should be added in * /etc/shells. */ -static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; -static char **curshell, **shells, *strings; -static char **initshells __P((void)); +static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; +static const char *const *curshell; +static StringList *sl; +static const char *const *initshells __P((void)); + /* - * Get a list of shells from _PATH_SHELLS, if it exists. + * Get a list of shells from "shells" nsswitch database */ char * -getusershell() +getusershell(void) { char *ret; if (curshell == NULL) curshell = initshells(); - ret = *curshell; + /*LINTED*/ + ret = (char *)*curshell; if (ret != NULL) curshell++; return (ret); } void -endusershell() +endusershell(void) { - - if (shells != NULL) - free(shells); - shells = NULL; - if (strings != NULL) - free(strings); - strings = NULL; + if (sl) + sl_free(sl, 1); + sl = NULL; curshell = NULL; } void -setusershell() +setusershell(void) { curshell = initshells(); } -static char ** -initshells() + +static int _local_initshells __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_local_initshells(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - register char **sp, *cp; - register FILE *fp; - struct stat statb; + char *sp, *cp; + FILE *fp; + char line[MAXPATHLEN + 2]; - if (shells != NULL) - free(shells); - shells = NULL; - if (strings != NULL) - free(strings); - strings = NULL; + if (sl) + sl_free(sl, 1); + sl = sl_init(); + if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) - return (okshells); - if (fstat(fileno(fp), &statb) == -1) { - (void)fclose(fp); - return (okshells); - } - if ((strings = malloc((u_int)statb.st_size)) == NULL) { - (void)fclose(fp); - return (okshells); - } - shells = calloc((unsigned)statb.st_size / 3, sizeof (char *)); - if (shells == NULL) { - (void)fclose(fp); - free(strings); - strings = NULL; - return (okshells); - } - sp = shells; - cp = strings; + return NS_UNAVAIL; + + sp = cp = line; while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { while (*cp != '#' && *cp != '/' && *cp != '\0') cp++; if (*cp == '#' || *cp == '\0') continue; - *sp++ = cp; - while (!isspace((unsigned char)*cp) && *cp != '#' && *cp != '\0') + sp = cp; + while (!isspace(*cp) && *cp != '#' && *cp != '\0') cp++; *cp++ = '\0'; + sl_add(sl, strdup(sp)); } - *sp = NULL; (void)fclose(fp); - return (shells); + return NS_SUCCESS; +} + +#ifdef HESIOD +static int _dns_initshells __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_dns_initshells(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + char shellname[] = "shells-XXXXX"; + int hsindex, hpi, r; + char **hp; + void *context; + + if (sl) + sl_free(sl, 1); + sl = sl_init(); + r = NS_UNAVAIL; + if (hesiod_init(&context) == -1) + return (r); + + for (hsindex = 0; ; hsindex++) { + snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex); + hp = hesiod_resolve(context, shellname, "shells"); + if (hp == NULL) { + if (errno == ENOENT) { + if (hsindex == 0) + r = NS_NOTFOUND; + else + r = NS_SUCCESS; + } + break; + } else { + for (hpi = 0; hp[hpi]; hpi++) + sl_add(sl, hp[hpi]); + free(hp); + } + } + hesiod_end(context); + return (r); +} +#endif /* HESIOD */ + +#ifdef YP +static int _nis_initshells __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_nis_initshells(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + static char *ypdomain; + + if (sl) + sl_free(sl, 1); + sl = sl_init(); + + if (ypdomain == NULL) { + switch (yp_get_default_domain(&ypdomain)) { + case 0: + break; + case YPERR_RESRC: + return NS_TRYAGAIN; + default: + return NS_UNAVAIL; + } + } + + for (;;) { + char *ypcur = NULL; + int ypcurlen = 0; /* XXX: GCC */ + char *key, *data; + int keylen, datalen; + int r; + + key = data = NULL; + if (ypcur) { + r = yp_next(ypdomain, "shells", ypcur, ypcurlen, + &key, &keylen, &data, &datalen); + free(ypcur); + switch (r) { + case 0: + break; + case YPERR_NOMORE: + free(key); + free(data); + return NS_SUCCESS; + default: + free(key); + free(data); + return NS_UNAVAIL; + } + ypcur = key; + ypcurlen = keylen; + } else { + if (yp_first(ypdomain, "shells", &ypcur, + &ypcurlen, &data, &datalen)) { + free(data); + return NS_UNAVAIL; + } + } + data[datalen] = '\0'; /* clear trailing \n */ + sl_add(sl, data); + } +} +#endif /* YP */ + +static const char *const * +initshells() +{ + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_initshells, NULL) + NS_DNS_CB(_dns_initshells, NULL) + NS_NIS_CB(_nis_initshells, NULL) + { 0 } + }; + if (sl) + sl_free(sl, 1); + sl = sl_init(); + + if (nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc) + != NS_SUCCESS) { + if (sl) + sl_free(sl, 1); + sl = NULL; + return (okshells); + } + sl_add(sl, NULL); + + return (const char *const *)(sl->sl_str); } Index: head/lib/libc/gen/pw_scan.c =================================================================== --- head/lib/libc/gen/pw_scan.c (revision 65531) +++ head/lib/libc/gen/pw_scan.c (revision 65532) @@ -1,174 +1,180 @@ /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #ifndef lint #if 0 static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ /* * This module is used to "verify" password entries by chpass(1) and * pwd_mkdb(8). */ #include #include #include #include #include #include #include #include #include #include "pw_scan.h" /* * Some software assumes that IDs are short. We should emit warnings * for id's which can not be stored in a short, but we are more liberal * by default, warning for IDs greater than USHRT_MAX. * * If pw_big_ids_warning is anything other than -1 on entry to pw_scan() * it will be set based on the existance of PW_SCAN_BIG_IDS in the * environment. */ -int pw_big_ids_warning = -1; +static int pw_big_ids_warning = -1; int -pw_scan(bp, pw) - char *bp; - struct passwd *pw; +__pw_scan(char *bp, struct passwd *pw, int flags) { uid_t id; int root; char *p, *sh; if (pw_big_ids_warning == -1) pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0; pw->pw_fields = 0; if (!(pw->pw_name = strsep(&bp, ":"))) /* login */ goto fmt; root = !strcmp(pw->pw_name, "root"); if(pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0')) pw->pw_fields |= _PWF_NAME; if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */ goto fmt; if(pw->pw_passwd[0]) pw->pw_fields |= _PWF_PASSWD; if (!(p = strsep(&bp, ":"))) /* uid */ goto fmt; if (p[0]) pw->pw_fields |= _PWF_UID; else { if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') { - warnx("no uid for user %s", pw->pw_name); + if (flags & _PWSCAN_WARN) + warnx("no uid for user %s", pw->pw_name); return (0); } } id = strtoul(p, (char **)NULL, 10); if (errno == ERANGE) { - warnx("%s > max uid value (%u)", p, ULONG_MAX); + if (flags & _PWSCAN_WARN) + warnx("%s > max uid value (%u)", p, ULONG_MAX); return (0); } if (root && id) { - warnx("root uid should be 0"); + if (flags & _PWSCAN_WARN) + warnx("root uid should be 0"); return (0); } - if (pw_big_ids_warning && id > USHRT_MAX) { + if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) { warnx("%s > recommended max uid value (%u)", p, USHRT_MAX); /*return (0);*/ /* THIS SHOULD NOT BE FATAL! */ } pw->pw_uid = id; if (!(p = strsep(&bp, ":"))) /* gid */ goto fmt; if(p[0]) pw->pw_fields |= _PWF_GID; id = strtoul(p, (char **)NULL, 10); if (errno == ERANGE) { - warnx("%s > max gid value (%u)", p, ULONG_MAX); + if (flags & _PWSCAN_WARN) + warnx("%s > max gid value (%u)", p, ULONG_MAX); return (0); } - if (pw_big_ids_warning && id > USHRT_MAX) { + if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) { warnx("%s > recommended max gid value (%u)", p, USHRT_MAX); /* return (0); This should not be fatal! */ } pw->pw_gid = id; - pw->pw_class = strsep(&bp, ":"); /* class */ - if(pw->pw_class[0]) pw->pw_fields |= _PWF_CLASS; - - if (!(p = strsep(&bp, ":"))) /* change */ - goto fmt; - if(p[0]) pw->pw_fields |= _PWF_CHANGE; - pw->pw_change = atol(p); - - if (!(p = strsep(&bp, ":"))) /* expire */ - goto fmt; - if(p[0]) pw->pw_fields |= _PWF_EXPIRE; - pw->pw_expire = atol(p); - + if (flags & _PWSCAN_MASTER ) { + pw->pw_class = strsep(&bp, ":"); /* class */ + if(pw->pw_class[0]) pw->pw_fields |= _PWF_CLASS; + + if (!(p = strsep(&bp, ":"))) /* change */ + goto fmt; + if(p[0]) pw->pw_fields |= _PWF_CHANGE; + pw->pw_change = atol(p); + + if (!(p = strsep(&bp, ":"))) /* expire */ + goto fmt; + if(p[0]) pw->pw_fields |= _PWF_EXPIRE; + pw->pw_expire = atol(p); + } if (!(pw->pw_gecos = strsep(&bp, ":"))) /* gecos */ goto fmt; if(pw->pw_gecos[0]) pw->pw_fields |= _PWF_GECOS; if (!(pw->pw_dir = strsep(&bp, ":"))) /* directory */ goto fmt; if(pw->pw_dir[0]) pw->pw_fields |= _PWF_DIR; if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */ goto fmt; p = pw->pw_shell; if (root && *p) /* empty == /bin/sh */ for (setusershell();;) { if (!(sh = getusershell())) { - warnx("warning, unknown root shell"); + if (flags & _PWSCAN_WARN) + warnx("warning, unknown root shell"); break; } if (!strcmp(p, sh)) break; } if(p[0]) pw->pw_fields |= _PWF_SHELL; if ((p = strsep(&bp, ":"))) { /* too many */ -fmt: warnx("corrupted entry"); +fmt: + if (flags & _PWSCAN_WARN) + warnx("corrupted entry"); return (0); } return (1); } Index: head/lib/libc/gen/pw_scan.h =================================================================== --- head/lib/libc/gen/pw_scan.h (revision 65531) +++ head/lib/libc/gen/pw_scan.h (revision 65532) @@ -1,40 +1,41 @@ /*- * Copyright (c) 1994 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94 * * $FreeBSD$ */ -extern int pw_big_ids_warning; +#define _PWSCAN_MASTER 0x01 +#define _PWSCAN_WARN 0x02 -extern int pw_scan __P((char *, struct passwd *)); +extern int __pw_scan __P((char *, struct passwd *, int)); Index: head/lib/libc/net/Makefile.inc =================================================================== --- head/lib/libc/net/Makefile.inc (revision 65531) +++ head/lib/libc/net/Makefile.inc (revision 65532) @@ -1,83 +1,97 @@ # from @(#)Makefile.inc 8.2 (Berkeley) 9/5/93 # $FreeBSD$ # machine-independent net sources .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/net ${.CURDIR}/../libc/net SRCS+= addr2ascii.c ascii2addr.c base64.c ether_addr.c getaddrinfo.c \ gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \ getifaddrs.c getnameinfo.c \ getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \ getproto.c getprotoent.c getprotoname.c getservbyname.c \ - getservbyport.c getservent.c herror.c inet_addr.c ifname.c \ - inet_lnaof.c \ + getservbyport.c getservent.c herror.c hesiod.c inet_addr.c \ + ifname.c inet_lnaof.c \ inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c \ inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \ inet_pton.c ip6opt.c linkaddr.c map_v4v6.c name6.c ns_addr.c \ ns_name.c ns_netint.c \ - ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c nsap_addr.c \ - rcmd.c recv.c res_comp.c res_data.c res_debug.c \ + ns_ntoa.c ns_parse.c ns_print.c ns_ttl.c \ + nsdispatch.c nslexer.c nsparser.c \ + nsap_addr.c rcmd.c recv.c res_comp.c res_data.c res_debug.c \ res_init.c res_mkquery.c res_mkupdate.c res_query.c res_send.c \ res_update.c rthdr.c send.c vars.c # not supported: iso_addr.c -CFLAGS+=-DINET6 +CFLAGS+=-DINET6 -I${.OBJDIR} +YFLAGS+=-p_nsyy +LFLAGS+=-P_nsyy + +CLEANFILES+=nsparser.c nslexer.c nsparser.h + +nsparser.h: nsparser.c + mv y.tab.h ${.TARGET} + +nslexer.c: nslexer.l nsparser.h + ${LEX} ${LFLAGS} -o/dev/stdout ${.IMPSRC} | \ + sed -e '/YY_BUF_SIZE/s/16384/1024/' >${.TARGET} + # machine-dependent net sources .include "${.CURDIR}/../libc/${MACHINE_ARCH}/net/Makefile.inc" .if ${LIB} == "c" MAN3+= addr2ascii.3 byteorder.3 ethers.3 getaddrinfo.3 gethostbyname.3 \ getifaddrs.3 getipnodebyname.3 \ - getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 if_indextoname.3 \ + getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 hesiod.3 \ + if_indextoname.3 \ inet.3 inet6_option_space.3 inet6_rthdr_space.3 linkaddr.3 \ - rcmd.3 resolver.3 + nsdispatch.3 rcmd.3 resolver.3 # not installed: iso_addr.3 ns.3 MLINKS+=addr2ascii.3 ascii2addr.3 MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \ byteorder.3 ntohs.3 MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \ ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3 MLINKS+=getaddrinfo.3 freeaddrinfo.3 getaddrinfo.3 gai_strerror.3 MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \ gethostbyname.3 gethostbyname2.3 gethostbyname.3 gethostent.3 \ gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \ gethostbyname.3 sethostent.3 MLINKS+=getifaddrs.3 freeifaddrs.3 MLINKS+=getipnodebyname.3 getipnodebyaddr.3 getipnodebyname.3 freehostent.3 MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \ getnetent.3 getnetbyname.3 getnetent.3 setnetent.3 MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \ getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3 MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \ getservent.3 getservbyport.3 getservent.3 setservent.3 MLINKS+=if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \ if_indextoname.3 if_freenameindex.3 MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \ inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \ inet.3 inet_network.3 inet.3 inet_ntoa.3 \ inet.3 inet_ntop.3 inet.3 inet_pton.3 \ inet.3 network.3 inet.3 ntoa.3 MLINKS+=inet6_option_space.3 inet6_option_alloc.3 \ inet6_option_space.3 inet6_option_append.3 \ inet6_option_space.3 inet6_option_find.3 \ inet6_option_space.3 inet6_option_init.3 \ inet6_option_space.3 inet6_option_next.3 \ inet6_rthdr_space.3 inet6_rthdr_add.3 \ inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \ inet6_rthdr_space.3 inet6_rthdr_getflags.3 \ inet6_rthdr_space.3 inet6_rthdr_init.3 \ inet6_rthdr_space.3 inet6_rthdr_lasthop.3 \ inet6_rthdr_space.3 inet6_rthdr_reverse.3 \ inet6_rthdr_space.3 inet6_rthdr_segments.3 MLINKS+=linkaddr.3 link_addr.3 linkaddr.3 link_ntoa.3 #MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3 MLINKS+=rcmd.3 iruserok.3 rcmd.3 iruserok_sa.3 \ rcmd.3 rcmd_af.3 \ rcmd.3 rresvport.3 rcmd.3 rresvport_af.3 \ rcmd.3 ruserok.3 MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \ resolver.3 res_mkquery.3 resolver.3 res_query.3 \ resolver.3 res_search.3 resolver.3 res_send.3 .endif Index: head/lib/libc/net/getaddrinfo.3 =================================================================== --- head/lib/libc/net/getaddrinfo.3 (revision 65531) +++ head/lib/libc/net/getaddrinfo.3 (revision 65532) @@ -1,605 +1,605 @@ .\" $FreeBSD$ .\" $KAME: getaddrinfo.3,v 1.22 2000/08/09 21:16:17 itojun Exp $ .\" .\" Copyright (c) 1983, 1987, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 .\" .Dd May 25, 1995 .Dt GETADDRINFO 3 .Os .\" .Sh NAME .Nm getaddrinfo , .Nm freeaddrinfo , .Nm gai_strerror .Nd nodename-to-address translation in protocol-independent manner .\" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Fd #include .Fd #include .Ft int .Fn getaddrinfo "const char *nodename" "const char *servname" \ "const struct addrinfo *hints" "struct addrinfo **res" .Ft void .Fn freeaddrinfo "struct addrinfo *ai" .Ft "char *" .Fn gai_strerror "int ecode" .\" .Sh DESCRIPTION The .Fn getaddrinfo function is defined for protocol-independent nodename-to-address translation. It performs the functionality of .Xr gethostbyname 3 and .Xr getservbyname 3 , but in a more sophisticated manner. .Pp The .Li addrinfo structure is defined as a result of including the .Aq Pa netdb.h header: .Bd -literal -offset struct addrinfo { * int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for nodename */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; .Ed .Pp The .Fa nodename and .Fa servname arguments are pointers to null-terminated strings or .Dv NULL . One or both of these two arguments must be a .Pf non Dv -NULL pointer. In the normal client scenario, both the .Fa nodename and .Fa servname are specified. In the normal server scenario, only the .Fa servname is specified. A .Pf non Dv -NULL .Fa nodename string can be either a node name or a numeric host address string .Po i.e., a dotted-decimal IPv4 address or an IPv6 hex address .Pc . A .Pf non Dv -NULL .Fa servname string can be either a service name or a decimal port number. .Pp The caller can optionally pass an .Li addrinfo structure, pointed to by the third argument, to provide hints concerning the type of socket that the caller supports. In this .Fa hints structure all members other than .Fa ai_flags , .Fa ai_family , .Fa ai_socktype , and .Fa ai_protocol must be zero or a .Dv NULL pointer. A value of .Dv PF_UNSPEC for .Fa ai_family means the caller will accept any protocol family. A value of 0 for .Fa ai_socktype means the caller will accept any socket type. A value of 0 for .Fa ai_protocol means the caller will accept any protocol. For example, if the caller handles only TCP and not UDP, then the .Fa ai_socktype member of the hints structure should be set to .Dv SOCK_STREAM when .Fn getaddrinfo is called. If the caller handles only IPv4 and not IPv6, then the .Fa ai_family member of the .Fa hints structure should be set to .Dv PF_INET when .Fn getaddrinfo is called. If the third argument to .Fn getaddrinfo is a .Dv NULL pointer, this is the same as if the caller had filled in an .Li addrinfo structure initialized to zero with .Fa ai_family set to .Dv PF_UNSPEC . .Pp Upon successful return a pointer to a linked list of one or more .Li addrinfo structures is returned through the final argument. The caller can process each .Li addrinfo structure in this list by following the .Fa ai_next pointer, until a .Dv NULL pointer is encountered. In each returned .Li addrinfo structure the three members .Fa ai_family , .Fa ai_socktype , and .Fa ai_protocol are the corresponding arguments for a call to the .Fn socket function. In each .Li addrinfo structure the .Fa ai_addr member points to a filled-in socket address structure whose length is specified by the .Fa ai_addrlen member. .Pp If the .Dv AI_PASSIVE bit is set in the .Fa ai_flags member of the .Fa hints structure, then the caller plans to use the returned socket address structure in a call to .Fn bind . In this case, if the .Fa nodename argument is a .Dv NULL pointer, then the IP address portion of the socket address structure will be set to .Dv INADDR_ANY for an IPv4 address or .Dv IN6ADDR_ANY_INIT for an IPv6 address. .Pp If the .Dv AI_PASSIVE bit is not set in the .Fa ai_flags member of the .Fa hints structure, then the returned socket address structure will be ready for a call to .Fn connect .Pq for a connection-oriented protocol or either .Fn connect , .Fn sendto , or .Fn sendmsg .Pq for a connectionless protocol . In this case, if the .Fa nodename argument is a .Dv NULL pointer, then the IP address portion of the socket address structure will be set to the loopback address. .Pp If the .Dv AI_CANONNAME bit is set in the .Fa ai_flags member of the .Fa hints structure, then upon successful return the .Fa ai_canonname member of the first .Li addrinfo structure in the linked list will point to a null-terminated string containing the canonical name of the specified .Fa nodename . .Pp If the .Dv AI_NUMERICHOST bit is set in the .Fa ai_flags member of the .Fa hints structure, then a .Pf non Dv -NULL .Fa nodename string must be a numeric host address string. Otherwise an error of .Dv EAI_NONAME is returned. This flag prevents any type of name resolution service (e.g., the DNS) from being called. .Pp The arguments to .Fn getaddrinfo must sufficiently be consistent and unambiguous. Here are pitfall cases you may encounter: .Bl -bullet .It .Fn getaddrinfo will raise error if members in .Fa hints structure is not consistent. For example, for internet address families, .Fn getaddrinfo will raise error if you specify .Dv SOCK_STREAM to .Fa ai_socktype while you specify .Dv IPPROTO_UDP to .Fa ai_protocol . .It If you specify a .Fa servname which is defined only for certain .Fa ai_socktype , .Fn getaddrinfo will raise error because the arguments are not consistent. For example, .Fn getaddrinfo will raise error if you ask for .Dq Li tftp service on .Dv SOCK_STREAM . .It For internet address families, if you specify .Fa servname while you set .Fa ai_socktype to .Dv SOCK_RAW , .Fn getaddrinfo will raise error, because service names are not defined for the internet .Dv SOCK_RAW space. .It If you specify numeric .Fa servname , while leaving .Fa ai_socktype and .Fa ai_protocol unspecified, .Fn getaddrinfo will raise error. This is because the numeric .Fa servname does not identify any socket type, and .Fn getaddrinfo is not allowed to glob the argument in such case. .El .Pp All of the information returned by .Fn getaddrinfo is dynamically allocated: the .Li addrinfo structures, the socket address structures, and canonical node name strings pointed to by the addrinfo structures. To return this information to the system the function .Fn freeaddrinfo is called. The .Fa addrinfo structure pointed to by the .Fa ai argument is freed, along with any dynamic storage pointed to by the structure. This operation is repeated until a .Dv NULL .Fa ai_next pointer is encountered. .Pp To aid applications in printing error messages based on the .Dv EAI_xxx codes returned by .Fn getaddrinfo , .Fn gai_strerror is defined. The argument is one of the .Dv EAI_xxx values defined earlier and the return value points to a string describing the error. If the argument is not one of the .Dv EAI_xxx values, the function still returns a pointer to a string whose contents indicate an unknown error. .\" .Sh EXTENSION The implementation allows experimental numeric IPv6 address notation with scope identifier. By appending atmark and scope identifier to addresses, you can fill .Li sin6_scope_id field for addresses. This would make management of scoped address easier, and allows cut-and-paste input of scoped address. .Pp At this moment the code supports only link-local addresses with the format. Scope identifier is hardcoded to name of hardware interface associated with the link. .Po such as .Li ne0 .Pc . Example would be like .Dq Li fe80::1%ne0 , which means .Do .Li fe80::1 on the link associated with .Li ne0 interface .Dc . .Pp The implementation is still very experimental and non-standard. The current implementation assumes one-by-one relationship between interface and link, which is not necessarily true from the specification. .\" .Sh EXAMPLES The following code tries to connect to .Dq Li www.kame.net service .Dq Li http . via stream socket. It loops through all the addresses available, regardless from address family. If the destination resolves to IPv4 address, it will use .Dv AF_INET socket. Similarly, if it resolves to IPv6, .Dv AF_INET6 socket is used. Observe that there is no hardcoded reference to particular address family. The code works even if .Nm getaddrinfo returns addresses that are not IPv4/v6. .Bd -literal -offset indent struct addrinfo hints, *res, *res0; int error; int s; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo("www.kame.net", "http", &hints, &res0); if (error) { err1(1, "%s", gai_strerror(error)); /*NOTREACHED*/ } s = -1; for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { cause = "socket"; continue; } if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { cause = "connect"; close(s); s = -1; continue; } break; /* okay we got one */ } if (s < 0) { err(1, cause); /*NOTREACHED*/ } freeaddrinfo(res0); .Ed .Pp The following example tries to open wildcard listening socket onto service .Dq Li http , for all the address families available. .Bd -literal -offset indent struct addrinfo hints, *res, *res0; int error; int s[MAXSOCK]; int nsock; const char *cause = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; error = getaddrinfo(NULL, "http", &hints, &res0); if (error) { err1(1, "%s", gai_strerror(error)); /*NOTREACHED*/ } nsock = 0; for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) { s[nsock] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s[nsock] < 0) { cause = "socket"; continue; } if (connect(s[nsock], res->ai_addr, res->ai_addrlen) < 0) { cause = "connect"; close(s[nsock]); continue; } nsock++; } if (nsock == 0) { err(1, cause); /*NOTREACHED*/ } freeaddrinfo(res0); .Ed .\" .Sh FILES -.Bl -tag -width /etc/resolv.conf -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts -.It Pa /etc/host.conf +.It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El .\" .Sh DIAGNOSTICS Error return status from .Fn getaddrinfo is zero on success and non-zero on errors. Non-zero error codes are defined in .Aq Pa netdb.h , and as follows: .Pp .Bl -tag -width EAI_ADDRFAMILY -compact .It Dv EAI_ADDRFAMILY Address family for .Fa nodename not supported. .It Dv EAI_AGAIN Temporary failure in name resolution. .It Dv EAI_BADFLAGS Invalid value for .Fa ai_flags . .It Dv EAI_FAIL Non-recoverable failure in name resolution. .It Dv EAI_FAMILY .Fa ai_family not supported. .It Dv EAI_MEMORY Memory allocation failure. .It Dv EAI_NODATA No address associated with .Fa nodename . .It Dv EAI_NONAME .Fa nodename nor .Fa servname provided, or not known. .It Dv EAI_SERVICE .Fa servname not supported for .Fa ai_socktype . .It Dv EAI_SOCKTYPE .Fa ai_socktype not supported. .It Dv EAI_SYSTEM System error returned in .Va errno . .El .Pp If called with proper argument, .Fn gai_strerror returns a pointer to a string describing the given error code. If the argument is not one of the .Dv EAI_xxx values, the function still returns a pointer to a string whose contents indicate an unknown error. .\" .Sh SEE ALSO .Xr getnameinfo 3 , .Xr gethostbyname 3 , .Xr getservbyname 3 , .Xr hosts 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 .Pp .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 .%R RFC2553 .%D March 1999 .Re .Rs .%A Tatsuya Jinmei .%A Atsushi Onoe .%T "An Extension of Format for IPv6 Scoped Addresses" .%R internet draft .%N draft-ietf-ipngwg-scopedaddr-format-02.txt .%O work in progress material .Re .Rs .%A Craig Metz .%T Protocol Independence Using the Sockets API .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re .\" .Sh HISTORY The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit. .\" .Sh STANDARDS The .Fn getaddrinfo function is defined IEEE POSIX 1003.1g draft specification, and documented in .Dq Basic Socket Interface Extensions for IPv6 .Pq RFC2553 . .\" .Sh BUGS The current implementation is not thread-safe. .Pp The text was shamelessly copied from RFC2553. Index: head/lib/libc/net/getaddrinfo.c =================================================================== --- head/lib/libc/net/getaddrinfo.c (revision 65531) +++ head/lib/libc/net/getaddrinfo.c (revision 65532) @@ -1,1960 +1,1978 @@ -/* $FreeBSD$ */ +/* $FreeBSD$ */ /* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ /* * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. * * Issues to be discussed: * - Thread safe-ness must be checked. * - Return values. There are nonstandard return values defined and used * in the source code. This is because RFC2553 is silent about which error * code must be returned for which situation. * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is * invalid. * current code - SEGV on freeaddrinfo(NULL) * Note: * - We use getipnodebyname() just for thread-safeness. There's no intent * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to * getipnodebyname(). * - The code filters out AFs that are not supported by the kernel, * when globbing NULL hostname (to loopback, or wildcard). Is it the right * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG * in ai_flags? * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. * (1) what should we do against numeric hostname (2) what should we do * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? * non-loopback address configured? global address configured? * - To avoid search order issue, we have a big amount of code duplicate * from gethnamaddr.c and some other places. The issues that there's no * lower layer function to lookup "IPv4 or IPv6" record. Calling * gethostbyname2 from getaddrinfo will end up in wrong search order, as * follows: * - The code makes use of following calls when asked to resolver with * ai_family = PF_UNSPEC: * getipnodebyname(host, AF_INET6); * getipnodebyname(host, AF_INET); * This will result in the following queries if the node is configure to * prefer /etc/hosts than DNS: * lookup /etc/hosts for IPv6 address * lookup DNS for IPv6 address * lookup /etc/hosts for IPv4 address * lookup DNS for IPv4 address * which may not meet people's requirement. * The right thing to happen is to have underlying layer which does * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. * This would result in a bit of code duplicate with _dns_ghbyname() and * friends. */ /* * diffs with other KAME platforms: * - other KAME platforms already nuked FAITH ($GAI), but as FreeBSD * 4.0-RELEASE supplies it, we still have the code here. * - EAI_RESNULL support * - AI_ADDRCONFIG support is supplied * - EDNS0 support is not available due to resolver differences * - some of FreeBSD style (#define tabify and others) * - AI_ADDRCONFIG is turned on by default. * - classful IPv4 numeric (127.1) is allowed. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include + #if defined(__KAME__) && defined(INET6) # define FAITH #endif -#define SUCCESS 0 -#define ANY 0 -#define YES 1 -#define NO 0 +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 static const char in_addrany[] = { 0, 0, 0, 0 }; static const char in6_addrany[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char in_loopback[] = { 127, 0, 0, 1 }; static const char in6_loopback[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; static const struct afd { int a_af; int a_addrlen; int a_socklen; int a_off; const char *a_addrany; - const char *a_loopback; + const char *a_loopback; int a_scoped; } afdl [] = { #ifdef INET6 #define N_INET6 0 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), offsetof(struct sockaddr_in6, sin6_addr), in6_addrany, in6_loopback, 1}, #define N_INET 1 #else #define N_INET 0 #endif {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), offsetof(struct sockaddr_in, sin_addr), in_addrany, in_loopback, 0}, {0, 0, 0, 0, NULL, NULL, 0}, }; struct explore { int e_af; int e_socktype; int e_protocol; const char *e_protostr; int e_wild; -#define WILD_AF(ex) ((ex)->e_wild & 0x01) -#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) -#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +#define WILD_AF(ex) ((ex)->e_wild & 0x01) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) }; static const struct explore explore[] = { #if 0 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, #endif #ifdef INET6 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, #endif { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, { -1, 0, 0, NULL, 0 }, }; #ifdef INET6 -#define PTON_MAX 16 +#define PTON_MAX 16 #else -#define PTON_MAX 4 +#define PTON_MAX 4 #endif +static const ns_src default_dns_files[] = { + { NSSRC_FILES, NS_SUCCESS }, + { NSSRC_DNS, NS_SUCCESS }, + { 0 } +}; + #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ #else #define MAXPACKET 1024 #endif typedef union { HEADER hdr; u_char buf[MAXPACKET]; } querybuf; struct res_target { struct res_target *next; const char *name; /* domain name */ int qclass, qtype; /* class and type of query */ u_char *answer; /* buffer to put answer */ int anslen; /* size of answer buffer */ int n; /* result length */ }; static int str_isnumber __P((const char *)); static int explore_fqdn __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int explore_null __P((const struct addrinfo *, const char *, struct addrinfo **)); static int explore_numeric __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int explore_numeric_scope __P((const struct addrinfo *, const char *, const char *, struct addrinfo **)); static int get_canonname __P((const struct addrinfo *, struct addrinfo *, const char *)); static struct addrinfo *get_ai __P((const struct addrinfo *, const struct afd *, const char *)); static int get_portmatch __P((const struct addrinfo *, const char *)); static int get_port __P((struct addrinfo *, const char *, int)); static const struct afd *find_afd __P((int)); static int addrconfig __P((struct addrinfo *)); #ifdef INET6 static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *)); #endif -static struct addrinfo *getanswer __P((const querybuf *, int, const char *, - int, const struct addrinfo *)); -static int _dns_getaddrinfo __P((const struct addrinfo *, const char *, - struct addrinfo **)); -static struct addrinfo *_gethtent __P((FILE *fp, const char *, - const struct addrinfo *)); -static int _files_getaddrinfo __P((const struct addrinfo *, const char *, - struct addrinfo **)); +static struct addrinfo *getanswer __P((const querybuf *, int, const char *, int, + const struct addrinfo *)); +static int _dns_getaddrinfo __P((void *, void *, va_list)); +static void _sethtent __P((void)); +static void _endhtent __P((void)); +static struct addrinfo *_gethtent __P((const char *, const struct addrinfo *)); +static int _files_getaddrinfo __P((void *, void *, va_list)); #ifdef YP -static int _nis_getaddrinfo __P((const struct addrinfo *, const char *, - struct addrinfo **)); +static struct addrinfo *_yphostent __P((char *, const struct addrinfo *)); +static int _yp_getaddrinfo __P((void *, void *, va_list)); #endif static int res_queryN __P((const char *, struct res_target *)); static int res_searchN __P((const char *, struct res_target *)); static int res_querydomainN __P((const char *, const char *, - struct res_target *)); + struct res_target *)); - static char *ai_errlist[] = { "Success", "Address family for hostname not supported", /* EAI_ADDRFAMILY */ "Temporary failure in name resolution", /* EAI_AGAIN */ "Invalid value for ai_flags", /* EAI_BADFLAGS */ "Non-recoverable failure in name resolution", /* EAI_FAIL */ "ai_family not supported", /* EAI_FAMILY */ "Memory allocation failure", /* EAI_MEMORY */ "No address associated with hostname", /* EAI_NODATA */ "hostname nor servname provided, or not known", /* EAI_NONAME */ "servname not supported for ai_socktype", /* EAI_SERVICE */ "ai_socktype not supported", /* EAI_SOCKTYPE */ "System error returned in errno", /* EAI_SYSTEM */ "Invalid value for hints", /* EAI_BADHINTS */ "Resolved protocol is unknown", /* EAI_PROTOCOL */ #ifdef EAI_RESNULL "Argument res is NULL", /* EAI_RESNULL */ #endif "Unknown error", /* EAI_MAX */ }; -/* - * Select order host function. - */ -#define MAXHOSTCONF 4 - -#ifndef HOSTCONF -# define HOSTCONF "/etc/host.conf" -#endif /* !HOSTCONF */ - -struct _hostconf { - int (*byname)(const struct addrinfo *, const char *, - struct addrinfo **); -}; - -/* default order */ -static struct _hostconf _hostconf[MAXHOSTCONF] = { - _dns_getaddrinfo, - _files_getaddrinfo, -#ifdef ICMPNL - NULL, -#endif /* ICMPNL */ -}; - -static int _hostconf_init_done; -static void _hostconf_init(void); - /* XXX macros that make external reference is BAD. */ -#define GET_AI(ai, afd, addr) \ +#define GET_AI(ai, afd, addr) \ do { \ /* external reference: pai, error, and label free */ \ (ai) = get_ai(pai, (afd), (addr)); \ if ((ai) == NULL) { \ error = EAI_MEMORY; \ goto free; \ } \ } while (/*CONSTCOND*/0) -#define GET_PORT(ai, serv) \ +#define GET_PORT(ai, serv) \ do { \ /* external reference: error and label free */ \ error = get_port((ai), (serv), 0); \ if (error != 0) \ goto free; \ } while (/*CONSTCOND*/0) -#define GET_CANONNAME(ai, str) \ +#define GET_CANONNAME(ai, str) \ do { \ /* external reference: pai, error and label free */ \ error = get_canonname(pai, (ai), (str)); \ if (error != 0) \ goto free; \ } while (/*CONSTCOND*/0) -#define ERR(err) \ +#define ERR(err) \ do { \ /* external reference: error, and label bad */ \ error = (err); \ goto bad; \ /*NOTREACHED*/ \ } while (/*CONSTCOND*/0) -#define MATCH_FAMILY(x, y, w) \ +#define MATCH_FAMILY(x, y, w) \ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) -#define MATCH(x, y, w) \ +#define MATCH(x, y, w) \ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) char * gai_strerror(ecode) int ecode; { if (ecode < 0 || ecode > EAI_MAX) ecode = EAI_MAX; return ai_errlist[ecode]; } void freeaddrinfo(ai) struct addrinfo *ai; { struct addrinfo *next; do { next = ai->ai_next; if (ai->ai_canonname) free(ai->ai_canonname); /* no need to free(ai->ai_addr) */ free(ai); ai = next; } while (ai); } static int str_isnumber(p) const char *p; { char *ep; if (*p == '\0') return NO; ep = NULL; (void)strtoul(p, &ep, 10); if (ep && *ep == '\0') return YES; else return NO; } int getaddrinfo(hostname, servname, hints, res) const char *hostname, *servname; const struct addrinfo *hints; struct addrinfo **res; { struct addrinfo sentinel; struct addrinfo *cur; int error = 0; struct addrinfo ai; struct addrinfo ai0; struct addrinfo *pai; const struct explore *ex; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; pai = &ai; pai->ai_flags = 0; pai->ai_family = PF_UNSPEC; pai->ai_socktype = ANY; pai->ai_protocol = ANY; pai->ai_addrlen = 0; pai->ai_canonname = NULL; pai->ai_addr = NULL; pai->ai_next = NULL; if (hostname == NULL && servname == NULL) return EAI_NONAME; #ifdef EAI_RESNULL if (res == NULL) return EAI_RESNULL; /* xxx */ #endif if (hints) { /* error check for hints */ if (hints->ai_addrlen || hints->ai_canonname || hints->ai_addr || hints->ai_next) ERR(EAI_BADHINTS); /* xxx */ if (hints->ai_flags & ~AI_MASK) ERR(EAI_BADFLAGS); switch (hints->ai_family) { case PF_UNSPEC: case PF_INET: #ifdef INET6 case PF_INET6: #endif break; default: ERR(EAI_FAMILY); } memcpy(pai, hints, sizeof(*pai)); /* * if both socktype/protocol are specified, check if they * are meaningful combination. */ if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { for (ex = explore; ex->e_af >= 0; ex++) { if (pai->ai_family != ex->e_af) continue; if (ex->e_socktype == ANY) continue; if (ex->e_protocol == ANY) continue; if (pai->ai_socktype == ex->e_socktype && pai->ai_protocol != ex->e_protocol) { ERR(EAI_BADHINTS); } } } } /* * post-2553: AI_ALL and AI_V4MAPPED are effective only against * AF_INET6 query. They needs to be ignored if specified in other * occassions. */ switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { case AI_V4MAPPED: case AI_ALL | AI_V4MAPPED: if (pai->ai_family != AF_INET6) pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); break; case AI_ALL: #if 1 /* illegal */ ERR(EAI_BADFLAGS); #else pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); #endif break; } /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed * for raw and other inet{,6} sockets. */ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) #ifdef PF_INET6 - || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) + || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) #endif ) { ai0 = *pai; /* backup *pai */ if (pai->ai_family == PF_UNSPEC) { #ifdef PF_INET6 pai->ai_family = PF_INET6; #else pai->ai_family = PF_INET; #endif } error = get_portmatch(pai, servname); if (error) ERR(error); *pai = ai0; } ai0 = *pai; /* NULL hostname, or numeric hostname */ for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; /* PF_UNSPEC entries are prepared for DNS queries only */ if (ex->e_af == PF_UNSPEC) continue; if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) continue; - if (!MATCH(pai->ai_socktype, ex->e_socktype, - WILD_SOCKTYPE(ex))) + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) continue; - if (!MATCH(pai->ai_protocol, ex->e_protocol, - WILD_PROTOCOL(ex))) + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) continue; if (pai->ai_family == PF_UNSPEC) pai->ai_family = ex->e_af; if (pai->ai_socktype == ANY && ex->e_socktype != ANY) pai->ai_socktype = ex->e_socktype; if (pai->ai_protocol == ANY && ex->e_protocol != ANY) pai->ai_protocol = ex->e_protocol; if (hostname == NULL) error = explore_null(pai, servname, &cur->ai_next); else - error = explore_numeric_scope(pai, hostname, servname, - &cur->ai_next); + error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next); if (error) goto free; while (cur && cur->ai_next) cur = cur->ai_next; } /* * XXX * If numreic representation of AF1 can be interpreted as FQDN * representation of AF2, we need to think again about the code below. */ if (sentinel.ai_next) goto good; if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NODATA); if (hostname == NULL) ERR(EAI_NODATA); #if 1 /* XXX: temporarily, behave as if AI_ADDRCONFIG is specified */ pai->ai_flags |= AI_ADDRCONFIG; #endif if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0)) ERR(EAI_FAIL); /* * hostname as alphabetical name. * we would like to prefer AF_INET6 than AF_INET, so we'll make a * outer loop by AFs. */ for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; /* require exact match for family field */ if (pai->ai_family != ex->e_af) continue; if (!MATCH(pai->ai_socktype, ex->e_socktype, - WILD_SOCKTYPE(ex))) { + WILD_SOCKTYPE(ex))) { continue; } if (!MATCH(pai->ai_protocol, ex->e_protocol, - WILD_PROTOCOL(ex))) { + WILD_PROTOCOL(ex))) { continue; } if (pai->ai_socktype == ANY && ex->e_socktype != ANY) pai->ai_socktype = ex->e_socktype; if (pai->ai_protocol == ANY && ex->e_protocol != ANY) pai->ai_protocol = ex->e_protocol; - error = explore_fqdn(pai, hostname, servname, &cur->ai_next); + error = explore_fqdn(pai, hostname, servname, + &cur->ai_next); while (cur && cur->ai_next) cur = cur->ai_next; } /* XXX */ if (sentinel.ai_next) error = 0; if (error) goto free; if (error == 0) { if (sentinel.ai_next) { good: *res = sentinel.ai_next; return SUCCESS; } else error = EAI_FAIL; } free: bad: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); *res = NULL; return error; } -static char * -_hgetword(char **pp) -{ - char c, *p, *ret; - const char *sp; - static const char sep[] = "# \t\n"; - - ret = NULL; - for (p = *pp; (c = *p) != '\0'; p++) { - for (sp = sep; *sp != '\0'; sp++) { - if (c == *sp) - break; - } - if (c == '#') - p[1] = '\0'; /* ignore rest of line */ - if (ret == NULL) { - if (*sp == '\0') - ret = p; - } else { - if (*sp != '\0') { - *p++ = '\0'; - break; - } - } - } - *pp = p; - if (ret == NULL || *ret == '\0') - return NULL; - return ret; -} - /* - * Initialize hostconf structure. - */ - -static void -_hostconf_init(void) -{ - FILE *fp; - int n; - char *p, *line; - char buf[BUFSIZ]; - - _hostconf_init_done = 1; - n = 0; - p = HOSTCONF; - if ((fp = fopen(p, "r")) == NULL) - return; - while (n < MAXHOSTCONF && fgets(buf, sizeof(buf), fp)) { - line = buf; - if ((p = _hgetword(&line)) == NULL) - continue; - do { - if (strcmp(p, "hosts") == 0 - || strcmp(p, "local") == 0 - || strcmp(p, "file") == 0 - || strcmp(p, "files") == 0) - _hostconf[n++].byname = _files_getaddrinfo; - else if (strcmp(p, "dns") == 0 - || strcmp(p, "bind") == 0) - _hostconf[n++].byname = _dns_getaddrinfo; -#ifdef YP - else if (strcmp(p, "nis") == 0) - _hostconf[n++].byname = _nis_getaddrinfo; -#endif - } while ((p = _hgetword(&line)) != NULL); - } - fclose(fp); - if (n < 0) { - /* no keyword found. do not change default configuration */ - return; - } - for (; n < MAXHOSTCONF; n++) - _hostconf[n].byname = NULL; -} - -/* * FQDN hostname, DNS lookup */ static int explore_fqdn(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { struct addrinfo *result; struct addrinfo *cur; - int error = 0, i; + int error = 0; + static const ns_dtab dtab[] = { + NS_FILES_CB(_files_getaddrinfo, NULL) + { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ + NS_NIS_CB(_yp_getaddrinfo, NULL) + { 0 } + }; result = NULL; - *res = NULL; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; - if (!_hostconf_init_done) - _hostconf_init(); - - for (i = 0; i < MAXHOSTCONF; i++) { - if (!_hostconf[i].byname) - continue; - error = (*_hostconf[i].byname)(pai, hostname, &result); - if (error != 0) - continue; + switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", + default_dns_files, hostname, pai)) { + case NS_TRYAGAIN: + error = EAI_AGAIN; + goto free; + case NS_UNAVAIL: + error = EAI_FAIL; + goto free; + case NS_NOTFOUND: + error = EAI_NODATA; + goto free; + case NS_SUCCESS: + error = 0; for (cur = result; cur; cur = cur->ai_next) { GET_PORT(cur, servname); /* canonname should be filled already */ } - *res = result; - return 0; + break; } + *res = result; + + return 0; + free: if (result) freeaddrinfo(result); return error; } /* * hostname == NULL. * passive socket -> anyaddr (0.0.0.0 or ::) * non-passive socket -> localhost (127.0.0.1 or ::1) */ static int explore_null(pai, servname, res) const struct addrinfo *pai; const char *servname; struct addrinfo **res; { int s; const struct afd *afd; struct addrinfo *cur; struct addrinfo sentinel; int error; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; /* * filter out AFs that are not supported by the kernel * XXX errno? */ s = socket(pai->ai_family, SOCK_DGRAM, 0); if (s < 0) { if (errno != EMFILE) return 0; } else _close(s); /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; if (pai->ai_flags & AI_PASSIVE) { GET_AI(cur->ai_next, afd, afd->a_addrany); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "anyaddr"); */ GET_PORT(cur->ai_next, servname); } else { GET_AI(cur->ai_next, afd, afd->a_loopback); /* xxx meaningless? * GET_CANONNAME(cur->ai_next, "localhost"); */ GET_PORT(cur->ai_next, servname); } cur = cur->ai_next; *res = sentinel.ai_next; return 0; free: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error; } /* * numeric hostname */ static int explore_numeric(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { const struct afd *afd; struct addrinfo *cur; struct addrinfo sentinel; int error; char pton[PTON_MAX]; *res = NULL; sentinel.ai_next = NULL; cur = &sentinel; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; switch (afd->a_af) { #if 1 /*X/Open spec*/ case AF_INET: if (inet_aton(hostname, (struct in_addr *)pton) == 1) { if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) { GET_AI(cur->ai_next, afd, pton); GET_PORT(cur->ai_next, servname); while (cur && cur->ai_next) cur = cur->ai_next; } else ERR(EAI_FAMILY); /*xxx*/ } break; #endif default: if (inet_pton(afd->a_af, hostname, pton) == 1) { if (pai->ai_family == afd->a_af || pai->ai_family == PF_UNSPEC /*?*/) { GET_AI(cur->ai_next, afd, pton); GET_PORT(cur->ai_next, servname); while (cur && cur->ai_next) cur = cur->ai_next; } else ERR(EAI_FAMILY); /*xxx*/ } break; } *res = sentinel.ai_next; return 0; free: bad: if (sentinel.ai_next) freeaddrinfo(sentinel.ai_next); return error; } /* * numeric hostname with scope */ static int explore_numeric_scope(pai, hostname, servname, res) const struct addrinfo *pai; const char *hostname; const char *servname; struct addrinfo **res; { #if !defined(SCOPE_DELIMITER) || !defined(INET6) return explore_numeric(pai, hostname, servname, res); #else const struct afd *afd; struct addrinfo *cur; int error; char *cp, *hostname2 = NULL, *scope, *addr; struct sockaddr_in6 *sin6; /* * if the servname does not match socktype/protocol, ignore it. */ if (get_portmatch(pai, servname) != 0) return 0; afd = find_afd(pai->ai_family); if (afd == NULL) return 0; + if (!afd->a_scoped) return explore_numeric(pai, hostname, servname, res); cp = strchr(hostname, SCOPE_DELIMITER); if (cp == NULL) return explore_numeric(pai, hostname, servname, res); /* * Handle special case of */ hostname2 = strdup(hostname); if (hostname2 == NULL) return EAI_MEMORY; /* terminate at the delimiter */ hostname2[cp - hostname] = '\0'; addr = hostname2; scope = cp + 1; error = explore_numeric(pai, addr, servname, res); if (error == 0) { int scopeid; for (cur = *res; cur; cur = cur->ai_next) { if (cur->ai_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; if ((scopeid = ip6_str2scopeid(scope, sin6)) == -1) { free(hostname2); return(EAI_NODATA); /* XXX: is return OK? */ } sin6->sin6_scope_id = scopeid; } } free(hostname2); return error; #endif } static int get_canonname(pai, ai, str) const struct addrinfo *pai; struct addrinfo *ai; const char *str; { if ((pai->ai_flags & AI_CANONNAME) != 0) { ai->ai_canonname = (char *)malloc(strlen(str) + 1); if (ai->ai_canonname == NULL) return EAI_MEMORY; strcpy(ai->ai_canonname, str); } return 0; } static struct addrinfo * get_ai(pai, afd, addr) const struct addrinfo *pai; const struct afd *afd; const char *addr; { char *p; struct addrinfo *ai; #ifdef FAITH struct in6_addr faith_prefix; char *fp_str; int translate = 0; #endif #ifdef FAITH /* * Transfrom an IPv4 addr into a special IPv6 addr format for * IPv6->IPv4 translation gateway. (only TCP is supported now) * * +-----------------------------------+------------+ * | faith prefix part (12 bytes) | embedded | * | | IPv4 addr part (4 bytes) * +-----------------------------------+------------+ * * faith prefix part is specified as ascii IPv6 addr format * in environmental variable GAI. * For FAITH to work correctly, routing to faith prefix must be * setup toward a machine where a FAITH daemon operates. * Also, the machine must enable some mechanizm * (e.g. faith interface hack) to divert those packet with * faith prefixed destination addr to user-land FAITH daemon. */ fp_str = getenv("GAI"); if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 && afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) { u_int32_t v4a; u_int8_t v4a_top; memcpy(&v4a, addr, sizeof v4a); v4a_top = v4a >> IN_CLASSA_NSHIFT; if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) && v4a_top != 0 && v4a != IN_LOOPBACKNET) { afd = &afdl[N_INET6]; memcpy(&faith_prefix.s6_addr[12], addr, sizeof(struct in_addr)); translate = 1; } } #endif ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); if (ai == NULL) return NULL; memcpy(ai, pai, sizeof(struct addrinfo)); ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); memset(ai->ai_addr, 0, (size_t)afd->a_socklen); ai->ai_addr->sa_len = afd->a_socklen; ai->ai_addrlen = afd->a_socklen; ai->ai_addr->sa_family = ai->ai_family = afd->a_af; - p = (char *)(ai->ai_addr); + p = (char *)(void *)(ai->ai_addr); #ifdef FAITH if (translate == 1) - memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen); + memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen); else #endif - memcpy(p + afd->a_off, addr, afd->a_addrlen); - + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); return ai; } static int get_portmatch(ai, servname) const struct addrinfo *ai; const char *servname; { /* get_port does not touch first argument. when matchonly == 1. */ /* LINTED const cast */ return get_port((struct addrinfo *)ai, servname, 1); } static int get_port(ai, servname, matchonly) struct addrinfo *ai; const char *servname; int matchonly; { const char *proto; struct servent *sp; int port; int allownumeric; if (servname == NULL) return 0; switch (ai->ai_family) { case AF_INET: #ifdef AF_INET6 case AF_INET6: #endif break; default: return 0; } switch (ai->ai_socktype) { case SOCK_RAW: return EAI_SERVICE; case SOCK_DGRAM: case SOCK_STREAM: allownumeric = 1; break; case ANY: allownumeric = 0; break; default: return EAI_SOCKTYPE; } if (str_isnumber(servname)) { if (!allownumeric) return EAI_SERVICE; port = htons(atoi(servname)); if (port < 0 || port > 65535) return EAI_SERVICE; } else { switch (ai->ai_socktype) { case SOCK_DGRAM: proto = "udp"; break; case SOCK_STREAM: proto = "tcp"; break; default: proto = NULL; break; } if ((sp = getservbyname(servname, proto)) == NULL) return EAI_SERVICE; port = sp->s_port; } if (!matchonly) { switch (ai->ai_family) { case AF_INET: ((struct sockaddr_in *)(void *) ai->ai_addr)->sin_port = port; break; #ifdef INET6 case AF_INET6: ((struct sockaddr_in6 *)(void *) ai->ai_addr)->sin6_port = port; break; #endif } } return 0; } static const struct afd * find_afd(af) int af; { const struct afd *afd; if (af == PF_UNSPEC) return NULL; for (afd = afdl; afd->a_af; afd++) { if (afd->a_af == af) return afd; } return NULL; } /* * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend * will take care of it. * the semantics of AI_ADDRCONFIG is not defined well. we are not sure * if the code is right or not. * * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with * _dns_getaddrinfo. */ static int addrconfig(pai) struct addrinfo *pai; { int s, af; /* * TODO: * Note that implementation dependent test for address * configuration should be done everytime called * (or apropriate interval), * because addresses will be dynamically assigned or deleted. */ af = pai->ai_family; if (af == AF_UNSPEC) { if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) af = AF_INET; else { _close(s); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) af = AF_INET6; else _close(s); } - } if (af != AF_UNSPEC) { if ((s = socket(af, SOCK_DGRAM, 0)) < 0) return 0; _close(s); } pai->ai_family = af; return 1; } #ifdef INET6 /* convert a string to a scope identifier. XXX: IPv6 specific */ static int ip6_str2scopeid(scope, sin6) char *scope; struct sockaddr_in6 *sin6; { int scopeid; struct in6_addr *a6 = &sin6->sin6_addr; char *ep; /* empty scopeid portion is invalid */ if (*scope == '\0') return -1; if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { /* * We currently assume a one-to-one mapping between links * and interfaces, so we simply use interface indices for * like-local scopes. */ scopeid = if_nametoindex(scope); if (scopeid == 0) goto trynumeric; return(scopeid); } /* still unclear about literal, allow numeric only - placeholder */ if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) goto trynumeric; if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) goto trynumeric; else goto trynumeric; /* global */ /* try to convert to a numeric id as a last resort */ trynumeric: scopeid = (int)strtoul(scope, &ep, 10); if (*ep == '\0') return scopeid; else return -1; } #endif #ifdef DEBUG static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\""; #endif +static FILE *hostf = NULL; static struct addrinfo * getanswer(answer, anslen, qname, qtype, pai) const querybuf *answer; int anslen; const char *qname; int qtype; const struct addrinfo *pai; { struct addrinfo sentinel, *cur; struct addrinfo ai; const struct afd *afd; char *canonname; const HEADER *hp; const u_char *cp; int n; const u_char *eom; char *bp; int type, class, buflen, ancount, qdcount; int haveanswer, had_error; char tbuf[MAXDNAME]; int (*name_ok) __P((const char *)); char hostbuf[8*1024]; memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; canonname = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: case T_AAAA: case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ name_ok = res_hnok; break; default: return (NULL); /* XXX should be abort(); */ } /* * find first satisfactory answer */ hp = &answer->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; buflen = sizeof hostbuf; cp = answer->buf + HFIXEDSZ; if (qdcount != 1) { h_errno = NO_RECOVERY; return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !(*name_ok)(bp)) { h_errno = NO_RECOVERY; return (NULL); } cp += n + QFIXEDSZ; if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { /* res_send() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { h_errno = NO_RECOVERY; return (NULL); } canonname = bp; bp += n; buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ qname = canonname; } haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; } cp += n; /* name */ type = _getshort(cp); cp += INT16SZ; /* type */ class = _getshort(cp); cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); cp += INT16SZ; /* len */ if (class != C_IN) { /* XXX - debug? syslog? */ cp += n; continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { had_error++; continue; } cp += n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); canonname = bp; bp += n; buflen -= n; continue; } if (qtype == T_ANY) { if (!(type == T_A || type == T_AAAA)) { cp += n; continue; } } else if (type != qtype) { #ifdef DEBUG if (type != T_KEY && type != T_SIG) syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", qname, p_class(C_IN), p_type(qtype), p_type(type)); #endif cp += n; continue; /* XXX - had_error++ ? */ } switch (type) { case T_A: case T_AAAA: if (strcasecmp(canonname, bp) != 0) { #ifdef DEBUG syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, canonname, bp); #endif cp += n; continue; /* XXX - had_error++ ? */ } if (type == T_A && n != INADDRSZ) { cp += n; continue; } if (type == T_AAAA && n != IN6ADDRSZ) { cp += n; continue; } #ifdef FILTER_V4MAPPED if (type == T_AAAA) { struct in6_addr in6; memcpy(&in6, cp, sizeof(in6)); if (IN6_IS_ADDR_V4MAPPED(&in6)) { cp += n; continue; } } #endif if (!haveanswer) { int nn; canonname = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; buflen -= nn; } /* don't overwrite pai */ ai = *pai; ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; afd = find_afd(ai.ai_family); if (afd == NULL) { cp += n; continue; } cur->ai_next = get_ai(&ai, afd, (const char *)cp); if (cur->ai_next == NULL) had_error++; while (cur && cur->ai_next) cur = cur->ai_next; cp += n; break; default: abort(); } if (!had_error) haveanswer++; } if (haveanswer) { if (!canonname) (void)get_canonname(pai, sentinel.ai_next, qname); else (void)get_canonname(pai, sentinel.ai_next, canonname); h_errno = NETDB_SUCCESS; return sentinel.ai_next; } h_errno = NO_RECOVERY; return NULL; } /*ARGSUSED*/ static int -_dns_getaddrinfo(pai, hostname, res) - const struct addrinfo *pai; - const char *hostname; - struct addrinfo **res; +_dns_getaddrinfo(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { struct addrinfo *ai; querybuf buf, buf2; const char *name; + const struct addrinfo *pai; struct addrinfo sentinel, *cur; struct res_target q, q2; + name = va_arg(ap, char *); + pai = va_arg(ap, const struct addrinfo *); + memset(&q, 0, sizeof(q2)); memset(&q2, 0, sizeof(q2)); memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; switch (pai->ai_family) { case AF_UNSPEC: /* prefer IPv6 */ q.qclass = C_IN; q.qtype = T_AAAA; q.answer = buf.buf; q.anslen = sizeof(buf); q.next = &q2; q2.qclass = C_IN; q2.qtype = T_A; q2.answer = buf2.buf; q2.anslen = sizeof(buf2); break; case AF_INET: q.qclass = C_IN; q.qtype = T_A; q.answer = buf.buf; q.anslen = sizeof(buf); break; case AF_INET6: q.qclass = C_IN; q.qtype = T_AAAA; q.answer = buf.buf; q.anslen = sizeof(buf); break; default: - return EAI_FAIL; + return NS_UNAVAIL; } - if (res_searchN(hostname, &q) < 0) - return EAI_NODATA; + if (res_searchN(name, &q) < 0) + return NS_NOTFOUND; ai = getanswer(&buf, q.n, q.name, q.qtype, pai); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } if (q.next) { ai = getanswer(&buf2, q2.n, q2.name, q2.qtype, pai); if (ai) cur->ai_next = ai; } if (sentinel.ai_next == NULL) switch (h_errno) { case HOST_NOT_FOUND: - return EAI_NODATA; + return NS_NOTFOUND; case TRY_AGAIN: - return EAI_AGAIN; + return NS_TRYAGAIN; default: - return EAI_FAIL; + return NS_UNAVAIL; } - *res = sentinel.ai_next; - return 0; + *((struct addrinfo **)rv) = sentinel.ai_next; + return NS_SUCCESS; } +static void +_sethtent() +{ + if (!hostf) + hostf = fopen(_PATH_HOSTS, "r" ); + else + rewind(hostf); +} + +static void +_endhtent() +{ + if (hostf) { + (void) fclose(hostf); + hostf = NULL; + } +} + static struct addrinfo * -_gethtent(hostf, name, pai) - FILE *hostf; +_gethtent(name, pai) const char *name; const struct addrinfo *pai; { char *p; char *cp, *tname, *cname; struct addrinfo hints, *res0, *res; int error; const char *addr; char hostbuf[8*1024]; + if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) + return (NULL); again: if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) return (NULL); if (*p == '#') goto again; if (!(cp = strpbrk(p, "#\n"))) goto again; *cp = '\0'; if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; addr = p; cname = NULL; /* if this is not something we're looking for, skip it. */ while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } tname = cp; if (cname == NULL) cname = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; if (strcasecmp(name, tname) == 0) goto found; } goto again; found: hints = *pai; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(addr, NULL, &hints, &res0); if (error) goto again; #ifdef FILTER_V4MAPPED /* XXX should check all items in the chain */ if (res0->ai_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) { freeaddrinfo(res0); goto again; } #endif for (res = res0; res; res = res->ai_next) { /* cover it up */ res->ai_flags = pai->ai_flags; if (pai->ai_flags & AI_CANONNAME) { if (get_canonname(pai, res, cname) != 0) { freeaddrinfo(res0); goto again; } } } return res0; } /*ARGSUSED*/ static int -_files_getaddrinfo(pai, hostname, res) - const struct addrinfo *pai; - const char *hostname; - struct addrinfo **res; +_files_getaddrinfo(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - FILE *hostf; + const char *name; + const struct addrinfo *pai; struct addrinfo sentinel, *cur; struct addrinfo *p; - sentinel.ai_next = NULL; + name = va_arg(ap, char *); + pai = va_arg(ap, struct addrinfo *); + + memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; - if ((hostf = fopen(_PATH_HOSTS, "r")) == NULL) - return EAI_FAIL; - while ((p = _gethtent(hostf, hostname, pai)) != NULL) { + _sethtent(); + while ((p = _gethtent(name, pai)) != NULL) { cur->ai_next = p; while (cur && cur->ai_next) cur = cur->ai_next; } - fclose(hostf); + _endhtent(); - if (!sentinel.ai_next) - return EAI_NODATA; - - *res = sentinel.ai_next; - return 0; + *((struct addrinfo **)rv) = sentinel.ai_next; + if (sentinel.ai_next == NULL) + return NS_NOTFOUND; + return NS_SUCCESS; } #ifdef YP +static char *__ypdomain; + /*ARGSUSED*/ -static int -_nis_getaddrinfo(pai, hostname, res) +static struct addrinfo * +_yphostent(line, pai) + char *line; const struct addrinfo *pai; - const char *hostname; - struct addrinfo **res; { - struct hostent *hp; - int h_error; - int af; struct addrinfo sentinel, *cur; - int i; - const struct afd *afd; + struct addrinfo hints, *res, *res0; int error; + char *p = line; + const char *addr, *canonname; + char *nextline; + char *cp; - sentinel.ai_next = NULL; + addr = canonname = NULL; + + memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; - af = (pai->ai_family == AF_UNSPEC) ? AF_INET : pai->ai_family; - if (af != AF_INET) - return (EAI_ADDRFAMILY); +nextline: + /* terminate line */ + cp = strchr(p, '\n'); + if (cp) { + *cp++ = '\0'; + nextline = cp; + } else + nextline = NULL; - if ((hp = _gethostbynisname(hostname, af)) == NULL) { - switch (errno) { - /* XXX: should be filled in */ - default: - error = EAI_FAIL; - break; - } - } else if (hp->h_name == NULL || - hp->h_name[0] == 0 || hp->h_addr_list[0] == NULL) { - hp = NULL; - error = EAI_FAIL; + cp = strpbrk(p, " \t"); + if (cp == NULL) { + if (canonname == NULL) + return (NULL); + else + goto done; } + *cp++ = '\0'; - if (hp == NULL) - return error; + addr = p; - for (i = 0; hp->h_addr_list[i] != NULL; i++) { - if (hp->h_addrtype != af) + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; continue; + } + if (!canonname) + canonname = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } - afd = find_afd(hp->h_addrtype); - if (afd == NULL) - continue; + hints = *pai; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(addr, NULL, &hints, &res0); + if (error == 0) { + for (res = res0; res; res = res->ai_next) { + /* cover it up */ + res->ai_flags = pai->ai_flags; - GET_AI(cur->ai_next, afd, hp->h_addr_list[i]); - if ((pai->ai_flags & AI_CANONNAME) != 0) { - /* - * RFC2553 says that ai_canonname will be set only for - * the first element. we do it for all the elements, - * just for convenience. - */ - GET_CANONNAME(cur->ai_next, hp->h_name); + if (pai->ai_flags & AI_CANONNAME) + (void)get_canonname(pai, res, canonname); } - + } else + res0 = NULL; + if (res0) { + cur->ai_next = res0; while (cur && cur->ai_next) cur = cur->ai_next; } - *res = sentinel.ai_next; - return 0; + if (nextline) { + p = nextline; + goto nextline; + } -free: - if (sentinel.ai_next) - freeaddrinfo(sentinel.ai_next); - return error; +done: + return sentinel.ai_next; +} + +/*ARGSUSED*/ +static int +_yp_getaddrinfo(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + struct addrinfo sentinel, *cur; + struct addrinfo *ai = NULL; + static char *__ypcurrent; + int __ypcurrentlen, r; + const char *name; + const struct addrinfo *pai; + + name = va_arg(ap, char *); + pai = va_arg(ap, const struct addrinfo *); + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + if (!__ypdomain) { + if (_yp_check(&__ypdomain) == 0) + return NS_UNAVAIL; + } + if (__ypcurrent) + free(__ypcurrent); + __ypcurrent = NULL; + + /* hosts.byname is only for IPv4 (Solaris8) */ + if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) { + r = yp_match(__ypdomain, "hosts.byname", name, + (int)strlen(name), &__ypcurrent, &__ypcurrentlen); + if (r == 0) { + struct addrinfo ai4; + + ai4 = *pai; + ai4.ai_family = AF_INET; + ai = _yphostent(__ypcurrent, &ai4); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + } + + /* ipnodes.byname can hold both IPv4/v6 */ + r = yp_match(__ypdomain, "ipnodes.byname", name, + (int)strlen(name), &__ypcurrent, &__ypcurrentlen); + if (r == 0) { + ai = _yphostent(__ypcurrent, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) { + h_errno = HOST_NOT_FOUND; + return NS_NOTFOUND; + } + *((struct addrinfo **)rv) = sentinel.ai_next; + return NS_SUCCESS; } #endif /* resolver logic */ extern const char *__hostalias __P((const char *)); extern int h_errno; /* * Formulate a normal query, send, and await answer. * Returned answer is placed in supplied buffer "answer". * Perform preliminary check of answer, returning success only * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. * Error number is left in h_errno. * * Caller must parse answer and determine whether it answers the question. */ static int res_queryN(name, target) const char *name; /* domain name */ struct res_target *target; { u_char buf[MAXPACKET]; HEADER *hp; int n; struct res_target *t; int rcode; int ancount; rcode = NOERROR; ancount = 0; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); } for (t = target; t; t = t->next) { int class, type; u_char *answer; int anslen; hp = (HEADER *)(void *)t->answer; hp->rcode = NOERROR; /* default */ /* make it easier... */ class = t->qclass; type = t->qtype; answer = t->answer; anslen = t->anslen; #ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type); #endif n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, buf, sizeof(buf)); if (n <= 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); #endif h_errno = NO_RECOVERY; return (n); } n = res_send(buf, n, answer, anslen); #if 0 if (n < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: send error\n"); #endif h_errno = TRY_AGAIN; return (n); } #endif if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { rcode = hp->rcode; /* record most recent error */ #ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; rcode = %d, ancount=%d\n", hp->rcode, ntohs(hp->ancount)); #endif continue; } ancount += ntohs(hp->ancount); t->n = n; } if (ancount == 0) { switch (rcode) { case NXDOMAIN: h_errno = HOST_NOT_FOUND; break; case SERVFAIL: h_errno = TRY_AGAIN; break; case NOERROR: h_errno = NO_DATA; break; case FORMERR: case NOTIMP: case REFUSED: default: h_errno = NO_RECOVERY; break; } return (-1); } return (ancount); } /* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. * If enabled, implement search rules until answer or unrecoverable failure * is detected. Error code, if any, is left in h_errno. */ static int res_searchN(name, target) const char *name; /* domain name */ struct res_target *target; { const char *cp, * const *domain; HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/ u_int dots; int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, tried_as_is = 0; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); } errno = 0; h_errno = HOST_NOT_FOUND; /* default, if we never query */ dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); trailing_dot = 0; if (cp > name && *--cp == '.') trailing_dot++; /* * if there aren't any dots, it could be a user-level alias */ if (!dots && (cp = __hostalias(name)) != NULL) return (res_queryN(cp, target)); /* * If there are dots in the name already, let's just give it a try * 'as is'. The threshold can be set with the "ndots" option. */ saved_herrno = -1; if (dots >= _res.ndots) { ret = res_querydomainN(name, NULL, target); if (ret > 0) return (ret); saved_herrno = h_errno; tried_as_is++; } /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ if ((!dots && (_res.options & RES_DEFNAMES)) || (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { int done = 0; for (domain = (const char * const *)_res.dnsrch; *domain && !done; domain++) { ret = res_querydomainN(name, *domain, target); if (ret > 0) return (ret); /* * If no server present, give up. * If name isn't found in this domain, * keep trying higher domains in the search list * (if that's enabled). * On a NO_DATA error, keep trying, otherwise * a wildcard entry of another type could keep us * from finding this entry higher in the domain. * If we get some other error (negative answer or * server failure), then stop searching up, * but try the input name below in case it's * fully-qualified. */ if (errno == ECONNREFUSED) { h_errno = TRY_AGAIN; return (-1); } switch (h_errno) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ case HOST_NOT_FOUND: /* keep trying */ break; case TRY_AGAIN: if (hp->rcode == SERVFAIL) { /* try next search element, if any */ got_servfail++; break; } /* FALLTHROUGH */ default: /* anything else implies that we're done */ done++; } /* * if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ if (!(_res.options & RES_DNSRCH)) done++; } } /* * if we have not already tried the name "as is", do that now. * note that we do this regardless of how many dots were in the * name or whether it ends with a dot. */ if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { ret = res_querydomainN(name, NULL, target); if (ret > 0) return (ret); } /* * if we got here, we didn't satisfy the search. * if we did an initial full query, return that query's h_errno * (note that we wouldn't be here if that query had succeeded). * else if we ever got a nodata, send that back as the reason. * else send back meaningless h_errno, that being the one from * the last DNSRCH we did. */ if (saved_herrno != -1) h_errno = saved_herrno; else if (got_nodata) h_errno = NO_DATA; else if (got_servfail) h_errno = TRY_AGAIN; return (-1); } /* * Perform a call on res_query on the concatenation of name and domain, * removing a trailing dot from name if domain is NULL. */ static int res_querydomainN(name, domain, target) const char *name, *domain; struct res_target *target; { char nbuf[MAXDNAME]; const char *longname = nbuf; size_t n, d; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return (-1); } #ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_querydomain(%s, %s)\n", name, domain?domain:""); #endif if (domain == NULL) { /* * Check for trailing '.'; * copy without '.' if present. */ n = strlen(name); if (n >= MAXDNAME) { h_errno = NO_RECOVERY; return (-1); } if (n > 0 && name[--n] == '.') { strncpy(nbuf, name, n); nbuf[n] = '\0'; } else longname = name; } else { n = strlen(name); d = strlen(domain); if (n + d + 1 >= MAXDNAME) { h_errno = NO_RECOVERY; return (-1); } sprintf(nbuf, "%s.%s", name, domain); } return (res_queryN(longname, target)); } Index: head/lib/libc/net/gethostbydns.c =================================================================== --- head/lib/libc/net/gethostbydns.c (revision 65531) +++ head/lib/libc/net/gethostbydns.c (revision 65532) @@ -1,778 +1,795 @@ /* * ++Copyright++ 1985, 1988, 1993 * - * Copyright (c) 1985, 1988, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $"; static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include "res_config.h" #define SPRINTF(x) ((size_t)sprintf x) #define MAXALIASES 35 #define MAXADDRS 35 static const char AskedForGot[] = "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; static char *h_addr_ptrs[MAXADDRS + 1]; static struct hostent host; static char *host_aliases[MAXALIASES]; static char hostbuf[8*1024]; static u_char host_addr[16]; /* IPv4 or IPv6 */ #ifdef RESOLVSORT static void addrsort __P((char **, int)); #endif #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ #else #define MAXPACKET 1024 #endif typedef union { HEADER hdr; u_char buf[MAXPACKET]; } querybuf; typedef union { int32_t al; char ac; } align; extern int h_errno; int _dns_ttl_; #ifdef DEBUG static void dprintf(msg, num) char *msg; int num; { if (_res.options & RES_DEBUG) { int save = errno; printf(msg, num); errno = save; } } #else # define dprintf(msg, num) /*nada*/ #endif #define BOUNDED_INCR(x) \ do { \ cp += x; \ if (cp > eom) { \ h_errno = NO_RECOVERY; \ return (NULL); \ } \ } while (0) #define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eom) { \ h_errno = NO_RECOVERY; \ return (NULL); \ } \ } while (0) static struct hostent * gethostanswer(answer, anslen, qname, qtype) const querybuf *answer; int anslen; const char *qname; int qtype; { register const HEADER *hp; register const u_char *cp; register int n; const u_char *eom, *erdata; char *bp, **ap, **hap; int type, class, buflen, ancount, qdcount; int haveanswer, had_error; int toobig = 0; char tbuf[MAXDNAME]; const char *tname; int (*name_ok) __P((const char *)); tname = qname; host.h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: case T_AAAA: name_ok = res_hnok; break; case T_PTR: name_ok = res_dnok; break; default: h_errno = NO_RECOVERY; return (NULL); /* XXX should be abort(); */ } /* * find first satisfactory answer */ hp = &answer->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; buflen = sizeof hostbuf; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { h_errno = NO_RECOVERY; return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !(*name_ok)(bp)) { h_errno = NO_RECOVERY; return (NULL); } BOUNDED_INCR(n + QFIXEDSZ); if (qtype == T_A || qtype == T_AAAA) { /* res_send() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { h_errno = NO_RECOVERY; return (NULL); } host.h_name = bp; bp += n; buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ qname = host.h_name; } ap = host_aliases; *ap = NULL; host.h_aliases = host_aliases; hap = h_addr_ptrs; *hap = NULL; host.h_addr_list = h_addr_ptrs; haveanswer = 0; had_error = 0; _dns_ttl_ = -1; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !(*name_ok)(bp)) { had_error++; continue; } cp += n; /* name */ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); type = _getshort(cp); cp += INT16SZ; /* type */ class = _getshort(cp); cp += INT16SZ; /* class */ if (qtype == T_A && type == T_A) _dns_ttl_ = _getlong(cp); cp += INT32SZ; /* TTL */ n = _getshort(cp); cp += INT16SZ; /* len */ BOUNDS_CHECK(cp, n); erdata = cp + n; if (class != C_IN) { /* XXX - debug? syslog? */ cp += n; continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { if (ap >= &host_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { had_error++; continue; } cp += n; if (cp != erdata) { h_errno = NO_RECOVERY; return (NULL); } /* Store alias. */ *ap++ = bp; n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { had_error++; continue; } bp += n; buflen -= n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); host.h_name = bp; bp += n; buflen -= n; continue; } if (qtype == T_PTR && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if (n < 0 || !res_dnok(tbuf)) { had_error++; continue; } cp += n; if (cp != erdata) { h_errno = NO_RECOVERY; return (NULL); } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); tname = bp; bp += n; buflen -= n; continue; } if (type != qtype) { if (type != T_SIG) syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"", qname, p_class(C_IN), p_type(qtype), p_type(type)); cp += n; continue; /* XXX - had_error++ ? */ } switch (type) { case T_PTR: if (strcasecmp(tname, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, qname, bp); cp += n; continue; /* XXX - had_error++ ? */ } n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !res_hnok(bp)) { had_error++; break; } #if MULTI_PTRS_ARE_ALIASES cp += n; if (cp != erdata) { h_errno = NO_RECOVERY; return (NULL); } if (!haveanswer) host.h_name = bp; else if (ap < &host_aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; if (n != -1) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { had_error++; break; } bp += n; buflen -= n; } break; #else host.h_name = bp; if (_res.options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { had_error++; break; } bp += n; buflen -= n; _map_v4v6_hostent(&host, &bp, &buflen); } h_errno = NETDB_SUCCESS; return (&host); #endif case T_A: case T_AAAA: if (strcasecmp(host.h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, AskedForGot, host.h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } if (n != host.h_length) { cp += n; continue; } if (!haveanswer) { register int nn; host.h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; buflen -= nn; } bp += sizeof(align) - ((u_long)bp % sizeof(align)); if (bp + n >= &hostbuf[sizeof hostbuf]) { dprintf("size (%d) too big\n", n); had_error++; continue; } if (hap >= &h_addr_ptrs[MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", MAXADDRS); cp += n; continue; } bcopy(cp, *hap++ = bp, n); bp += n; buflen -= n; cp += n; if (cp != erdata) { h_errno = NO_RECOVERY; return (NULL); } break; default: dprintf("Impossible condition (type=%d)\n", type); h_errno = NO_RECOVERY; return (NULL); /* BIND has abort() here, too risky on bad data */ } if (!had_error) haveanswer++; } if (haveanswer) { *ap = NULL; *hap = NULL; # if defined(RESOLVSORT) /* * Note: we sort even if host can take only one address * in its return structures - should give it the "best" * address in that case, not some random one */ if (_res.nsort && haveanswer > 1 && qtype == T_A) addrsort(h_addr_ptrs, haveanswer); # endif /*RESOLVSORT*/ if (!host.h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); host.h_name = bp; bp += n; buflen -= n; } if (_res.options & RES_USE_INET6) _map_v4v6_hostent(&host, &bp, &buflen); h_errno = NETDB_SUCCESS; return (&host); } no_recovery: h_errno = NO_RECOVERY; return (NULL); } struct hostent * __dns_getanswer(answer, anslen, qname, qtype) const char *answer; int anslen; const char *qname; int qtype; { switch(qtype) { case T_AAAA: host.h_addrtype = AF_INET6; host.h_length = IN6ADDRSZ; break; case T_A: default: host.h_addrtype = AF_INET; host.h_length = INADDRSZ; break; } return(gethostanswer((const querybuf *)answer, anslen, qname, qtype)); } -struct hostent * -_gethostbydnsname(name, af) +int +_dns_gethostbyname(void *rval, void *cb_data, va_list ap) +{ const char *name; int af; -{ querybuf buf; register const char *cp; char *bp; int n, size, type, len; + name = va_arg(ap, const char *); + af = va_arg(ap, int); + *(struct hostent **)rval = NULL; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; - return (NULL); + return NS_UNAVAIL; } switch (af) { case AF_INET: size = INADDRSZ; type = T_A; break; case AF_INET6: size = IN6ADDRSZ; type = T_AAAA; break; default: h_errno = NETDB_INTERNAL; errno = EAFNOSUPPORT; - return (NULL); + return NS_UNAVAIL; } host.h_addrtype = af; host.h_length = size; /* * if there aren't any dots, it could be a user-level alias. * this is also done in res_query() since we are not the only * function that looks up host names. */ if (!strchr(name, '.') && (cp = __hostalias(name))) name = cp; /* * disallow names consisting only of digits/dots, unless * they end in a dot. */ if (isdigit((unsigned char)name[0])) for (cp = name;; ++cp) { if (!*cp) { if (*--cp == '.') break; /* * All-numeric, no dot at the end. * Fake up a hostent as if we'd actually * done a lookup. */ if (inet_pton(af, name, host_addr) <= 0) { h_errno = HOST_NOT_FOUND; - return (NULL); + return NS_NOTFOUND; } strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; len = sizeof hostbuf - MAXDNAME; host.h_name = hostbuf; host.h_aliases = host_aliases; host_aliases[0] = NULL; h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; host.h_addr_list = h_addr_ptrs; if (_res.options & RES_USE_INET6) _map_v4v6_hostent(&host, &bp, &len); h_errno = NETDB_SUCCESS; - return (&host); + *(struct hostent **)rval = &host; + return NS_SUCCESS; } if (!isdigit((unsigned char)*cp) && *cp != '.') break; } if ((isxdigit((unsigned char)name[0]) && strchr(name, ':') != NULL) || name[0] == ':') for (cp = name;; ++cp) { if (!*cp) { if (*--cp == '.') break; /* * All-IPv6-legal, no dot at the end. * Fake up a hostent as if we'd actually * done a lookup. */ if (inet_pton(af, name, host_addr) <= 0) { h_errno = HOST_NOT_FOUND; - return (NULL); + return NS_NOTFOUND; } strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; len = sizeof hostbuf - MAXDNAME; host.h_name = hostbuf; host.h_aliases = host_aliases; host_aliases[0] = NULL; h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; host.h_addr_list = h_addr_ptrs; h_errno = NETDB_SUCCESS; - return (&host); + *(struct hostent **)rval = &host; + return NS_SUCCESS; } if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.') break; } if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) { dprintf("res_search failed (%d)\n", n); - return (NULL); + return NS_UNAVAIL; } - return (gethostanswer(&buf, n, name, type)); + *(struct hostent **)rval = gethostanswer(&buf, n, name, type); + return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } -struct hostent * -_gethostbydnsaddr(addr, len, af) +int +_dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) +{ const char *addr; /* XXX should have been def'd as u_char! */ int len, af; -{ - const u_char *uaddr = (const u_char *)addr; + const u_char *uaddr; static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; int n, size; querybuf buf; register struct hostent *hp; char qbuf[MAXDNAME+1], *qp; #ifdef SUNSECURITY register struct hostent *rhp; char **haddr; u_long old_options; char hname2[MAXDNAME+1]; #endif /*SUNSECURITY*/ + + addr = va_arg(ap, const char *); + uaddr = (const u_char *)addr; + len = va_arg(ap, int); + af = va_arg(ap, int); + *(struct hostent **)rval = NULL; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; - return (NULL); + return NS_UNAVAIL; } if (af == AF_INET6 && len == IN6ADDRSZ && (!bcmp(uaddr, mapped, sizeof mapped) || !bcmp(uaddr, tunnelled, sizeof tunnelled))) { /* Unmap. */ addr += sizeof mapped; uaddr += sizeof mapped; af = AF_INET; len = INADDRSZ; } switch (af) { case AF_INET: size = INADDRSZ; break; case AF_INET6: size = IN6ADDRSZ; break; default: errno = EAFNOSUPPORT; h_errno = NETDB_INTERNAL; - return (NULL); + return NS_UNAVAIL; } if (size != len) { errno = EINVAL; h_errno = NETDB_INTERNAL; - return (NULL); + return NS_UNAVAIL; } switch (af) { case AF_INET: (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff), (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff)); break; case AF_INET6: qp = qbuf; for (n = IN6ADDRSZ - 1; n >= 0; n--) { qp += SPRINTF((qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf)); } strcpy(qp, "ip6.int"); break; default: abort(); } n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); if (n < 0) { dprintf("res_query failed (%d)\n", n); - return (NULL); + return NS_UNAVAIL; } if (n > sizeof buf.buf) { dprintf("static buffer is too small (%d)\n", n); - return (NULL); + return NS_UNAVAIL; } if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR))) - return (NULL); /* h_errno was set by gethostanswer() */ + return NS_NOTFOUND; /* h_errno was set by gethostanswer() */ #ifdef SUNSECURITY if (af == AF_INET) { /* * turn off search as the name should be absolute, * 'localhost' should be matched by defnames */ strncpy(hname2, hp->h_name, MAXDNAME); hname2[MAXDNAME] = '\0'; old_options = _res.options; _res.options &= ~RES_DNSRCH; _res.options |= RES_DEFNAMES; if (!(rhp = gethostbyname(hname2))) { syslog(LOG_NOTICE|LOG_AUTH, "gethostbyaddr: No A record for %s (verifying [%s])", hname2, inet_ntoa(*((struct in_addr *)addr))); _res.options = old_options; h_errno = HOST_NOT_FOUND; - return (NULL); + return NS_NOTFOUND; } _res.options = old_options; for (haddr = rhp->h_addr_list; *haddr; haddr++) if (!memcmp(*haddr, addr, INADDRSZ)) break; if (!*haddr) { syslog(LOG_NOTICE|LOG_AUTH, "gethostbyaddr: A record of %s != PTR record [%s]", hname2, inet_ntoa(*((struct in_addr *)addr))); h_errno = HOST_NOT_FOUND; - return (NULL); + return NS_NOTFOUND; } } #endif /*SUNSECURITY*/ hp->h_addrtype = af; hp->h_length = len; bcopy(addr, host_addr, len); h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; if (af == AF_INET && (_res.options & RES_USE_INET6)) { _map_v4v6_address((char*)host_addr, (char*)host_addr); hp->h_addrtype = AF_INET6; hp->h_length = IN6ADDRSZ; } h_errno = NETDB_SUCCESS; - return (hp); + *(struct hostent **)rval = hp; + return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; } #ifdef RESOLVSORT static void addrsort(ap, num) char **ap; int num; { int i, j; char **p; short aval[MAXADDRS]; int needsort = 0; p = ap; for (i = 0; i < num; i++, p++) { for (j = 0 ; (unsigned)j < _res.nsort; j++) if (_res.sort_list[j].addr.s_addr == (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) break; aval[i] = j; if (needsort == 0 && i > 0 && j < aval[i-1]) needsort = i; } if (!needsort) return; while (needsort < num) { for (j = needsort - 1; j >= 0; j--) { if (aval[j] > aval[j+1]) { char *hp; i = aval[j]; aval[j] = aval[j+1]; aval[j+1] = i; hp = ap[j]; ap[j] = ap[j+1]; ap[j+1] = hp; } else break; } needsort++; } } #endif void _sethostdnsent(stayopen) int stayopen; { if ((_res.options & RES_INIT) == 0 && res_init() == -1) return; if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC; } void _endhostdnsent() { _res.options &= ~(RES_STAYOPEN | RES_USEVC); res_close(); } Index: head/lib/libc/net/gethostbyht.c =================================================================== --- head/lib/libc/net/gethostbyht.c (revision 65531) +++ head/lib/libc/net/gethostbyht.c (revision 65532) @@ -1,202 +1,215 @@ /*- * Copyright (c) 1985, 1988, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include +#include +#include #include /* XXX */ #include /* XXX */ #define MAXALIASES 35 static struct hostent host; static char *host_aliases[MAXALIASES]; static char hostbuf[BUFSIZ+1]; static FILE *hostf = NULL; static u_int32_t host_addr[4]; /* IPv4 or IPv6 */ static char *h_addr_ptrs[2]; static int stayopen = 0; void _sethosthtent(f) int f; { if (!hostf) hostf = fopen(_PATH_HOSTS, "r" ); else rewind(hostf); stayopen = f; } void _endhosthtent() { if (hostf && !stayopen) { (void) fclose(hostf); hostf = NULL; } } struct hostent * gethostent() { char *p; register char *cp, **q; int af, len; if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { h_errno = NETDB_INTERNAL; return (NULL); } again: if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { h_errno = HOST_NOT_FOUND; return (NULL); } if (*p == '#') goto again; if (!(cp = strpbrk(p, "#\n"))) goto again; *cp = '\0'; if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; if (inet_pton(AF_INET6, p, host_addr) > 0) { af = AF_INET6; len = IN6ADDRSZ; } else if (inet_pton(AF_INET, p, host_addr) > 0) { if (_res.options & RES_USE_INET6) { _map_v4v6_address((char*)host_addr, (char*)host_addr); af = AF_INET6; len = IN6ADDRSZ; } else { af = AF_INET; len = INADDRSZ; } } else { goto again; } h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; host.h_addr_list = h_addr_ptrs; host.h_length = len; host.h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; host.h_name = cp; q = host.h_aliases = host_aliases; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &host_aliases[MAXALIASES - 1]) *q++ = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } *q = NULL; h_errno = NETDB_SUCCESS; return (&host); } -struct hostent * -_gethostbyhtname(name, af) +int +_ht_gethostbyname(void *rval, void *cb_data, va_list ap) +{ const char *name; int af; -{ register struct hostent *p; register char **cp; + + name = va_arg(ap, const char *); + af = va_arg(ap, int); sethostent(0); while ((p = gethostent()) != NULL) { if (p->h_addrtype != af) continue; if (strcasecmp(p->h_name, name) == 0) break; for (cp = p->h_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } found: endhostent(); - return (p); + *(struct hostent **)rval = p; + + return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; } -struct hostent * -_gethostbyhtaddr(addr, len, af) +int +_ht_gethostbyaddr(void *rval, void *cb_data, va_list ap) +{ const char *addr; int len, af; -{ register struct hostent *p; + addr = va_arg(ap, const char *); + len = va_arg(ap, int); + af = va_arg(ap, int); + sethostent(0); while ((p = gethostent()) != NULL) if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) break; endhostent(); - return (p); + + *(struct hostent **)rval = p; + return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; } Index: head/lib/libc/net/gethostbyname.3 =================================================================== --- head/lib/libc/net/gethostbyname.3 (revision 65531) +++ head/lib/libc/net/gethostbyname.3 (revision 65532) @@ -1,307 +1,312 @@ .\" Copyright (c) 1983, 1987, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 .\" $FreeBSD$ .\" .Dd May 25, 1995 .Dt GETHOSTBYNAME 3 .Os BSD 4.2 .Sh NAME .Nm gethostbyname , .Nm gethostbyname2 , .Nm gethostbyaddr , .Nm gethostent , .Nm sethostent , .Nm endhostent , .Nm herror , .Nm hstrerror .Nd get network host entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Vt extern int h_errno; .Ft struct hostent * .Fn gethostbyname "const char *name" .Ft struct hostent * .Fn gethostbyname2 "const char *name" "int af" .Ft struct hostent * .Fn gethostbyaddr "const char *addr" "int len" "int type" .Ft struct hostent * .Fn gethostent void .Ft void .Fn sethostent "int stayopen" .Ft void .Fn endhostent void .Ft void .Fn herror "const char *string" .Ft const char * .Fn hstrerror "int err" .Sh DESCRIPTION The .Fn gethostbyname , .Fn gethostbyname2 and .Fn gethostbyaddr functions each return a pointer to an object with the following structure describing an internet host referenced by name or by address, respectively. This structure contains either the information obtained from the name server, .Xr named 8 , -or broken-out fields from a line in -.Pa /etc/hosts . -If the local name server is not running these routines do a lookup in -.Pa /etc/hosts . +broken-out fields from a line in +.Pa /etc/hosts , +or database entries supplied by the +.Xr yp 4 +system. +The order of the lookups is controlled by the +.Sq hosts +entry in +.Xr nsswitch.conf 5 . .Bd -literal struct hostent { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ int h_addrtype; /* host address type */ int h_length; /* length of address */ char **h_addr_list; /* list of addresses from name server */ }; #define h_addr h_addr_list[0] /* address, for backward compatibility */ .Ed .Pp The members of this structure are: .Bl -tag -width h_addr_list .It Fa h_name Official name of the host. .It Fa h_aliases A NULL-terminated array of alternate names for the host. .It Fa h_addrtype The type of address being returned; usually .Dv AF_INET . .It Fa h_length The length, in bytes, of the address. .It Fa h_addr_list A NULL-terminated array of network addresses for the host. Host addresses are returned in network byte order. .It Fa h_addr The first address in .Fa h_addr_list ; this is for backward compatibility. .El .Pp When using the nameserver, .Fn gethostbyname and .Fn gethostbyname2 will search for the named host in the current domain and its parents unless the name ends in a dot. If the name contains no dot, and if the environment variable .Dq Ev HOSTALIASES contains the name of an alias file, the alias file will first be searched for an alias matching the input name. See .Xr hostname 7 for the domain search procedure and the alias file format. .Pp The .Fn gethostbyname2 function is an evolution of .Fn gethostbyname which is intended to allow lookups in address families other than .Dv AF_INET , for example .Dv AF_INET6 . Currently the .Fa af argument must be specified as .Dv AF_INET else the function will return .Dv NULL after having set .Va h_errno to .Dv NETDB_INTERNAL .Pp The .Fn sethostent function may be used to request the use of a connected .Tn TCP socket for queries. If the .Fa stayopen flag is non-zero, this sets the option to send all queries to the name server using .Tn TCP and to retain the connection after each call to .Fn gethostbyname , .Fn gethostbyname2 or .Fn gethostbyaddr . Otherwise, queries are performed using .Tn UDP datagrams. .Pp The .Fn endhostent function closes the .Tn TCP connection. .Pp The .Fn herror function writes a message to the diagnostic output consisting of the string parameter .Fa s , the constant string ": ", and a message corresponding to the value of .Va h_errno . .Pp The .Fn hstrerror function returns a string which is the message text corresponding to the value of the .Fa err parameter. .Sh FILES -.Bl -tag -width /etc/resolv.conf -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts -.It Pa /etc/host.conf +.It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El .Sh DIAGNOSTICS Error return status from .Fn gethostbyname , .Fn gethostbyname2 and .Fn gethostbyaddr is indicated by return of a null pointer. The external integer .Va h_errno may then be checked to see whether this is a temporary failure or an invalid or unknown host. The routine .Fn herror can be used to print an error message describing the failure. If its argument .Fa string is .Pf non Dv -NULL , it is printed, followed by a colon and a space. The error message is printed with a trailing newline. .Pp The variable .Va h_errno can have the following values: .Bl -tag -width HOST_NOT_FOUND .It Dv HOST_NOT_FOUND No such host is known. .It Dv TRY_AGAIN This is usually a temporary error and means that the local server did not receive a response from an authoritative server. A retry at some later time may succeed. .It Dv NO_RECOVERY Some unexpected server failure was encountered. This is a non-recoverable error. .It Dv NO_DATA The requested name is valid but does not have an IP address; this is not a temporary error. This means that the name is known to the name server but there is no address associated with this name. Another type of request to the name server using this domain name will result in an answer; for example, a mail-forwarder may be registered for this domain. .El .Sh SEE ALSO .Xr resolver 3 , .Xr hosts 5 , .Xr hostname 7 , .Xr named 8 .Sh CAVEAT The .Fn gethostent function is defined, and .Fn sethostent and .Fn endhostent are redefined, when .Xr libc 3 is built to use only the routines to lookup in .Pa /etc/hosts and not the name server. .Pp The .Fn gethostent function reads the next line of .Pa /etc/hosts , opening the file if necessary. .Pp The .Fn sethostent function opens and/or rewinds the file .Pa /etc/hosts . If the .Fa stayopen argument is non-zero, the file will not be closed after each call to .Fn gethostbyname , .Fn gethostbyname2 or .Fn gethostbyaddr . .Pp The .Fn endhostent function closes the file. .Sh HISTORY The .Fn herror function appeared in .Bx 4.3 . The .Fn endhostent , .Fn gethostbyaddr , .Fn gethostbyname , .Fn gethostent , and .Fn sethostent functions appeared in .Bx 4.2 . The .Fn gethostbyname2 function first appeared in bind-4.9.4. .Sh BUGS These functions use static data storage; if the data is needed for future use, it should be copied before any subsequent calls overwrite it. Only the Internet address format is currently understood. Index: head/lib/libc/net/gethostbynis.c =================================================================== --- head/lib/libc/net/gethostbynis.c (revision 65531) +++ head/lib/libc/net/gethostbynis.c (revision 65532) @@ -1,145 +1,185 @@ /*- * Copyright (c) 1994, Garrett Wollman * * 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 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 REGENTS 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)$FreeBSD$"; static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include #include #include +#include +#include #ifdef YP #include #include #include #endif #define MAXALIASES 35 #define MAXADDRS 35 #ifdef YP static char *host_aliases[MAXALIASES]; static char hostaddr[MAXADDRS]; static char *host_addrs[2]; -#endif /* YP */ static struct hostent * _gethostbynis(name, map, af) const char *name; char *map; int af; { -#ifdef YP register char *cp, **q; char *result; int resultlen,size; static struct hostent h; static char *domain = (char *)NULL; static char ypbuf[YPMAXRECORD + 2]; switch(af) { case AF_INET: size = NS_INADDRSZ; break; default: case AF_INET6: size = NS_IN6ADDRSZ; errno = EAFNOSUPPORT; return NULL; } if (domain == (char *)NULL) if (yp_get_default_domain (&domain)) return ((struct hostent *)NULL); if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) return ((struct hostent *)NULL); /* avoid potential memory leak */ bcopy((char *)result, (char *)&ypbuf, resultlen); ypbuf[resultlen] = '\0'; free(result); result = (char *)&ypbuf; if ((cp = index(result, '\n'))) *cp = '\0'; cp = strpbrk(result, " \t"); *cp++ = '\0'; h.h_addr_list = host_addrs; h.h_addr = hostaddr; *((u_long *)h.h_addr) = inet_addr(result); h.h_length = size; h.h_addrtype = AF_INET; while (*cp == ' ' || *cp == '\t') cp++; h.h_name = cp; q = h.h_aliases = host_aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &host_aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return (&h); -#else - return (NULL); -#endif /* YP */ } +#endif /* YP */ +/* XXX _gethostbynisname/_gethostbynisaddr only used by getaddrinfo */ struct hostent * -_gethostbynisname(name, af) - const char *name; - int af; +_gethostbynisname(const char *name, int af) { +#ifdef YP return _gethostbynis(name, "hosts.byname", af); +#else + return NULL; +#endif } struct hostent * -_gethostbynisaddr(addr, len, af) +_gethostbynisaddr(const char *addr, int len, int af) +{ +#ifdef YP + return _gethostbynis(inet_ntoa(*(struct in_addr *)addr), + "hosts.byaddr", af); +#else + return NULL; +#endif +} + + +int +_nis_gethostbyname(void *rval, void *cb_data, va_list ap) +{ +#ifdef YP + const char *name; + int af; + + name = va_arg(ap, const char *); + af = va_arg(ap, int); + + *(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af); + return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; +#else + return NS_UNAVAIL; +#endif +} + +int +_nis_gethostbyaddr(void *rval, void *cb_data, va_list ap) +{ +#ifdef YP const char *addr; int len; int af; -{ - return _gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af); + + addr = va_arg(ap, const char *); + len = va_arg(ap, int); + af = va_arg(ap, int); + + *(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af); + return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; +#else + return NS_UNAVAIL; +#endif } Index: head/lib/libc/net/gethostnamadr.c =================================================================== --- head/lib/libc/net/gethostnamadr.c (revision 65531) +++ head/lib/libc/net/gethostnamadr.c (revision 65532) @@ -1,224 +1,150 @@ /*- * Copyright (c) 1994, Garrett Wollman * * 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 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 REGENTS 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)$FreeBSD$"; static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include +#include +#include #include /* XXX hack for _res */ #include /* XXX hack for _res */ -#define _PATH_HOSTCONF "/etc/host.conf" +extern int _ht_gethostbyname(void *, void *, va_list); +extern int _dns_gethostbyname(void *, void *, va_list); +extern int _nis_gethostbyname(void *, void *, va_list); +extern int _ht_gethostbyaddr(void *, void *, va_list); +extern int _dns_gethostbyaddr(void *, void *, va_list); +extern int _nis_gethostbyaddr(void *, void *, va_list); -enum service_type { - SERVICE_NONE = 0, - SERVICE_BIND, - SERVICE_HOSTS, - SERVICE_NIS }; -#define SERVICE_MAX SERVICE_NIS - -static struct { - const char *name; - enum service_type type; -} service_names[] = { - { "hosts", SERVICE_HOSTS }, - { "/etc/hosts", SERVICE_HOSTS }, - { "hosttable", SERVICE_HOSTS }, - { "htable", SERVICE_HOSTS }, - { "bind", SERVICE_BIND }, - { "dns", SERVICE_BIND }, - { "domain", SERVICE_BIND }, - { "yp", SERVICE_NIS }, - { "yellowpages", SERVICE_NIS }, - { "nis", SERVICE_NIS }, - { 0, SERVICE_NONE } +/* Host lookup order if nsswitch.conf is broken or nonexistant */ +static const ns_src default_src[] = { + { NSSRC_FILES, NS_SUCCESS }, + { NSSRC_DNS, NS_SUCCESS }, + { 0 } }; -static enum service_type service_order[SERVICE_MAX + 1]; -static int service_done = 0; - -static enum service_type -get_service_name(const char *name) { - int i; - for(i = 0; service_names[i].type != SERVICE_NONE; i++) { - if(!strcasecmp(name, service_names[i].name)) { - return service_names[i].type; - } - } - return SERVICE_NONE; -} - -static void -init_services() -{ - char *cp, *p, buf[BUFSIZ]; - register int cc = 0; - FILE *fd; - - if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) { - /* make some assumptions */ - service_order[0] = SERVICE_BIND; - service_order[1] = SERVICE_HOSTS; - service_order[2] = SERVICE_NONE; - } else { - while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) { - if(buf[0] == '#') - continue; - - p = buf; - while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0') - ; - if (cp == NULL) - continue; - do { - if (isalpha((unsigned char)cp[0])) { - service_order[cc] = get_service_name(cp); - if(service_order[cc] != SERVICE_NONE) - cc++; - } - while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0') - ; - } while(cp != NULL && cc < SERVICE_MAX); - } - service_order[cc] = SERVICE_NONE; - fclose(fd); - } - service_done = 1; -} - struct hostent * gethostbyname(const char *name) { struct hostent *hp; if (_res.options & RES_USE_INET6) { /* XXX */ hp = gethostbyname2(name, AF_INET6); /* XXX */ if (hp) /* XXX */ return (hp); /* XXX */ } /* XXX */ return (gethostbyname2(name, AF_INET)); } struct hostent * gethostbyname2(const char *name, int type) { struct hostent *hp = 0; - int nserv = 0; + int rval; - if (!service_done) - init_services(); + static const ns_dtab dtab[] = { + NS_FILES_CB(_ht_gethostbyname, NULL) + { NSSRC_DNS, _dns_gethostbyname, NULL }, + NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ + { 0 } + }; + + rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", + default_src, name, type); - while (!hp) { - switch (service_order[nserv]) { - case SERVICE_NONE: - return NULL; - case SERVICE_HOSTS: - hp = _gethostbyhtname(name, type); - break; - case SERVICE_BIND: - hp = _gethostbydnsname(name, type); - break; - case SERVICE_NIS: - hp = _gethostbynisname(name, type); - break; - } - nserv++; - } - return hp; + if (rval != NS_SUCCESS) + return NULL; + else + return hp; } struct hostent * gethostbyaddr(const char *addr, int len, int type) { struct hostent *hp = 0; - int nserv = 0; + int rval; - if (!service_done) - init_services(); + static const ns_dtab dtab[] = { + NS_FILES_CB(_ht_gethostbyaddr, NULL) + { NSSRC_DNS, _dns_gethostbyaddr, NULL }, + NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */ + { 0 } + }; - while (!hp) { - switch (service_order[nserv]) { - case SERVICE_NONE: - return 0; - case SERVICE_HOSTS: - hp = _gethostbyhtaddr(addr, len, type); - break; - case SERVICE_BIND: - hp = _gethostbydnsaddr(addr, len, type); - break; - case SERVICE_NIS: - hp = _gethostbynisaddr(addr, len, type); - break; - } - nserv++; - } - return hp; + rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr", + default_src, addr, len, type); + + if (rval != NS_SUCCESS) + return NULL; + else + return hp; } #ifdef _THREAD_SAFE struct hostent_data; /* * Temporary function (not thread safe) */ int gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result, struct hostent_data *buffer) { struct hostent *hp; int ret; if ((hp = gethostbyaddr(addr, len, type)) == NULL) { ret = -1; } else { memcpy(result, hp, sizeof(struct hostent)); ret = 0; } return(ret); } #endif void sethostent(stayopen) int stayopen; { _sethosthtent(stayopen); _sethostdnsent(stayopen); } void endhostent() { _endhosthtent(); _endhostdnsent(); } Index: head/lib/libc/net/getipnodebyname.3 =================================================================== --- head/lib/libc/net/getipnodebyname.3 (revision 65531) +++ head/lib/libc/net/getipnodebyname.3 (revision 65532) @@ -1,472 +1,473 @@ .\" $FreeBSD$ .\" $KAME: getipnodebyname.3,v 1.6 2000/08/09 21:16:17 itojun Exp $ .\" .\" Copyright (c) 1983, 1987, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 .\" .Dd May 25, 1995 .Dt GETIPNODEBYNAME 3 .Os .\" .Sh NAME .Nm getipnodebyname , .Nm getipnodebyaddr , .Nm freehostent .Nd nodename-to-address and address-to-nodename translation .\" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Fd #include .Fd #include .Ft "struct hostent *" .Fn getipnodebyname "const char *name" "int af" "int flags" "int *error_num" .Ft "struct hostent *" .Fn getipnodebyaddr "const void *src" "size_t len" "int af" "int *error_num" .Ft void .Fn freehostent "struct hostent *ptr" .\" .Sh DESCRIPTION .Fn getipnodebyname and .Fn getipnodebyaddr functions are very similar to .Xr gethostbyname 3 , .Xr gethostbyname2 3 and .Xr gethostbyaddr 3 . The functions cover all the functionalities provided by the older ones, and provide better interface to programmers. The functions require additional arguments, .Ar af , and .Ar flags , for specifying address family and operation mode. The additional arguments allow programmer to get address for a nodename, for specific address family .Po such as .Dv AF_INET or .Dv AF_INET6 .Pc . The functions also require an additional pointer argument, .Ar error_num to return the appropriate error code, to support thread safe error code returns. .Pp The type and usage of the return value, .Li "struct hostent" is described in .Xr gethostbyname 3 . .Pp For .Fn getipnodebyname , the .Ar name argument can be either a node name or a numeric address string .Po i.e., a dotted-decimal IPv4 address or an IPv6 hex address .Pc . The .Ar af argument specifies the address family, either .Dv AF_INET or .Dv AF_INET6 . The .Ar flags argument specifies the types of addresses that are searched for, and the types of addresses that are returned. We note that a special flags value of .Dv AI_DEFAULT .Pq defined below should handle most applications. That is, porting simple applications to use IPv6 replaces the call .Bd -literal -offset hptr = gethostbyname(name); .Ed .Pp with .Bd -literal -offset hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num); .Ed .Pp Applications desiring finer control over the types of addresses searched for and returned, can specify other combinations of the .Ar flags argument. .Pp A .Ar flags of .Li 0 implies a strict interpretation of the .Ar af argument: .Bl -bullet .It If .Ar flags is 0 and .Ar af is .Dv AF_INET , then the caller wants only IPv4 addresses. A query is made for .Li A records. If successful, the IPv4 addresses are returned and the .Li h_length member of the .Li hostent structure will be 4, else the function returns a .Dv NULL pointer. .It If .Ar flags is 0 and if .Ar af is .Li AF_INET6 , then the caller wants only IPv6 addresses. A query is made for .Li AAAA records. If successful, the IPv6 addresses are returned and the .Li h_length member of the .Li hostent structure will be 16, else the function returns a .Dv NULL pointer. .El .Pp Other constants can be logically-ORed into the .Ar flags argument, to modify the behavior of the function. .Bl -bullet .It If the .Dv AI_V4MAPPED flag is specified along with an .Ar af of .Dv AF_INET6 , then the caller will accept IPv4-mapped IPv6 addresses. That is, if no .Li AAAA records are found then a query is made for .Li A records and any found are returned as IPv4-mapped IPv6 addresses .Po .Li h_length will be 16 .Pc . The .Dv AI_V4MAPPED flag is ignored unless .Ar af equals .Dv AF_INET6 . .It The .Dv AI_V4MAPPED_CFG flag is exact same as the .Dv AI_V4MAPPED flag only if the kernel supports IPv4-mapped IPv6 address. .It If the .Dv AI_ALL flag is used in conjunction with the .Dv AI_V4MAPPED flag, and only used with the IPv6 address family. When .Dv AI_ALL is logically or'd with .Dv AI_V4MAPPED flag then the caller wants all addresses: IPv6 and IPv4-mapped IPv6. A query is first made for .Li AAAA records and if successful, the IPv6 addresses are returned. Another query is then made for .Li A records and any found are returned as IPv4-mapped IPv6 addresses. .Li h_length will be 16. Only if both queries fail does the function return a .Dv NULL pointer. This flag is ignored unless af equals AF_INET6. If both .Dv AI_ALL and .Dv AI_V4MAPPED are specified, .Dv AI_ALL takes precedence. .It The .Dv AI_ADDRCONFIG flag specifies that a query for .Li AAAA records should occur only if the node has at least one IPv6 source address configured and a query for .Li A records should occur only if the node has at least one IPv4 source address configured. .Pp For example, if the node has no IPv6 source addresses configured, and .Ar af equals AF_INET6, and the node name being looked up has both .Li AAAA and .Li A records, then: (a) if only .Dv AI_ADDRCONFIG is specified, the function returns a .Dv NULL pointer; (b) if .Dv AI_ADDRCONFIG | .Dv AI_V4MAPPED is specified, the .Li A records are returned as IPv4-mapped IPv6 addresses; .El .Pp The special flags value of .Dv AI_DEFAULT is defined as .Bd -literal -offset #define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG) .Ed .Pp We noted that the .Fn getipnodebyname function must allow the .Ar name argument to be either a node name or a literal address string .Po i.e., a dotted-decimal IPv4 address or an IPv6 hex address .Pc . This saves applications from having to call .Xr inet_pton 3 to handle literal address strings. When the .Ar name argument is a literal address string, the .Ar flags argument is always ignored. .Pp There are four scenarios based on the type of literal address string and the value of the .Ar af argument. The two simple cases are when .Ar name is a dotted-decimal IPv4 address and .Ar af equals .Dv AF_INET , or when .Ar name is an IPv6 hex address and .Ar af equals .Dv AF_INET6 . The members of the returned hostent structure are: .Li h_name points to a copy of the .Ar name argument, .Li h_aliases is a .Dv NULL pointer, .Li h_addrtype is a copy of the .Ar af argument, .Li h_length is either 4 .Po for .Dv AF_INET .Pc or 16 .Po for .Dv AF_INET6 .Pc , .Li h_addr_list[0] is a pointer to the 4-byte or 16-byte binary address, and .Li h_addr_list[1] is a .Dv NULL pointer. .Pp When .Ar name is a dotted-decimal IPv4 address and .Ar af equals .Dv AF_INET6 , and .Dv AI_V4MAPPED is specified, an IPv4-mapped IPv6 address is returned: .Li h_name points to an IPv6 hex address containing the IPv4-mapped IPv6 address, .Li h_aliases is a .Dv NULL pointer, .Li h_addrtype is .Dv AF_INET6 , .Li h_length is 16, .Li h_addr_list[0] is a pointer to the 16-byte binary address, and .Li h_addr_list[1] is a .Dv NULL pointer. .Pp It is an error when .Ar name is an IPv6 hex address and .Ar af equals .Dv AF_INET . The function's return value is a .Dv NULL pointer and the value pointed to by .Ar error_num equals .Dv HOST_NOT_FOUND . .Pp .Fn getipnodebyaddr takes almost the same argument as .Xr gethostbyaddr 3 , but adds a pointer to return an error number. Additionally it takes care of IPv4-mapped IPv6 addresses, and IPv4-compatible IPv6 addresses. .Pp .Fn getipnodebyname and .Fn getipnodebyaddr dynamically allocate the structure to be returned to the caller. .Fn freehostent reclaims memory region allocated and returned by .Fn getipnodebyname or .Fn getipnodebyaddr . .\" .Sh FILES -.Bl -tag -width /etc/resolv.conf -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts -.It Pa /etc/host.conf +.It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El .\" .Sh DIAGNOSTICS .Fn getipnodebyname and .Fn getipnodebyaddr returns .Dv NULL on errors. The integer values pointed to by .Ar error_num may then be checked to see whether this is a temporary failure or an invalid or unknown host. The meanings of each error code are described in .Xr gethostbyname 3 . .\" .Sh SEE ALSO .Xr gethostbyname 3 , .Xr gethostbyaddr 3 , .Xr hosts 5 , +.Xr nsswitch.conf 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 .Pp .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 .%R RFC2553 .%D March 1999 .Re .\" .Sh HISTORY The implementation first appeared in KAME advanced networking kit. .\" .Sh STANDARDS .Fn getipnodebyname and .Fn getipnodebyaddr are documented in .Dq Basic Socket Interface Extensions for IPv6 .Pq RFC2553 . .\" .Sh BUGS .Fn getipnodebyname and .Fn getipnodebyaddr do not handle scoped IPv6 address properly. If you use these functions, your program will not be able to handle scoped IPv6 addresses. For IPv6 address manipulation, .Fn getaddrinfo 3 and .Fn getnameinfo 3 are recommended. .Pp The current implementation is not thread-safe. .Pp The text was shamelessly copied from RFC2553. Index: head/lib/libc/net/getnameinfo.3 =================================================================== --- head/lib/libc/net/getnameinfo.3 (revision 65531) +++ head/lib/libc/net/getnameinfo.3 (revision 65532) @@ -1,314 +1,314 @@ .\" $FreeBSD$ .\" $KAME: getnameinfo.3,v 1.17 2000/08/09 21:16:17 itojun Exp $ .\" .\" Copyright (c) 1983, 1987, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95 .\" .Dd May 25, 1995 .Dt GETNAMEINFO 3 .Os .\" .Sh NAME .Nm getnameinfo .Nd address-to-nodename translation in protocol-independent manner .\" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Fd #include .Fd #include .Ft int .Fn getnameinfo "const struct sockaddr *sa" "socklen_t salen" \ "char *host" "size_t hostlen" "char *serv" "size_t servlen" "int flags" .\" .Sh DESCRIPTION The .Fn getnameinfo function is defined for protocol-independent address-to-nodename translation. Its functionality is a reverse conversion of .Xr getaddrinfo 3 , and implements similar functionality with .Xr gethostbyaddr 3 and .Xr getservbyport 3 in more sophisticated manner. .Pp This function looks up an IP address and port number provided by the caller in the DNS and system-specific database, and returns text strings for both in buffers provided by the caller. The function indicates successful completion by a zero return value; a non-zero return value indicates failure. .Pp The first argument, .Fa sa , points to either a .Li sockaddr_in structure (for IPv4) or a .Li sockaddr_in6 structure (for IPv6) that holds the IP address and port number. The .Fa salen argument gives the length of the .Li sockaddr_in or .Li sockaddr_in6 structure. .Pp The function returns the nodename associated with the IP address in the buffer pointed to by the .Fa host argument. The caller provides the size of this buffer via the .Fa hostlen argument. The service name associated with the port number is returned in the buffer pointed to by .Fa serv , and the .Fa servlen argument gives the length of this buffer. The caller specifies not to return either string by providing a zero value for the .Fa hostlen or .Fa servlen arguments. Otherwise, the caller must provide buffers large enough to hold the nodename and the service name, including the terminating null characters. .Pp Unfortunately most systems do not provide constants that specify the maximum size of either a fully-qualified domain name or a service name. Therefore to aid the application in allocating buffers for these two returned strings the following constants are defined in .Aq Pa netdb.h : .Bd -literal -offset #define NI_MAXHOST 1025 #define NI_MAXSERV 32 .Ed .Pp The first value is actually defined as the constant .Dv MAXDNAME in recent versions of BIND's .Aq Pa arpa/nameser.h header .Po older versions of BIND define this constant to be 256 .Pc and the second is a guess based on the services listed in the current Assigned Numbers RFC. .Pp The final argument is a .Fa flag that changes the default actions of this function. By default the fully-qualified domain name (FQDN) for the host is looked up in the DNS and returned. If the flag bit .Dv NI_NOFQDN is set, only the nodename portion of the FQDN is returned for local hosts. .Pp If the .Fa flag bit .Dv NI_NUMERICHOST is set, or if the host's name cannot be located in the DNS, the numeric form of the host's address is returned instead of its name .Po e.g., by calling .Fn inet_ntop instead of .Fn getnodebyaddr .Pc . If the .Fa flag bit .Dv NI_NAMEREQD is set, an error is returned if the host's name cannot be located in the DNS. .Pp If the flag bit .Dv NI_NUMERICSERV is set, the numeric form of the service address is returned .Pq e.g., its port number instead of its name. The two .Dv NI_NUMERICxxx flags are required to support the .Fl n flag that many commands provide. .Pp A fifth flag bit, .Dv NI_DGRAM , specifies that the service is a datagram service, and causes .Fn getservbyport to be called with a second argument of .Dq udp instead of its default of .Dq tcp . This is required for the few ports (512-514) that have different services for UDP and TCP. .Pp These .Dv NI_xxx flags are defined in .Aq Pa netdb.h . .\" .Sh EXTENSION The implementation allows experimental numeric IPv6 address notation with scope identifier. IPv6 link-local address will appear as string like .Dq Li fe80::1%ne0 , if .Dv NI_WITHSCOPEID bit is enabled in .Ar flags argument. Refer to .Xr getaddrinfo 3 for the notation. .\" .Sh EXAMPLES The following code tries to get numeric hostname, and service name, for given socket address. Observe that there is no hardcoded reference to particular address family. .Bd -literal -offset indent struct sockaddr *sa; /* input */ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { errx(1, "could not get numeric hostname"); /*NOTREACHED*/ } printf("host=%s, serv=%s\\n", hbuf, sbuf); .Ed .Pp The following version checks if the socket address has reverse address mapping. .Bd -literal -offset indent struct sockaddr *sa; /* input */ char hbuf[NI_MAXHOST]; if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD)) { errx(1, "could not resolve hostname"); /*NOTREACHED*/ } printf("host=%s\\n", hbuf); .Ed .\" .Sh FILES -.Bl -tag -width /etc/resolv.conf -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/hosts -.It Pa /etc/host.conf +.It Pa /etc/nsswitch.conf .It Pa /etc/resolv.conf .El .\" .Sh DIAGNOSTICS The function indicates successful completion by a zero return value; a non-zero return value indicates failure. Error codes are as below: .Bl -tag -width Er .It Bq Er EAI_AGAIN The name could not be resolved at this time. Future attempts may succeed. .It Bq Er EAI_BADFLAGS The flags had an invalid value. .It Bq Er EAI_FAIL A non-recoverable error occurred. .It Bq Er EAI_FAMILY The address family was not recognized or the address length was invalid for the specified family. .It Bq Er EAI_MEMORY There was a memory allocation failure. .It Bq Er EAI_NONAME The name does not resolve for the supplied parameters. .Dv NI_NAMEREQD is set and the host's name cannot be located, or both nodename and servname were null. .It Bq Er EAI_SYSTEM A system error occurred. The error code can be found in errno. .El .\" .Sh SEE ALSO .Xr getaddrinfo 3 , .Xr gethostbyaddr 3 , .Xr getservbyport 3 , .Xr hosts 5 , .Xr services 5 , .Xr hostname 7 , .Xr named 8 .Pp .Rs .%A R. Gilligan .%A S. Thomson .%A J. Bound .%A W. Stevens .%T Basic Socket Interface Extensions for IPv6 .%R RFC2553 .%D March 1999 .Re .Rs .%A Tatsuya Jinmei .%A Atsushi Onoe .%T "An Extension of Format for IPv6 Scoped Addresses" .%R internet draft .%N draft-ietf-ipngwg-scopedaddr-format-02.txt .%O work in progress material .Re .Rs .%A Craig Metz .%T Protocol Independence Using the Sockets API .%B "Proceedings of the freenix track: 2000 USENIX annual technical conference" .%D June 2000 .Re .\" .Sh HISTORY The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit. .\" .Sh STANDARDS The .Fn getaddrinfo function is defined IEEE POSIX 1003.1g draft specification, and documented in .Dq Basic Socket Interface Extensions for IPv6 .Pq RFC2553 . .\" .Sh BUGS The current implementation is not thread-safe. .Pp The text was shamelessly copied from RFC2553. .Pp The type of the 2nd argument should be .Li socklen_t for RFC2553 conformance. The current code is based on pre-RFC2553 specification. Index: head/lib/libc/net/getnetbydns.c =================================================================== --- head/lib/libc/net/getnetbydns.c (revision 65531) +++ head/lib/libc/net/getnetbydns.c (revision 65532) @@ -1,313 +1,326 @@ /*- * Copyright (c) 1985, 1988, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ /* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro * Dep. Matematica Universidade de Coimbra, Portugal, Europe * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include "res_config.h" extern int h_errno; #define BYADDR 0 #define BYNAME 1 #define MAXALIASES 35 #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ #else #define MAXPACKET 1024 #endif typedef union { HEADER hdr; u_char buf[MAXPACKET]; } querybuf; typedef union { long al; char ac; } align; static struct netent * getnetanswer(answer, anslen, net_i) querybuf *answer; int anslen; int net_i; { register HEADER *hp; register u_char *cp; register int n; u_char *eom; int type, class, buflen, ancount, qdcount, haveanswer, i, nchar; char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN]; char *in, *st, *pauxt, *bp, **ap; char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0; static struct netent net_entry; static char *net_aliases[MAXALIASES], netbuf[PACKETSZ]; /* * find first satisfactory answer * * answer --> +------------+ ( MESSAGE ) * | Header | * +------------+ * | Question | the question for the name server * +------------+ * | Answer | RRs answering the question * +------------+ * | Authority | RRs pointing toward an authority * | Additional | RRs holding additional information * +------------+ */ eom = answer->buf + anslen; hp = &answer->hdr; ancount = ntohs(hp->ancount); /* #/records in the answer section */ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ bp = netbuf; buflen = sizeof(netbuf); cp = answer->buf + HFIXEDSZ; if (!qdcount) { if (hp->aa) h_errno = HOST_NOT_FOUND; else h_errno = TRY_AGAIN; return (NULL); } while (qdcount-- > 0) cp += __dn_skipname(cp, eom) + QFIXEDSZ; ap = net_aliases; *ap = NULL; net_entry.n_aliases = net_aliases; haveanswer = 0; while (--ancount >= 0 && cp < eom) { n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !res_dnok(bp)) break; cp += n; ans[0] = '\0'; (void)strncpy(&ans[0], bp, sizeof(ans) - 1); ans[sizeof(ans) - 1] = '\0'; GETSHORT(type, cp); GETSHORT(class, cp); cp += INT32SZ; /* TTL */ GETSHORT(n, cp); if (class == C_IN && type == T_PTR) { n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !res_hnok(bp)) { cp += n; return (NULL); } cp += n; *ap++ = bp; bp += strlen(bp) + 1; net_entry.n_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; haveanswer++; } } if (haveanswer) { *ap = NULL; switch (net_i) { case BYADDR: net_entry.n_name = *net_entry.n_aliases; net_entry.n_net = 0L; break; case BYNAME: in = *net_entry.n_aliases; net_entry.n_name = &ans[0]; aux2[0] = '\0'; for (i = 0; i < 4; i++) { for (st = in, nchar = 0; *st != '.'; st++, nchar++) ; if (nchar != 1 || *in != '0' || flag) { flag = 1; (void)strncpy(paux1, (i==0) ? in : in-1, (i==0) ?nchar : nchar+1); paux1[(i==0) ? nchar : nchar+1] = '\0'; pauxt = paux2; paux2 = strcat(paux1, paux2); paux1 = pauxt; } in = ++st; } net_entry.n_net = inet_network(paux2); break; } net_entry.n_aliases++; return (&net_entry); } h_errno = TRY_AGAIN; return (NULL); } -struct netent * -_getnetbydnsaddr(net, net_type) - register unsigned long net; - register int net_type; +int +_dns_getnetbyaddr(void *rval, void *cb_data, va_list ap) { + unsigned long net; + int net_type; unsigned int netbr[4]; int nn, anslen; querybuf buf; char qbuf[MAXDNAME]; unsigned long net2; struct netent *net_entry; + net = va_arg(ap, unsigned long); + net_type = va_arg(ap, int); + + *(struct netent **)rval = NULL; + if (net_type != AF_INET) - return (NULL); + return NS_UNAVAIL; for (nn = 4, net2 = net; net2; net2 >>= 8) netbr[--nn] = net2 & 0xff; switch (nn) { case 3: /* Class A */ sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); break; case 2: /* Class B */ sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); break; case 1: /* Class C */ sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], netbr[1]); break; case 0: /* Class D - E */ sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], netbr[1], netbr[0]); break; } anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); if (anslen < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf("res_query failed\n"); #endif - return (NULL); + return NS_UNAVAIL; } net_entry = getnetanswer(&buf, anslen, BYADDR); if (net_entry) { unsigned u_net = net; /* maybe net should be unsigned ? */ /* Strip trailing zeros */ while ((u_net & 0xff) == 0 && u_net != 0) u_net >>= 8; net_entry->n_net = u_net; - return (net_entry); + *(struct netent **)rval = net_entry; + return NS_SUCCESS; } - return (NULL); + return NS_NOTFOUND; } -struct netent * -_getnetbydnsname(net) - register const char *net; +int +_dns_getnetbyname(void *rval, void *cb_data, va_list ap) { + const char *net; int anslen; querybuf buf; char qbuf[MAXDNAME]; + net = va_arg(ap, const char *); + + *(struct netent**)rval = NULL; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; - return (NULL); + return NS_UNAVAIL; } strncpy(qbuf, net, sizeof(qbuf) - 1); qbuf[sizeof(qbuf) - 1] = '\0'; anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf)); if (anslen < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf("res_query failed\n"); #endif - return (NULL); + return NS_UNAVAIL; } - return getnetanswer(&buf, anslen, BYNAME); + *(struct netent**)rval = getnetanswer(&buf, anslen, BYNAME); + return (*(struct netent**)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } void _setnetdnsent(stayopen) int stayopen; { if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC; } void _endnetdnsent() { _res.options &= ~(RES_STAYOPEN | RES_USEVC); res_close(); } Index: head/lib/libc/net/getnetbyht.c =================================================================== --- head/lib/libc/net/getnetbyht.c (revision 65531) +++ head/lib/libc/net/getnetbyht.c (revision 65532) @@ -1,173 +1,182 @@ /* * Copyright (c) 1983, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ /* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro * Dep. Matematica Universidade de Coimbra, Portugal, Europe * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * from getnetent.c 1.1 (Coimbra) 93/06/02 */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93"; static char orig_rcsid[] = "From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp"; static chat rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include +#include +#include #define MAXALIASES 35 static FILE *netf; static char line[BUFSIZ+1]; static struct netent net; static char *net_aliases[MAXALIASES]; static int _net_stayopen; void _setnethtent(f) int f; { if (netf == NULL) netf = fopen(_PATH_NETWORKS, "r" ); else rewind(netf); _net_stayopen |= f; } void _endnethtent() { if (netf) { fclose(netf); netf = NULL; } _net_stayopen = 0; } struct netent * getnetent() { char *p; register char *cp, **q; if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL) return (NULL); again: p = fgets(line, sizeof line, netf); if (p == NULL) return (NULL); if (*p == '#') goto again; cp = strpbrk(p, "#\n"); if (cp == NULL) goto again; *cp = '\0'; net.n_name = p; cp = strpbrk(p, " \t"); if (cp == NULL) goto again; *cp++ = '\0'; while (*cp == ' ' || *cp == '\t') cp++; p = strpbrk(cp, " \t"); if (p != NULL) *p++ = '\0'; net.n_net = inet_network(cp); net.n_addrtype = AF_INET; q = net.n_aliases = net_aliases; if (p != NULL) cp = p; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &net_aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return (&net); } -struct netent * -_getnetbyhtname(name) - register const char *name; +int +_ht_getnetbyname(void *rval, void *cb_data, va_list ap) { + const char *name; register struct netent *p; register char **cp; + name = va_arg(ap, const char *); + setnetent(_net_stayopen); while ( (p = getnetent()) ) { if (strcasecmp(p->n_name, name) == 0) break; for (cp = p->n_aliases; *cp != 0; cp++) if (strcasecmp(*cp, name) == 0) goto found; } found: if (!_net_stayopen) endnetent(); - return (p); + *(struct netent **)rval = p; + return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; } -struct netent * -_getnetbyhtaddr(net, type) - register unsigned long net; - register int type; +int +_ht_getnetbyaddr(void *rval, void *cb_data, va_list ap) { + unsigned long net; + int type; register struct netent *p; + net = va_arg(ap, unsigned long); + type = va_arg(ap, int); + setnetent(_net_stayopen); while ( (p = getnetent()) ) if (p->n_addrtype == type && p->n_net == net) break; if (!_net_stayopen) endnetent(); - return (p); + *(struct netent **)rval = p; + return (p != NULL) ? NS_SUCCESS : NS_NOTFOUND; } Index: head/lib/libc/net/getnetbynis.c =================================================================== --- head/lib/libc/net/getnetbynis.c (revision 65531) +++ head/lib/libc/net/getnetbynis.c (revision 65532) @@ -1,177 +1,191 @@ /*- * Copyright (c) 1994, Garrett Wollman * * 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 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 REGENTS 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)$FreeBSD$"; static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include #include +#include +#include #include #ifdef YP #include #include #include #endif #define MAXALIASES 35 #define MAXADDRS 35 #ifdef YP static char *host_aliases[MAXALIASES]; -#endif /* YP */ static struct netent * -_getnetbynis(name, map, af) - const char *name; - char *map; - int af; +_getnetbynis(const char *name, char *map, int af) { -#ifdef YP register char *cp, **q; static char *result; int resultlen; static struct netent h; static char *domain = (char *)NULL; static char ypbuf[YPMAXRECORD + 2]; switch(af) { case AF_INET: break; default: case AF_INET6: errno = EAFNOSUPPORT; return NULL; } if (domain == (char *)NULL) if (yp_get_default_domain (&domain)) return (NULL); if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) return (NULL); bcopy((char *)result, (char *)&ypbuf, resultlen); ypbuf[resultlen] = '\0'; free(result); result = (char *)&ypbuf; if ((cp = index(result, '\n'))) *cp = '\0'; cp = strpbrk(result, " \t"); *cp++ = '\0'; h.n_name = result; while (*cp == ' ' || *cp == '\t') cp++; h.n_net = inet_network(cp); h.n_addrtype = AF_INET; q = h.n_aliases = host_aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &host_aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return (&h); -#else - return (NULL); -#endif } +#endif /* YP */ -struct netent * -_getnetbynisname(name) - const char *name; +int +_nis_getnetbyname(void *rval, void *cb_data, va_list ap) { - return _getnetbynis(name, "networks.byname", AF_INET); +#ifdef YP + const char *name; + + name = va_arg(ap, const char *); + + *(struct netent **)rval = _getnetbynis(name, "networks.byname", AF_INET); + return (*(struct netent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; +#else + return NS_UNAVAIL; +#endif + } -struct netent * -_getnetbynisaddr(addr, af) +int +_nis_getnetbyaddr(void *rval, void *cb_data, va_list ap) +{ +#ifdef YP unsigned long addr; int af; -{ char *str, *cp; unsigned long net2; int nn; unsigned int netbr[4]; char buf[MAXDNAME]; + addr = va_arg(ap, unsigned long); + af = va_arg(ap, int); + + *(struct netent **)rval = NULL; + if (af != AF_INET) { errno = EAFNOSUPPORT; - return (NULL); + return NS_UNAVAIL; } for (nn = 4, net2 = addr; net2; net2 >>= 8) { netbr[--nn] = net2 & 0xff; } switch (nn) { case 3: /* Class A */ sprintf(buf, "%u", netbr[3]); break; case 2: /* Class B */ sprintf(buf, "%u.%u", netbr[2], netbr[3]); break; case 1: /* Class C */ sprintf(buf, "%u.%u.%u", netbr[1], netbr[2], netbr[3]); break; case 0: /* Class D - E */ sprintf(buf, "%u.%u.%u.%u", netbr[0], netbr[1], netbr[2], netbr[3]); break; } str = (char *)&buf; cp = str + (strlen(str) - 2); while(!strcmp(cp, ".0")) { *cp = '\0'; cp = str + (strlen(str) - 2); } - return _getnetbynis(str, "networks.byaddr", af); + *(struct netent **)rval = _getnetbynis(str, "networks.byaddr", af); + return (*(struct netent**)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; +#else + return NS_UNAVAIL; +#endif /* YP */ } Index: head/lib/libc/net/getnetent.3 =================================================================== --- head/lib/libc/net/getnetent.3 (revision 65531) +++ head/lib/libc/net/getnetent.3 (revision 65532) @@ -1,162 +1,172 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" .Dd June 4, 1993 .Dt GETNETENT 3 .Os BSD 4.2 .Sh NAME .Nm getnetent , .Nm getnetbyaddr , .Nm getnetbyname , .Nm setnetent , .Nm endnetent .Nd get network entry .Sh LIBRARY .Lb libc .Sh SYNOPSIS .Fd #include .Ft struct netent * .Fn getnetent void .Ft struct netent * .Fn getnetbyname "const char *name" .Ft struct netent * .Fn getnetbyaddr "unsigned long net" "int type" .Ft void .Fn setnetent "int stayopen" .Ft void .Fn endnetent void .Sh DESCRIPTION The .Fn getnetent , .Fn getnetbyname , and .Fn getnetbyaddr functions each return a pointer to an object with the -following structure -containing the broken-out -fields of a line in the network data base, -.Pa /etc/networks . +following structure describing an internet network. +This structure contains either the information obtained +from the nameserver, +.Xr named 8 , +broken-out fields of a line in the network data base +.Pa /etc/networks , +or entries supplied by the +.Xr yp 4 +system. The order of the lookups is controlled by the +`networks' entry in +.Xr nsswitch.conf 5 . +.Pp .Bd -literal -offset indent struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net number type */ unsigned long n_net; /* net number */ }; .Ed .Pp The members of this structure are: .Bl -tag -width n_addrtype .It Fa n_name The official name of the network. .It Fa n_aliases A zero terminated list of alternate names for the network. .It Fa n_addrtype The type of the network number returned; currently only AF_INET. .It Fa n_net The network number. Network numbers are returned in machine byte order. .El .Pp The .Fn getnetent function reads the next line of the file, opening the file if necessary. .Pp The .Fn setnetent function opens and rewinds the file. If the .Fa stayopen flag is non-zero, the net data base will not be closed after each call to .Fn getnetbyname or .Fn getnetbyaddr . .Pp The .Fn endnetent function closes the file. .Pp The .Fn getnetbyname function and .Fn getnetbyaddr sequentially search from the beginning of the file until a matching net name or net address and type is found, or until .Dv EOF is encountered. The .Fa type must be .Dv AF_INET . Network numbers are supplied in host order. .Sh FILES -.Bl -tag -width /etc/networks -compact +.Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/networks +.It Pa /etc/nsswitch.conf +.It Pa /etc/resolv.conf .El .Sh DIAGNOSTICS Null pointer (0) returned on .Dv EOF or error. .Sh SEE ALSO .Xr networks 5 .Pp .%T RFC 1101 .Sh HISTORY The .Fn getnetent , .Fn getnetbyaddr , .Fn getnetbyname , .Fn setnetent , and .Fn endnetent functions appeared in .Bx 4.2 . .Sh BUGS The data space used by these functions is static; if future use requires the data, it should be copied before any subsequent calls to these functions overwrite it. Only Internet network numbers are currently understood. Expecting network numbers to fit in no more than 32 bits is probably naive. Index: head/lib/libc/net/getnetnamadr.c =================================================================== --- head/lib/libc/net/getnetnamadr.c (revision 65531) +++ head/lib/libc/net/getnetnamadr.c (revision 65532) @@ -1,190 +1,114 @@ /*- * Copyright (c) 1994, Garrett Wollman * * 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 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 REGENTS 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. */ #if defined(LIBC_SCCS) && !defined(lint) static char rcsid[] = "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include #include #include #include +#include +#include -#ifndef _PATH_NETCONF -#define _PATH_NETCONF "/etc/host.conf" -#endif +extern int _ht_getnetbyname(void *, void *, va_list); +extern int _dns_getnetbyname(void *, void *, va_list); +extern int _nis_getnetbyname(void *, void *, va_list); +extern int _ht_getnetbyaddr(void *, void *, va_list); +extern int _dns_getnetbyaddr(void *, void *, va_list); +extern int _nis_getnetbyaddr(void *, void *, va_list); -enum service_type { - SERVICE_NONE = 0, - SERVICE_BIND, - SERVICE_TABLE, - SERVICE_NIS }; -#define SERVICE_MAX SERVICE_NIS - -static struct { - const char *name; - enum service_type type; -} service_names[] = { - { "hosts", SERVICE_TABLE }, - { "/etc/hosts", SERVICE_TABLE }, - { "hosttable", SERVICE_TABLE }, - { "htable", SERVICE_TABLE }, - { "bind", SERVICE_BIND }, - { "dns", SERVICE_BIND }, - { "domain", SERVICE_BIND }, - { "yp", SERVICE_NIS }, - { "yellowpages", SERVICE_NIS }, - { "nis", SERVICE_NIS }, - { 0, SERVICE_NONE } +/* Network lookup order if nsswitch.conf is broken or nonexistant */ +static const ns_src default_src[] = { + { NSSRC_FILES, NS_SUCCESS }, + { NSSRC_DNS, NS_SUCCESS }, + { 0 } }; -static enum service_type service_order[SERVICE_MAX + 1]; -static int service_done = 0; - -static enum service_type -get_service_name(const char *name) { - int i; - for(i = 0; service_names[i].type != SERVICE_NONE; i++) { - if(!strcasecmp(name, service_names[i].name)) { - return service_names[i].type; - } - } - return SERVICE_NONE; -} - -static void -init_services() -{ - char *cp, *p, buf[BUFSIZ]; - register int cc = 0; - FILE *fd; - - if ((fd = (FILE *)fopen(_PATH_NETCONF, "r")) == NULL) { - /* make some assumptions */ - service_order[0] = SERVICE_TABLE; - service_order[1] = SERVICE_NONE; - } else { - while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) { - if(buf[0] == '#') - continue; - - p = buf; - while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0') - ; - if (cp == NULL) - continue; - do { - if (isalpha((unsigned char)cp[0])) { - service_order[cc] = get_service_name(cp); - if(service_order[cc] != SERVICE_NONE) - cc++; - } - while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0') - ; - } while(cp != NULL && cc < SERVICE_MAX); - } - service_order[cc] = SERVICE_NONE; - fclose(fd); - } - service_done = 1; -} - struct netent * getnetbyname(const char *name) { struct netent *hp = 0; - int nserv = 0; + int rval; - if (!service_done) - init_services(); - while (!hp) { - switch (service_order[nserv]) { - case SERVICE_NONE: - return NULL; - case SERVICE_TABLE: - hp = _getnetbyhtname(name); - break; - case SERVICE_BIND: - hp = _getnetbydnsname(name); - break; - case SERVICE_NIS: - hp = _getnetbynisname(name); - break; - } - nserv++; - } - return hp; + static const ns_dtab dtab[] = { + NS_FILES_CB(_ht_getnetbyname, NULL) + { NSSRC_DNS, _dns_getnetbyname, NULL }, + NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */ + { 0 } + }; + + rval = nsdispatch((void *)&hp, dtab, NSDB_NETWORKS, "getnetbyname", + default_src, name); + + if (rval != NS_SUCCESS) + return NULL; + else + return hp; } struct netent * -getnetbyaddr(addr, af) - u_long addr; - int af; +getnetbyaddr(u_long addr, int af) { struct netent *hp = 0; - int nserv = 0; + int rval; - if (!service_done) - init_services(); + static const ns_dtab dtab[] = { + NS_FILES_CB(_ht_getnetbyaddr, NULL) + { NSSRC_DNS, _dns_getnetbyaddr, NULL }, + NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */ + { 0 } + }; - while (!hp) { - switch (service_order[nserv]) { - case SERVICE_NONE: - return 0; - case SERVICE_TABLE: - hp = _getnetbyhtaddr(addr, af); - break; - case SERVICE_BIND: - hp = _getnetbydnsaddr(addr, af); - break; - case SERVICE_NIS: - hp = _getnetbynisaddr(addr, af); - break; - } - nserv++; - } - return hp; + rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "getnetbyaddr", + default_src, addr, af); + + if (rval != NS_SUCCESS) + return NULL; + else + return hp; } void setnetent(stayopen) int stayopen; { _setnethtent(stayopen); _setnetdnsent(stayopen); } void endnetent() { _endnethtent(); _endnetdnsent(); } Index: head/lib/libc/net/hesiod.3 =================================================================== --- head/lib/libc/net/hesiod.3 (nonexistent) +++ head/lib/libc/net/hesiod.3 (revision 65532) @@ -0,0 +1,136 @@ +.\" $NetBSD: hesiod.3,v 1.1 1999/01/25 03:43:04 lukem Exp $ +.\" $FreeBSD$ +.\" +.\" from: #Id: hesiod.3,v 1.9.2.1 1997/01/03 21:02:23 ghudson Exp # +.\" +.\" Copyright 1988, 1996 by the Massachusetts Institute of Technology. +.\" +.\" Permission to use, copy, modify, and distribute this +.\" software and its documentation for any purpose and without +.\" fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright +.\" notice and this permission notice appear in supporting +.\" documentation, and that the name of M.I.T. not be used in +.\" advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. +.\" M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" +.\" without express or implied warranty. +.\" +.TH HESIOD 3 "30 November 1996" +.SH NAME +hesiod, hesiod_init, hesiod_resolve, hesiod_free_list, hesiod_to_bind, hesiod_end \- Hesiod name server interface library +.SH SYNOPSIS +.nf +.B #include +.PP +.B int hesiod_init(void **\fIcontext\fP) +.B char **hesiod_resolve(void *\fIcontext\fP, const char *\fIname\fP, +.B const char *\fItype\fP) +.B void hesiod_free_list(void *\fIcontext\fP, char **\fIlist\fP); +.B char *hesiod_to_bind(void *\fIcontext\fP, const char *\fIname\fP, +.B const char *\fItype\fP) +.B void hesiod_end(void *\fIcontext\fP) +.PP +.B cc file.c -lhesiod +.fi +.SH DESCRIPTION +This family of functions allows you to perform lookups of Hesiod +information, which is stored as text records in the Domain Name +Service. To perform lookups, you must first initialize a +.IR context , +an opaque object which stores information used internally by the +library between calls. +.I hesiod_init +initializes a context, storing a pointer to the context in the +location pointed to by the +.I context +argument. +.I hesiod_end +frees the resources used by a context. +.PP +.I hesiod_resolve +is the primary interface to the library. If successful, it returns a +list of one or more strings giving the records matching +.I name +and +.IR type . +The last element of the list is followed by a NULL pointer. It is the +caller's responsibility to call +.I hesiod_free_list +to free the resources used by the returned list. +.PP +.I hesiod_to_bind +converts +.I name +and +.I type +into the DNS name used by +.IR hesiod_resolve . +It is the caller's responsibility to free the returned string using +.IR free . +.SH RETURN VALUES +If successful, +.I hesiod_init +returns 0; otherwise it returns \-1 and sets +.I errno +to indicate the error. On failure, +.I hesiod_resolve +and +.I hesiod_to_bind +return NULL and set the global variable +.I errno +to indicate the error. +.SH ENVIRONMENT +If the environment variable +.B HES_DOMAIN +is set, it will override the domain in the Hesiod configuration file. +If the environment variable +.B HESIOD_CONFIG +is set, it specifies the location of the Hesiod configuration file. +.SH SEE ALSO +`Hesiod - Project Athena Technical Plan -- Name Service', named(8), +hesiod.conf(5) +.SH ERRORS +Hesiod calls may fail because of: +.IP ENOMEM +Insufficient memory was available to carry out the requested +operation. +.IP ENOEXEC +.I hesiod_init +failed because the Hesiod configuration file was invalid. +.IP ECONNREFUSED +.I hesiod_resolve +failed because no name server could be contacted to answer the query. +.IP EMSGSIZE +.I hesiod_resolve +or +.I hesiod_to_bind +failed because the query or response was too big to fit into the +packet buffers. +.IP ENOENT +.I hesiod_resolve +failed because the name server had no text records matching +.I name +and +.IR type , +or +.I hesiod_to_bind +failed because the +.I name +argument had a domain extension which could not be resolved with type +``rhs-extension'' in the local Hesiod domain. +.SH AUTHOR +Steve Dyer, IBM/Project Athena +.br +Greg Hudson, MIT Team Athena +.br +Copyright 1987, 1988, 1995, 1996 by the Massachusetts Institute of Technology. +.SH BUGS +The strings corresponding to the +.I errno +values set by the Hesiod functions are not particularly indicative of +what went wrong, especially for +.I ENOEXEC +and +.IR ENOENT . Property changes on: head/lib/libc/net/hesiod.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libc/net/hesiod.c =================================================================== --- head/lib/libc/net/hesiod.c (nonexistent) +++ head/lib/libc/net/hesiod.c (revision 65532) @@ -0,0 +1,572 @@ +/* $NetBSD: hesiod.c,v 1.9 1999/02/11 06:16:38 simonb Exp $ */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* Copyright 1996 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +/* This file is part of the hesiod library. It implements the core + * portion of the hesiod resolver. + * + * This file is loosely based on an interim version of hesiod.c from + * the BIND IRS library, which was in turn based on an earlier version + * of this file. Extensive changes have been made on each step of the + * path. + * + * This implementation is not truly thread-safe at the moment because + * it uses res_send() and accesses _res. + */ + +#include + +#if defined(LIBC_SCCS) && !defined(lint) +static char *orig_rcsid = "$NetBSD: hesiod.c,v 1.9 1999/02/11 06:16:38 simonb Exp $"; +static char *rcsid = "$FreeBSD$"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct hesiod_p { + char *lhs; /* normally ".ns" */ + char *rhs; /* AKA the default hesiod domain */ + int classes[2]; /* The class search order. */ +}; + +#define MAX_HESRESP 1024 + +static int read_config_file __P((struct hesiod_p *, const char *)); +static char **get_txt_records __P((int, const char *)); +static int init_context __P((void)); +static void translate_errors __P((void)); + + +/* + * hesiod_init -- + * initialize a hesiod_p. + */ +int +hesiod_init(context) + void **context; +{ + struct hesiod_p *ctx; + const char *p, *configname; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx) { + *context = ctx; + configname = getenv("HESIOD_CONFIG"); + if (!configname) + configname = _PATH_HESIOD_CONF; + if (read_config_file(ctx, configname) >= 0) { + /* + * The default rhs can be overridden by an + * environment variable. + */ + p = getenv("HES_DOMAIN"); + if (p) { + if (ctx->rhs) + free(ctx->rhs); + ctx->rhs = malloc(strlen(p) + 2); + if (ctx->rhs) { + *ctx->rhs = '.'; + strcpy(ctx->rhs + 1, + (*p == '.') ? p + 1 : p); + return 0; + } else + errno = ENOMEM; + } else + return 0; + } + } else + errno = ENOMEM; + + if (ctx->lhs) + free(ctx->lhs); + if (ctx->rhs) + free(ctx->rhs); + if (ctx) + free(ctx); + return -1; +} + +/* + * hesiod_end -- + * Deallocates the hesiod_p. + */ +void +hesiod_end(context) + void *context; +{ + struct hesiod_p *ctx = (struct hesiod_p *) context; + + free(ctx->rhs); + if (ctx->lhs) + free(ctx->lhs); + free(ctx); +} + +/* + * hesiod_to_bind -- + * takes a hesiod (name, type) and returns a DNS + * name which is to be resolved. + */ +char * +hesiod_to_bind(void *context, const char *name, const char *type) +{ + struct hesiod_p *ctx = (struct hesiod_p *) context; + char bindname[MAXDNAME], *p, *ret, **rhs_list = NULL; + const char *rhs; + int len; + + strcpy(bindname, name); + + /* + * Find the right right hand side to use, possibly + * truncating bindname. + */ + p = strchr(bindname, '@'); + if (p) { + *p++ = 0; + if (strchr(p, '.')) + rhs = name + (p - bindname); + else { + rhs_list = hesiod_resolve(context, p, "rhs-extension"); + if (rhs_list) + rhs = *rhs_list; + else { + errno = ENOENT; + return NULL; + } + } + } else + rhs = ctx->rhs; + + /* See if we have enough room. */ + len = strlen(bindname) + 1 + strlen(type); + if (ctx->lhs) + len += strlen(ctx->lhs) + ((ctx->lhs[0] != '.') ? 1 : 0); + len += strlen(rhs) + ((rhs[0] != '.') ? 1 : 0); + if (len > sizeof(bindname) - 1) { + if (rhs_list) + hesiod_free_list(context, rhs_list); + errno = EMSGSIZE; + return NULL; + } + /* Put together the rest of the domain. */ + strcat(bindname, "."); + strcat(bindname, type); + /* Only append lhs if it isn't empty. */ + if (ctx->lhs && ctx->lhs[0] != '\0' ) { + if (ctx->lhs[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->lhs); + } + if (rhs[0] != '.') + strcat(bindname, "."); + strcat(bindname, rhs); + + /* rhs_list is no longer needed, since we're done with rhs. */ + if (rhs_list) + hesiod_free_list(context, rhs_list); + + /* Make a copy of the result and return it to the caller. */ + ret = strdup(bindname); + if (!ret) + errno = ENOMEM; + return ret; +} + +/* + * hesiod_resolve -- + * Given a hesiod name and type, return an array of strings returned + * by the resolver. + */ +char ** +hesiod_resolve(context, name, type) + void *context; + const char *name; + const char *type; +{ + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname, **retvec; + + bindname = hesiod_to_bind(context, name, type); + if (!bindname) + return NULL; + + retvec = get_txt_records(ctx->classes[0], bindname); + if (retvec == NULL && errno == ENOENT && ctx->classes[1]) + retvec = get_txt_records(ctx->classes[1], bindname); + + free(bindname); + return retvec; +} + +/*ARGSUSED*/ +void +hesiod_free_list(context, list) + void *context; + char **list; +{ + char **p; + + if (list == NULL) + return; + for (p = list; *p; p++) + free(*p); + free(list); +} + + +/* read_config_file -- + * Parse the /etc/hesiod.conf file. Returns 0 on success, + * -1 on failure. On failure, it might leave values in ctx->lhs + * or ctx->rhs which need to be freed by the caller. + */ +static int +read_config_file(ctx, filename) + struct hesiod_p *ctx; + const char *filename; +{ + char *key, *data, *p, **which; + char buf[MAXDNAME + 7]; + int n; + FILE *fp; + + /* Set default query classes. */ + ctx->classes[0] = C_IN; + ctx->classes[1] = C_HS; + + /* Try to open the configuration file. */ + fp = fopen(filename, "r"); + if (!fp) { + /* Use compiled in default domain names. */ + ctx->lhs = strdup(DEF_LHS); + ctx->rhs = strdup(DEF_RHS); + if (ctx->lhs && ctx->rhs) + return 0; + else { + errno = ENOMEM; + return -1; + } + } + ctx->lhs = NULL; + ctx->rhs = NULL; + while (fgets(buf, sizeof(buf), fp) != NULL) { + p = buf; + if (*p == '#' || *p == '\n' || *p == '\r') + continue; + while (*p == ' ' || *p == '\t') + p++; + key = p; + while (*p != ' ' && *p != '\t' && *p != '=') + p++; + *p++ = 0; + + while (isspace(*p) || *p == '=') + p++; + data = p; + while (!isspace(*p)) + p++; + *p = 0; + + if (strcasecmp(key, "lhs") == 0 || + strcasecmp(key, "rhs") == 0) { + which = (strcasecmp(key, "lhs") == 0) + ? &ctx->lhs : &ctx->rhs; + *which = strdup(data); + if (!*which) { + errno = ENOMEM; + return -1; + } + } else { + if (strcasecmp(key, "classes") == 0) { + n = 0; + while (*data && n < 2) { + p = data; + while (*p && *p != ',') + p++; + if (*p) + *p++ = 0; + if (strcasecmp(data, "IN") == 0) + ctx->classes[n++] = C_IN; + else + if (strcasecmp(data, "HS") == 0) + ctx->classes[n++] = + C_HS; + data = p; + } + while (n < 2) + ctx->classes[n++] = 0; + } + } + } + fclose(fp); + + if (!ctx->rhs || ctx->classes[0] == 0 || + ctx->classes[0] == ctx->classes[1]) { + errno = ENOEXEC; + return -1; + } + return 0; +} + +/* + * get_txt_records -- + * Given a DNS class and a DNS name, do a lookup for TXT records, and + * return a list of them. + */ +static char ** +get_txt_records(qclass, name) + int qclass; + const char *name; +{ + HEADER *hp; + unsigned char qbuf[PACKETSZ], abuf[MAX_HESRESP], *p, *eom, *eor; + char *dst, **list; + int ancount, qdcount, i, j, n, skip, type, class, len; + + /* Make sure the resolver is initialized. */ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return NULL; + + /* Construct the query. */ + n = res_mkquery(QUERY, name, qclass, T_TXT, NULL, 0, + NULL, qbuf, PACKETSZ); + if (n < 0) + return NULL; + + /* Send the query. */ + n = res_send(qbuf, n, abuf, MAX_HESRESP); + if (n < 0) { + errno = ECONNREFUSED; + return NULL; + } + /* Parse the header of the result. */ + hp = (HEADER *) (void *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + p = abuf + sizeof(HEADER); + eom = abuf + n; + + /* + * Skip questions, trying to get to the answer section + * which follows. + */ + for (i = 0; i < qdcount; i++) { + skip = dn_skipname(p, eom); + if (skip < 0 || p + skip + QFIXEDSZ > eom) { + errno = EMSGSIZE; + return NULL; + } + p += skip + QFIXEDSZ; + } + + /* Allocate space for the text record answers. */ + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) { + errno = ENOMEM; + return NULL; + } + /* Parse the answers. */ + j = 0; + for (i = 0; i < ancount; i++) { + /* Parse the header of this answer. */ + skip = dn_skipname(p, eom); + if (skip < 0 || p + skip + 10 > eom) + break; + type = p[skip + 0] << 8 | p[skip + 1]; + class = p[skip + 2] << 8 | p[skip + 3]; + len = p[skip + 8] << 8 | p[skip + 9]; + p += skip + 10; + if (p + len > eom) { + errno = EMSGSIZE; + break; + } + /* Skip entries of the wrong class and type. */ + if (class != qclass || type != T_TXT) { + p += len; + continue; + } + /* Allocate space for this answer. */ + list[j] = malloc((size_t)len); + if (!list[j]) { + errno = ENOMEM; + break; + } + dst = list[j++]; + + /* Copy answer data into the allocated area. */ + eor = p + len; + while (p < eor) { + n = (unsigned char) *p++; + if (p + n > eor) { + errno = EMSGSIZE; + break; + } + memcpy(dst, p, (size_t)n); + p += n; + dst += n; + } + if (p < eor) { + errno = EMSGSIZE; + break; + } + *dst = 0; + } + + /* + * If we didn't terminate the loop normally, something + * went wrong. + */ + if (i < ancount) { + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return NULL; + } + if (j == 0) { + errno = ENOENT; + free(list); + return NULL; + } + list[j] = NULL; + return list; +} + + /* + * COMPATIBILITY FUNCTIONS + */ + +static int inited = 0; +static void *context; +static int errval = HES_ER_UNINIT; + +int +hes_init() +{ + init_context(); + return errval; +} + +char * +hes_to_bind(name, type) + const char *name; + const char *type; +{ + static char *bindname; + if (init_context() < 0) + return NULL; + if (bindname) + free(bindname); + bindname = hesiod_to_bind(context, name, type); + if (!bindname) + translate_errors(); + return bindname; +} + +char ** +hes_resolve(name, type) + const char *name; + const char *type; +{ + static char **list; + + if (init_context() < 0) + return NULL; + + /* + * In the old Hesiod interface, the caller was responsible for + * freeing the returned strings but not the vector of strings itself. + */ + if (list) + free(list); + + list = hesiod_resolve(context, name, type); + if (!list) + translate_errors(); + return list; +} + +int +hes_error() +{ + return errval; +} + +void +hes_free(hp) + char **hp; +{ + hesiod_free_list(context, hp); +} + +static int +init_context() +{ + if (!inited) { + inited = 1; + if (hesiod_init(&context) < 0) { + errval = HES_ER_CONFIG; + return -1; + } + errval = HES_ER_OK; + } + return 0; +} + +static void +translate_errors() +{ + switch (errno) { + case ENOENT: + errval = HES_ER_NOTFOUND; + break; + case ECONNREFUSED: + case EMSGSIZE: + errval = HES_ER_NET; + break; + case ENOMEM: + default: + /* Not a good match, but the best we can do. */ + errval = HES_ER_CONFIG; + break; + } +} Property changes on: head/lib/libc/net/hesiod.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libc/net/name6.c =================================================================== --- head/lib/libc/net/name6.c (revision 65531) +++ head/lib/libc/net/name6.c (revision 65532) @@ -1,1794 +1,1782 @@ /* $FreeBSD$ */ /* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. */ /* * ++Copyright++ 1985, 1988, 1993 * - * Copyright (c) 1985, 1988, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ /* * Atsushi Onoe */ /* * TODO for thread safe * use mutex for _hostconf, _hostconf_init. * rewrite resolvers to be thread safe */ #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include #ifndef _PATH_HOSTS #define _PATH_HOSTS "/etc/hosts" #endif #ifndef MAXALIASES #define MAXALIASES 10 #endif #ifndef MAXADDRS #define MAXADDRS 20 #endif #ifndef MAXDNAME #define MAXDNAME 1025 #endif #ifdef INET6 #define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \ sizeof(struct in_addr)) #else #define ADDRLEN(af) sizeof(struct in_addr) #endif #define MAPADDR(ab, ina) \ do { \ memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \ memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \ memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \ } while (0) #define MAPADDRENABLED(flags) \ (((flags) & AI_V4MAPPED) || \ (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled())) union inx_addr { struct in_addr in_addr; #ifdef INET6 struct in6_addr in6_addr; #endif struct { u_char mau_zero[10]; u_char mau_one[2]; struct in_addr mau_inaddr; } map_addr_un; #define map_zero map_addr_un.mau_zero #define map_one map_addr_un.mau_one #define map_inaddr map_addr_un.mau_inaddr }; static struct hostent *_hpcopy(struct hostent *hp, int *errp); static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp); static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp); #ifdef INET6 static struct hostent *_hpmapv6(struct hostent *hp, int *errp); #endif static struct hostent *_hpsort(struct hostent *hp); static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp); static char *_hgetword(char **pp); static int _mapped_addr_enabled(void); static FILE *_files_open(int *errp); -static struct hostent *_files_ghbyname(const char *name, int af, int *errp); -static struct hostent *_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp); +static int _files_ghbyname(void *, void *, va_list); +static int _files_ghbyaddr(void *, void *, va_list); static void _files_shent(int stayopen); static void _files_ehent(void); #ifdef YP -static struct hostent *_nis_ghbyname(const char *name, int af, int *errp); -static struct hostent *_nis_ghbyaddr(const void *addr, int addrlen, int af, int *errp); +static int _nis_ghbyname(void *, void *, va_list); +static int _nis_ghbyaddr(void *, void *, va_list); #endif -static struct hostent *_dns_ghbyname(const char *name, int af, int *errp); -static struct hostent *_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp); +static int _dns_ghbyname(void *, void *, va_list); +static int _dns_ghbyaddr(void *, void *, va_list); static void _dns_shent(int stayopen); static void _dns_ehent(void); #ifdef ICMPNL -static struct hostent *_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp); +static int _icmp_ghbyaddr(void *, void *, va_list); #endif /* ICMPNL */ -/* - * Select order host function. - */ -#define MAXHOSTCONF 4 - -#ifndef HOSTCONF -# define HOSTCONF "/etc/host.conf" -#endif /* !HOSTCONF */ - -struct _hostconf { - struct hostent *(*byname)(const char *name, int af, int *errp); - struct hostent *(*byaddr)(const void *addr, int addrlen, int af, int *errp); -}; - -/* default order */ -static struct _hostconf _hostconf[MAXHOSTCONF] = { - { _dns_ghbyname, _dns_ghbyaddr }, - { _files_ghbyname, _files_ghbyaddr }, +/* Host lookup order if nsswitch.conf is broken or nonexistant */ +static const ns_src default_src[] = { + { NSSRC_FILES, NS_SUCCESS }, + { NSSRC_DNS, NS_SUCCESS }, #ifdef ICMPNL - { NULL, _icmp_ghbyaddr }, -#endif /* ICMPNL */ +#define NSSRC_ICMP "icmp" + { NSSRC_ICMP, NS_SUCCESS }, +#endif + { 0 } }; -static int _hostconf_init_done; -static void _hostconf_init(void); - /* - * Initialize hostconf structure. - */ - -static void -_hostconf_init(void) -{ - FILE *fp; - int n; - char *p, *line; - char buf[BUFSIZ]; - - _hostconf_init_done = 1; - n = 0; - p = HOSTCONF; - if ((fp = fopen(p, "r")) == NULL) - return; - while (n < MAXHOSTCONF && fgets(buf, sizeof(buf), fp)) { - line = buf; - if ((p = _hgetword(&line)) == NULL) - continue; - do { - if (strcmp(p, "hosts") == 0 - || strcmp(p, "local") == 0 - || strcmp(p, "file") == 0 - || strcmp(p, "files") == 0) { - _hostconf[n].byname = _files_ghbyname; - _hostconf[n].byaddr = _files_ghbyaddr; - n++; - } - else if (strcmp(p, "dns") == 0 - || strcmp(p, "bind") == 0) { - _hostconf[n].byname = _dns_ghbyname; - _hostconf[n].byaddr = _dns_ghbyaddr; - n++; - } -#ifdef YP - else if (strcmp(p, "nis") == 0) { - _hostconf[n].byname = _nis_ghbyname; - _hostconf[n].byaddr = _nis_ghbyaddr; - n++; - } -#endif -#ifdef ICMPNL - else if (strcmp(p, "icmp") == 0) { - _hostconf[n].byname = NULL; - _hostconf[n].byaddr = _icmp_ghbyaddr; - n++; - } -#endif /* ICMPNL */ - } while ((p = _hgetword(&line)) != NULL); - } - fclose(fp); - if (n < 0) { - /* no keyword found. do not change default configuration */ - return; - } - for (; n < MAXHOSTCONF; n++) { - _hostconf[n].byname = NULL; - _hostconf[n].byaddr = NULL; - } -} - -/* * Check if kernel supports mapped address. * implementation dependent */ #ifdef __KAME__ #include #endif /* __KAME__ */ static int _mapped_addr_enabled(void) { /* implementation dependent check */ #if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR) int mib[4]; size_t len; int val; mib[0] = CTL_NET; mib[1] = PF_INET6; mib[2] = IPPROTO_IPV6; mib[3] = IPV6CTL_MAPPED_ADDR; len = sizeof(val); if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0) return 1; #endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */ return 0; } /* * Functions defined in RFC2553 * getipnodebyname, getipnodebyaddr, freehostent */ static struct hostent * _ghbyname(const char *name, int af, int flags, int *errp) { struct hostent *hp; - int i; + int i, rval; + + static const ns_dtab dtab[] = { + NS_FILES_CB(_files_ghbyname, NULL) + { NSSRC_DNS, _dns_ghbyname, NULL }, + NS_NIS_CB(_nis_ghbyname, NULL) + { 0 } + }; if (flags & AI_ADDRCONFIG) { int s; /* * TODO: * Note that implementation dependent test for address * configuration should be done everytime called * (or apropriate interval), * because addresses will be dynamically assigned or deleted. */ if (af == AF_UNSPEC) { if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) af = AF_INET; else { _close(s); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) af = AF_INET6; else _close(s); } } if (af != AF_UNSPEC) { if ((s = socket(af, SOCK_DGRAM, 0)) < 0) return NULL; _close(s); } } - for (i = 0; i < MAXHOSTCONF; i++) { - if (_hostconf[i].byname - && (hp = (*_hostconf[i].byname)(name, af, errp)) != NULL) - return hp; - } - - return NULL; + rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyname", default_src, + name, af, errp); + return (rval == NS_SUCCESS) ? hp : NULL; } /* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */ struct hostent * _getipnodebyname_multi(const char *name, int af, int flags, int *errp) { struct hostent *hp; union inx_addr addrbuf; /* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */ if (af != AF_INET #ifdef INET6 && af != AF_INET6 #endif && af != PF_UNSPEC ) { *errp = NO_RECOVERY; return NULL; } #ifdef INET6 /* special case for literal address */ if (inet_pton(AF_INET6, name, &addrbuf) == 1) { if (af != AF_INET6) { *errp = HOST_NOT_FOUND; return NULL; } return _hpaddr(af, name, &addrbuf, errp); } #endif if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) { if (af != AF_INET) { if (MAPADDRENABLED(flags)) { MAPADDR(&addrbuf, &addrbuf.in_addr); } else { *errp = HOST_NOT_FOUND; return NULL; } } return _hpaddr(af, name, &addrbuf, errp); } - if (!_hostconf_init_done) - _hostconf_init(); - *errp = HOST_NOT_FOUND; hp = _ghbyname(name, af, flags, errp); #ifdef INET6 if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) && (MAPADDRENABLED(flags))) { struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp); if (hp == NULL) hp = _hpmapv6(hp2, errp); else { if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) { freehostent(hp2); hp2 = NULL; } hp = _hpmerge(hp, hp2, errp); } } #endif return _hpsort(hp); } struct hostent * getipnodebyname(const char *name, int af, int flags, int *errp) { if (af != AF_INET #ifdef INET6 && af != AF_INET6 #endif ) { *errp = NO_RECOVERY; return NULL; } return(_getipnodebyname_multi(name, af ,flags, errp)); } struct hostent * getipnodebyaddr(const void *src, size_t len, int af, int *errp) { struct hostent *hp; - int i; + int i, rval; #ifdef INET6 struct in6_addr addrbuf; #else struct in_addr addrbuf; #endif + static const ns_dtab dtab[] = { + NS_FILES_CB(_files_ghbyaddr, NULL) + { NSSRC_DNS, _dns_ghbyaddr, NULL }, + NS_NIS_CB(_nis_ghbyaddr, NULL) +#ifdef ICMPNL + { NSSRC_ICMP, _icmp_ghbyaddr, NULL }, +#endif + { 0 } + }; + *errp = HOST_NOT_FOUND; switch (af) { case AF_INET: if (len != sizeof(struct in_addr)) { *errp = NO_RECOVERY; return NULL; } if ((long)src & ~(sizeof(struct in_addr) - 1)) { memcpy(&addrbuf, src, len); src = &addrbuf; } if (((struct in_addr *)src)->s_addr == 0) return NULL; break; #ifdef INET6 case AF_INET6: if (len != sizeof(struct in6_addr)) { *errp = NO_RECOVERY; return NULL; } if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/ memcpy(&addrbuf, src, len); src = &addrbuf; } if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src)) return NULL; if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { src = (char *)src + (sizeof(struct in6_addr) - sizeof(struct in_addr)); af = AF_INET; len = sizeof(struct in_addr); } break; #endif default: *errp = NO_RECOVERY; return NULL; } - if (!_hostconf_init_done) - _hostconf_init(); - for (i = 0; i < MAXHOSTCONF; i++) { - if (_hostconf[i].byaddr - && (hp = (*_hostconf[i].byaddr)(src, len, af, errp)) != NULL) - return hp; - } - - return NULL; + rval = nsdispatch(&hp, dtab, NSDB_HOSTS, "ghbyaddr", default_src, + src, len, af, errp); + return (rval == NS_SUCCESS) ? hp : NULL; } void freehostent(struct hostent *ptr) { free(ptr); } #if 0 /* XXX: should be deprecated */ struct hostent * getnodebyname(const char *name, int af, int flags) { return getipnodebyname(name, af, flags, &h_errno); } #ifdef __warn_references __warn_references(getnodebyname, "warning: getnodebyname() deprecated, " "should use getaddrinfo() or getipnodebyname()"); #endif struct hostent * getnodebyaddr(const void *src, size_t len, int af) { return getipnodebyaddr(src, len, af, &h_errno); } #ifdef __warn_references __warn_references(getnodebyaddr, "warning: getnodebyaddr() deprecated, " "should use getnameinfo() or getipnodebyaddr()"); #endif #endif /* * Private utility functions */ /* * _hpcopy: allocate and copy hostent structure */ static struct hostent * _hpcopy(struct hostent *hp, int *errp) { struct hostent *nhp; char *cp, **pp; int size, addrsize; int nalias = 0, naddr = 0; int al_off; int i; if (hp == NULL) return hp; /* count size to be allocated */ size = sizeof(struct hostent); if (hp->h_name != NULL) size += strlen(hp->h_name) + 1; if ((pp = hp->h_aliases) != NULL) { for (i = 0; *pp != NULL; i++, pp++) { if (**pp != '\0') { size += strlen(*pp) + 1; nalias++; } } } /* adjust alignment */ size = ALIGN(size); al_off = size; size += sizeof(char *) * (nalias + 1); addrsize = ALIGN(hp->h_length); if ((pp = hp->h_addr_list) != NULL) { while (*pp++ != NULL) naddr++; } size += addrsize * naddr; size += sizeof(char *) * (naddr + 1); /* copy */ if ((nhp = (struct hostent *)malloc(size)) == NULL) { *errp = TRY_AGAIN; return NULL; } cp = (char *)&nhp[1]; if (hp->h_name != NULL) { nhp->h_name = cp; strcpy(cp, hp->h_name); cp += strlen(cp) + 1; } else nhp->h_name = NULL; nhp->h_aliases = (char **)((char *)nhp + al_off); if ((pp = hp->h_aliases) != NULL) { for (i = 0; *pp != NULL; pp++) { if (**pp != '\0') { nhp->h_aliases[i++] = cp; strcpy(cp, *pp); cp += strlen(cp) + 1; } } } nhp->h_aliases[nalias] = NULL; cp = (char *)&nhp->h_aliases[nalias + 1]; nhp->h_addrtype = hp->h_addrtype; nhp->h_length = hp->h_length; nhp->h_addr_list = (char **)cp; if ((pp = hp->h_addr_list) != NULL) { cp = (char *)&nhp->h_addr_list[naddr + 1]; for (i = 0; *pp != NULL; pp++) { nhp->h_addr_list[i++] = cp; memcpy(cp, *pp, hp->h_length); cp += addrsize; } } nhp->h_addr_list[naddr] = NULL; return nhp; } /* * _hpaddr: construct hostent structure with one address */ static struct hostent * _hpaddr(int af, const char *name, void *addr, int *errp) { struct hostent *hp, hpbuf; char *addrs[2]; hp = &hpbuf; hp->h_name = (char *)name; hp->h_aliases = NULL; hp->h_addrtype = af; hp->h_length = ADDRLEN(af); hp->h_addr_list = addrs; addrs[0] = (char *)addr; addrs[1] = NULL; return _hpcopy(hp, errp); } /* * _hpmerge: merge 2 hostent structure, arguments will be freed */ static struct hostent * _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) { int i, j; int naddr, nalias; char **pp; struct hostent *hp, hpbuf; char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; union inx_addr addrbuf[MAXADDRS]; if (hp1 == NULL) return hp2; if (hp2 == NULL) return hp1; #define HP(i) (i == 1 ? hp1 : hp2) hp = &hpbuf; hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name); hp->h_aliases = aliases; nalias = 0; for (i = 1; i <= 2; i++) { if ((pp = HP(i)->h_aliases) == NULL) continue; for (; nalias < MAXALIASES && *pp != NULL; pp++) { /* check duplicates */ for (j = 0; j < nalias; j++) if (strcasecmp(*pp, aliases[j]) == 0) break; if (j == nalias) aliases[nalias++] = *pp; } } aliases[nalias] = NULL; #ifdef INET6 if (hp1->h_length != hp2->h_length) { hp->h_addrtype = AF_INET6; hp->h_length = sizeof(struct in6_addr); } else { #endif hp->h_addrtype = hp1->h_addrtype; hp->h_length = hp1->h_length; #ifdef INET6 } #endif hp->h_addr_list = addrs; naddr = 0; for (i = 1; i <= 2; i++) { if ((pp = HP(i)->h_addr_list) == NULL) continue; if (HP(i)->h_length == hp->h_length) { while (naddr < MAXADDRS && *pp != NULL) addrs[naddr++] = *pp++; } else { /* copy IPv4 addr as mapped IPv6 addr */ while (naddr < MAXADDRS && *pp != NULL) { MAPADDR(&addrbuf[naddr], *pp++); addrs[naddr] = (char *)&addrbuf[naddr]; naddr++; } } } addrs[naddr] = NULL; hp = _hpcopy(hp, errp); freehostent(hp1); freehostent(hp2); return hp; } /* * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses */ #ifdef INET6 static struct hostent * _hpmapv6(struct hostent *hp, int *errp) { struct hostent *hp6; if (hp == NULL) return NULL; if (hp->h_addrtype == AF_INET6) return hp; /* make dummy hostent to convert IPv6 address */ if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) { *errp = TRY_AGAIN; return NULL; } hp6->h_name = NULL; hp6->h_aliases = NULL; hp6->h_addrtype = AF_INET6; hp6->h_length = sizeof(struct in6_addr); hp6->h_addr_list = NULL; return _hpmerge(hp6, hp, errp); } #endif /* * _hpsort: sort address by sortlist */ static struct hostent * _hpsort(struct hostent *hp) { int i, j, n; u_char *ap, *sp, *mp, **pp; char t; char order[MAXADDRS]; int nsort = _res.nsort; if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0) return hp; for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) { for (j = 0; j < nsort; j++) { #ifdef INET6 if (_res_ext.sort_list[j].af != hp->h_addrtype) continue; sp = (u_char *)&_res_ext.sort_list[j].addr; mp = (u_char *)&_res_ext.sort_list[j].mask; #else sp = (u_char *)&_res.sort_list[j].addr; mp = (u_char *)&_res.sort_list[j].mask; #endif for (n = 0; n < hp->h_length; n++) { if ((ap[n] & mp[n]) != sp[n]) break; } if (n == hp->h_length) break; } order[i] = j; } n = i; pp = (u_char **)hp->h_addr_list; for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { if (order[i] > order[j]) { ap = pp[i]; pp[i] = pp[j]; pp[j] = ap; t = order[i]; order[i] = order[j]; order[j] = t; } } } return hp; } static char * _hgetword(char **pp) { char c, *p, *ret; const char *sp; static const char sep[] = "# \t\n"; ret = NULL; for (p = *pp; (c = *p) != '\0'; p++) { for (sp = sep; *sp != '\0'; sp++) { if (c == *sp) break; } if (c == '#') p[1] = '\0'; /* ignore rest of line */ if (ret == NULL) { if (*sp == '\0') ret = p; } else { if (*sp != '\0') { *p++ = '\0'; break; } } } *pp = p; if (ret == NULL || *ret == '\0') return NULL; return ret; } /* * FILES (/etc/hosts) */ static FILE * _files_open(int *errp) { FILE *fp; fp = fopen(_PATH_HOSTS, "r"); if (fp == NULL) *errp = NO_RECOVERY; return fp; } -static struct hostent * -_files_ghbyname(const char *name, int af, int *errp) +static int +_files_ghbyname(void *rval, void *cb_data, va_list ap) { + const char *name; + int af; + int *errp; int match, nalias; char *p, *line, *addrstr, *cname; FILE *fp; struct hostent *rethp, *hp, hpbuf; char *aliases[MAXALIASES + 1], *addrs[2]; union inx_addr addrbuf; char buf[BUFSIZ]; int af0 = af; + name = va_arg(ap, const char *); + af = va_arg(ap, int); + errp = va_arg(ap, int *); + + *(struct hostent **)rval = NULL; + if ((fp = _files_open(errp)) == NULL) - return NULL; + return NS_UNAVAIL; rethp = hp = NULL; while (fgets(buf, sizeof(buf), fp)) { line = buf; if ((addrstr = _hgetword(&line)) == NULL || (cname = _hgetword(&line)) == NULL) continue; match = (strcasecmp(cname, name) == 0); nalias = 0; while ((p = _hgetword(&line)) != NULL) { if (!match) match = (strcasecmp(p, name) == 0); if (nalias < MAXALIASES) aliases[nalias++] = p; } if (!match) continue; switch (af0) { case AF_INET: if (inet_aton(addrstr, (struct in_addr *)&addrbuf) != 1) { *errp = NO_DATA; /* name found */ continue; } af = af0; break; #ifdef INET6 case AF_INET6: if (inet_pton(af, addrstr, &addrbuf) != 1) { *errp = NO_DATA; /* name found */ continue; } af = af0; break; #endif case AF_UNSPEC: if (inet_aton(addrstr, (struct in_addr *)&addrbuf) == 1) { af = AF_INET; break; } #ifdef INET6 if (inet_pton(AF_INET6, addrstr, &addrbuf) == 1) { af = AF_INET6; break; } #endif *errp = NO_DATA; /* name found */ continue; /* NOTREACHED */ } hp = &hpbuf; hp->h_name = cname; hp->h_aliases = aliases; aliases[nalias] = NULL; hp->h_addrtype = af; hp->h_length = ADDRLEN(af); hp->h_addr_list = addrs; addrs[0] = (char *)&addrbuf; addrs[1] = NULL; hp = _hpcopy(hp, errp); rethp = _hpmerge(rethp, hp, errp); } fclose(fp); - return rethp; + *(struct hostent **)rval = rethp; + return (rethp != NULL) ? NS_SUCCESS : NS_NOTFOUND; } -static struct hostent * -_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp) +static int +_files_ghbyaddr(void *rval, void *cb_data, va_list ap) { + const void *addr; + int addrlen; + int af; + int *errp; int nalias; char *p, *line; FILE *fp; struct hostent *hp, hpbuf; char *aliases[MAXALIASES + 1], *addrs[2]; union inx_addr addrbuf; char buf[BUFSIZ]; + addr = va_arg(ap, const void *); + addrlen = va_arg(ap, int); + af = va_arg(ap, int); + errp = va_arg(ap, int *); + + *(struct hostent**)rval = NULL; + if ((fp = _files_open(errp)) == NULL) - return NULL; + return NS_UNAVAIL; hp = NULL; while (fgets(buf, sizeof(buf), fp)) { line = buf; if ((p = _hgetword(&line)) == NULL || (af == AF_INET ? inet_aton(p, (struct in_addr *)&addrbuf) : inet_pton(af, p, &addrbuf)) != 1 || memcmp(addr, &addrbuf, addrlen) != 0 || (p = _hgetword(&line)) == NULL) continue; hp = &hpbuf; hp->h_name = p; hp->h_aliases = aliases; nalias = 0; while ((p = _hgetword(&line)) != NULL) { if (nalias < MAXALIASES) aliases[nalias++] = p; } aliases[nalias] = NULL; hp->h_addrtype = af; hp->h_length = addrlen; hp->h_addr_list = addrs; addrs[0] = (char *)&addrbuf; addrs[1] = NULL; hp = _hpcopy(hp, errp); break; } fclose(fp); - return hp; + *(struct hostent **)rval = hp; + return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; } #ifdef YP /* * NIS * * XXX actually a hack, these are INET4 specific. */ -static struct hostent * -_nis_ghbyname(const char *name, int af, int *errp) +static int +_nis_ghbyname(void *rval, void *cb_data, va_list ap) { + const char *name; + int af; + int *errp; struct hostent *hp = NULL; + name = va_arg(ap, const char *); + af = va_arg(ap, int); + errp = va_arg(ap, int *); + if (af == AF_UNSPEC) af = AF_INET; if (af == AF_INET) { hp = _gethostbynisname(name, af); if (hp != NULL) hp = _hpcopy(hp, errp); } - return (hp); + *(struct hostent **)rval = hp; + return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; + } -static struct hostent * -_nis_ghbyaddr(const void *addr, int addrlen, int af, int *errp) +static int +_nis_ghbyaddr(void *rval, void *cb_data, va_list ap) { + const void *addr; + int addrlen; + int af; + int *errp; struct hostent *hp = NULL; + addr = va_arg(ap, const void *); + addrlen = va_arg(ap, int); + af = va_arg(ap, int); + if (af == AF_INET) { hp = _gethostbynisaddr(addr, addrlen, af); if (hp != NULL) hp = _hpcopy(hp, errp); } - return (hp); + *(struct hostent **)rval = hp; + return (hp != NULL) ? NS_SUCCESS : NS_NOTFOUND; } #endif struct __res_type_list { SLIST_ENTRY(__res_type_list) rtl_entry; int rtl_type; }; #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ #else #define MAXPACKET 1024 #endif typedef union { HEADER hdr; u_char buf[MAXPACKET]; } querybuf; static struct hostent *getanswer __P((const querybuf *, int, const char *, int, struct hostent *, int *)); /* * we don't need to take care about sorting, nor IPv4 mapped address here. */ static struct hostent * getanswer(answer, anslen, qname, qtype, template, errp) const querybuf *answer; int anslen; const char *qname; int qtype; struct hostent *template; int *errp; { register const HEADER *hp; register const u_char *cp; register int n; const u_char *eom, *erdata; char *bp, **ap, **hap; int type, class, buflen, ancount, qdcount; int haveanswer, had_error; char tbuf[MAXDNAME]; const char *tname; int (*name_ok) __P((const char *)); static char *h_addr_ptrs[MAXADDRS + 1]; static char *host_aliases[MAXALIASES]; static char hostbuf[8*1024]; #define BOUNDED_INCR(x) \ do { \ cp += x; \ if (cp > eom) { \ *errp = NO_RECOVERY; \ return (NULL); \ } \ } while (0) #define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eom) { \ *errp = NO_RECOVERY; \ return (NULL); \ } \ } while (0) /* XXX do {} while (0) cannot be put here */ #define DNS_ASSERT(x) \ { \ if (!(x)) { \ cp += n; \ continue; \ } \ } /* XXX do {} while (0) cannot be put here */ #define DNS_FATAL(x) \ { \ if (!(x)) { \ had_error++; \ continue; \ } \ } tname = qname; template->h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: case T_AAAA: name_ok = res_hnok; break; case T_PTR: name_ok = res_dnok; break; default: return (NULL); /* XXX should be abort(); */ } /* * find first satisfactory answer */ hp = &answer->hdr; ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; buflen = sizeof hostbuf; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { *errp = NO_RECOVERY; return (NULL); } n = dn_expand(answer->buf, eom, cp, bp, buflen); if ((n < 0) || !(*name_ok)(bp)) { *errp = NO_RECOVERY; return (NULL); } BOUNDED_INCR(n + QFIXEDSZ); if (qtype == T_A || qtype == T_AAAA) { /* res_send() has already verified that the query name is the * same as the one we sent; this just gets the expanded name * (i.e., with the succeeding search-domain tacked on). */ n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { *errp = NO_RECOVERY; return (NULL); } template->h_name = bp; bp += n; buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ qname = template->h_name; } ap = host_aliases; *ap = NULL; template->h_aliases = host_aliases; hap = h_addr_ptrs; *hap = NULL; template->h_addr_list = h_addr_ptrs; haveanswer = 0; had_error = 0; while (ancount-- > 0 && cp < eom && !had_error) { n = dn_expand(answer->buf, eom, cp, bp, buflen); DNS_FATAL(n >= 0); DNS_FATAL((*name_ok)(bp)); cp += n; /* name */ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); type = _getshort(cp); cp += INT16SZ; /* type */ class = _getshort(cp); cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); cp += INT16SZ; /* len */ BOUNDS_CHECK(cp, n); erdata = cp + n; DNS_ASSERT(class == C_IN); if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { if (ap >= &host_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); DNS_FATAL(n >= 0); DNS_FATAL((*name_ok)(tbuf)); cp += n; if (cp != erdata) { *errp = NO_RECOVERY; return (NULL); } /* Store alias. */ *ap++ = bp; n = strlen(bp) + 1; /* for the \0 */ DNS_FATAL(n < MAXHOSTNAMELEN); bp += n; buflen -= n; /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ DNS_FATAL(n <= buflen); DNS_FATAL(n < MAXHOSTNAMELEN); strcpy(bp, tbuf); template->h_name = bp; bp += n; buflen -= n; continue; } if (qtype == T_PTR && type == T_CNAME) { n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if (n < 0 || !res_dnok(tbuf)) { had_error++; continue; } cp += n; if (cp != erdata) { *errp = NO_RECOVERY; return (NULL); } /* Get canonical name. */ n = strlen(tbuf) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) { had_error++; continue; } strcpy(bp, tbuf); tname = bp; bp += n; buflen -= n; continue; } DNS_ASSERT(type == qtype); switch (type) { case T_PTR: DNS_ASSERT(strcasecmp(tname, bp) == 0); n = dn_expand(answer->buf, eom, cp, bp, buflen); DNS_FATAL(n >= 0); DNS_FATAL(res_hnok(bp)); #if MULTI_PTRS_ARE_ALIASES cp += n; if (cp != erdata) { *errp = NO_RECOVERY; return (NULL); } if (!haveanswer) template->h_name = bp; else if (ap < &host_aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; if (n != -1) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { had_error++; break; } bp += n; buflen -= n; } break; #else template->h_name = bp; *errp = NETDB_SUCCESS; return (template); #endif case T_A: case T_AAAA: DNS_ASSERT(strcasecmp(template->h_name, bp) == 0); DNS_ASSERT(n == template->h_length); if (!haveanswer) { register int nn; template->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; buflen -= nn; } bp = (char *)ALIGN(bp); DNS_FATAL(bp + n < &hostbuf[sizeof hostbuf]); DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]); #ifdef FILTER_V4MAPPED if (type == T_AAAA) { struct in6_addr in6; memcpy(&in6, cp, sizeof(in6)); DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0); } #endif bcopy(cp, *hap++ = bp, n); bp += n; buflen -= n; cp += n; if (cp != erdata) { *errp = NO_RECOVERY; return (NULL); } break; default: abort(); } if (!had_error) haveanswer++; } if (haveanswer) { *ap = NULL; *hap = NULL; if (!template->h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); template->h_name = bp; bp += n; buflen -= n; } *errp = NETDB_SUCCESS; return (template); } no_recovery: *errp = NO_RECOVERY; return (NULL); #undef BOUNDED_INCR #undef BOUNDS_CHECK #undef DNS_ASSERT #undef DNS_FATAL } /* res_search() variant with multiple query support. */ static struct hostent * _res_search_multi(name, rtl, errp) const char *name; /* domain name */ struct __res_type_list *rtl; /* list of query types */ int *errp; { const char *cp, * const *domain; struct hostent *hp0 = NULL, *hp; struct hostent hpbuf; u_int dots; int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, tried_as_is = 0; struct __res_type_list *rtl0 = rtl; querybuf buf; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { *errp = NETDB_INTERNAL; return (NULL); } dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); trailing_dot = 0; if (cp > name && *--cp == '.') trailing_dot++; /* If there aren't any dots, it could be a user-level alias */ if (!dots && (cp = hostalias(name)) != NULL) { for(rtl = rtl0; rtl != NULL; rtl = SLIST_NEXT(rtl, rtl_entry)) { ret = res_query(cp, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } return (hp0); } /* * If there are dots in the name already, let's just give it a try * 'as is'. The threshold can be set with the "ndots" option. */ saved_herrno = -1; if (dots >= _res.ndots) { for(rtl = rtl0; rtl != NULL; rtl = SLIST_NEXT(rtl, rtl_entry)) { ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } if (hp0 != NULL) return (hp0); saved_herrno = *errp; tried_as_is++; } /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ if ((!dots && (_res.options & RES_DEFNAMES)) || (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { int done = 0; for (domain = (const char * const *)_res.dnsrch; *domain && !done; domain++) { for(rtl = rtl0; rtl != NULL; rtl = SLIST_NEXT(rtl, rtl_entry)) { ret = res_querydomain(name, *domain, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } if (hp0 != NULL) return (hp0); /* * If no server present, give up. * If name isn't found in this domain, * keep trying higher domains in the search list * (if that's enabled). * On a NO_DATA error, keep trying, otherwise * a wildcard entry of another type could keep us * from finding this entry higher in the domain. * If we get some other error (negative answer or * server failure), then stop searching up, * but try the input name below in case it's * fully-qualified. */ if (errno == ECONNREFUSED) { *errp = TRY_AGAIN; return (NULL); } switch (*errp) { case NO_DATA: got_nodata++; /* FALLTHROUGH */ case HOST_NOT_FOUND: /* keep trying */ break; case TRY_AGAIN: if (buf.hdr.rcode == SERVFAIL) { /* try next search element, if any */ got_servfail++; break; } /* FALLTHROUGH */ default: /* anything else implies that we're done */ done++; } /* if we got here for some reason other than DNSRCH, * we only wanted one iteration of the loop, so stop. */ if (!(_res.options & RES_DNSRCH)) done++; } } /* * If we have not already tried the name "as is", do that now. * note that we do this regardless of how many dots were in the * name or whether it ends with a dot unless NOTLDQUERY is set. */ if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { for(rtl = rtl0; rtl != NULL; rtl = SLIST_NEXT(rtl, rtl_entry)) { ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, buf.buf, sizeof(buf.buf)); if (ret > 0) { hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) ? AF_INET6 : AF_INET; hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); hp = getanswer(&buf, ret, name, rtl->rtl_type, &hpbuf, errp); if (!hp) continue; hp = _hpcopy(&hpbuf, errp); hp0 = _hpmerge(hp0, hp, errp); } } if (hp0 != NULL) return (hp0); } /* if we got here, we didn't satisfy the search. * if we did an initial full query, return that query's h_errno * (note that we wouldn't be here if that query had succeeded). * else if we ever got a nodata, send that back as the reason. * else send back meaningless h_errno, that being the one from * the last DNSRCH we did. */ if (saved_herrno != -1) *errp = saved_herrno; else if (got_nodata) *errp = NO_DATA; else if (got_servfail) *errp = TRY_AGAIN; return (NULL); } -static struct hostent * -_dns_ghbyname(const char *name, int af, int *errp) +static int +_dns_ghbyname(void *rval, void *cb_data, va_list ap) { + const char *name; + int af; + int *errp; struct __res_type_list *rtl, rtl4; #ifdef INET6 struct __res_type_list rtl6; #endif + name = va_arg(ap, const char *); + af = va_arg(ap, int); + errp = va_arg(ap, int *); + #ifdef INET6 switch (af) { case AF_UNSPEC: SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; SLIST_NEXT(&rtl6, rtl_entry) = &rtl4; rtl6.rtl_type = T_AAAA; rtl = &rtl6; break; case AF_INET6: SLIST_NEXT(&rtl6, rtl_entry) = NULL; rtl6.rtl_type = T_AAAA; rtl = &rtl6; break; case AF_INET: SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; rtl = &rtl4; break; } #else SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; rtl = &rtl4; #endif - return(_res_search_multi(name, rtl, errp)); + *(struct hostent **)rval = _res_search_multi(name, rtl, errp); + return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } -static struct hostent * -_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp) +static int +_dns_ghbyaddr(void *rval, void *cb_data, va_list ap) { + const void *addr; + int addrlen; + int af; + int *errp; int n; struct hostent *hp; u_char c, *cp; char *bp; struct hostent hbuf; int na; #ifdef INET6 static const char hex[] = "0123456789abcdef"; #endif querybuf buf; char qbuf[MAXDNAME+1]; char *hlist[2]; + addr = va_arg(ap, const void *); + addrlen = va_arg(ap, int); + af = va_arg(ap, int); + errp = va_arg(ap, int *); + + *(struct hostent **)rval = NULL; + #ifdef INET6 /* XXX */ if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr)) - return NULL; + return NS_NOTFOUND; #endif if ((_res.options & RES_INIT) == 0) { if (res_init() < 0) { *errp = h_errno; - return NULL; + return NS_UNAVAIL; } } memset(&hbuf, 0, sizeof(hbuf)); hbuf.h_name = NULL; hbuf.h_addrtype = af; hbuf.h_length = addrlen; na = 0; /* XXX assumes that MAXDNAME is big enough */ n = 0; bp = qbuf; cp = (u_char *)addr+addrlen-1; switch (af) { #ifdef INET6 case AF_INET6: for (; n < addrlen; n++, cp--) { c = *cp; *bp++ = hex[c & 0xf]; *bp++ = '.'; *bp++ = hex[c >> 4]; *bp++ = '.'; } strcpy(bp, "ip6.int"); break; #endif default: for (; n < addrlen; n++, cp--) { c = *cp; if (c >= 100) *bp++ = '0' + c / 100; if (c >= 10) *bp++ = '0' + (c % 100) / 10; *bp++ = '0' + c % 10; *bp++ = '.'; } strcpy(bp, "in-addr.arpa"); break; } n = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf); if (n < 0) { *errp = h_errno; - return NULL; + return NS_UNAVAIL; } hp = getanswer(&buf, n, qbuf, T_PTR, &hbuf, errp); if (!hp) - return NULL; + return NS_NOTFOUND; hbuf.h_addrtype = af; hbuf.h_length = addrlen; hbuf.h_addr_list = hlist; hlist[0] = (char *)addr; hlist[1] = NULL; - return _hpcopy(&hbuf, errp); + *(struct hostent **)rval = _hpcopy(&hbuf, errp); + return NS_SUCCESS; } static void _dns_shent(int stayopen) { if ((_res.options & RES_INIT) == 0) { if (res_init() < 0) return; } if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC; } static void _dns_ehent(void) { _res.options &= ~(RES_STAYOPEN | RES_USEVC); res_close(); } #ifdef ICMPNL /* * experimental: * draft-ietf-ipngwg-icmp-namelookups-02.txt * ifindex is assumed to be encoded in addr. */ #include #include #include struct _icmp_host_cache { struct _icmp_host_cache *hc_next; int hc_ifindex; struct in6_addr hc_addr; char *hc_name; }; static char * _icmp_fqdn_query(const struct in6_addr *addr, int ifindex) { int s; struct icmp6_filter filter; struct msghdr msg; struct cmsghdr *cmsg; struct in6_pktinfo *pkt; char cbuf[256]; char buf[1024]; int cc; struct icmp6_fqdn_query *fq; struct icmp6_fqdn_reply *fr; struct _icmp_host_cache *hc; struct sockaddr_in6 sin6; struct iovec iov; fd_set s_fds, fds; struct timeval tout; int len; char *name; static int pid; static struct _icmp_host_cache *hc_head; for (hc = hc_head; hc; hc = hc->hc_next) { if (hc->hc_ifindex == ifindex && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) return hc->hc_name; } if (pid == 0) pid = getpid(); ICMP6_FILTER_SETBLOCKALL(&filter); ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); FD_ZERO(&s_fds); tout.tv_sec = 0; tout.tv_usec = 200000; /*XXX: 200ms*/ fq = (struct icmp6_fqdn_query *)buf; fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY; fq->icmp6_fqdn_code = 0; fq->icmp6_fqdn_cksum = 0; fq->icmp6_fqdn_id = (u_short)pid; fq->icmp6_fqdn_unused = 0; fq->icmp6_fqdn_cookie[0] = 0; fq->icmp6_fqdn_cookie[1] = 0; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr; memset(&msg, 0, sizeof(msg)); msg.msg_name = (caddr_t)&sin6; msg.msg_namelen = sizeof(sin6); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; iov.iov_base = (caddr_t)buf; iov.iov_len = sizeof(struct icmp6_fqdn_query); if (ifindex) { msg.msg_control = cbuf; msg.msg_controllen = sizeof(cbuf); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; pkt = (struct in6_pktinfo *)&cmsg[1]; memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); pkt->ipi6_ifindex = ifindex; cmsg = CMSG_NXTHDR(&msg, cmsg); msg.msg_controllen = (char *)cmsg - cbuf; } if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) return NULL; (void)setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, (char *)&filter, sizeof(filter)); cc = sendmsg(s, &msg, 0); if (cc < 0) { _close(s); return NULL; } FD_SET(s, &s_fds); for (;;) { fds = s_fds; if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) { _close(s); return NULL; } len = sizeof(sin6); cc = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&sin6, &len); if (cc <= 0) { _close(s); return NULL; } if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) continue; if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr)) continue; fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr)); if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY) break; } _close(s); if (fr->icmp6_fqdn_cookie[1] != 0) { /* rfc1788 type */ name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4; len = (buf + cc) - name; } else { len = fr->icmp6_fqdn_namelen; name = fr->icmp6_fqdn_name; } if (len <= 0) return NULL; name[len] = 0; if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL) return NULL; /* XXX: limit number of cached entries */ hc->hc_ifindex = ifindex; hc->hc_addr = *addr; hc->hc_name = strdup(name); hc->hc_next = hc_head; hc_head = hc; return hc->hc_name; } static struct hostent * _icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp) { char *hname; int ifindex; struct in6_addr addr6; if (af != AF_INET6) { /* * Note: rfc1788 defines Who Are You for IPv4, * but no one implements it. */ return NULL; } memcpy(&addr6, addr, addrlen); ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3]; addr6.s6_addr[2] = addr6.s6_addr[3] = 0; if (!IN6_IS_ADDR_LINKLOCAL(&addr6)) return NULL; /*XXX*/ if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL) return NULL; return _hpaddr(af, hname, &addr6, errp); } #endif /* ICMPNL */ Index: head/lib/libc/net/nsdispatch.3 =================================================================== --- head/lib/libc/net/nsdispatch.3 (nonexistent) +++ head/lib/libc/net/nsdispatch.3 (revision 65532) @@ -0,0 +1,231 @@ +.\" $NetBSD: nsdispatch.3,v 1.8 1999/03/22 19:44:53 garbled Exp $ +.\" $FreeBSD$ +.\" +.\" Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Luke Mewburn. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. +.\" +.Dd January 19, 1999 +.Dt NSDISPATCH 3 +.Os +.Sh NAME +.Nm nsdispatch +.Nd name-service switch dispatcher routine +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fo nsdispatch +.Fa "void *retval" +.Fa "const ns_dtab dtab[]" +.Fa "const char *database" +.Fa "const char *method" +.Fa "const ns_src defaults[]" +.Fa "..." +.Fc +.Sh DESCRIPTION +The +.Fn nsdispatch +function invokes the callback functions specified in +.Va dtab +in the order given in +.Pa /etc/nsswitch.conf +for the database +.Va database +until a successful entry is found. +.Pp +.Va retval +is passed to each callback function to modify as necessary +(to pass back to the caller of +.Fn nsdispatch ) +.Pp +.Va dtab +is an array of +.Va ns_dtab +structures, which have the following format: +.Bd -literal -offset indent +typedef struct { + const char *src; + int (*cb)(void *retval, void *cb_data, va_list ap); + void *cb_data; +} ns_dtab; +.Ed +.Pp +.Bd -ragged -offset indent +For each source type that is implemented, an entry with +.Va src +set to the name of the source, +.Va cb +defined as a function which handles that source, and +.Va cb_data +is used to pass arbritrary data to the callback function. +The last entry in +.Va dtab +should contain +.Dv NULL +values for +.Va src , +.Va cb , +and +.Va cb_data . +.Ed +.Pp +.Va method +is usually the name of the function calling +.Fn nsdispatch . +When dynamic loading is supported, a symbol constructed from +.Va database , +the current source, and +.Va method +will be used as the name to invoke the dynamically loaded function. +.Pp +.Va defaults +contains a list of default sources to try in the case of +a missing or corrupt +.Xr nsswitch.conf 5 , +or if there isn't a relevant entry for +.Va database . +It is an array of +.Va ns_src +structures, which have the following format: +.Bd -literal -offset indent +typedef struct { + const char *src; + u_int32_t flags; +} ns_src; +.Ed +.Pp +.Bd -ragged -offset indent +For each default source type, an entry with +.Va src +set to the name of the source, and +.Va flags +set to the relevant flags +(usually +.Dv NS_SUCCESS ; +refer to +.Sx Callback return values +for more information). +The last entry in +.Va defaults +should have +.Va src +set to +.Dv NULL +and +.Va flags +set to 0. +.Pp +For convenience, a global variable defined as: +.Dl extern const ns_src __nsdefaultsrc[]; +exists which contains a single default entry for +.Sq files +for use by callers which don't require complicated default rules. +.Ed +.Pp +.Va Sq ... +are optional extra arguments, which +are passed to the appropriate callback function as a variable argument +list of the type +.Va va_list . +.Ss Valid source types +Whilst there is support for arbitrary sources, the following +#defines for commonly implementated sources are available: +.Bl -column NS_COMPAT COMPAT -offset indent +.Sy #define value +.It NSSRC_FILES "files" +.It NSSRC_DNS "dns" +.It NSSRC_NIS "nis" +.It NSSRC_COMPAT "compat" +.El +.Pp +Refer to +.Xr nsswitch.conf 5 +for a complete description of what each source type is. +.Pp +.Ss Callback return values +The callback functions should return one of the following values +depending upon status of the lookup: +.Bl -column NS_NOTFOUND -offset indent +.Sy "Return value" Status code +.It NS_SUCCESS success +.It NS_NOTFOUND notfound +.It NS_UNAVAIL unavail +.It NS_TRYAGAIN tryagain +.El +.Pp +Refer to +.Xr nsswitch.conf 5 +for a complete description of what each status code is. +.Pp +.Nm +returns the value of the callback that caused the dispatcher to finish, +or NS_NOTFOUND otherwise. +.Sh SEE ALSO +.Xr hesiod 3 , +.Xr stdarg 3 , +.Xr ypclnt 3 , +.Xr nsswitch.conf 5 +.Sh HISTORY +The +.Nm +routines first appeared in +.Fx 4.1 . +They were imported from the +.Nx +Project, +where they appeared first in +.Nx 1.4 . +.Sh AUTHORS +Luke Mewburn +.Aq lukem@netbsd.org +wrote this freely distributable name-service switch implementation, +using ideas from the +.Tn ULTRIX +.Xr svc.conf 5 +and +.Tn Solaris +.Xr nsswitch.conf 4 +manual pages. +.Sh BUGS +The +.Nm +routines are not thread safe. +This will be rectified in the future. +.Pp +Currently there is no support for dynamically loadable dispatcher callback +functions. +It is anticipated that this will be added in the future in the back-end +without requiring changes to code that invokes +.Fn nsdispatch . Property changes on: head/lib/libc/net/nsdispatch.3 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libc/net/nsdispatch.c =================================================================== --- head/lib/libc/net/nsdispatch.c (nonexistent) +++ head/lib/libc/net/nsdispatch.c (revision 65532) @@ -0,0 +1,270 @@ +/* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = + "$FreeBSD$"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +#include +#include +#define _NS_PRIVATE +#include +#include +#include +#include +#include + +/* + * default sourcelist: `files' + */ +const ns_src __nsdefaultsrc[] = { + { NSSRC_FILES, NS_SUCCESS }, + { 0 }, +}; + + +static int _nsmapsize = 0; +static ns_dbt *_nsmap = NULL; + +/* + * size of dynamic array chunk for _nsmap and _nsmap[x].srclist + */ +#define NSELEMSPERCHUNK 8 + + +int _nscmp __P((const void *, const void *)); + + +int +_nscmp(a, b) + const void *a; + const void *b; +{ + return (strcasecmp(((const ns_dbt *)a)->name, + ((const ns_dbt *)b)->name)); +} + + +void +_nsdbtaddsrc(dbt, src) + ns_dbt *dbt; + const ns_src *src; +{ + if ((dbt->srclistsize % NSELEMSPERCHUNK) == 0) { + dbt->srclist = (ns_src *)realloc(dbt->srclist, + (dbt->srclistsize + NSELEMSPERCHUNK) * sizeof(ns_src)); + if (dbt->srclist == NULL) + err(1, "nsdispatch: memory allocation failure"); + } + memmove(&dbt->srclist[dbt->srclistsize++], src, sizeof(ns_src)); +} + + +void +_nsdbtdump(dbt) + const ns_dbt *dbt; +{ + int i; + + printf("%s (%d source%s):", dbt->name, dbt->srclistsize, + dbt->srclistsize == 1 ? "" : "s"); + for (i = 0; i < dbt->srclistsize; i++) { + printf(" %s", dbt->srclist[i].name); + if (!(dbt->srclist[i].flags & + (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) && + (dbt->srclist[i].flags & NS_SUCCESS)) + continue; + printf(" ["); + if (!(dbt->srclist[i].flags & NS_SUCCESS)) + printf(" SUCCESS=continue"); + if (dbt->srclist[i].flags & NS_UNAVAIL) + printf(" UNAVAIL=return"); + if (dbt->srclist[i].flags & NS_NOTFOUND) + printf(" NOTFOUND=return"); + if (dbt->srclist[i].flags & NS_TRYAGAIN) + printf(" TRYAGAIN=return"); + printf(" ]"); + } + printf("\n"); +} + + +const ns_dbt * +_nsdbtget(name) + const char *name; +{ + static time_t confmod; + + struct stat statbuf; + ns_dbt dbt; + + extern FILE *_nsyyin; + extern int _nsyyparse __P((void)); + + dbt.name = name; + + if (confmod) { + if (stat(_PATH_NS_CONF, &statbuf) == -1) + return (NULL); + if (confmod < statbuf.st_mtime) { + int i, j; + + for (i = 0; i < _nsmapsize; i++) { + for (j = 0; j < _nsmap[i].srclistsize; j++) { + if (_nsmap[i].srclist[j].name != NULL) { + /*LINTED const cast*/ + free((void *) + _nsmap[i].srclist[j].name); + } + } + if (_nsmap[i].srclist) + free(_nsmap[i].srclist); + if (_nsmap[i].name) { + /*LINTED const cast*/ + free((void *)_nsmap[i].name); + } + } + if (_nsmap) + free(_nsmap); + _nsmap = NULL; + _nsmapsize = 0; + confmod = 0; + } + } + if (!confmod) { + if (stat(_PATH_NS_CONF, &statbuf) == -1) + return (NULL); + _nsyyin = fopen(_PATH_NS_CONF, "r"); + if (_nsyyin == NULL) + return (NULL); + _nsyyparse(); + (void)fclose(_nsyyin); + qsort(_nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), _nscmp); + confmod = statbuf.st_mtime; + } + return (bsearch(&dbt, _nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), + _nscmp)); +} + + +void +_nsdbtput(dbt) + const ns_dbt *dbt; +{ + int i; + + for (i = 0; i < _nsmapsize; i++) { + if (_nscmp(dbt, &_nsmap[i]) == 0) { + /* overwrite existing entry */ + if (_nsmap[i].srclist != NULL) + free(_nsmap[i].srclist); + memmove(&_nsmap[i], dbt, sizeof(ns_dbt)); + return; + } + } + + if ((_nsmapsize % NSELEMSPERCHUNK) == 0) { + _nsmap = (ns_dbt *)realloc(_nsmap, + (_nsmapsize + NSELEMSPERCHUNK) * sizeof(ns_dbt)); + if (_nsmap == NULL) + err(1, "nsdispatch: memory allocation failure"); + } + memmove(&_nsmap[_nsmapsize++], dbt, sizeof(ns_dbt)); +} + + +int +#if __STDC__ +nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, + const char *method, const ns_src defaults[], ...) +#else +nsdispatch(retval, disp_tab, database, method, defaults, va_alist) + void *retval; + const ns_dtab disp_tab[]; + const char *database; + const char *method; + const ns_src defaults[]; + va_dcl +#endif +{ + va_list ap; + int i, curdisp, result; + const ns_dbt *dbt; + const ns_src *srclist; + int srclistsize; + + dbt = _nsdbtget(database); + if (dbt != NULL) { + srclist = dbt->srclist; + srclistsize = dbt->srclistsize; + } else { + srclist = defaults; + srclistsize = 0; + while (srclist[srclistsize].name != NULL) + srclistsize++; + } + result = 0; + + for (i = 0; i < srclistsize; i++) { + for (curdisp = 0; disp_tab[curdisp].src != NULL; curdisp++) + if (strcasecmp(disp_tab[curdisp].src, + srclist[i].name) == 0) + break; + result = 0; + if (disp_tab[curdisp].callback) { +#if __STDC__ + va_start(ap, defaults); +#else + va_start(ap); +#endif + result = disp_tab[curdisp].callback(retval, + disp_tab[curdisp].cb_data, ap); + va_end(ap); + if (result & srclist[i].flags) { + break; + } + } + } + return (result ? result : NS_NOTFOUND); +} Property changes on: head/lib/libc/net/nsdispatch.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libc/net/nslexer.l =================================================================== --- head/lib/libc/net/nslexer.l (nonexistent) +++ head/lib/libc/net/nslexer.l (revision 65532) @@ -0,0 +1,116 @@ +%{ +/* $NetBSD: nslexer.l,v 1.3 1999/01/25 00:16:17 lukem Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = + "$FreeBSD$"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#define _NS_PRIVATE +#include +#include + +#include "nsparser.h" + +#define YY_NO_UNPUT + +%} + +%option yylineno + +BLANK [ \t] +CR \n +STRING [a-zA-Z][a-zA-Z0-9_]* + +%% + +{BLANK}+ ; /* skip whitespace */ + +#.* ; /* skip comments */ + +\\{CR} ; /* allow continuation */ + +{CR} return NL; + +[sS][uU][cC][cC][eE][sS][sS] return SUCCESS; +[uU][nN][aA][vV][aA][iI][lL] return UNAVAIL; +[nN][oO][tT][fF][oO][uU][nN][dD] return NOTFOUND; +[tT][rR][yY][aA][gG][aA][iI][nN] return TRYAGAIN; + +[rR][eE][tT][uU][rR][nN] return RETURN; +[cC][oO][nN][tT][iI][nN][uU][eE] return CONTINUE; + +{STRING} { + char *p; + int i; + + if ((p = strdup(yytext)) == NULL) + err(1, "nsdispatch: memory allocation failure"); + + for (i = 0; i < strlen(p); i++) { + if (isupper((unsigned char)p[i])) + p[i] = tolower((unsigned char)p[i]); + } + _nsyylval.str = p; + return STRING; + } + +[:=\[\]] return yytext[0]; + +. ; /* ignore all else */ + +%% + +#undef _nsyywrap +int +_nsyywrap() +{ + return 1; +} /* _nsyywrap */ + +void +_nsyyerror(msg) + const char *msg; +{ + + warnx("%s line %d: %s at '%s'", _PATH_NS_CONF, yylineno, msg, yytext); +} /* _nsyyerror */ Property changes on: head/lib/libc/net/nslexer.l ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libc/net/nsparser.y =================================================================== --- head/lib/libc/net/nsparser.y (nonexistent) +++ head/lib/libc/net/nsparser.y (revision 65532) @@ -0,0 +1,175 @@ +%{ +/* $NetBSD: nsparser.y,v 1.3 1999/01/25 00:16:18 lukem Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = + "$FreeBSD$"; +#endif /* LIBC_SCCS and not lint */ + +#include +#define _NS_PRIVATE +#include +#include +#include + + +static void _nsaddsrctomap __P((const char *)); + +static ns_dbt curdbt; +static ns_src cursrc; +%} + +%union { + char *str; + int mapval; +} + +%token NL +%token SUCCESS UNAVAIL NOTFOUND TRYAGAIN +%token RETURN CONTINUE +%token STRING + +%type Status Action + +%% + +File + : /* empty */ + | Lines + ; + +Lines + : Entry + | Lines Entry + ; + +Entry + : NL + | Database ':' NL + | Database ':' Srclist NL + { + _nsdbtput(&curdbt); + } + ; + +Database + : STRING + { + curdbt.name = yylval.str; + curdbt.srclist = NULL; + curdbt.srclistsize = 0; + } + ; + +Srclist + : Item + | Srclist Item + ; + +Item + : STRING + { + cursrc.flags = NS_SUCCESS; + _nsaddsrctomap($1); + } + | STRING '[' { cursrc.flags = NS_SUCCESS; } Criteria ']' + { + _nsaddsrctomap($1); + } + ; + +Criteria + : Criterion + | Criteria Criterion + ; + +Criterion + : Status '=' Action + { + if ($3) /* if action == RETURN set RETURN bit */ + cursrc.flags |= $1; + else /* else unset it */ + cursrc.flags &= ~$1; + } + ; + +Status + : SUCCESS { $$ = NS_SUCCESS; } + | UNAVAIL { $$ = NS_UNAVAIL; } + | NOTFOUND { $$ = NS_NOTFOUND; } + | TRYAGAIN { $$ = NS_TRYAGAIN; } + ; + +Action + : RETURN { $$ = 1L; } + | CONTINUE { $$ = 0L; } + ; + +%% + +static void +_nsaddsrctomap(elem) + const char *elem; +{ + int i, lineno; + extern int _nsyylineno; + extern char * _nsyytext; + + lineno = _nsyylineno - (*_nsyytext == '\n' ? 1 : 0); + if (curdbt.srclistsize > 0) { + if ((strcasecmp(elem, NSSRC_COMPAT) == 0) || + (strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) { + /* XXX: syslog the following */ + warnx("%s line %d: 'compat' used with other sources", + _PATH_NS_CONF, lineno); + return; + } + } + for (i = 0; i < curdbt.srclistsize; i++) { + if (strcasecmp(curdbt.srclist[i].name, elem) == 0) { + /* XXX: syslog the following */ + warnx("%s line %d: duplicate source '%s'", + _PATH_NS_CONF, lineno, elem); + return; + } + } + cursrc.name = elem; + _nsdbtaddsrc(&curdbt, &cursrc); +} Property changes on: head/lib/libc/net/nsparser.y ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/release/sysinstall/installUpgrade.c =================================================================== --- head/release/sysinstall/installUpgrade.c (revision 65531) +++ head/release/sysinstall/installUpgrade.c (revision 65532) @@ -1,492 +1,492 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. 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, * verbatim and that no modifications are made prior to this * point in the file. * 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 JORDAN HUBBARD ``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 JORDAN HUBBARD OR HIS PETS 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, LIFE 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. * */ #include "sysinstall.h" #include #include #include #include #include #include #include #include #include static int installUpgradeNonInteractive(dialogMenuItem *self); typedef struct _hitList { enum { JUST_COPY, CALL_HANDLER } action ; char *name; Boolean optional; void (*handler)(struct _hitList *self); } HitList; /* These are the only meaningful files I know about */ static HitList etc_files [] = { { JUST_COPY, "Xaccel.ini", TRUE, NULL }, { JUST_COPY, "XF86Config", TRUE, NULL }, { JUST_COPY, "adduser.conf", TRUE, NULL }, { JUST_COPY, "aliases", TRUE, NULL }, { JUST_COPY, "aliases.db", TRUE, NULL }, { JUST_COPY, "amd.map", TRUE, NULL }, { JUST_COPY, "auth.conf", TRUE, NULL }, { JUST_COPY, "crontab", TRUE, NULL }, { JUST_COPY, "csh.cshrc", TRUE, NULL }, { JUST_COPY, "csh.login", TRUE, NULL }, { JUST_COPY, "csh.logout", TRUE, NULL }, { JUST_COPY, "cvsupfile", TRUE, NULL }, { JUST_COPY, "disktab", TRUE, NULL }, { JUST_COPY, "dm.conf", TRUE, NULL }, { JUST_COPY, "dumpdates", TRUE, NULL }, { JUST_COPY, "exports", TRUE, NULL }, { JUST_COPY, "fbtab", TRUE, NULL }, { JUST_COPY, "fstab", FALSE, NULL }, { JUST_COPY, "ftpusers", TRUE, NULL }, { JUST_COPY, "gettytab", TRUE, NULL }, { JUST_COPY, "gnats", TRUE, NULL }, { JUST_COPY, "group", FALSE, NULL }, - { JUST_COPY, "host.conf", TRUE, NULL }, { JUST_COPY, "hosts", TRUE, NULL }, { JUST_COPY, "hosts.equiv", TRUE, NULL }, { JUST_COPY, "hosts.lpd", TRUE, NULL }, { JUST_COPY, "inetd.conf", TRUE, NULL }, { JUST_COPY, "kerberosIV", TRUE, NULL }, { JUST_COPY, "localtime", TRUE, NULL }, { JUST_COPY, "login.access", TRUE, NULL }, { JUST_COPY, "login.conf", TRUE, NULL }, { JUST_COPY, "mail.rc", TRUE, NULL }, { JUST_COPY, "make.conf", TRUE, NULL }, { JUST_COPY, "manpath.config", TRUE, NULL }, { JUST_COPY, "master.passwd", FALSE, NULL }, { JUST_COPY, "modems", TRUE, NULL }, { JUST_COPY, "motd", TRUE, NULL }, { JUST_COPY, "namedb", TRUE, NULL }, { JUST_COPY, "networks", TRUE, NULL }, { JUST_COPY, "newsyslog.conf", TRUE, NULL }, + { JUST_COPY, "nsswitch.conf", TRUE, NULL }, { JUST_COPY, "pam.conf", TRUE, NULL }, { JUST_COPY, "passwd", TRUE, NULL }, { JUST_COPY, "periodic", TRUE, NULL }, { JUST_COPY, "ppp", TRUE, NULL }, { JUST_COPY, "printcap", TRUE, NULL }, { JUST_COPY, "profile", TRUE, NULL }, { JUST_COPY, "pwd.db", TRUE, NULL }, { JUST_COPY, "rc.local", TRUE, NULL }, { JUST_COPY, "rc.firewall", TRUE, NULL }, { JUST_COPY, "rc.conf.local", TRUE, NULL }, { JUST_COPY, "remote", TRUE, NULL }, { JUST_COPY, "resolv.conf", TRUE, NULL }, { JUST_COPY, "rmt", TRUE, NULL }, { JUST_COPY, "sendmail.cf", TRUE, NULL }, { JUST_COPY, "sendmail.cw", TRUE, NULL }, { JUST_COPY, "services", TRUE, NULL }, { JUST_COPY, "shells", TRUE, NULL }, { JUST_COPY, "skeykeys", TRUE, NULL }, { JUST_COPY, "spwd.db", TRUE, NULL }, { JUST_COPY, "syslog.conf", TRUE, NULL }, { JUST_COPY, "ttys", TRUE, NULL }, { JUST_COPY, "uucp", TRUE, NULL }, { 0 }, }; void traverseHitlist(HitList *h) { system("rm -rf /etc/upgrade"); Mkdir("/etc/upgrade"); while (h->name) { if (!file_readable(h->name)) { if (!h->optional) msgConfirm("Unable to find an old /etc/%s file! That is decidedly non-standard and\n" "your upgraded system may function a little strangely as a result.", h->name); } else { if (h->action == JUST_COPY) { /* Move the just-loaded copy aside */ vsystem("mv /etc/%s /etc/upgrade/%s", h->name, h->name); /* Copy the old one into its place */ msgNotify("Resurrecting %s..", h->name); /* Do this with tar so that symlinks and such are preserved */ if (vsystem("tar cf - %s | tar xpf - -C /etc", h->name)) msgConfirm("Unable to resurrect your old /etc/%s! Hmmmm.", h->name); } else /* call handler */ h->handler(h); } ++h; } } int installUpgrade(dialogMenuItem *self) { char saved_etc[FILENAME_MAX]; Boolean extractingBin = TRUE; if (variable_get(VAR_NONINTERACTIVE)) return installUpgradeNonInteractive(self); variable_set2(SYSTEM_STATE, "upgrade", 0); dialog_clear(); systemDisplayHelp("UPGRADE"); if (msgYesNo("Given all that scary stuff you just read, are you sure you want to\n" "risk it all and proceed with this upgrade?") != 0) return DITEM_FAILURE; if (!Dists) { msgConfirm("First, you must select some distribution components. The upgrade procedure\n" "will only upgrade the distributions you select in the next set of menus."); if (!dmenuOpenSimple(&MenuDistributions, FALSE) || !Dists) return DITEM_FAILURE; } else if (!(Dists & DIST_BIN)) { /* No bin selected? Not much of an upgrade.. */ if (msgYesNo("You didn't select the bin distribution as one of the distributons to load.\n" "This one is pretty vital to a successful upgrade. Are you SURE you don't\n" "want to select the bin distribution? Chose No to bring up the Distributions\n" "menu again.") != 0) { if (!dmenuOpenSimple(&MenuDistributions, FALSE)) return DITEM_FAILURE; } } /* Still?! OK! They must know what they're doing.. */ if (!(Dists & DIST_BIN)) extractingBin = FALSE; if (RunningAsInit) { Device **devs; int i, cnt; char *cp; cp = variable_get(VAR_DISK); devs = deviceFind(cp, DEVICE_TYPE_DISK); cnt = deviceCount(devs); if (!cnt) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE | DITEM_RESTORE; } else { /* Enable all the drives before we start */ for (i = 0; i < cnt; i++) devs[i]->enabled = TRUE; } msgConfirm("OK. First, we're going to go to the disk label editor. In this editor\n" "you will be expected to Mount any partitions you're interested in\n" "upgrading. DO NOT set the Newfs flag to Y on anything in the label editor\n" "unless you're absolutely sure you know what you're doing! In this\n" "instance, you'll be using the label editor as little more than a fancy\n" "screen-oriented partition mounting tool.\n\n" "Once you're done in the label editor, press Q to return here for the next\n" "step."); if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE) { msgConfirm("The disk label editor returned an error status. Upgrade operation\n" "aborted."); return DITEM_FAILURE | DITEM_RESTORE; } /* Don't write out MBR info */ variable_set2(DISK_PARTITIONED, "written", 0); if (DITEM_STATUS(diskLabelCommit(self)) == DITEM_FAILURE) { msgConfirm("Not all file systems were properly mounted. Upgrade operation\n" "aborted."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE | DITEM_RESTORE; } msgNotify("Updating /stand on root filesystem"); (void)vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity()); if (DITEM_STATUS(chroot("/mnt")) == DITEM_FAILURE) { msgConfirm("Unable to chroot to /mnt - something is wrong with the\n" "root partition or the way it's mounted if this doesn't work."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE | DITEM_RESTORE; } chdir("/"); installEnvironment(); systemCreateHoloshell(); } saved_etc[0] = '\0'; /* Don't allow sources to be upgraded unless if we have src already */ if (directory_exists("/usr/src/") && (Dists & DIST_SRC)) { Dists &= ~DIST_SRC; msgConfirm("Warning: /usr/src exists and sources were selected as upgrade\n" "targets. Unfortunately, this is not the way to upgrade your\n" "sources - please use CTM or CVSup or some other method which\n" "handles ``deletion events'', unlike this particular feature.\n\n" "Your existing /usr/src will not be affected by this upgrade.\n"); } if (extractingBin) { while (!*saved_etc) { char *cp = msgGetInput("/usr/tmp/etc", "Under which directory do you wish to save your current /etc?"); if (!cp || !*cp || Mkdir(cp)) { if (msgYesNo("Directory was not specified, was invalid or user selected Cancel.\n\n" "Doing an upgrade without first backing up your /etc directory is a very\n" "bad idea! Do you want to go back and specify the save directory again?") != 0) break; } else { SAFE_STRCPY(saved_etc, cp); } } if (saved_etc[0]) { msgNotify("Preserving /etc directory.."); if (vsystem("tar -cBpf - -C /etc . | tar --unlink -xBpf - -C %s", saved_etc)) if (msgYesNo("Unable to backup your /etc into %s.\n" "Do you want to continue anyway?", saved_etc) != 0) return DITEM_FAILURE; msgNotify("Preserving /root directory.."); vsystem("tar -cBpf - -C / root | tar --unlink -xBpf - -C %s", saved_etc); } msgNotify("chflags'ing old binaries - please wait."); (void)vsystem("chflags -R noschg /bin /sbin /usr/sbin /usr/bin /usr/lib /usr/libexec /kernel*"); if (file_readable("/kernel")) { msgNotify("Moving old kernel to /kernel.prev"); if (system("mv /kernel /kernel.prev")) { if (!msgYesNo("Hmmm! I couldn't move the old kernel over! Do you want to\n" "treat this as a big problem and abort the upgrade? Due to the\n" "way that this upgrade process works, you will have to reboot\n" "and start over from the beginning. Select Yes to reboot now")) systemShutdown(1); } else msgConfirm("NOTICE: Your old kernel is in /kernel.prev should this upgrade\n" "fail for any reason and you need to boot your old kernel"); } } media: /* We do this very late, but we unfortunately need to back up /etc first */ if (!mediaVerify()) return DITEM_FAILURE; if (!mediaDevice->init(mediaDevice)) { if (!msgYesNo("Couldn't initialize the media. Would you like\n" "to adjust your media selection and try again?")) { mediaDevice = NULL; goto media; } else return DITEM_FAILURE | DITEM_REDRAW | DITEM_RESTORE; } msgNotify("Beginning extraction of distributions.."); if (DITEM_STATUS(distExtractAll(self)) == DITEM_FAILURE) { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } else if (Dists) { if (!extractingBin || !(Dists & DIST_BIN)) { msgNotify("The extraction process seems to have had some problems, but we got most\n" "of the essentials. We'll treat this as a warning since it may have been\n" "only non-essential distributions which failed to load."); } else { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } } if (extractingBin) vsystem("disklabel -B `awk '$2~/\\/$/ {print substr($1, 6, 3)}' /etc/fstab`"); msgNotify("First stage of upgrade completed successfully!\n\n" "Next comes stage 2, where we attempt to resurrect your /etc\n" "directory!"); if (saved_etc && chdir(saved_etc)) { msgConfirm("Unable to go to your saved /etc directory in %s?! Argh!\n" "Something went seriously wrong! It's quite possible that\n" "your former /etc is toast. I hope you didn't have any\n" "important customizations you wanted to keep in there.. :(", saved_etc); } else { /* Now try to resurrect the /etc files */ traverseHitlist(etc_files); /* Resurrect the root dotfiles */ vsystem("tar -cBpf - root | tar -xBpf - -C / && rm -rf root"); } msgConfirm("Upgrade completed! All of your old /etc files have been restored.\n" "For your reference, the new /etc files are in /etc/upgrade/ in case\n" "you wish to upgrade these files by hand (though that should not be\n" "strictly necessary). If your root partition is specified in /etc/fstab\n" "using the old \"compatibility\" slice, you may also wish to update it to\n" "use a fully qualified slice name in order to avoid warnings on startup.\n\n" "When you're ready to reboot into the new system, simply exit the installation."); return DITEM_SUCCESS | DITEM_REDRAW | DITEM_RESTORE; } static int installUpgradeNonInteractive(dialogMenuItem *self) { char *saved_etc; Boolean extractingBin = TRUE; variable_set2(SYSTEM_STATE, "upgrade", 0); /* Make sure at least BIN is selected */ Dists |= DIST_BIN; if (RunningAsInit) { Device **devs; int i, cnt; char *cp; cp = variable_get(VAR_DISK); devs = deviceFind(cp, DEVICE_TYPE_DISK); cnt = deviceCount(devs); if (!cnt) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE; } else { /* Enable all the drives befor we start */ for (i = 0; i < cnt; i++) devs[i]->enabled = TRUE; } msgConfirm("OK. First, we're going to go to the disk label editor. In this editor\n" "you will be expected to Mount any partitions you're interested in\n" "upgrading. DO NOT set the Newfs flag to Y on anything in the label editor\n" "unless you're absolutely sure you know what you're doing! In this\n" "instance, you'll be using the label editor as little more than a fancy\n" "screen-oriented partition mounting tool.\n\n" "Once you're done in the label editor, press Q to return here for the next\n" "step."); if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE) { msgConfirm("The disk label editor returned an error status. Upgrade operation\n" "aborted."); return DITEM_FAILURE; } /* Don't write out MBR info */ variable_set2(DISK_PARTITIONED, "written", 0); if (DITEM_STATUS(diskLabelCommit(self)) == DITEM_FAILURE) { msgConfirm("Not all file systems were properly mounted. Upgrade operation\n" "aborted."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE; } if (extractingBin) { msgNotify("chflags'ing old binaries - please wait."); (void)vsystem("chflags -R noschg /mnt/"); } msgNotify("Updating /stand on root filesystem"); (void)vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity()); if (DITEM_STATUS(chroot("/mnt")) == DITEM_FAILURE) { msgConfirm("Unable to chroot to /mnt - something is wrong with the\n" "root partition or the way it's mounted if this doesn't work."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE; } chdir("/"); systemCreateHoloshell(); } if (!mediaVerify() || !mediaDevice->init(mediaDevice)) { msgNotify("Upgrade: Couldn't initialize media."); return DITEM_FAILURE; } saved_etc = "/usr/tmp/etc"; Mkdir(saved_etc); msgNotify("Preserving /etc directory.."); if (vsystem("tar -cpBf - -C /etc . | tar -xpBf - -C %s", saved_etc)) { msgNotify("Unable to backup your /etc into %s.", saved_etc); return DITEM_FAILURE; } if (file_readable("/kernel")) { msgNotify("Moving old kernel to /kernel.prev"); if (!system("chflags noschg /kernel && mv /kernel /kernel.prev")) { /* Give us a working kernel in case we crash and reboot */ system("cp /kernel.prev /kernel"); } } msgNotify("Beginning extraction of distributions.."); if (DITEM_STATUS(distExtractAll(self)) == DITEM_FAILURE) { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } else if (Dists) { if (!(Dists & DIST_BIN)) { msgNotify("The extraction process seems to have had some problems, but we got most\n" "of the essentials. We'll treat this as a warning since it may have been\n" "only non-essential distributions which failed to upgrade."); } else { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } } msgNotify("First stage of upgrade completed successfully."); if (vsystem("tar -cpBf - -C %s . | tar --unlink -xpBf - -C /etc", saved_etc)) { msgNotify("Unable to resurrect your old /etc!"); return DITEM_FAILURE; } return DITEM_SUCCESS | DITEM_REDRAW; } Index: head/release/texts/UPGRADE.TXT =================================================================== --- head/release/texts/UPGRADE.TXT (revision 65531) +++ head/release/texts/UPGRADE.TXT (revision 65532) @@ -1,178 +1,177 @@ +===================== Upgrading FreeBSD ==========================+ | | | 0.0 Preface | | 0.1 DISCLAIMER | | 0.2 IMPORTANT NOTES | | | | 1.0 Introduction | | 1.1 Upgrade Overview | | | | 2.0 Procedure | | 2.1 Backup | | 2.2 Mount Filesystems | | 2.3 Select Distributions | | 2.4 After Installation | | | | 3.0 Alternative Upgrade Techniques | | | +=====================================================================+ 0.1 DISCLAIMER --- ---------- While the FreeBSD upgrade procedure does its best to safeguard against accidental loss of data, it is still more than possible to WIPE OUT YOUR ENTIRE DISK with this installation! Please do not accept the final confirmation request unless you have adequately backed up any important data files. 0.2 IMPORTANT NOTES --- --------------- These notes assume that you are using the version of sysinstall supplied with the version of FreeBSD to which you intend to upgrade. Using a mismatched version of sysinstall is almost guaranteed to cause problems and has been known to leave systems in an unusable state. The most commonly made mistake in this regard is the use of an old copy of /stand/sysinstall from an existing installation to upgrade to a newer version of FreeBSD. This is NOT recommended. Furthermore, if you are upgrading from FreeBSD 2.2.5 or earlier, see section 2.4 for important details regarding changes to the /etc/fstab file required during the upgrade procedure. 1.0 Introduction --- ------------ The upgrade procedure replaces distributions selected by the user with those corresponding to the new FreeBSD release. It preserves standard system configuration data, as well as user data, installed packages and other software. Administrators contemplating an upgrade are encouraged to study this document in its entirety before commencing an upgrade. Failure to do so may result in a failed upgrade or loss of data. 1.1 Upgrade Overview --- ---------------- Upgrading of a distribution is performed by extracting the new version of the component over the top of the previous version. Files belonging to the old distribution are not deleted. System configuration is preserved by retaining and restoring the previous version of the following files: - Xaccel.ini, XF86Config, adduser.conf, aliases, aliases.db, amd.map, - aliases, aliases.db, auth.conf, crontab, csh.cshrc, csh.login, - csh.logout, cvsupfile, disktab, dm.conf, dumpdates, exports, - fbtab, fstab, ftpusers, gettytab, gnats, group, host.conf, hosts, - hosts.equiv, hosts.lpd, inetd.conf, kerberosIV, localtime, login.access, - login.conf, mail.rc, make.conf, manpath.config, master.passwd, modems, - motd, namedb, networks, newsyslog.conf, pam.conf, passwd, periodic, - phones, ppp, printcap, profile, protocols, pwd.db, rc.conf.local, - rc.firewall, rc.local, remote, resolv.conf, rmt, sendmail.cf, - sendmail.cw, services, shells, skeykeys, spwd.db, syslog.conf, - ttys, uucp + Xaccel.ini, adduser.conf, aliases, aliases.db, amd.map, crontab, + csh.cshrc, csh.login, csh.logout, daily, disktab, dm.conf, exports, + fbtab, fstab, ftpusers, gettytab, gnats, group, hosts, hosts.equiv, + hosts.lpd, inetd.conf, kerberosIV, localtime, login.access, + mail.rc, make.conf, manpath.config, master.passwd, mib.txt, modems, + monthly, motd, namedb, networks, nsswitch.conf, passwd, phones, + ppp, printcap, profile, protocols, pwd.db, rc, rc.firewall, + rc.i386, rc.local, rc.network, rc.conf, remote, resolv.conf, rmt, + security, sendmail.cf, services, shells, skeykeys, spwd.db, + supfile, syslog.conf, termcap, ttys, uucp, weekly The versions of these files which correspond to the new version are moved to /etc/upgrade/. The system administrator may peruse these new versions and merge components as desired. Note that many of these files are interdependent, and the best merge procedure is to copy all site-specific data from the current files into the new. During the upgrade procedure, the administrator is prompted for a location into which all files from /etc/ are saved. In the event that local modifications have been made to other files, they may be subsequently retrieved from this location. 2.0 Procedure --- --------- This section details the upgrade procedure. Particular attention is given to items which substantially differ from a normal installation. 2.1 Backup --- ------ User data and system configuration should be backed up before upgrading. While the upgrade procedure does its best to prevent accidental mistakes, it is possible to partially or completely destroy data and configuration information. 2.2 Mount Filesystems --- ----------------- The disklabel editor is entered with the nominated disk's filesystem devices listed. Prior to commencing the upgrade, the administrator should make a note of the device names and corresponding mountpoints. These mountpoints should be entered here. DO NOT set the 'newfs flag' for any filesystems, as this will cause data loss. 2.3 Select Distributions --- -------------------- When selecting distributions, there are no constraints on which must be selected. As a general rule, the 'bin' distribution should be selected for an update, and the 'man' distribution if manpages are already installed. Other distributions may be selected beyond those originally installed if the administrator wishes to add additional functionality. 2.4 After Installation --- ------------------ Once the installation procedure has completed, the administrator is prompted to examine the new configuration files. At this point, checks should be made to ensure that the system configuration is valid. In particular, the /etc/rc.conf and /etc/fstab files should be checked. Read the following, but DO NOT update /etc/fstab as described below until the new system has booted correctly. The upgrade procedure replaces the previous FreeBSD kernel with a GENERIC kernel, and a custom kernel may need to be generated to suit the local system configuration. IMPORTANT NOTE: ============== FreeBSD 2.2.6 introduced a change in the naming of the device from which the root filesystem is mounted. This change affects all systems, however user intervention is only required for systems undergoing an upgrade installation from a version prior to FreeBSD 2.2.6. Previously, the root filesystem was always mounted from the compatibility slice, while other partitions on the same disk were mounted from their true slice. This might, for example, have resulted in an /etc/fstab file like: # Device Mountpoint FStype Options Dump Pass# /dev/wd0s2b none swap sw 0 0 /dev/wd0a / ufs rw 1 1 /dev/wd0s2f /local0 ufs rw 1 1 /dev/wd0s2e /usr ufs rw 1 1 For FreeBSD 2.2.6 and later, this format changes so that the device for '/' is consistent with others. Also, the driver for the ATA-drives has changed from wd(4) to ad(4), so the new file could look something like: # Device Mountpoint FStype Options Dump Pass# /dev/ad0s2b none swap sw 0 0 /dev/ad0s2a / ufs rw 1 1 /dev/ad0s2f /local0 ufs rw 1 1 /dev/ad0s2e /usr ufs rw 1 1 If /etc/fstab is not updated manually in this case, the system will issue a warning message whenever / is mounted (normally at startup) indicating the change that must be made. In addition, trouble may be experienced if the root filesystem is not correctly unmounted, whereby the root filesystem will not be marked clean at the next reboot. This change should be made as soon as the upgraded system has been successfully rebooted. 3.0 Alternative Upgrade Techniques --- ------------------------------ Those interested in an upgrade method that allows more flexibility and sophistication should take a look at the "Upgrading FreeBSD from source" tutorial found at http://www.freebsd.org/docs.html. This method requires reliable network connectivity, extra disk space and spare time, but has advantages for networks and other more complex installations. Index: head/sbin/dhclient/Makefile =================================================================== --- head/sbin/dhclient/Makefile (revision 65531) +++ head/sbin/dhclient/Makefile (revision 65532) @@ -1,24 +1,24 @@ # $FreeBSD$ DIST_DIR= ${.CURDIR}/../../contrib/isc-dhcp .PATH: ${DIST_DIR}/client ${DIST_DIR}/common PROG= dhclient SRCS= clparse.c dhclient.c SRCS+= alloc.c bpf.c conflex.c convert.c dispatch.c errwarn.c ethernet.c \ hash.c icmp.c inet.c inet_addr.c memory.c nit.c options.c packet.c \ parse.c print.c raw.c socket.c tables.c tree.c upf.c CFLAGS+= -I${DIST_DIR}/includes -I${DIST_DIR} -CFLAGS+= -DCLIENT_PATH='"PATH=/sbin:/bin:/usr/sbin:/usr/bin"' +CFLAGS+= -DCLIENT_PATH='"PATH=/sbin:/bin:/usr/sbin:/usr/bin"' -Dwarn=dhcp_warn MAN5= dhclient.conf.5 dhclient.leases.5 dhcp-options.5 MAN8= dhclient.8 dhclient-script.8 beforeinstall: ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ ${DIST_DIR}/client/scripts/freebsd \ ${DESTDIR}${BINDIR}/dhclient-script .include Index: head/share/examples/etc/README.examples =================================================================== --- head/share/examples/etc/README.examples (revision 65531) +++ head/share/examples/etc/README.examples (revision 65532) @@ -1,67 +1,67 @@ $FreeBSD$ The /usr/share/examples/etc directory contains the original distribution versions of the files which are shipped in /etc. This is intended to make it easy to recover when the /etc versions are accidentally deleted or broken beyond repair. This directory contains the following files: aliases - sendmail aliases file (see aliases(5)) amd.map - filesystem automounter lookup resolution map (see amd(8)) auth.conf - authentication capability database (see auth.conf(5)) crontab - system scheduled command table (see crontab(5)) csh.cshrc - sample .cshrc (see csh(1)) csh.login - sample .login csh.logout - sample .logout disktab - disk description file (see disktab(5)) dm.conf - configuration file for games (see dm(6)) fbtab - configuration file for login(1) ftpusers - user restriction file for ftpd(8) gettytab - defines port configuration for getty(8) group - group permissions file (see group(5)) -host.conf - defines name resolution order for gethostbyname(3) hosts - see hosts(5) hosts.equiv - defines system-wide trusted hosts (see ruserok(3)) hosts.lpd - defines trusted hosts for lpd(8) inetd.conf - configuration file for inetd(8) locate.rc - confiuration file for locate(1) login.access - configuration file for login(8) (see login.access(5)) login.conf - login class capabilities database (see login.conf(5)) mail.rc - systemwide initialization files for mail(1) make.conf - defines configuration variables for system builds manpath.config - configuration file for man(1) modems - modem configuration database (see modems(5)) motd - sample Message of the Day netstart - network startup script run from /etc/rc networks - see networks(5) newsyslog.conf - configuration for system log file rotator newsyslog(8) +nsswitch.conf - name-service switch config file (see nsswitch.conf(5)) pam.conf - configuration file for pam(8) pccard_ether - confiuration script for ethernet pccards (see pccardd(8)) phones - phone number database for tip(1) printcap - configuration file for lpr(1) protocols - see protocols(5) profile - system-wide .profile for sh(1) rc - system startup script (see init(8)) rc.atm - networking startup script for atm(8) rc.devfs - startup script for devfs(5) rc.diskless1 - general BOOTP startup script rc.diskless2 - rc.firewall - setup system for ipfw(8) rc.i386 - startup script for i386-specific processing rc.alpha - startup script for axp-specific processing rc.isdn - startup script for isdnd(8) rc.network - network startup script rc.pccard - startup script for PC-cards rc.serial - sample local startup script fragments rc.shutdown - system shutdown script (see init(8)) remote - configuration file for tip(1) rpc - see rpc(5) security - script run from crontab to do nightly security checks services - see services(5) shells - list of configurable shells (see shells(5)) skey.access - configuration file for S/Key (see skey.access(5)) syslog.conf - configuration file for syslogd(8) ttys - defines port configuration for init(8) defaults/rc.conf - default system configuration info (see rc.conf(5)) defaults/pccard.conf - default configuration file for pccardd(8) Index: head/share/man/man4/yp.4 =================================================================== --- head/share/man/man4/yp.4 (revision 65531) +++ head/share/man/man4/yp.4 (revision 65532) @@ -1,535 +1,529 @@ .\" Copyright (c) 1992/3 Theo de Raadt .\" 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. .\" 3. The name of the author may not be used to endorse or promote .\" products derived from this software without specific prior written .\" permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. .\" .\" from: @(#)yp.8 1.0 (deraadt) 4/26/93 .\" $FreeBSD$ .\" .Dd April 5, 1993 .Dt YP 4 .Os BSD 4.2 .Sh NAME .Nm yp .Nd description of the YP/NIS system .Sh SYNOPSIS .Nm yp .Sh DESCRIPTION The .Nm YP subsystem allows network management of passwd, group, netgroup, hosts, services, rpc, bootparams and ethers file entries through the functions .Xr getpwent 3 , .Xr getgrent 3 , .Xr getnetgrent 3 , .Xr gethostent 3 , .Xr getnetent 3 , .Xr getrpcent 3 , and .Xr ethers 3 . The .Xr bootparamd 8 daemon makes direct .Tn NIS library calls since there are no functions in the standard C library for reading bootparams. .Tn NIS -support for the hosts, services and rpc databases is enabled by -uncommenting the -.Em nis -line in -.Pa /etc/host.conf . -.Tn NIS -support for the remaining services is -activated by adding a special '+' entry to the appropriate file. +support is enabled in +.Xr nsswitch.conf . .Pp The .Nm YP subsystem is started automatically in .Pa /etc/rc if it has been initialized in .Pa /etc/rc.conf and if the directory .Pa /var/yp exists (which it does in the default distribution). The default .Tn NIS domain must also be set with the .Xr domainname 1 command, which will happen automatically at system startup if it is specified in .Pa /etc/rc.conf . .Pp .Tn NIS is an .Tn RPC Ns -based client/server system that allows a group of machines within an .Tn NIS domain to share a common set of configuration files. This permits a system administrator to set up .Tn NIS client systems with only minimal configuration data and add, remove or modify configuration data from a single location. .Pp The canonical copies of all .Tn NIS information are stored on a single machine called the .Em Tn NIS master server . The databases used to store the information are called .Em Tn NIS maps . In .Bx Free , these maps are stored in .Pa /var/yp/[domainname] where .Pa [domainname] is the name of the .Tn NIS domain being served. A single .Tn NIS server can support several domains at once, therefore it is possible to have several such directories, one for each supported domain. Each domain will have its own independent set of maps. .Pp In .Bx Free , the .Tn NIS maps are Berkeley DB hashed database files (the same format used for the .Xr passwd 5 database files). Other operating systems that support .Tn NIS use old-style ndbm databases instead (largely because Sun Microsystems originally based their .Tn NIS implementation on ndbm, and other vendors have simply licensed Sun's code rather than design their own implementation with a different database format). On these systems, the databases are generally split into .Em .dir and .Em .pag files which the ndbm code uses to hold separate parts of the hash database. The Berkeley DB hash method instead uses a single file for both pieces of information. This means that while you may have .Pa passwd.byname.dir and .Pa passwd.byname.pag files on other operating systems (both of which are really parts of the same map), .Bx Free will have only one file called .Pa passwd.byname . The difference in format is not significant: only the .Tn NIS server, .Xr ypserv 8 , and related tools need to know the database format of the .Tn NIS maps. Client .Tn NIS systems receive all .Tn NIS data in .Tn ASCII form. .Pp There are three main types of .Tn NIS systems: .Bl -enum -offset indent .It .Pa Tn NIS clients , which query .Tn NIS servers for information. .It .Pa Tn NIS master servers , which maintain the canonical copies of all .Tn NIS maps. .It .Pa Tn NIS slave servers , which maintain backup copies of .Tn NIS maps that are periodically updated by the master. .El .Pp An .Tn NIS client establishes what is called a .Em binding to a particular .Tn NIS server using the .Xr ypbind 8 daemon. .Xr Ypbind 8 checks the system's default domain (as set by the .Xr domainname 1 command) and begins broadcasting .Tn RPC requests on the local network. These requests specify the name of the domain for which .Xr ypbind 8 is attempting to establish a binding. If a server that has been configured to serve the requested domain receives one of the broadcasts, it will respond to .Xr ypbind 8 , which will record the server's address. If there are several servers available (a master and several slaves, for example), .Xr ypbind 8 will use the address of the first one to respond. From that point on, the client system will direct all of its .Tn NIS requests to that server. .Xr Ypbind 8 will occasionally ``ping'' the server to make sure it's still up and running. If it fails to receive a reply to one of its pings within a reasonable amount of time, .Xr ypbind 8 will mark the domain as unbound and begin broadcasting again in the hopes of locating another server. .Pp .Tn NIS master and slave servers handle all .Tn NIS requests with the .Xr ypserv 8 daemon. .Xr Ypserv 8 is responsible for receiving incoming requests from .Tn NIS clients, translating the requested domain and map name to a path to the corresponding database file and transmitting data from the database back to the client. There is a specific set of requests that .Xr ypserv 8 is designed to handle, most of which are implemented as functions within the standard C library: .Bl -bullet -offset indent .It .Fn yp_order -- check the creation date of a particular map .It .Fn yp_master -- obtain the name of the .Tn NIS master server for a given map/domain .It .Fn yp_match -- lookup the data corresponding to a given in key in a particular map/domain .It .Fn yp_first -- obtain the first key/data pair in a particular map/domain .It .Fn yp_next -- pass .Xr ypserv 8 a key in a particular map/domain and have it return the key/data pair immediately following it (the functions .Fn yp_first and .Fn yp_next can be used to do a sequential search of an .Tn NIS map) .It .Fn yp_all -- retrieve the entire contents of a map .El .Pp There are a few other requests which .Xr ypserv 8 is capable of handling (i.e. acknowledge whether or not you can handle a particular domain (YPPROC_DOMAIN), or acknowledge only if you can handle the domain and be silent otherwise (YPPROC_DOMAIN_NONACK)) but these requests are usually generated only by .Xr ypbind 8 and are not meant to be used by standard utilities. .Pp On networks with a large number of hosts, it is often a good idea to use a master server and several slaves rather than just a single master server. A slave server provides the exact same information as a master server: whenever the maps on the master server are updated, the new data should be propagated to the slave systems using the .Xr yppush 8 command. The .Tn NIS Makefile .Pf ( Pa /var/yp/Makefile ) will do this automatically if the administrator comments out the line which says .Em NOPUSH=true (NOPUSH is set to true by default because the default configuration is for a small network with only one .Tn NIS server). The .Xr yppush 8 command will initiate a transaction between the master and slave during which the slave will transfer the specified maps from the master server using .Xr ypxfr 8 . (The slave server calls .Xr ypxfr 8 automatically from within .Xr ypserv 8 ; therefore it is not usually necessary for the administrator to use it directly. It can be run manually if desired, however.) Maintaining slave servers helps improve .Tn NIS performance on large networks by: .Pp .Bl -bullet -offset indent .It Providing backup services in the event that the .Tn NIS master crashes or becomes unreachable .It Spreading the client load out over several machines instead of causing the master to become overloaded .It Allowing a single .Tn NIS domain to extend beyond a local network (the .Xr ypbind 8 daemon might not be able to locate a server automatically if it resides on a network outside the reach of its broadcasts. It is possible to force .Xr ypbind 8 to bind to a particular server with .Xr ypset 8 but this is sometimes inconvenient. This problem can be avoided simply by placing a slave server on the local network.) .El .Pp The .Bx Free .Xr ypserv 8 is specially designed to provided enhanced security (compared to other .Tn NIS implementations) when used exclusively with .Bx Free client systems. The .Bx Free password database system (which is derived directly from .Bx 4.4 ) includes support for .Em "shadow passwords" . The standard password database does not contain users' encrypted passwords: these are instead stored (along with other information) is a separate database which is accessible only by the super-user. If the encrypted password database were made available as an .Tn NIS map, this security feature would be totally disabled, since any user is allowed to retrieve .Tn NIS data. .Pp To help prevent this, .Bx Free Ns 's .Tn NIS server handles the shadow password maps .Pf ( Pa master.passwd.byname and .Pa master.passwd.byuid ) in a special way: the server will only provide access to these maps in response to requests that originate on privileged ports. Since only the super-user is allowed to bind to a privileged port, the server assumes that all such requests come from privileged users. All other requests are denied: requests from non-privileged ports will receive only an error code from the server. Additionally, .Bx Free Ns 's .Xr ypserv 8 includes support for Wietse Venema's tcp wrapper package; with tcp wrapper support enabled, the administrator can configure .Xr ypserv 8 to respond only to selected client machines. .Pp While these enhancements provide better security than stock .Tn NIS Ns , they are by no means 100% effective. It is still possible for someone with access to your network to spoof the server into disclosing the shadow password maps. .Pp On the client side, .Bx Free Ns 's .Fn getpwent 3 functions will automatically search for the .Pa master.passwd maps and use them if they exist. If they do, they will be used, and all fields in these special maps (class, password age and account expiration) will be decoded. If they aren't found, the standard .Pa passwd maps will be used instead. .Sh COMPATIBILITY Some systems, such as SunOS 4.x, need .Tn NIS to be running in order for their hostname resolution functions ( .Fn gethostbyname , .Fn gethostbyaddr , etc) to work properly. On these systems, .Xr ypserv 8 performs .Tn DNS lookups when asked to return information about a host that doesn't exist in its .Pa hosts.byname or .Pa hosts.byaddr maps. .Bx Free Ns 's resolver uses .Tn DNS by default (it can be made to use .Tn NIS Ns , if desired), therefore its .Tn NIS server doesn't do .Tn DNS lookups by default. However, .Xr ypserv 8 can be made to perform .Tn DNS lookups if it is started with a special flag. It can also be made to register itself as an .Tn NIS v1 server in order to placate certain systems that insist on the presence of a v1 server .Pf ( Bx Free uses only .Tn NIS v2, but many other systems, including .Tn SunOS 4.x, search for both a v1 and v2 server when binding). .Bx Free Ns 's .Xr ypserv 8 does not actually handle .Tn NIS v1 requests, but this ``kludge mode'' is useful for silencing stubborn systems that search for both a v1 and v2 server. .Pp (Please see the .Xr ypserv 8 manual page for a detailed description of these special features and flags.) .Sh BUGS While .Bx Free now has both .Tn NIS client and server capabilities, it does not yet have support for .Xr ypupdated 8 or the .Fn yp_update function. Both of these require secure .Tn RPC Ns , which .Bx Free doesn't support yet either. .Pp The .Xr getservent 3 and .Xr getprotoent 3 functions do not yet have .Tn NIS support. Fortunately, these files don't need to be updated that often. .Pp Many more manual pages should be written, especially .Xr ypclnt 3 . For the time being, seek out a local Sun machine and read the manuals for there. .Pp Neither Sun nor this author have found a clean way to handle the problems that occur when ypbind cannot find its server upon bootup. .Sh HISTORY The .Nm YP subsystem was written from the ground up by .An Theo de Raadt to be compatible to Sun's implementation. Bug fixes, improvements and .Tn NIS server support were later added by .An Bill Paul Ns . The server-side code was originally written by .An Peter Eriksson and .An Tobias Reber and is subject to the GNU Public License. No Sun code was referenced. Index: head/share/man/man5/Makefile =================================================================== --- head/share/man/man5/Makefile (revision 65531) +++ head/share/man/man5/Makefile (revision 65532) @@ -1,19 +1,20 @@ # @(#)Makefile 8.1 (Berkeley) 6/5/93 # $FreeBSD$ #MISSING: dump.5 plot.5 MAN5= a.out.5 acct.5 core.5 devfs.5 dir.5 disktab.5 ethers.5 \ elf.5 fbtab.5 fdesc.5 forward.5 fs.5 fstab.5 group.5 \ + hesiod.conf.5 \ hosts.5 hosts.equiv.5 hosts.lpd.5 intro.5 kernfs.5 link.5 \ - linprocfs.5 mailer.conf.5 motd.5 networks.5 passwd.5 pbm.5 \ - periodic.conf.5 phones.5 procfs.5 protocols.5 rc.conf.5 \ - remote.5 resolver.5 services.5 shells.5 stab.5 sysctl.conf.5 \ - types.5 utmp.5 + linprocfs.5 mailer.conf.5 motd.5 networks.5 nsswitch.conf.5 \ + passwd.5 pbm.5 periodic.conf.5 \ + phones.5 procfs.5 protocols.5 rc.conf.5 remote.5 resolver.5 \ + services.5 shells.5 stab.5 sysctl.conf.5 types.5 utmp.5 MLINKS= dir.5 dirent.5 MLINKS+=fs.5 inode.5 MLINKS+=hosts.equiv.5 rhosts.5 MLINKS+=resolver.5 resolv.conf.5 MLINKS+=utmp.5 lastlog.5 utmp.5 wtmp.5 .include Index: head/share/man/man5/group.5 =================================================================== --- head/share/man/man5/group.5 (revision 65531) +++ head/share/man/man5/group.5 (revision 65532) @@ -1,177 +1,159 @@ .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)group.5 8.3 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" .Dd September 29, 1994 .Dt GROUP 5 .Os .Sh NAME .Nm group .Nd format of the group permissions file .Sh DESCRIPTION +The +.Nm +file is the local source of group information. It +can be used in conjunction with the Hesiod domain +`group', and the NIS maps `group.byname' and `group.bygid', +as controlled by +.Xr nsswitch.conf 5 . +.Pp The file .Aq Pa /etc/group consists of newline separated .Tn ASCII records, one per group, containing four colon .Ql \&: separated fields. These fields are as follows: .Bl -tag -width password -offset indent -compact .It group Name of the group. .It passwd Group's .Em encrypted password. .It gid The group's decimal ID. .It member Group members. .El .Pp Lines whose first non-whitespace character is a pound-sign (#) are comments, and are ignored. Blank lines that consist only of spaces, tabs or newlines are also ignored. .Pp The .Ar group field is the group name used for granting file access to users who are members of the group. The .Ar gid field is the number associated with the group name. They should both be unique across the system (and often across a group of systems) since they control file access. The .Ar passwd field is an optional .Em encrypted password. This field is rarely used and an asterisk is normally placed in it rather than leaving it blank. The .Ar member field contains the names of users granted the privileges of .Ar group . The member names are separated by commas without spaces or newlines. A user is automatically in a group if that group was specified in their .Pa /etc/passwd entry and does not need to be added to that group in the .Pa /etc/group file. .\" .Pp .\" When the system reads the file .\" .Pa /etc/group .\" the fields are read into the structure .\" .Fa group .\" declared in .\" .Aq Pa grp.h : .\" .Bd -literal -offset indent .\" struct group { .\" char *gr_name; /* group name */ .\" char *gr_passwd; /* group password */ .\" int gr_gid; /* group id */ .\" char **gr_mem; /* group members */ .\" }; .\" .Ed -.Sh YP/NIS INTERACTION -The -.Pa /etc/group -file can be configured to enable the YP/NIS group database. -An entry whose -.Ar name -field consists of a plus sign (`+') followed by a group name, will be -replaced internally to the C library with the YP/NIS group entry for the -named group. An entry whose -.Ar name -field consists of a single plus sign with no group name following, -will be replaced with the entire YP/NIS -.Dq Li group.byname -map. -.Pp -If the YP/NIS group database is enabled for any reason, all reverse -lookups (i.e., -.Fn getgrgid ) -will use the entire database, even if only a few groups are enabled. -Thus, the group name returned by -.Fn getgrgid -is not guaranteed to have a valid forward mapping. .Sh LIMITS There are various limitations which are explained in the function where they occur; see section .Sx SEE ALSO . In older implementations, a group cannot have more than 200 members. The maximum line length of .Pa /etc/group is 1024 characters. Longer lines will be skipped. This limitation disappeared in .Fx 3.0 . Older binaries that are statically linked, depend on old shared libraries, or non-FreeBSD binaries in compatibility mode may still have this limits. .Sh FILES .Bl -tag -width /etc/group -compact .It Pa /etc/group .El .Sh SEE ALSO .Xr passwd 1 , .Xr setgroups 2 , .Xr crypt 3 , .Xr getgrent 3 , .Xr initgroups 3 , .Xr yp 4 , +.Xr nsswitch.conf 5 , .Xr passwd 5 .Sh BUGS The .Xr passwd 1 command does not change the .Nm group passwords. .Sh HISTORY A .Nm file format appeared in .At v6 . -The YP/NIS functionality is modeled after -.Tn SunOS -and first appeared in -.Tn FreeBSD -1.1. Support for comments first appeared in .Fx 3.0 . Index: head/share/man/man5/hesiod.conf.5 =================================================================== --- head/share/man/man5/hesiod.conf.5 (nonexistent) +++ head/share/man/man5/hesiod.conf.5 (revision 65532) @@ -0,0 +1,53 @@ +.\" $NetBSD: hesiod.conf.5,v 1.2 1999/01/25 22:37:06 lukem Exp $ +.\" $FreeBSD$ +.\" +.\" from: #Id: hesiod.conf.5,v 1.1 1996/12/08 21:36:38 ghudson Exp # +.\" +.\" Copyright 1996 by the Massachusetts Institute of Technology. +.\" +.\" Permission to use, copy, modify, and distribute this +.\" software and its documentation for any purpose and without +.\" fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright +.\" notice and this permission notice appear in supporting +.\" documentation, and that the name of M.I.T. not be used in +.\" advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. +.\" M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" +.\" without express or implied warranty. +.\" +.TH HESIOD.CONF 5 "30 November 1996" +.SH NAME +hesiod.conf \- Configuration file for the Hesiod library +.SH DESCRIPTION +The file hesiod.conf determines the behavior of the Hesiod library. +Blank lines and lines beginning with a `#' character are ignored. All +other lines should be of the form +.I variable += +.IR value , +where the value should be a single word. Possible variables and +values are: +.IP lhs +Specifies the domain prefix used for Hesiod queries. In almost all +cases, you should specify ``lhs=.ns''. The default value if you do +not specify an lhs value is no domain prefix, which is not compatible +with most Hesiod domains. +.IP rhs +Specifies the default Hesiod domain; this value may be overridden by +the +.B HES_DOMAIN +environment variable. You must specify an rhs line for the Hesiod +library to work properly. +.IP classes +Specifies which DNS classes Hesiod should do lookups in. Possible +values are IN (the preferred class) and HS (the deprecated class, +still used by some sites). You may specify both classes separated by +a comma to try one class first and then the other if no entry is +available in the first class. The default value of the classes +variable is ``IN,HS''. +.SH SEE ALSO +hesiod(3) +.SH BUGS +The default value for ``lhs'' should probably be more reasonable. Property changes on: head/share/man/man5/hesiod.conf.5 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/share/man/man5/hosts.5 =================================================================== --- head/share/man/man5/hosts.5 (revision 65531) +++ head/share/man/man5/hosts.5 (revision 65532) @@ -1,110 +1,114 @@ .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" @(#)hosts.5 8.2 (Berkeley) 12/11/93 .\" $FreeBSD$ .\" .Dd December 11, 1993 .Dt HOSTS 5 .Os BSD 4.2 .Sh NAME .Nm hosts .Nd host name data base .Sh DESCRIPTION The .Nm hosts file contains information regarding the known hosts on the network. +It can be used in conjunction with DNS, and the NIS +maps `hosts.byaddr' and `hosts.byname', as controlled by +.Xr nsswitch.conf 5 . For each host a single line should be present with the following information: .Bd -unfilled -offset indent Internet address official host name aliases .Ed .Pp Items are separated by any number of blanks and/or tab characters. A ``#'' indicates the beginning of a comment; characters up to the end of the line are not interpreted by routines which search the file. .Pp When using the name server .Xr named 8 , this file provides a backup used when the name server is not running. For the name server, it is suggested that only a few addresses be included in this file. These include addresses for the local interfaces that .Xr ifconfig 8 needs at boot time and a few machines on the local network. .Pp This file may be created from the official host data base maintained at the Network Information Control Center .Pq Tn NIC , though local changes may be required to bring it up to date regarding unofficial aliases and/or unknown hosts. As the data base maintained at .Tn NIC is incomplete, use of the name server is recommended for sites on the .Tn DARPA Internet. .Pp Network addresses are specified in the conventional ``.'' (dot) notation using the .Xr inet_addr 3 routine from the Internet address manipulation library, .Xr inet 3 . Host names may contain any printable character other than a field delimiter, newline, or comment character. .Sh FILES .Bl -tag -width /etc/hosts -compact .It Pa /etc/hosts The .Nm hosts file resides in .Pa /etc . .El .Sh SEE ALSO .Xr gethostbyname 3 , +.Xr nsswitch.conf 5 , .Xr ifconfig 8 , .Xr named 8 .Rs .%T "Name Server Operations Guide for BIND" .Re .Sh HISTORY The .Nm file format appeared in .Bx 4.2 . Index: head/share/man/man5/nsswitch.conf.5 =================================================================== --- head/share/man/man5/nsswitch.conf.5 (nonexistent) +++ head/share/man/man5/nsswitch.conf.5 (revision 65532) @@ -0,0 +1,266 @@ +.\" $NetBSD: nsswitch.conf.5,v 1.14 1999/03/17 20:19:47 garbled Exp $ +.\" $FreeBSD$ +.\" +.\" Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Luke Mewburn. +.\" +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Luke Mewburn. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. +.\" +.Dd January 22, 1998 +.Dt NSSWITCH.CONF 5 +.Os +.Sh NAME +.Nm nsswitch.conf +.Nd name-service switch configuration file +.Sh DESCRIPTION +The +.Nm +file specifies how the +.Xr nsdispatch 3 +(name-service switch dispatcher) routines in the C library should operate. +.Pp +The configuration file controls how a process looks up various databases +containing information regarding hosts, users (passwords), groups, etc. +Each database comes from a source (such as local files, DNS, and +.Tn NIS ) , +and the order to look up the sources is specified in +.Nm nsswitch.conf . +.Pp +Each entry in +.Nm +consists of a database name, and a space separated list of sources. +Each source can have an optional trailing criterion that determines +whether the next listed source is used, or the search terminates at +the current source. +Each criterion consists of one or more status codes, and actions to +take if that status code occurs. +.Ss Sources +The following sources are implemented: +.Bl -column "compat" -offset indent -compact +.Sy Source Description +.It files Local files, such as +.Pa /etc/hosts , +and +.Pa /etc/passwd . +.It dns Internet Domain Name System. +.Dq hosts +and +.Sq networks +use +.Sy IN +class entries, all other databases use +.Sy HS +class (Hesiod) entries. +.It nis NIS (formerly YP) +.It compat support +.Sq +/- +in the +.Dq passwd +and +.Dq group +databases. +If this is present, it must be the only source for that entry. +.El +.Ss Databases +The following databases are used by the following C library functions: +.Bl -column "networks" -offset indent -compact +.Sy Database Used by +.It group +.Xr getgrent 3 +.It hosts +.Xr gethostbyname 3 +.It networks +.Xr getnetbyname 3 +.It passwd +.Xr getpwent 3 +.It shells +.Xr getusershell 3 +.El +.Ss Status codes +The following status codes are available: +.Bl -column "tryagain" -offset indent -compact +.Sy Status Description +.It success The requested entry was found. +.It notfound The entry is not present at this source. +.It tryagain The source is busy, and may respond to retries. +.It unavail The source is not responding, or entry is corrupt. +.El +.Ss Actions +For each of the status codes, one of two actions is possible: +.Bl -column "continue" -offset indent -compact +.Sy Action Description +.It continue Try the next source +.It return Return with the current result +.El +.Ss Format of file +A +.Tn BNF +description of the syntax of +.Nm +is: +.Bl -column "" -offset indent +.It ::= + ":" [ []]* +.It ::= +"[" + "]" +.It ::= + "=" +.It ::= +"success" | "notfound" | "unavail" | "tryagain" +.It ::= +"return" | "continue" +.El +.Pp +Each entry starts on a new line in the file. +A +.Sq # +delimits a comment to end of line. +Blank lines are ignored. +A +.Sq \e +at the end of a line escapes the newline, and causes the next line to +be a continuation of the current line. +All entries are case-insensitive. +.Pp +The default criteria is to return on +.Dq success , +and continue on anything else (i.e, +.Li [success=return notfound=continue unavail=continue tryagain=continue] +). +.Ss Compat mode: +/- syntax +In historical multi-source implementations, the +.Sq + +and +.Sq - +characters are used to specify the importing of user password and +group information from +.Tn NIS . +Although +.Nm +provides alternative methods of accessing distributed sources such as +.Tn NIS , +specifying a sole source of +.Dq compat +will provide the historical behaviour. +.Pp +An alternative source for the information accessed via +.Sq +/- +can be used by specifying +.Dq passwd_compat: source . +.Dq source +in this case can be +.Sq dns , +.Sq nis , +or +any other source except for +.Sq files +and +.Sq compat . +.Ss Notes +Historically, many of the databases had enumeration functions, often of +the form +.Fn getXXXent . +These made sense when the databases were in local files, but don't make +sense or have lesser relevance when there are possibly multiple sources, +each of an unknown size. +The interfaces are still provided for compatibility, but the source +may not be able to provide complete entries, or duplicate entries may +be retrieved if multiple sources that contain similar information are +specified. +.Pp +To ensure compatibility with previous and current implementations, the +.Dq compat +source must appear alone for a given database. +.Ss Default source lists +If, for any reason, +.Nm nsswitch.conf +doesn't exist, or it has missing or corrupt entries, +.Xr nsdispatch 3 +will default to an entry of +.Dq files +for the requested database. +Exceptions are: +.Bl -column passwd_compat "dns files" -offset indent +.Sy Database Default source list +.It group compat +.It group_compat nis +.It hosts dns files +.It passwd compat +.It passwd_compat nis +.El +.Sh FILES +.Bl -tag -width /etc/nsswitch.conf -compact +.It Pa /etc/nsswitch.conf +The file +.Nm +resides in +.Pa /etc . +.El +.Sh EXAMPLES +To lookup hosts in +.Pa /etc/hosts +and then from the DNS, and lookup user information from +.Tn NIS +then files, use: +.Bl -column "passwd:" -offset indent +.It hosts: files dns +.It passwd: nis [notfound=return] files +.It group: nis [notfound=return] files +.El +.Pp +The criteria +.Dq [notfound=return] +sets a policy of "if the user is notfound in nis, don't try files." +This treats nis as the authoritive source of information, except +when the server is down. +.Sh SEE ALSO +.Xr nsdispatch 3 , +.Xr resolv.conf 5 , +.Xr named 8 , +.Xr ypbind 8 +.Sh HISTORY +The +.Nm +file format first appeared in +.Fx 4.1 . +It was imported from the +.Nx +Project, where it appeared first in +.Nx 1.4 . +.Sh AUTHORS +Luke Mewburn +.Aq lukem@netbsd.org +wrote this freely distributable name-service switch implementation, +using ideas from the +.Tn ULTRIX +.Xr svc.conf 5 +and +.Tn Solaris +.Xr nsswitch.conf 4 +manual pages. Property changes on: head/share/man/man5/nsswitch.conf.5 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/share/man/man5/passwd.5 =================================================================== --- head/share/man/man5/passwd.5 (revision 65531) +++ head/share/man/man5/passwd.5 (revision 65532) @@ -1,802 +1,348 @@ +.\" $NetBSD: passwd.5,v 1.12.2.2 1999/12/17 23:14:50 he Exp $ +.\" .\" Copyright (c) 1988, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Portions Copyright (c) 1994, Jason Downs. 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. .\" .\" From: @(#)passwd.5 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd September 29, 1994 +.Dd January 16, 1999 .Dt PASSWD 5 .Os .Sh NAME -.Nm passwd +.Nm passwd , +.Nm master.passwd .Nd format of the password file .Sh DESCRIPTION The .Nm passwd -files are files consisting of newline separated records, one per user, -containing ten colon -.Pq Ql \&: -separated fields. These fields are as -follows: +files are the local source of password information. +They can be used in conjunction with the Hesiod domains +.Sq passwd +and +.Sq uid , +and the +.Tn NIS +maps +.Sq passwd.byname , +.Sq passwd.byuid , +.Sq master.passwd.byname , +and +.Sq master.passwd.byuid , +as controlled by +.Xr nsswitch.conf 5 . .Pp +The +.Nm master.passwd +file is readable only by root, and consists of newline separated +records, one per user, containing ten colon (``:'') separated +fields. These fields are as follows: +.Pp .Bl -tag -width password -offset indent .It name User's login name. .It password User's .Em encrypted password. .It uid User's id. .It gid User's login group id. .It class -User's login class. +User's general classification (unused). .It change Password change time. .It expire Account expiration time. .It gecos General information about the user. .It home_dir User's home directory. .It shell User's login shell. .El .Pp -Lines whose first non-whitespace character is a pound-sign (#) -are comments, and are ignored. Blank lines which consist -only of spaces, tabs or newlines are also ignored. +The +.Nm +file is generated from the +.Nm master.password +file by +.Xr pwd_mkdb 8 , +has the class, change, and expire fields removed, and the password +field replaced by a ``*''. .Pp The .Ar name field is the login used to access the computer account, and the .Ar uid field is the number associated with it. They should both be unique across the system (and often across a group of systems) since they control file access. .Pp While it is possible to have multiple entries with identical login names -and/or identical uids, it is usually a mistake to do so. Routines +and/or identical user id's, it is usually a mistake to do so. Routines that manipulate these files will often return only one of the multiple entries, and that one by random selection. .Pp -The login name must never begin with a hyphen -.Pq Ql \&- ; -also, it is strongly -suggested that neither upper-case characters nor dots -.Pq Ql \&. -be part -of the name, as this tends to confuse mailers. +The login name must never begin with a hyphen (``-''); also, it is strongly +suggested that neither upper-case characters or dots (``.'') be part +of the name, as this tends to confuse mailers. No field may contain a +colon (``:'') as this has been used historically to separate the fields +in the user database. .Pp The password field is the .Em encrypted form of the password. If the .Ar password field is empty, no password will be required to gain access to the machine. This is almost invariably a mistake. Because these files contain the encrypted user passwords, they should not be readable by anyone without appropriate privileges. -Administrative accounts have a password field containing an asterisk -.Ql \&* -which disallows normal logins. .Pp The group field is the group that the user will be placed in upon login. -Although this system supports multiple groups (see +Since this system supports multiple groups (see .Xr groups 1 ) -this field indicates the user's primary group. -Secondary group memberships are selected in -.Pa /etc/group . +this field currently has little special meaning. .Pp The .Ar class -field is a key for a user's login class. -Login classes are defined in +field is a key for a user's login class. Login classes +are defined in .Xr login.conf 5 , -which is a +which is a .Xr termcap 5 -style database of user attributes, accounting, resource and -environment settings. +style database of user attributes, accounting, resource, +and environment settings. .Pp The .Ar change -field is the number in seconds, -.Dv GMT , -from the epoch, until the +field is the number of seconds from the epoch, +.Dv UTC , +until the password for the account must be changed. -This field may be left empty or set to 0 to turn off the -password aging feature. +This field may be left empty to turn off the password aging feature. .Pp The .Ar expire -field is the number in seconds, -.Dv GMT , -from the epoch, until the +field is the number of seconds from the epoch, +.Dv UTC , +until the account expires. -This field may be left empty or set to 0 to turn off the account -aging feature. +This field may be left empty to turn off the account aging feature. .Pp The .Ar gecos -field normally contains comma -.Pq Ql \&, -separated subfields as follows: +field normally contains comma (``,'') separated subfields as follows: .Pp -.Bl -bullet -compact -offset indent -.It +.Bl -tag -width office -offset indent -compact +.It name user's full name -.It -user's office location -.It +.It office +user's office number +.It wphone user's work phone number -.It +.It hphone user's home phone number .El .Pp -This information is used by the +The full name may contain a ampersand (``&'') which will be replaced by +the capitalized login name when the gecos field is displayed or used +by various programs such as +.Xr finger 1 , +.Xr sendmail 8 , +etc. +.Pp +The office and phone number subfields are used by the .Xr finger 1 -program, and the first field used by the system mailer. -If an ampersand -.Pq Ql \&& -character appears within the fullname field, programs that -use this field will substitute it with a capitalized version -of the account's login name. +program, and possibly other applications. .Pp The user's home directory is the full -.Tn UNIX +.Ux path name where the user will be placed on login. .Pp The shell field is the command interpreter the user prefers. If there is nothing in the .Ar shell field, the Bourne shell .Pq Pa /bin/sh is assumed. -For security reasons, if the shell is set to a script that disallows -access to the system (the -.Xr nologin 8 -script, for example), care should be taken not to import any environment -variables. With -.Xr sh 1 , -this can be done by specifying the -.Fl p -flag. -Check the specific shell documentation to determine how this is -done with other shells. -.Sh YP/NIS INTERACTION -.Ss Enabling access to NIS passwd data -The system administrator can configure -.Tn FreeBSD -to use NIS/YP for -its password information by adding special records to the -.Pa /etc/master.passwd -file. -These entries should be added with -.Xr vipw 8 -so that the changes can be properly merged with the hashed -password databases and the -.Pa /etc/passwd -file ( -.Pa /etc/passwd -should never be edited manually). Alternatively, the administrator -can modify -.Pa /etc/master.passwd -in some other way and then manually update the password databases with -.Xr pwd_mkdb 8 . -.Pp -The simplest way to activate NIS is to add an empty record -with only a plus sign -.Pq Ql \&+ -in the name field, such as this: -.Bd -literal -offset indent -+::::::::: - -.Ed -The -.Ql \&+ -will tell the -.Xr getpwent 3 -routines in -.Tn FreeBSD Ns 's -standard C library to begin using the NIS passwd maps -for lookups. -.Pp -Note that the entry shown above is known as a -.Em wildcard -entry, because it matches all users (the -.Ql \&+ -without any other information -matches everybody) and allows all NIS password data to be retrieved -unaltered. -However, by -specifying a username or netgroup next to the -.Ql \&+ -in the NIS -entry, the administrator can affect what data are extracted from the -NIS passwd maps and how it is interpreted. -Here are a few example -records that illustrate this feature (note that you can have several -NIS entries in a single -.Pa master.passwd -file): -.Bd -literal -offset indent --mitnick::::::::: -+@staff::::::::: -+@permitted-users::::::::: -+dennis::::::::: -+ken:::::::::/bin/csh -+@rejected-users::32767:32767::::::/bin/false - -.Ed -Specific usernames are listed explicitly while netgroups are signified -by a preceding -.Ql \&@ . -In the above example, users in the -.Dq staff -and -.Dq permitted-users -netgroups will have their password information -read from NIS and used unaltered. -In other words, they will be allowed -normal access to the machine. -Users -.Dq ken -and -.Dq dennis , -who have -been named explicitly rather than through a netgroup, will also have -their password data read from NIS, -.Em except -that user -.Dq ken -will have his shell remapped to -.Pa /bin/csh . -This means that value for his shell specified in the NIS password map -will be overridden by the value specified in the special NIS entry in -the local -.Pa master.passwd -file. -User -.Dq ken -may have been assigned the csh shell because his -NIS password entry specified a different shell that may not be -installed on the client machine for political or technical reasons. -Meanwhile, users in the -.Dq rejected-users -netgroup are prevented -from logging in because their UIDs, GIDs and shells have been overridden -with invalid values. -.Pp -User -.Dq mitnick -will be be ignored entirely because his entry is -specified with a -.Ql \&- -instead of a -.Ql \&+ . -A minus entry can be used -to block out certain NIS password entries completely; users whose -password data has been excluded in this way are not recognized by -the system at all. -(Any overrides specified with minus entries are -also ignored since there is no point in processing override information -for a user that the system isn't going to recognize in the first place.) -In general, a minus entry is used to specifically exclude a user -who might otherwise be granted access because he happens to be a -member of an authorized netgroup. -For example, if -.Dq mitnick -is -a member of the -.Dq permitted-users -netgroup and must, for whatever -the reason, be permitted to remain in that netgroup (possibly to -retain access to other machines within the domain), the administrator -can still deny him access to a particular system with a minus entry. -Also, it is sometimes easier to explicitly list those users who are not -allowed access rather than generate a possibly complicated list of -users who are allowed access and omit the rest. -.Pp -Note that the plus and minus entries are evaluated in order from -first to last with the first match taking precedence. -This means -the system will only use the first entry that matches a particular user. -If, using the same example, there is a user -.Dq foo -who is a member of both the -.Dq staff -netgroup and the -.Dq rejected-users -netgroup, he will be admitted to -the system because the above example lists the entry for -.Dq staff -before the entry for -.Dq rejected-users . -If the order were reversed, -user -.Dq foo -would be flagged as a -.Dq rejected-user -instead and denied access. -.Pp -Lastly, any NIS password database records that do not match against -at least one of the users or netgroups specified by the NIS access -entries in the -.Pa /etc/master.passwd -file will be ignored (along with any users specified using minus -entries). In our example shown above, we do not have a wildcard -entry at the end of the list; therefore, the system will not recognize -anyone except -.Dq ken , -.Dq dennis , -the -.Dq staff -netgroup, and the -.Dq permitted-users -netgroup as authorized users. -The -.Dq rejected-users -netgroup will -be recognized but all members will have their shells remapped and -therefore be denied access. -All other NIS password records -will be ignored. -The administrator may add a wildcard entry to the -end of the list such as: -.Bd -literal -offset indent -+:::::::::/sbin/nologin - -.Ed -This entry acts as a catch-all for all users that don't match against -any of the other entries. -This technique is sometimes useful when it is -desirable to have the system be able to recognize all users in a -particular NIS domain without necessarily granting them login access. -See the description of the shell field regarding security concerns when using -a shell script as the login shell. -.Pp -The primary use of this -.Pa override -feature is to permit the administrator -to enforce access restrictions on NIS client systems. -Users can be -granted access to one group of machines and denied access to other -machines simply by adding or removing them from a particular netgroup. -Since the netgroup database can also be accessed via NIS, this allows -access restrictions to be administered from a single location, namely -the NIS master server; once a host's access list has been set in -.Pa /etc/master.passwd , -it need not be modified again unless new netgroups are created. -.Sh NOTES -.Ss Shadow passwords through NIS -.Tn FreeBSD -uses a shadow password scheme: users' encrypted passwords -are stored only in -.Pa /etc/master.passwd -and -.Pa /etc/spwd.db , -which are readable and writable only by the superuser. -This is done -to prevent users from running the encrypted passwords through -password-guessing programs and gaining unauthorized access to -other users' accounts. -NIS does not support a standard means of -password shadowing, which implies that placing your password data -into the NIS passwd maps totally defeats the security of -.Tn FreeBSD Ns 's -password shadowing system. -.Pp -.Tn FreeBSD -provides a few special features to help get around this -problem. -It is possible to implement password shadowing between -.Tn FreeBSD -NIS clients and -.Tn FreeBSD -NIS servers. -The -.Xr getpwent 3 -routines will search for a -.Pa master.passwd.byname -and -.Pa master.passwd.byuid -maps which should contain the same data found in the -.Pa /etc/master.passwd -file. -If the maps exist, -.Tn FreeBSD -will attempt to use them for user -authentication instead of the standard -.Pa passwd.byname -and -.Pa passwd.byuid +.Sh HESIOD SUPPORT +If +.Sq dns +is specified for the +.Sq passwd +database in +.Xr nsswitch.conf 5 , +then +.Nm +lookups occur from the +.Sq passwd +Hesiod domain. +.Sh NIS SUPPORT +If +.Sq nis +is specified for the +.Sq passwd +database in +.Xr nsswitch.conf 5 , +then +.Nm +lookups occur from the +.Sq passwd.byname , +.Sq passwd.byuid , +.Sq master.passwd.byname , +and +.Sq master.passwd.byuid +.Tn NIS maps. -.Tn FreeBSD Ns 's -.Xr ypserv 8 -will also check client requests to make sure they originate on a -privileged port. -Since only the superuser is allowed to bind to -a privileged port, the server can tell if the requesting user -is the superuser; all requests from non-privileged users to access -the -.Pa master.passwd -maps will be refused. -Since all user authentication programs run -with superuser privilege, they should have the required access to -users' encrypted password data while normal users will only -be allowed access to the standard -.Pa passwd -maps which contain no password information. +.Sh COMPAT SUPPORT +If +.Sq compat +is specified for the +.Sq passwd +database, and either +.Sq dns +or +.Sq nis +is specified for the +.Sq passwd_compat +database in +.Xr nsswitch.conf 5 , +then the +.Nm +file also supports standard +.Sq +/- +exclusions and inclusions, based on user names and netgroups. .Pp -Note that this feature cannot be used in an environment with -.No non- Ns Tn FreeBSD -systems. -Note also that a truly determined user with -unrestricted access to your network could still compromise the -.Pa master.passwd -maps. -.Ss UID and GID remapping with NIS overrides -Unlike -.Tn SunOS -and other operating systems that use Sun's NIS code, -.Tn FreeBSD -allows the user to override -.Pa all -of the fields in a user's NIS -.Pa passwd -entry. -For example, consider the following -.Pa /etc/master.passwd -entry: -.Bd -literal -offset indent -+@foo-users:???:666:666:0:0:0:Bogus user:/home/bogus:/bin/bogus - -.Ed -This entry will cause all users in the `foo-users' netgroup to -have -.Pa all -of their password information overridden, including UIDs, -GIDs and passwords. -The result is that all `foo-users' will be -locked out of the system, since their passwords will be remapped -to invalid values. +Lines beginning with a ``-'' (minus sign) are entries marked as being excluded +from any following inclusions, which are marked with a ``+'' (plus sign). .Pp -This is important to remember because most people are accustomed to -using an NIS wildcard entry that looks like this: -.Bd -literal -offset indent -+:*:0:0::: - -.Ed -This often leads to new -.Tn FreeBSD -administrators choosing NIS entries for their -.Pa master.passwd -files that look like this: -.Bd -literal -offset indent -+:*:0:0:::::: - -.Ed -Or worse, this -.Bd -literal -offset indent -+::0:0:::::: - -.Ed -.Sy DO _NOT_ PUT ENTRIES LIKE THIS IN YOUR -.Sy Pa master.passwd -.Sy FILE!! -The first tells -.Tn FreeBSD -to remap all passwords to -.Ql \&* -(which -will prevent anybody from logging in) and to remap all UIDs and GIDs -to 0 (which will make everybody appear to be the superuser). The -second case just maps all UIDs and GIDs to 0, which means that -all users will appear to be root! +If the second character of the line is a ``@'' (at sign), the operation +involves the user fields of all entries in the netgroup specified by the +remaining characters of the +.Ar name +field. +Otherwise, the remainder of the +.Ar name +field is assumed to be a specific user name. .Pp -.Ss Compatibility of NIS override evaluation -When Sun originally added NIS support to their -.Xr getpwent 3 -routines, they took into account the fact that the -.Tn SunOS -password -.Pa /etc/passwd -file is in plain -.Tn ASCII -format. -The -.Tn SunOS -documentation claims that -adding a -.Ql \&+ -entry to the password file causes the contents of -the NIS password database to be -.Dq inserted -at the position in the file where the -.Ql \&+ -entry appears. -If, for example, the -administrator places a -.Ql \&+:::::: -entry in the middle of -.Pa /etc/passwd , -then the entire contents of the NIS password map would appear -as though it had been copied into the middle of the password -file. -If the administrator places -.Ql \&+:::::: -entries at both the middle and the end of -.Pa /etc/passwd , -then the NIS password map would appear twice: once in the middle -of the file and once at the end. -(By using override entries -instead of simple wildcards, other combinations could be achieved.) -.Pp -By contrast, -.Fx -does not have a single -.Tn ASCII -password file: it -has a hashed password database. -This database does not have an -easily-defined beginning, middle or end, which makes it very hard -to design a scheme that is 100% compatible with -.Tn SunOS . -For example, -the -.Fn getpwnam +The ``+'' token may also be alone in the +.Ar name +field, which causes all users from either the Hesiod domain +.Nm +(with +.Sq passwd_compat: dns ) +or +.Sq passwd.byname and -.Fn getpwuid -functions in -.Tn FreeBSD -are designed to do direct queries to the -hash database rather than a linear search. -This approach is faster -on systems where the password database is large. -However, when -using direct database queries, the system does not know or care -about the order of the original password file, and therefore -it cannot easily apply the same override logic used by -.Tn SunOS . +.Sq passwd.byuid +.Tn NIS +maps (with +.Sq passwd_compat: nis ) +to be included. .Pp -Instead, -.Tn FreeBSD -groups all the NIS override entries together -and constructs a filter out of them. -Each NIS password entry -is compared against the override filter exactly once and -treated accordingly: if the filter allows the entry through -unaltered, it's treated unaltered; if the filter calls for remapping -of fields, then fields are remapped; if the filter calls for -explicit exclusion (i.e., the entry matches a -.Ql \&- -override), the entry is ignored; if the entry doesn't match against any -of the filter specifications, it's discarded. -.Pp -Again, note that the NIS -.Ql \&+ -and -.Ql \&- -entries themselves are handled in the order in which they were specified -in the -.Pa /etc/master.passwd -file, since doing otherwise would lead to unpredictable behavior. -.Pp -The end result is that -.Tn FreeBSD Ns 's -provides a very close approximation -of -.Tn SunOS Ns 's -behavior while maintaining the database paradigm, though the -.Xr getpwent 3 -functions do behave somewhat differently from their -.Tn SunOS -counterparts. -The primary differences are: -.Bl -bullet -offset indent -.It -Each NIS password map record can be mapped into the password -local password space only once. -.It -The placement of the NIS -.Ql \&+ -and -.Ql \&- -entries does not necessarily -affect where NIS password records will be mapped into -the password space. -.El -.Pp -In 99% of all -.Tn FreeBSD -configurations, NIS client behavior will be -indistinguishable from that of -.Tn SunOS -or other similar systems. -Even -so, users should be aware of these architectural differences. -.Pp -.Ss Using groups instead of netgroups for NIS overrides -.Tn FreeBSD -offers the capability to do override matching based on -user groups rather than netgroups. -If, for example, an NIS entry -is specified as: -.Bd -literal -offset indent -+@operator::::::::: - -.Ed -the system will first try to match users against a netgroup called -.Ql operator . -If an -.Ql operator -netgroup doesn't exist, the system -will try to match users against the normal -.Ql operator -group instead. -.Ss Changes in behavior from older versions of FreeBSD -There have been several bug fixes and improvements in -.Tn FreeBSD Ns 's -NIS/YP handling, some of which have caused changes in behavior. -While the behavior changes are generally positive, it is important -that users and system administrators be aware of them: -.Bl -enum -offset indent -.It -In versions prior to 2.0.5, reverse lookups (i.e. using -.Fn getpwuid ) -would not have overrides applied, which is to say that it -was possible for -.Fn getpwuid -to return a login name that -.Fn getpwnam -would not recognize. -This has been fixed: overrides specified -in -.Pa /etc/master.passwd -now apply to all -.Xr getpwent 3 -functions. -.It -Prior to -.Fx 2.0.5 , -netgroup overrides did not work at -all, largely because -.Tn FreeBSD -did not have support for reading -netgroups through NIS. -Again, this has been fixed, and -netgroups can be specified just as in -.Tn SunOS -and similar NIS-capable -systems. -.It -.Tn FreeBSD -now has NIS server capabilities and supports the use -of -.Pa master.passwd -NIS maps in addition to the standard Sixth Edition format -.Pa passwd -maps. -This means that you can specify change, expiration and class -information through NIS, provided you use a -.Tn FreeBSD -system as -the NIS server. -.El -.Sh FILES -.Bl -tag -width /etc/master.passwd -compact -.It Pa /etc/passwd -.Tn ASCII -password file, with passwords removed -.It Pa /etc/pwd.db -.Xr db 3 -format -password database, with passwords removed -.It Pa /etc/master.passwd -.Tn ASCII -password file, with passwords intact -.It Pa /etc/spwd.db -.Xr db 3 -format -password database, with passwords intact -.El +If the entry contains non-empty +.Ar uid +or +.Ar gid +fields, the specified numbers will override the information retrieved +from the Hesiod domain or the +.Tn NIS +maps. As well, if the +.Ar gecos, +.Ar dir +or +.Ar shell +entries contain text, it will override the information included via +Hesiod or +.Tn NIS . +On some systems, the +.Ar passwd +field may also be overridden. .Sh SEE ALSO .Xr chpass 1 , .Xr login 1 , .Xr passwd 1 , .Xr getpwent 3 , -.Xr login_getclass 3 , -.Xr yp 4 , -.Xr login.conf 5 , +.Xr netgroup 5 , .Xr adduser 8 , -.Xr pw 8 , .Xr pwd_mkdb 8 , -.Xr vipw 8 +.Xr vipw 8 , +.Xr yp 8 +.Pp +.%T "Managing NFS and NIS" +(O'Reilly & Associates) .Sh BUGS User information should (and eventually will) be stored elsewhere. .Pp -The YP/NIS password database makes encrypted passwords visible to -ordinary users, thus making password cracking easier unless you use -shadow passwords with the -.Pa master.passwd -maps and -.Tn FreeBSD Ns 's -.Xr ypserv 8 -server. -.Pp -Unless you're using -.Tn FreeBSD Ns 's -.Xr ypserv 8 , -which supports the use of -.Pa master.passwd -type maps, -the YP/NIS password database will be in old-style (Sixth Edition) format, -which means that site-wide values for user login class, password -expiration date, and other fields present in the current format -will not be available when a -.Tn FreeBSD -system is used as a client with -a standard NIS server. +Placing +Sq compat +exclusions in the file after any inclusions will have +unexpected results. .Sh COMPATIBILITY The password file format has changed since .Bx 4.3 . The following awk script can be used to convert your old-style password file into a new style password file. The additional fields .Dq class , .Dq change and .Dq expire are added, but are turned off by default. -These fields can then be set using -.Xr vipw 8 -or -.Xr pw 8 . +Class is currently not implemented, but change and expire are; to set them, +use the current day in seconds from the epoch + whatever number of seconds +of offset you want. .Bd -literal -offset indent BEGIN { FS = ":"} { print $1 ":" $2 ":" $3 ":" $4 "::0:0:" $5 ":" $6 ":" $7 } .Ed .Sh HISTORY A .Nm file format appeared in .At v6 . -The YP/NIS functionality is modeled after -.Tn SunOS -and first appeared in -.Fx 1.1 -The override capability is new in -.Fx 2.0 . -The override capability was updated to properly support netgroups -in -.Fx 2.0.5 . -Support for comments first appeared in -.Fx 3.0 . +.Pp +The +.Tn NIS +.Nm +file format first appeared in SunOS. +.Pp +The Hesiod support first appeared in +.Fx 4.1 . +It was imported from the +.Nx +Project, where it first appeared in +.Nx 1.4 . Index: head/share/man/man8/yp.8 =================================================================== --- head/share/man/man8/yp.8 (revision 65531) +++ head/share/man/man8/yp.8 (revision 65532) @@ -1,535 +1,529 @@ .\" Copyright (c) 1992/3 Theo de Raadt .\" 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. .\" 3. The name of the author may not be used to endorse or promote .\" products derived from this software without specific prior written .\" permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. .\" .\" from: @(#)yp.8 1.0 (deraadt) 4/26/93 .\" $FreeBSD$ .\" .Dd April 5, 1993 .Dt YP 4 .Os BSD 4.2 .Sh NAME .Nm yp .Nd description of the YP/NIS system .Sh SYNOPSIS .Nm yp .Sh DESCRIPTION The .Nm YP subsystem allows network management of passwd, group, netgroup, hosts, services, rpc, bootparams and ethers file entries through the functions .Xr getpwent 3 , .Xr getgrent 3 , .Xr getnetgrent 3 , .Xr gethostent 3 , .Xr getnetent 3 , .Xr getrpcent 3 , and .Xr ethers 3 . The .Xr bootparamd 8 daemon makes direct .Tn NIS library calls since there are no functions in the standard C library for reading bootparams. .Tn NIS -support for the hosts, services and rpc databases is enabled by -uncommenting the -.Em nis -line in -.Pa /etc/host.conf . -.Tn NIS -support for the remaining services is -activated by adding a special '+' entry to the appropriate file. +support is enabled in +.Xr nsswitch.conf . .Pp The .Nm YP subsystem is started automatically in .Pa /etc/rc if it has been initialized in .Pa /etc/rc.conf and if the directory .Pa /var/yp exists (which it does in the default distribution). The default .Tn NIS domain must also be set with the .Xr domainname 1 command, which will happen automatically at system startup if it is specified in .Pa /etc/rc.conf . .Pp .Tn NIS is an .Tn RPC Ns -based client/server system that allows a group of machines within an .Tn NIS domain to share a common set of configuration files. This permits a system administrator to set up .Tn NIS client systems with only minimal configuration data and add, remove or modify configuration data from a single location. .Pp The canonical copies of all .Tn NIS information are stored on a single machine called the .Em Tn NIS master server . The databases used to store the information are called .Em Tn NIS maps . In .Bx Free , these maps are stored in .Pa /var/yp/[domainname] where .Pa [domainname] is the name of the .Tn NIS domain being served. A single .Tn NIS server can support several domains at once, therefore it is possible to have several such directories, one for each supported domain. Each domain will have its own independent set of maps. .Pp In .Bx Free , the .Tn NIS maps are Berkeley DB hashed database files (the same format used for the .Xr passwd 5 database files). Other operating systems that support .Tn NIS use old-style ndbm databases instead (largely because Sun Microsystems originally based their .Tn NIS implementation on ndbm, and other vendors have simply licensed Sun's code rather than design their own implementation with a different database format). On these systems, the databases are generally split into .Em .dir and .Em .pag files which the ndbm code uses to hold separate parts of the hash database. The Berkeley DB hash method instead uses a single file for both pieces of information. This means that while you may have .Pa passwd.byname.dir and .Pa passwd.byname.pag files on other operating systems (both of which are really parts of the same map), .Bx Free will have only one file called .Pa passwd.byname . The difference in format is not significant: only the .Tn NIS server, .Xr ypserv 8 , and related tools need to know the database format of the .Tn NIS maps. Client .Tn NIS systems receive all .Tn NIS data in .Tn ASCII form. .Pp There are three main types of .Tn NIS systems: .Bl -enum -offset indent .It .Pa Tn NIS clients , which query .Tn NIS servers for information. .It .Pa Tn NIS master servers , which maintain the canonical copies of all .Tn NIS maps. .It .Pa Tn NIS slave servers , which maintain backup copies of .Tn NIS maps that are periodically updated by the master. .El .Pp An .Tn NIS client establishes what is called a .Em binding to a particular .Tn NIS server using the .Xr ypbind 8 daemon. .Xr Ypbind 8 checks the system's default domain (as set by the .Xr domainname 1 command) and begins broadcasting .Tn RPC requests on the local network. These requests specify the name of the domain for which .Xr ypbind 8 is attempting to establish a binding. If a server that has been configured to serve the requested domain receives one of the broadcasts, it will respond to .Xr ypbind 8 , which will record the server's address. If there are several servers available (a master and several slaves, for example), .Xr ypbind 8 will use the address of the first one to respond. From that point on, the client system will direct all of its .Tn NIS requests to that server. .Xr Ypbind 8 will occasionally ``ping'' the server to make sure it's still up and running. If it fails to receive a reply to one of its pings within a reasonable amount of time, .Xr ypbind 8 will mark the domain as unbound and begin broadcasting again in the hopes of locating another server. .Pp .Tn NIS master and slave servers handle all .Tn NIS requests with the .Xr ypserv 8 daemon. .Xr Ypserv 8 is responsible for receiving incoming requests from .Tn NIS clients, translating the requested domain and map name to a path to the corresponding database file and transmitting data from the database back to the client. There is a specific set of requests that .Xr ypserv 8 is designed to handle, most of which are implemented as functions within the standard C library: .Bl -bullet -offset indent .It .Fn yp_order -- check the creation date of a particular map .It .Fn yp_master -- obtain the name of the .Tn NIS master server for a given map/domain .It .Fn yp_match -- lookup the data corresponding to a given in key in a particular map/domain .It .Fn yp_first -- obtain the first key/data pair in a particular map/domain .It .Fn yp_next -- pass .Xr ypserv 8 a key in a particular map/domain and have it return the key/data pair immediately following it (the functions .Fn yp_first and .Fn yp_next can be used to do a sequential search of an .Tn NIS map) .It .Fn yp_all -- retrieve the entire contents of a map .El .Pp There are a few other requests which .Xr ypserv 8 is capable of handling (i.e. acknowledge whether or not you can handle a particular domain (YPPROC_DOMAIN), or acknowledge only if you can handle the domain and be silent otherwise (YPPROC_DOMAIN_NONACK)) but these requests are usually generated only by .Xr ypbind 8 and are not meant to be used by standard utilities. .Pp On networks with a large number of hosts, it is often a good idea to use a master server and several slaves rather than just a single master server. A slave server provides the exact same information as a master server: whenever the maps on the master server are updated, the new data should be propagated to the slave systems using the .Xr yppush 8 command. The .Tn NIS Makefile .Pf ( Pa /var/yp/Makefile ) will do this automatically if the administrator comments out the line which says .Em NOPUSH=true (NOPUSH is set to true by default because the default configuration is for a small network with only one .Tn NIS server). The .Xr yppush 8 command will initiate a transaction between the master and slave during which the slave will transfer the specified maps from the master server using .Xr ypxfr 8 . (The slave server calls .Xr ypxfr 8 automatically from within .Xr ypserv 8 ; therefore it is not usually necessary for the administrator to use it directly. It can be run manually if desired, however.) Maintaining slave servers helps improve .Tn NIS performance on large networks by: .Pp .Bl -bullet -offset indent .It Providing backup services in the event that the .Tn NIS master crashes or becomes unreachable .It Spreading the client load out over several machines instead of causing the master to become overloaded .It Allowing a single .Tn NIS domain to extend beyond a local network (the .Xr ypbind 8 daemon might not be able to locate a server automatically if it resides on a network outside the reach of its broadcasts. It is possible to force .Xr ypbind 8 to bind to a particular server with .Xr ypset 8 but this is sometimes inconvenient. This problem can be avoided simply by placing a slave server on the local network.) .El .Pp The .Bx Free .Xr ypserv 8 is specially designed to provided enhanced security (compared to other .Tn NIS implementations) when used exclusively with .Bx Free client systems. The .Bx Free password database system (which is derived directly from .Bx 4.4 ) includes support for .Em "shadow passwords" . The standard password database does not contain users' encrypted passwords: these are instead stored (along with other information) is a separate database which is accessible only by the super-user. If the encrypted password database were made available as an .Tn NIS map, this security feature would be totally disabled, since any user is allowed to retrieve .Tn NIS data. .Pp To help prevent this, .Bx Free Ns 's .Tn NIS server handles the shadow password maps .Pf ( Pa master.passwd.byname and .Pa master.passwd.byuid ) in a special way: the server will only provide access to these maps in response to requests that originate on privileged ports. Since only the super-user is allowed to bind to a privileged port, the server assumes that all such requests come from privileged users. All other requests are denied: requests from non-privileged ports will receive only an error code from the server. Additionally, .Bx Free Ns 's .Xr ypserv 8 includes support for Wietse Venema's tcp wrapper package; with tcp wrapper support enabled, the administrator can configure .Xr ypserv 8 to respond only to selected client machines. .Pp While these enhancements provide better security than stock .Tn NIS Ns , they are by no means 100% effective. It is still possible for someone with access to your network to spoof the server into disclosing the shadow password maps. .Pp On the client side, .Bx Free Ns 's .Fn getpwent 3 functions will automatically search for the .Pa master.passwd maps and use them if they exist. If they do, they will be used, and all fields in these special maps (class, password age and account expiration) will be decoded. If they aren't found, the standard .Pa passwd maps will be used instead. .Sh COMPATIBILITY Some systems, such as SunOS 4.x, need .Tn NIS to be running in order for their hostname resolution functions ( .Fn gethostbyname , .Fn gethostbyaddr , etc) to work properly. On these systems, .Xr ypserv 8 performs .Tn DNS lookups when asked to return information about a host that doesn't exist in its .Pa hosts.byname or .Pa hosts.byaddr maps. .Bx Free Ns 's resolver uses .Tn DNS by default (it can be made to use .Tn NIS Ns , if desired), therefore its .Tn NIS server doesn't do .Tn DNS lookups by default. However, .Xr ypserv 8 can be made to perform .Tn DNS lookups if it is started with a special flag. It can also be made to register itself as an .Tn NIS v1 server in order to placate certain systems that insist on the presence of a v1 server .Pf ( Bx Free uses only .Tn NIS v2, but many other systems, including .Tn SunOS 4.x, search for both a v1 and v2 server when binding). .Bx Free Ns 's .Xr ypserv 8 does not actually handle .Tn NIS v1 requests, but this ``kludge mode'' is useful for silencing stubborn systems that search for both a v1 and v2 server. .Pp (Please see the .Xr ypserv 8 manual page for a detailed description of these special features and flags.) .Sh BUGS While .Bx Free now has both .Tn NIS client and server capabilities, it does not yet have support for .Xr ypupdated 8 or the .Fn yp_update function. Both of these require secure .Tn RPC Ns , which .Bx Free doesn't support yet either. .Pp The .Xr getservent 3 and .Xr getprotoent 3 functions do not yet have .Tn NIS support. Fortunately, these files don't need to be updated that often. .Pp Many more manual pages should be written, especially .Xr ypclnt 3 . For the time being, seek out a local Sun machine and read the manuals for there. .Pp Neither Sun nor this author have found a clean way to handle the problems that occur when ypbind cannot find its server upon bootup. .Sh HISTORY The .Nm YP subsystem was written from the ground up by .An Theo de Raadt to be compatible to Sun's implementation. Bug fixes, improvements and .Tn NIS server support were later added by .An Bill Paul Ns . The server-side code was originally written by .An Peter Eriksson and .An Tobias Reber and is subject to the GNU Public License. No Sun code was referenced. Index: head/usr.bin/chpass/Makefile =================================================================== --- head/usr.bin/chpass/Makefile (revision 65531) +++ head/usr.bin/chpass/Makefile (revision 65532) @@ -1,70 +1,71 @@ # @(#)Makefile 8.2 (Berkeley) 4/2/94 # $FreeBSD$ PROG= chpass CFLAGS+=-Wall SRCS= chpass.c edit.c field.c pw_copy.c pw_scan.c pw_util.c pw_yp.c \ table.c util.c ypxfr_misc.c ${GENSRCS} GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c yppasswd_private.h \ yppasswd_private_clnt.c yppasswd_private_xdr.c BINMODE=4555 .PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../usr.sbin/vipw \ ${.CURDIR}/../../libexec/ypxfr \ - ${.CURDIR}/../../usr.sbin/rpc.yppasswdd -CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../usr.sbin/vipw + ${.CURDIR}/../../usr.sbin/rpc.yppasswdd \ + ${.CURDIR}/../../lib/libc/gen +CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../usr.sbin/vipw -I${.CURDIR}/../../lib/libc/gen LINKS= ${BINDIR}/chpass ${BINDIR}/chfn LINKS+= ${BINDIR}/chpass ${BINDIR}/chsh LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchpass LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchfn LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchsh MLINKS= chpass.1 chfn.1 chpass.1 chsh.1 MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1 COPTS+= -DYP -I. -I${.CURDIR}/../../libexec/ypxfr \ -I${.CURDIR}/../../usr.sbin/rpc.yppasswdd -Dyp_error=warnx #Some people need this, uncomment to activate #COPTS+= -DRESTRICT_FULLNAME_CHANGE DPADD= ${LIBRPCSVC} ${LIBCRYPT} ${LIBMD} LDADD+= -lrpcsvc -lcrypt -lmd CLEANFILES= ${GENSRCS} RPCGEN= rpcgen -C RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x RPCSRC_PW= ${DESTDIR}/usr/include/rpcsvc/yppasswd.x RPCSRC_PRIV= ${.CURDIR}/../../usr.sbin/rpc.yppasswdd/yppasswd_private.x yp.h: ${RPCSRC} ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} yp_clnt.c: ${RPCSRC} ${RPCGEN} -l -o ${.TARGET} ${RPCSRC} yppasswd.h: ${RPCSRC_PW} ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PW} yppasswd_clnt.c: ${RPCSRC_PW} ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PW} yppasswd_private.h: ${RPCSRC_PRIV} ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PRIV} yppasswd_private_xdr.c: ${RPCSRC_PRIV} ${RPCGEN} -c -o ${.TARGET} ${RPCSRC_PRIV} yppasswd_private_clnt.c: ${RPCSRC_PRIV} ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PRIV} beforeinstall: .for i in chpass chfn chsh ypchpass ypchfn ypchsh [ ! -e ${DESTDIR}${BINDIR}/$i ] || \ chflags noschg ${DESTDIR}${BINDIR}/$i || true .endfor afterinstall: -chflags schg ${DESTDIR}${BINDIR}/chpass .include Index: head/usr.bin/chpass/chpass.c =================================================================== --- head/usr.bin/chpass/chpass.c (revision 65531) +++ head/usr.bin/chpass/chpass.c (revision 65532) @@ -1,291 +1,291 @@ /*- * Copyright (c) 1988, 1993, 1994 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static const char sccsid[] = "From: @(#)chpass.c 8.4 (Berkeley) 4/2/94"; static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pw_copy.h" #ifdef YP #include int yp_errno = YP_TRUE; #include "pw_yp.h" #endif #include "chpass.h" #include "pathnames.h" char *tempname; uid_t uid; void baduser __P((void)); void usage __P((void)); int main(argc, argv) int argc; char **argv; { enum { NEWSH, LOADENTRY, EDITENTRY, NEWPW, NEWEXP } op; struct passwd *pw = NULL, lpw; char *username = NULL; int ch, pfd, tfd; char *arg = NULL; #ifdef YP int force_local = 0; int force_yp = 0; #endif op = EDITENTRY; #ifdef YP while ((ch = getopt(argc, argv, "a:p:s:e:d:h:oly")) != -1) #else while ((ch = getopt(argc, argv, "a:p:s:e:")) != -1) #endif switch(ch) { case 'a': op = LOADENTRY; arg = optarg; break; case 's': op = NEWSH; arg = optarg; break; case 'p': op = NEWPW; arg = optarg; break; case 'e': op = NEWEXP; arg = optarg; break; #ifdef YP case 'h': #ifdef PARANOID if (getuid()) { warnx("Only the superuser can use the -h flag"); } else { #endif yp_server = optarg; #ifdef PARANOID } #endif break; case 'd': #ifdef PARANOID if (getuid()) { warnx("Only the superuser can use the -d flag"); } else { #endif yp_domain = optarg; if (yp_server == NULL) yp_server = "localhost"; #ifdef PARANOID } #endif break; case 'l': _use_yp = 0; force_local = 1; break; case 'y': _use_yp = force_yp = 1; break; case 'o': force_old++; break; #endif case '?': default: usage(); } argc -= optind; argv += optind; uid = getuid(); if (op == EDITENTRY || op == NEWSH || op == NEWPW || op == NEWEXP) switch(argc) { #ifdef YP case 0: GETPWUID(uid) get_yp_master(1); /* XXX just to set the suser flag */ break; case 1: GETPWNAM(*argv) get_yp_master(1); /* XXX just to set the suser flag */ #else case 0: if (!(pw = getpwuid(uid))) errx(1, "unknown user: uid %u", uid); break; case 1: if (!(pw = getpwnam(*argv))) errx(1, "unknown user: %s", *argv); #endif if (uid && uid != pw->pw_uid) baduser(); break; default: usage(); } if (op == NEWSH) { /* protect p_shell -- it thinks NULL is /bin/sh */ if (!arg[0]) usage(); if (p_shell(arg, pw, (ENTRY *)NULL)) pw_error((char *)NULL, 0, 1); } if (op == NEWEXP) { if (uid) /* only root can change expire */ baduser(); if (p_expire(arg, pw, (ENTRY *)NULL)) pw_error((char *)NULL, 0, 1); } if (op == LOADENTRY) { if (uid) baduser(); pw = &lpw; - if (!pw_scan(arg, pw)) + if (!__pw_scan(arg, pw, _PWSCAN_WARN|_PWSCAN_MASTER)) exit(1); } username = pw->pw_name; if (op == NEWPW) { if (uid) baduser(); if(strchr(arg, ':')) { errx(1, "invalid format for password"); } pw->pw_passwd = arg; } /* * The temporary file/file descriptor usage is a little tricky here. * 1: We start off with two fd's, one for the master password * file (used to lock everything), and one for a temporary file. * 2: Display() gets an fp for the temporary file, and copies the * user's information into it. It then gives the temporary file * to the user and closes the fp, closing the underlying fd. * 3: The user edits the temporary file some number of times. * 4: Verify() gets an fp for the temporary file, and verifies the * contents. It can't use an fp derived from the step #2 fd, * because the user's editor may have created a new instance of * the file. Once the file is verified, its contents are stored * in a password structure. The verify routine closes the fp, * closing the underlying fd. * 5: Delete the temporary file. * 6: Get a new temporary file/fd. Pw_copy() gets an fp for it * file and copies the master password file into it, replacing * the user record with a new one. We can't use the first * temporary file for this because it was owned by the user. * Pw_copy() closes its fp, flushing the data and closing the * underlying file descriptor. We can't close the master * password fp, or we'd lose the lock. * 7: Call pw_mkdb() (which renames the temporary file) and exit. * The exit closes the master passwd fp/fd. */ pw_init(); pfd = pw_lock(); tfd = pw_tmp(); if (op == EDITENTRY) { display(tfd, pw); edit(pw); (void)unlink(tempname); tfd = pw_tmp(); } #ifdef YP if (_use_yp) { yp_submit(pw); (void)unlink(tempname); } else { #endif /* YP */ pw_copy(pfd, tfd, pw); if (!pw_mkdb(username)) pw_error((char *)NULL, 0, 1); #ifdef YP } #endif /* YP */ exit(0); } void baduser() { errx(1, "%s", strerror(EACCES)); } void usage() { (void)fprintf(stderr, #ifdef YP "usage: chpass [-l] [-y] [-d domain [-h host]] [-a list] [-p encpass] [-s shell] [-e mmm dd yy] [user]\n"); #else "usage: chpass [-a list] [-p encpass] [-s shell] [-e mmm dd yy] [user]\n"); #endif exit(1); } Index: head/usr.bin/chpass/edit.c =================================================================== --- head/usr.bin/chpass/edit.c (revision 65531) +++ head/usr.bin/chpass/edit.c (revision 65532) @@ -1,268 +1,268 @@ /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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$ */ #ifndef lint static const char sccsid[] = "@(#)edit.c 8.3 (Berkeley) 4/2/94"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "chpass.h" #ifdef YP #include "pw_yp.h" #endif /* YP */ extern char *tempname; void edit(pw) struct passwd *pw; { struct stat begin, end; char *begin_sum, *end_sum; for (;;) { if (stat(tempname, &begin)) pw_error(tempname, 1, 1); begin_sum = MD5File(tempname, (char *)NULL); pw_edit(1); if (stat(tempname, &end)) pw_error(tempname, 1, 1); end_sum = MD5File(tempname, (char *)NULL); if ((begin.st_mtime == end.st_mtime) && (strcmp(begin_sum, end_sum) == 0)) { warnx("no changes made"); pw_error(NULL, 0, 0); } free(begin_sum); free(end_sum); if (verify(pw)) break; pw_prompt(); } } /* * display -- * print out the file for the user to edit; strange side-effect: * set conditional flag if the user gets to edit the shell. */ void display(fd, pw) int fd; struct passwd *pw; { FILE *fp; char *bp, *p, *ttoa(); if (!(fp = fdopen(fd, "w"))) pw_error(tempname, 1, 1); (void)fprintf(fp, #ifdef YP "#Changing %s information for %s.\n", _use_yp ? "NIS" : "user database", pw->pw_name); if (!uid && (!_use_yp || suser_override)) { #else "#Changing user database information for %s.\n", pw->pw_name); if (!uid) { #endif /* YP */ (void)fprintf(fp, "Login: %s\n", pw->pw_name); (void)fprintf(fp, "Password: %s\n", pw->pw_passwd); (void)fprintf(fp, "Uid [#]: %d\n", pw->pw_uid); (void)fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid); (void)fprintf(fp, "Change [month day year]: %s\n", ttoa(pw->pw_change)); (void)fprintf(fp, "Expire [month day year]: %s\n", ttoa(pw->pw_expire)); (void)fprintf(fp, "Class: %s\n", pw->pw_class); (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir); (void)fprintf(fp, "Shell: %s\n", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); } /* Only admin can change "restricted" shells. */ #if 0 else if (ok_shell(pw->pw_shell)) /* * Make shell a restricted field. Ugly with a * necklace, but there's not much else to do. */ #else else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) || !uid) /* * If change not restrict (table.c) and standard shell * OR if root, then allow editing of shell. */ #endif (void)fprintf(fp, "Shell: %s\n", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); else list[E_SHELL].restricted = 1; bp = pw->pw_gecos; p = strsep(&bp, ","); p = strdup(p ? p : ""); list[E_NAME].save = p; if (!list[E_NAME].restricted || !uid) (void)fprintf(fp, "Full Name: %s\n", p); p = strsep(&bp, ","); p = strdup(p ? p : ""); list[E_LOCATE].save = p; if (!list[E_LOCATE].restricted || !uid) (void)fprintf(fp, "Office Location: %s\n", p); p = strsep(&bp, ","); p = strdup(p ? p : ""); list[E_BPHONE].save = p; if (!list[E_BPHONE].restricted || !uid) (void)fprintf(fp, "Office Phone: %s\n", p); p = strsep(&bp, ","); p = strdup(p ? p : ""); list[E_HPHONE].save = p; if (!list[E_HPHONE].restricted || !uid) (void)fprintf(fp, "Home Phone: %s\n", p); bp = strdup(bp ? bp : ""); list[E_OTHER].save = bp; if (!list[E_OTHER].restricted || !uid) (void)fprintf(fp, "Other information: %s\n", bp); (void)fchown(fd, getuid(), getgid()); (void)fclose(fp); } int verify(pw) struct passwd *pw; { ENTRY *ep; char *p; struct stat sb; FILE *fp; int len, line; static char buf[LINE_MAX]; if (!(fp = fopen(tempname, "r"))) pw_error(tempname, 1, 1); if (fstat(fileno(fp), &sb)) pw_error(tempname, 1, 1); if (sb.st_size == 0) { warnx("corrupted temporary file"); goto bad; } line = 0; while (fgets(buf, sizeof(buf), fp)) { line++; if (!buf[0] || buf[0] == '#') continue; if (!(p = strchr(buf, '\n'))) { warnx("line %d too long", line); goto bad; } *p = '\0'; for (ep = list;; ++ep) { if (!ep->prompt) { warnx("unrecognized field on line %d", line); goto bad; } if (!strncasecmp(buf, ep->prompt, ep->len)) { if (ep->restricted && uid) { warnx( "you may not change the %s field", ep->prompt); goto bad; } if (!(p = strchr(buf, ':'))) { warnx("line %d corrupted", line); goto bad; } while (isspace(*++p)); if (ep->except && strpbrk(p, ep->except)) { warnx( "illegal character in the \"%s\" field", ep->prompt); goto bad; } if ((ep->func)(p, pw, ep)) { bad: (void)fclose(fp); return (0); } break; } } } (void)fclose(fp); /* Build the gecos field. */ len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) + strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) + strlen(list[E_OTHER].save) + 5; if (!(p = malloc(len))) err(1, NULL); (void)sprintf(pw->pw_gecos = p, "%s,%s,%s,%s,%s", list[E_NAME].save, list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save, list[E_OTHER].save); while ((len = strlen(pw->pw_gecos)) && pw->pw_gecos[len - 1] == ',') pw->pw_gecos[len - 1] = '\0'; if (snprintf(buf, sizeof(buf), "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell) >= sizeof(buf)) { warnx("entries too long"); free(p); return (0); } free(p); - return (pw_scan(buf, pw)); + return (__pw_scan(buf, pw, _PWSCAN_WARN|_PWSCAN_MASTER)); } Index: head/usr.bin/hesinfo/Makefile =================================================================== --- head/usr.bin/hesinfo/Makefile (nonexistent) +++ head/usr.bin/hesinfo/Makefile (revision 65532) @@ -0,0 +1,5 @@ +# $FreeBSD$ + +PROG= hesinfo + +.include Property changes on: head/usr.bin/hesinfo/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/usr.bin/hesinfo/hesinfo.1 =================================================================== --- head/usr.bin/hesinfo/hesinfo.1 (nonexistent) +++ head/usr.bin/hesinfo/hesinfo.1 (revision 65532) @@ -0,0 +1,226 @@ +.\" $NetBSD: hesinfo.1,v 1.1 1999/01/25 22:45:55 lukem Exp $ +.\" $FreeBSD$ +.\" +.\" from: #Id: hesinfo.1,v 1.9 1996/11/07 01:57:12 ghudson Exp # +.\" +.\" Copyright 1987, 1996 by the Massachusetts Institute of Technology. +.\" +.\" Permission to use, copy, modify, and distribute this +.\" software and its documentation for any purpose and without +.\" fee is hereby granted, provided that the above copyright +.\" notice appear in all copies and that both that copyright +.\" notice and this permission notice appear in supporting +.\" documentation, and that the name of M.I.T. not be used in +.\" advertising or publicity pertaining to distribution of the +.\" software without specific, written prior permission. +.\" M.I.T. makes no representations about the suitability of +.\" this software for any purpose. It is provided "as is" +.\" without express or implied warranty. +.TH HESINFO 1 "27 October 1996" +.FM mit +.SH NAME +hesinfo \- find out what is stored in the Hesiod database +.SH SYNOPSIS +.nf +hesinfo \fI[-bl]\fR \fIHesiodName\fR \fIHesiodNameType\fR +.SH DESCRIPTION +.I hesinfo +takes two arguments, a name to be resolved and a string, known +as a HesiodNameType. It then prints the information returned by +the Hesiod nameserver. +.PP +The value returned by +.B hesinfo +is of the type +.I HesiodNameType. +.PP +.I hesinfo +understands the following options: +.TP +.B -l +Selects long format. +.TP +.B -b +Prints the fully-qualified string passed to the nameserver. + +.PP +.SS VALID Hesiod_Names +The following types of identifiers may be used in the +.I HesiodName +argument to +.B hesinfo. +These values will be resolved by accessing the +.B hesiod +database. + +.TP +.B \ +the 8-character-or-less string used to identify users or classes +(e.g. joeuser, root, 1.00, etc). +Used with the +.I Hesiod_Name_Types +.BR passwd, +.BR pobox, +and +.BR filsys. + + +.TP +.B \ +the id number assigned to a user. + +.TP +.B \ +the id number assigned to a group. + +.TP +.B \ +a name identifying a unique group. + +.TP +.B \ +the name of an athena file system. + +.TP +.B \: +the name of an rvd's server and pack seperated by a colon. + +.TP +.B \: +the name of an nfs server and its partition seperated by a colon. + +.TP +.B \ +the machine name of an Athena workstation (e.g. E40-343-3). + +.TP +.B \ +name of an Athena service (e.g. Zephyr). + +.TP +.B \ +name of Unix service (valid entries are defined in /etc/services). + +.TP +.B \ +name of a printer. + +.TP +.B \ +name of an Athena print cluster. + +.TP +.B \ +some +.B hesinfo +calls (e.g. +.B prclusterlist +) do not require a specific +.I HesiodName +argument. However, you must include a dummy string (e.g. 'foo') for +.B hesinfo + to work properly. + + + + +.PP +.SS VALID Hesiod_Name_Types +The following symbols are valid substitutions for the +.I HesiodNameType +argument to +.B hesinfo. + +.TP +.B \ passwd +returns string suitable for inclusion in +.I /etc/passwd, +searching with +.B . + +.TP +.B \ pobox +returns information on the pobox assigned to the user specified by +.I HesiodName, +searching with +.B . + + +.TP +.B \ uid +returns string suitable for inclusion in +.I /etc/passwd, +searching with +.B . + +.TP +.B \ gid +returns string suitable for inclusion in +.I /etc/group, +searching with +.B . + +.TP +.B \ group +returns string suitable for inclusion in +.I /etc/group, +searching with +.B . + +.TP +.B \ grplist +returns subgroups included in superset +defined by +.B . + +.TP +.B \ filsys +returns file system type, export point, server, mount mode, and import point +for the following valid +.I HesiodNames +(see above) +.B - , , :, +.B and : + +.TP +.B \ cluster +returns information about the local cluster the workstation, specified by +.B . +Included is information about the local file and print servers. This +information is accesses by +.B clusterinfo +at boot time. + +.TP +.B \ sloc +returns network name of service host for +.B . + +.TP +.B \ service +returns Internet protocol type and protocol service port for +.B . + +.TP +.B \ pcap +returns a valid entry for /etc/printcap for +.B . + +.TP +.B \ prcluserlist +returns a list of print clusters. + +.TP +.B \ prcluster +returns a list of printers in a cluster specified by +.B . + +.SH FILES +/etc/hesiod.conf +.SH "SEE ALSO" +`Hesiod - Project Athena Technical Plan -- Name Service', named(8), hesiod(3) +.SH AUTHOR +Steve Dyer, IBM/Project Athena +.br +Copyright 1987, 1988, 1996 by the Massachusetts Institute of Technology. +.br Property changes on: head/usr.bin/hesinfo/hesinfo.1 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/usr.bin/hesinfo/hesinfo.c =================================================================== --- head/usr.bin/hesinfo/hesinfo.c (nonexistent) +++ head/usr.bin/hesinfo/hesinfo.c (revision 65532) @@ -0,0 +1,116 @@ +/* $NetBSD: hesinfo.c,v 1.1 1999/01/25 22:45:55 lukem Exp $ */ + +/* Copyright 1988, 1996 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +/* This file is a simple driver for the Hesiod library. */ + + +#include +#ifndef lint +static char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include + +int main __P((int, char **)); +extern char *__progname; + +int +main(argc, argv) + int argc; + char **argv; +{ + char **list, **p, *bindname, *name, *type; + int lflag = 0, errflg = 0, bflag = 0, c; + void *context; + + while ((c = getopt(argc, argv, "lb")) != -1) { + switch (c) { + case 'l': + lflag = 1; + break; + case 'b': + bflag = 1; + break; + default: + errflg++; + break; + } + } + if (argc - optind != 2 || errflg) { + fprintf(stderr, "Usage: %s [-bl] name type\n", __progname); + fprintf(stderr, "\t-l selects long format\n"); + fprintf(stderr, "\t-b also does hes_to_bind conversion\n"); + exit(2); + } + name = argv[optind]; + type = argv[optind + 1]; + + if (hesiod_init(&context) < 0) { + if (errno == ENOEXEC) + warnx( + "hesiod_init: Invalid Hesiod configuration file."); + else + warn("hesiod_init"); + } + /* Display bind name if requested. */ + if (bflag) { + if (lflag) + printf("hes_to_bind(%s, %s) expands to\n", name, type); + bindname = hesiod_to_bind(context, name, type); + if (!bindname) { + if (lflag) + printf("nothing\n"); + if (errno == ENOENT) + warnx("hesiod_to_bind: Unknown rhs-extension."); + else + warn("hesiod_to_bind"); + exit(1); + } + printf("%s\n", bindname); + free(bindname); + if (lflag) + printf("which "); + } + if (lflag) + printf("resolves to\n"); + + /* Do the hesiod resolve and check for errors. */ + list = hesiod_resolve(context, name, type); + if (!list) { + if (lflag) + printf("nothing\n"); + if (errno == ENOENT) + warnx("hesiod_resolve: Hesiod name not found."); + else + warn("hesiod_resolve"); + exit(1); + } + /* Display the results. */ + for (p = list; *p; p++) + printf("%s\n", *p); + + hesiod_free_list(context, list); + hesiod_end(context); + exit(0); +} Property changes on: head/usr.bin/hesinfo/hesinfo.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/usr.sbin/pwd_mkdb/pw_scan.h =================================================================== --- head/usr.sbin/pwd_mkdb/pw_scan.h (revision 65531) +++ head/usr.sbin/pwd_mkdb/pw_scan.h (nonexistent) @@ -1,40 +0,0 @@ -/*- - * Copyright (c) 1994 - * The Regents of the University of California. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94 - * - * $FreeBSD$ - */ - -extern int pw_big_ids_warning; - -extern int pw_scan __P((char *, struct passwd *)); Property changes on: head/usr.sbin/pwd_mkdb/pw_scan.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/usr.sbin/pwd_mkdb/pw_scan.c =================================================================== --- head/usr.sbin/pwd_mkdb/pw_scan.c (revision 65531) +++ head/usr.sbin/pwd_mkdb/pw_scan.c (nonexistent) @@ -1,174 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -/* - * This module is used to "verify" password entries by chpass(1) and - * pwd_mkdb(8). - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pw_scan.h" - -/* - * Some software assumes that IDs are short. We should emit warnings - * for id's which can not be stored in a short, but we are more liberal - * by default, warning for IDs greater than USHRT_MAX. - * - * If pw_big_ids_warning is anything other than -1 on entry to pw_scan() - * it will be set based on the existance of PW_SCAN_BIG_IDS in the - * environment. - */ -int pw_big_ids_warning = -1; - -int -pw_scan(bp, pw) - char *bp; - struct passwd *pw; -{ - uid_t id; - int root; - char *p, *sh; - - if (pw_big_ids_warning == -1) - pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0; - - pw->pw_fields = 0; - if (!(pw->pw_name = strsep(&bp, ":"))) /* login */ - goto fmt; - root = !strcmp(pw->pw_name, "root"); - if(pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0')) - pw->pw_fields |= _PWF_NAME; - - if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */ - goto fmt; - if(pw->pw_passwd[0]) pw->pw_fields |= _PWF_PASSWD; - - if (!(p = strsep(&bp, ":"))) /* uid */ - goto fmt; - if (p[0]) - pw->pw_fields |= _PWF_UID; - else { - if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') { - warnx("no uid for user %s", pw->pw_name); - return (0); - } - } - id = strtoul(p, (char **)NULL, 10); - if (errno == ERANGE) { - warnx("%s > max uid value (%u)", p, ULONG_MAX); - return (0); - } - if (root && id) { - warnx("root uid should be 0"); - return (0); - } - if (pw_big_ids_warning && id > USHRT_MAX) { - warnx("%s > recommended max uid value (%u)", p, USHRT_MAX); - /*return (0);*/ /* THIS SHOULD NOT BE FATAL! */ - } - pw->pw_uid = id; - - if (!(p = strsep(&bp, ":"))) /* gid */ - goto fmt; - if(p[0]) pw->pw_fields |= _PWF_GID; - id = strtoul(p, (char **)NULL, 10); - if (errno == ERANGE) { - warnx("%s > max gid value (%u)", p, ULONG_MAX); - return (0); - } - if (pw_big_ids_warning && id > USHRT_MAX) { - warnx("%s > recommended max gid value (%u)", p, USHRT_MAX); - /* return (0); This should not be fatal! */ - } - pw->pw_gid = id; - - pw->pw_class = strsep(&bp, ":"); /* class */ - if(pw->pw_class[0]) pw->pw_fields |= _PWF_CLASS; - - if (!(p = strsep(&bp, ":"))) /* change */ - goto fmt; - if(p[0]) pw->pw_fields |= _PWF_CHANGE; - pw->pw_change = atol(p); - - if (!(p = strsep(&bp, ":"))) /* expire */ - goto fmt; - if(p[0]) pw->pw_fields |= _PWF_EXPIRE; - pw->pw_expire = atol(p); - - if (!(pw->pw_gecos = strsep(&bp, ":"))) /* gecos */ - goto fmt; - if(pw->pw_gecos[0]) pw->pw_fields |= _PWF_GECOS; - - if (!(pw->pw_dir = strsep(&bp, ":"))) /* directory */ - goto fmt; - if(pw->pw_dir[0]) pw->pw_fields |= _PWF_DIR; - - if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */ - goto fmt; - - p = pw->pw_shell; - if (root && *p) /* empty == /bin/sh */ - for (setusershell();;) { - if (!(sh = getusershell())) { - warnx("warning, unknown root shell"); - break; - } - if (!strcmp(p, sh)) - break; - } - if(p[0]) pw->pw_fields |= _PWF_SHELL; - - if ((p = strsep(&bp, ":"))) { /* too many */ -fmt: warnx("corrupted entry"); - return (0); - } - return (1); -} Property changes on: head/usr.sbin/pwd_mkdb/pw_scan.c ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/usr.sbin/pwd_mkdb/Makefile =================================================================== --- head/usr.sbin/pwd_mkdb/Makefile (revision 65531) +++ head/usr.sbin/pwd_mkdb/Makefile (revision 65532) @@ -1,7 +1,11 @@ +# $FreeBSD$ # @(#)Makefile 8.1 (Berkeley) 6/6/93 + +.PATH: ${.CURDIR}/../../lib/libc/gen # for pw_scan.c +CFLAGS+= -I${.CURDIR}/../../lib/libc/gen # for pw_scan.h PROG= pwd_mkdb SRCS= pw_scan.c pwd_mkdb.c MAN8= pwd_mkdb.8 .include Index: head/usr.sbin/pwd_mkdb/pwd_mkdb.c =================================================================== --- head/usr.sbin/pwd_mkdb/pwd_mkdb.c (revision 65531) +++ head/usr.sbin/pwd_mkdb/pwd_mkdb.c (revision 65532) @@ -1,615 +1,615 @@ /*- * Copyright (c) 1991, 1993, 1994 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1991, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pw_scan.h" #define INSECURE 1 #define SECURE 2 #define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) #define PERM_SECURE (S_IRUSR|S_IWUSR) HASHINFO openinfo = { 4096, /* bsize */ 32, /* ffactor */ 256, /* nelem */ 2048 * 1024, /* cachesize */ NULL, /* hash() */ 0 /* lorder */ }; static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean; static struct passwd pwd; /* password structure */ static char *pname; /* password file name */ static char prefix[MAXPATHLEN]; static int is_comment; /* flag for comments */ static char line[LINE_MAX]; void cleanup __P((void)); void error __P((char *)); void cp __P((char *, char *, mode_t mode)); void mv __P((char *, char *)); int scan __P((FILE *, struct passwd *)); static void usage __P((void)); int main(argc, argv) int argc; char *argv[]; { DB *dp, *sdp, *pw_db; DBT data, sdata, key; FILE *fp, *oldfp; sigset_t set; int ch, cnt, ypcnt, len, makeold, tfd, yp_enabled = 0; char *p, *t; char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024]; char sbuf[MAX(MAXPATHLEN, LINE_MAX * 2)]; char buf2[MAXPATHLEN]; char sbuf2[MAXPATHLEN]; char *username; u_int method, methoduid; int Cflag; int nblock = 0; Cflag = 0; strcpy(prefix, _PATH_PWD); makeold = 0; username = NULL; while ((ch = getopt(argc, argv, "Cd:ps:u:vN")) != -1) switch(ch) { case 'C': /* verify only */ Cflag = 1; break; case 'd': strncpy(prefix, optarg, sizeof prefix - 1); break; case 'p': /* create V7 "file.orig" */ makeold = 1; break; case 's': /* change default cachesize */ openinfo.cachesize = atoi(optarg) * 1024 * 1024; break; case 'u': /* only update this record */ username = optarg; break; case 'v': /* backward compatible */ break; case 'N': /* do not wait for lock */ nblock = LOCK_NB; break; default: usage(); } argc -= optind; argv += optind; if (argc != 1 || (username && (*username == '+' || *username == '-'))) usage(); /* * This could be changed to allow the user to interrupt. * Probably not worth the effort. */ sigemptyset(&set); sigaddset(&set, SIGTSTP); sigaddset(&set, SIGHUP); sigaddset(&set, SIGINT); sigaddset(&set, SIGQUIT); sigaddset(&set, SIGTERM); (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL); /* We don't care what the user wants. */ (void)umask(0); pname = *argv; /* * Open and lock the original password file. We have to check * the hardlink count after we get the lock to handle any potential * unlink/rename race. * * This lock is necessary when someone runs pwd_mkdb manually, directly * on master.passwd, to handle the case where a user might try to * change his password while pwd_mkdb is running. */ for (;;) { struct stat st; if (!(fp = fopen(pname, "r"))) error(pname); if (flock(fileno(fp), LOCK_EX|nblock) < 0) error("flock"); if (fstat(fileno(fp), &st) < 0) error(pname); if (st.st_nlink != 0) break; fclose(fp); fp = NULL; } /* check only if password database is valid */ if (Cflag) { for (cnt = 1; scan(fp, &pwd); ++cnt); exit(0); } /* Open the temporary insecure password database. */ (void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB); (void)snprintf(sbuf, sizeof(sbuf), "%s/%s.tmp", prefix, _SMP_DB); if (username) { (void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _MP_DB); (void)snprintf(sbuf2, sizeof(sbuf2), "%s/%s", prefix, _SMP_DB); clean = FILE_INSECURE; cp(buf2, buf, PERM_INSECURE); dp = dbopen(buf, O_RDWR|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo); if (dp == NULL) error(buf); clean = FILE_SECURE; cp(sbuf2, sbuf, PERM_SECURE); sdp = dbopen(sbuf, O_RDWR|O_EXCL, PERM_SECURE, DB_HASH, &openinfo); if (sdp == NULL) error(sbuf); /* * Do some trouble to check if we should store this users * uid. Don't use getpwnam/getpwuid as that interferes * with NIS. */ pw_db = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL); if (!pw_db) error(_MP_DB); buf[0] = _PW_KEYBYNAME; len = strlen(username); /* Only check that username fits in buffer */ memmove(buf + 1, username, MIN(len, sizeof(buf) - 1)); key.data = (u_char *)buf; key.size = len + 1; if ((pw_db->get)(pw_db, &key, &data, 0) == 0) { p = (char *)data.data; /* jump over pw_name and pw_passwd, to get to pw_uid */ while (*p++) ; while (*p++) ; buf[0] = _PW_KEYBYUID; memmove(buf + 1, p, sizeof(int)); key.data = (u_char *)buf; key.size = sizeof(int) + 1; if ((pw_db->get)(pw_db, &key, &data, 0) == 0) { /* First field of data.data holds pw_pwname */ if (!strcmp(data.data, username)) methoduid = 0; else methoduid = R_NOOVERWRITE; } else { methoduid = R_NOOVERWRITE; } } else { methoduid = R_NOOVERWRITE; } if ((pw_db->close)(pw_db)) error("close pw_db"); method = 0; } else { dp = dbopen(buf, O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo); if (dp == NULL) error(buf); clean = FILE_INSECURE; sdp = dbopen(sbuf, O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo); if (sdp == NULL) error(sbuf); clean = FILE_SECURE; method = R_NOOVERWRITE; methoduid = R_NOOVERWRITE; } /* * Open file for old password file. Minor trickiness -- don't want to * chance the file already existing, since someone (stupidly) might * still be using this for permission checking. So, open it first and * fdopen the resulting fd. The resulting file should be readable by * everyone. */ if (makeold) { (void)snprintf(buf, sizeof(buf), "%s.orig", pname); if ((tfd = open(buf, O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0) error(buf); if ((oldfp = fdopen(tfd, "w")) == NULL) error(buf); clean = FILE_ORIG; } /* * The databases actually contain three copies of the original data. * Each password file entry is converted into a rough approximation * of a ``struct passwd'', with the strings placed inline. This * object is then stored as the data for three separate keys. The * first key * is the pw_name field prepended by the _PW_KEYBYNAME * character. The second key is the pw_uid field prepended by the * _PW_KEYBYUID character. The third key is the line number in the * original file prepended by the _PW_KEYBYNUM character. (The special * characters are prepended to ensure that the keys do not collide.) */ ypcnt = 1; data.data = (u_char *)buf; sdata.data = (u_char *)sbuf; key.data = (u_char *)tbuf; for (cnt = 1; scan(fp, &pwd); ++cnt) { if (!is_comment && (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-')) yp_enabled = 1; if (is_comment) --cnt; #define COMPACT(e) t = e; while ((*p++ = *t++)); if (!is_comment && (!username || (strcmp(username, pwd.pw_name) == 0))) { /* Create insecure data. */ p = buf; COMPACT(pwd.pw_name); COMPACT("*"); memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid)); p += sizeof(int); memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid)); p += sizeof(int); memmove(p, &pwd.pw_change, sizeof(time_t)); p += sizeof(time_t); COMPACT(pwd.pw_class); COMPACT(pwd.pw_gecos); COMPACT(pwd.pw_dir); COMPACT(pwd.pw_shell); memmove(p, &pwd.pw_expire, sizeof(time_t)); p += sizeof(time_t); memmove(p, &pwd.pw_fields, sizeof pwd.pw_fields); p += sizeof pwd.pw_fields; data.size = p - buf; /* Create secure data. */ p = sbuf; COMPACT(pwd.pw_name); COMPACT(pwd.pw_passwd); memmove(p, &pwd.pw_uid, sizeof(pwd.pw_uid)); p += sizeof(int); memmove(p, &pwd.pw_gid, sizeof(pwd.pw_gid)); p += sizeof(int); memmove(p, &pwd.pw_change, sizeof(time_t)); p += sizeof(time_t); COMPACT(pwd.pw_class); COMPACT(pwd.pw_gecos); COMPACT(pwd.pw_dir); COMPACT(pwd.pw_shell); memmove(p, &pwd.pw_expire, sizeof(time_t)); p += sizeof(time_t); memmove(p, &pwd.pw_fields, sizeof pwd.pw_fields); p += sizeof pwd.pw_fields; sdata.size = p - sbuf; /* Store insecure by name. */ tbuf[0] = _PW_KEYBYNAME; len = strlen(pwd.pw_name); memmove(tbuf + 1, pwd.pw_name, len); key.size = len + 1; if ((dp->put)(dp, &key, &data, method) == -1) error("put"); /* Store insecure by number. */ tbuf[0] = _PW_KEYBYNUM; memmove(tbuf + 1, &cnt, sizeof(cnt)); key.size = sizeof(cnt) + 1; if ((dp->put)(dp, &key, &data, method) == -1) error("put"); /* Store insecure by uid. */ tbuf[0] = _PW_KEYBYUID; memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid)); key.size = sizeof(pwd.pw_uid) + 1; if ((dp->put)(dp, &key, &data, methoduid) == -1) error("put"); /* Store secure by name. */ tbuf[0] = _PW_KEYBYNAME; len = strlen(pwd.pw_name); memmove(tbuf + 1, pwd.pw_name, len); key.size = len + 1; if ((sdp->put)(sdp, &key, &sdata, method) == -1) error("put"); /* Store secure by number. */ tbuf[0] = _PW_KEYBYNUM; memmove(tbuf + 1, &cnt, sizeof(cnt)); key.size = sizeof(cnt) + 1; if ((sdp->put)(sdp, &key, &sdata, method) == -1) error("put"); /* Store secure by uid. */ tbuf[0] = _PW_KEYBYUID; memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid)); key.size = sizeof(pwd.pw_uid) + 1; if ((sdp->put)(sdp, &key, &sdata, methoduid) == -1) error("put"); /* Store insecure and secure special plus and special minus */ if (pwd.pw_name[0] == '+' || pwd.pw_name[0] == '-') { tbuf[0] = _PW_KEYYPBYNUM; memmove(tbuf + 1, &ypcnt, sizeof(cnt)); ypcnt++; key.size = sizeof(cnt) + 1; if ((dp->put)(dp, &key, &data, method) == -1) error("put"); if ((sdp->put)(sdp, &key, &sdata, method) == -1) error("put"); } } /* Create original format password file entry */ if (is_comment && makeold){ /* copy comments */ if (fprintf(oldfp, "%s\n", line) < 0) error("write old"); } else if (makeold) { char uidstr[20]; char gidstr[20]; snprintf(uidstr, sizeof(uidstr), "%u", pwd.pw_uid); snprintf(gidstr, sizeof(gidstr), "%u", pwd.pw_gid); if (fprintf(oldfp, "%s:*:%s:%s:%s:%s:%s\n", pwd.pw_name, pwd.pw_fields & _PWF_UID ? uidstr : "", pwd.pw_fields & _PWF_GID ? gidstr : "", pwd.pw_gecos, pwd.pw_dir, pwd.pw_shell) < 0) error("write old"); } } /* If YP enabled, set flag. */ if (yp_enabled) { buf[0] = yp_enabled + 2; data.size = 1; tbuf[0] = _PW_KEYYPENABLED; key.size = 1; if ((dp->put)(dp, &key, &data, method) == -1) error("put"); if ((sdp->put)(sdp, &key, &data, method) == -1) error("put"); } if ((dp->close)(dp) == -1) error("close"); if ((sdp->close)(sdp) == -1) error("close"); if (makeold) { (void)fflush(oldfp); if (fclose(oldfp) == EOF) error("close old"); } /* Set master.passwd permissions, in case caller forgot. */ (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR); /* Install as the real password files. */ (void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB); (void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _MP_DB); mv(buf, buf2); (void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _SMP_DB); (void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _SMP_DB); mv(buf, buf2); if (makeold) { (void)snprintf(buf2, sizeof(buf2), "%s/%s", prefix, _PASSWD); (void)snprintf(buf, sizeof(buf), "%s.orig", pname); mv(buf, buf2); } /* * Move the master password LAST -- chpass(1), passwd(1) and vipw(8) * all use flock(2) on it to block other incarnations of themselves. * The rename means that everything is unlocked, as the original file * can no longer be accessed. */ (void)snprintf(buf, sizeof(buf), "%s/%s", prefix, _MASTERPASSWD); mv(pname, buf); /* * Close locked password file after rename() */ if (fclose(fp) == EOF) error("close fp"); exit(0); } int scan(fp, pw) FILE *fp; struct passwd *pw; { static int lcnt; char *p; if (!fgets(line, sizeof(line), fp)) return (0); ++lcnt; /* * ``... if I swallow anything evil, put your fingers down my * throat...'' * -- The Who */ if (!(p = strchr(line, '\n'))) { warnx("line too long"); goto fmt; } *p = '\0'; /* * Ignore comments: ^[ \t]*# */ for (p = line; *p != '\0'; p++) if (*p != ' ' && *p != '\t') break; if (*p == '#' || *p == '\0') { is_comment = 1; return(1); } else is_comment = 0; - if (!pw_scan(line, pw)) { + if (!__pw_scan(line, pw, _PWSCAN_WARN|_PWSCAN_MASTER)) { warnx("at line #%d", lcnt); fmt: errno = EFTYPE; /* XXX */ error(pname); } return (1); } void cp(from, to, mode) char *from, *to; mode_t mode; { static char buf[MAXBSIZE]; int from_fd, rcount, to_fd, wcount; if ((from_fd = open(from, O_RDONLY, 0)) < 0) error(from); if ((to_fd = open(to, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0) error(to); while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { wcount = write(to_fd, buf, rcount); if (rcount != wcount || wcount == -1) { int sverrno = errno; (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); errno = sverrno; error(buf); } } if (rcount < 0) { int sverrno = errno; (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); errno = sverrno; error(buf); } } void mv(from, to) char *from, *to; { char buf[MAXPATHLEN]; if (rename(from, to)) { int sverrno = errno; (void)snprintf(buf, sizeof(buf), "%s to %s", from, to); errno = sverrno; error(buf); } } void error(name) char *name; { warn("%s", name); cleanup(); exit(1); } void cleanup() { char buf[MAXPATHLEN]; switch(clean) { case FILE_ORIG: (void)snprintf(buf, sizeof(buf), "%s.orig", pname); (void)unlink(buf); /* FALLTHROUGH */ case FILE_SECURE: (void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _SMP_DB); (void)unlink(buf); /* FALLTHROUGH */ case FILE_INSECURE: (void)snprintf(buf, sizeof(buf), "%s/%s.tmp", prefix, _MP_DB); (void)unlink(buf); } } static void usage() { (void)fprintf(stderr, "usage: pwd_mkdb [-C] [-N] [-p] [-d ] [-s ] [-u ] file\n"); exit(1); } Index: head/usr.sbin/rarpd/rarpd.8 =================================================================== --- head/usr.sbin/rarpd/rarpd.8 (revision 65531) +++ head/usr.sbin/rarpd/rarpd.8 (revision 65532) @@ -1,117 +1,117 @@ .\" @(#) $FreeBSD$ (LBL) .\" .\" Copyright (c) 1990, 1991, 1993 The Regents of the University of .\" California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that: (1) source code distributions .\" retain the above copyright notice and this paragraph in its entirety, (2) .\" distributions including binary code include the above copyright notice and .\" this paragraph in its entirety in the documentation or other materials .\" provided with the distribution, and (3) all advertising materials mentioning .\" features or use of this software display the following acknowledgement: .\" ``This product includes software developed by the University of California, .\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of .\" the University nor the names of its contributors may be used to endorse .\" or promote products derived from this software without specific prior .\" written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .Dd July 19, 1993 .Dt RARPD 8 .Os .Sh NAME .Nm rarpd .Nd reverse ARP daemon .Sh SYNOPSIS .Nm rarpd .Op Fl afsv .Op Ar interface .Sh DESCRIPTION .Nm Rarpd services Reverse ARP requests on the Ethernet connected to .Ar interface . Upon receiving a request, .Nm maps the target hardware address to an IP address via its name, which must be present in both the .Xr ethers 5 and .Xr hosts 5 databases. If a host does not exist in both databases, the translation cannot proceed and a reply will not be sent. By default, a request is honored only if the server (i.e., the host that .Nm is running on) can "boot" the target; that is, a file or directory matching the glob .Pa /tftpboot/\fIipaddr\fP* exists, where .Em ipaddr is the target IP address in hex. For example, the IP address 204.216.27.18 will be replied to if any of .Pa /tftpboot/CCD81B12 , .Pa /tftpboot/CCD81B12.SUN3 , or .Pa /tftpboot/CCD81B12-boot exist. This requirement can be overridden with the .Fl s flag (see below). In normal operation, .Nm forks a copy of itself and runs in the background. Anomalies and errors are reported via .Xr syslog 3 . .Pp The following options are available: .Bl -tag -width indent .It Fl a Listen on all the Ethernets attached to the system. If .Fl a is omitted, an interface must be specified. .It Fl f Run in the foreground. .It Fl s Supply a response to any RARP request for which an ethernet to IP address mapping exists; do not depend on the existence of .Pa /tftpboot/\fIipaddr\fP* . .It Fl v Enable verbose sysloging. .El .Sh FILES .Bl -tag -width /etc/ethers -compact .It Pa /etc/ethers .It Pa /etc/hosts .It Pa /tftpboot .El .Sh SEE ALSO .Xr bpf 4 .Pp RFC 903: Finlayson, R.; Mann, T.; Mogul, J.C.; Theimer, M. Reverse Address Resolution Protocol. 1984 June; 4 p. .Sh AUTHORS .An Craig Leres Aq leres@ee.lbl.gov and .An Steven McCanne Aq mccanne@ee.lbl.gov . Lawrence Berkeley Laboratory, University of California, Berkeley, CA. .Sh BUGS .Nm Rarpd can depend on the DNS to resolve the name discovered from .Pa /etc/ethers . If this name is not in the DNS but is in .Pa /etc/hosts , the DNS lookup can cause a delayed RARP response, so in this situation it is reccommended to configure -.Pa /etc/host.conf +.Xr nsswitch.conf to read .Pa /etc/hosts first. Index: head/usr.sbin/sysinstall/installUpgrade.c =================================================================== --- head/usr.sbin/sysinstall/installUpgrade.c (revision 65531) +++ head/usr.sbin/sysinstall/installUpgrade.c (revision 65532) @@ -1,492 +1,492 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. 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, * verbatim and that no modifications are made prior to this * point in the file. * 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 JORDAN HUBBARD ``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 JORDAN HUBBARD OR HIS PETS 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, LIFE 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. * */ #include "sysinstall.h" #include #include #include #include #include #include #include #include #include static int installUpgradeNonInteractive(dialogMenuItem *self); typedef struct _hitList { enum { JUST_COPY, CALL_HANDLER } action ; char *name; Boolean optional; void (*handler)(struct _hitList *self); } HitList; /* These are the only meaningful files I know about */ static HitList etc_files [] = { { JUST_COPY, "Xaccel.ini", TRUE, NULL }, { JUST_COPY, "XF86Config", TRUE, NULL }, { JUST_COPY, "adduser.conf", TRUE, NULL }, { JUST_COPY, "aliases", TRUE, NULL }, { JUST_COPY, "aliases.db", TRUE, NULL }, { JUST_COPY, "amd.map", TRUE, NULL }, { JUST_COPY, "auth.conf", TRUE, NULL }, { JUST_COPY, "crontab", TRUE, NULL }, { JUST_COPY, "csh.cshrc", TRUE, NULL }, { JUST_COPY, "csh.login", TRUE, NULL }, { JUST_COPY, "csh.logout", TRUE, NULL }, { JUST_COPY, "cvsupfile", TRUE, NULL }, { JUST_COPY, "disktab", TRUE, NULL }, { JUST_COPY, "dm.conf", TRUE, NULL }, { JUST_COPY, "dumpdates", TRUE, NULL }, { JUST_COPY, "exports", TRUE, NULL }, { JUST_COPY, "fbtab", TRUE, NULL }, { JUST_COPY, "fstab", FALSE, NULL }, { JUST_COPY, "ftpusers", TRUE, NULL }, { JUST_COPY, "gettytab", TRUE, NULL }, { JUST_COPY, "gnats", TRUE, NULL }, { JUST_COPY, "group", FALSE, NULL }, - { JUST_COPY, "host.conf", TRUE, NULL }, { JUST_COPY, "hosts", TRUE, NULL }, { JUST_COPY, "hosts.equiv", TRUE, NULL }, { JUST_COPY, "hosts.lpd", TRUE, NULL }, { JUST_COPY, "inetd.conf", TRUE, NULL }, { JUST_COPY, "kerberosIV", TRUE, NULL }, { JUST_COPY, "localtime", TRUE, NULL }, { JUST_COPY, "login.access", TRUE, NULL }, { JUST_COPY, "login.conf", TRUE, NULL }, { JUST_COPY, "mail.rc", TRUE, NULL }, { JUST_COPY, "make.conf", TRUE, NULL }, { JUST_COPY, "manpath.config", TRUE, NULL }, { JUST_COPY, "master.passwd", FALSE, NULL }, { JUST_COPY, "modems", TRUE, NULL }, { JUST_COPY, "motd", TRUE, NULL }, { JUST_COPY, "namedb", TRUE, NULL }, { JUST_COPY, "networks", TRUE, NULL }, { JUST_COPY, "newsyslog.conf", TRUE, NULL }, + { JUST_COPY, "nsswitch.conf", TRUE, NULL }, { JUST_COPY, "pam.conf", TRUE, NULL }, { JUST_COPY, "passwd", TRUE, NULL }, { JUST_COPY, "periodic", TRUE, NULL }, { JUST_COPY, "ppp", TRUE, NULL }, { JUST_COPY, "printcap", TRUE, NULL }, { JUST_COPY, "profile", TRUE, NULL }, { JUST_COPY, "pwd.db", TRUE, NULL }, { JUST_COPY, "rc.local", TRUE, NULL }, { JUST_COPY, "rc.firewall", TRUE, NULL }, { JUST_COPY, "rc.conf.local", TRUE, NULL }, { JUST_COPY, "remote", TRUE, NULL }, { JUST_COPY, "resolv.conf", TRUE, NULL }, { JUST_COPY, "rmt", TRUE, NULL }, { JUST_COPY, "sendmail.cf", TRUE, NULL }, { JUST_COPY, "sendmail.cw", TRUE, NULL }, { JUST_COPY, "services", TRUE, NULL }, { JUST_COPY, "shells", TRUE, NULL }, { JUST_COPY, "skeykeys", TRUE, NULL }, { JUST_COPY, "spwd.db", TRUE, NULL }, { JUST_COPY, "syslog.conf", TRUE, NULL }, { JUST_COPY, "ttys", TRUE, NULL }, { JUST_COPY, "uucp", TRUE, NULL }, { 0 }, }; void traverseHitlist(HitList *h) { system("rm -rf /etc/upgrade"); Mkdir("/etc/upgrade"); while (h->name) { if (!file_readable(h->name)) { if (!h->optional) msgConfirm("Unable to find an old /etc/%s file! That is decidedly non-standard and\n" "your upgraded system may function a little strangely as a result.", h->name); } else { if (h->action == JUST_COPY) { /* Move the just-loaded copy aside */ vsystem("mv /etc/%s /etc/upgrade/%s", h->name, h->name); /* Copy the old one into its place */ msgNotify("Resurrecting %s..", h->name); /* Do this with tar so that symlinks and such are preserved */ if (vsystem("tar cf - %s | tar xpf - -C /etc", h->name)) msgConfirm("Unable to resurrect your old /etc/%s! Hmmmm.", h->name); } else /* call handler */ h->handler(h); } ++h; } } int installUpgrade(dialogMenuItem *self) { char saved_etc[FILENAME_MAX]; Boolean extractingBin = TRUE; if (variable_get(VAR_NONINTERACTIVE)) return installUpgradeNonInteractive(self); variable_set2(SYSTEM_STATE, "upgrade", 0); dialog_clear(); systemDisplayHelp("UPGRADE"); if (msgYesNo("Given all that scary stuff you just read, are you sure you want to\n" "risk it all and proceed with this upgrade?") != 0) return DITEM_FAILURE; if (!Dists) { msgConfirm("First, you must select some distribution components. The upgrade procedure\n" "will only upgrade the distributions you select in the next set of menus."); if (!dmenuOpenSimple(&MenuDistributions, FALSE) || !Dists) return DITEM_FAILURE; } else if (!(Dists & DIST_BIN)) { /* No bin selected? Not much of an upgrade.. */ if (msgYesNo("You didn't select the bin distribution as one of the distributons to load.\n" "This one is pretty vital to a successful upgrade. Are you SURE you don't\n" "want to select the bin distribution? Chose No to bring up the Distributions\n" "menu again.") != 0) { if (!dmenuOpenSimple(&MenuDistributions, FALSE)) return DITEM_FAILURE; } } /* Still?! OK! They must know what they're doing.. */ if (!(Dists & DIST_BIN)) extractingBin = FALSE; if (RunningAsInit) { Device **devs; int i, cnt; char *cp; cp = variable_get(VAR_DISK); devs = deviceFind(cp, DEVICE_TYPE_DISK); cnt = deviceCount(devs); if (!cnt) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE | DITEM_RESTORE; } else { /* Enable all the drives before we start */ for (i = 0; i < cnt; i++) devs[i]->enabled = TRUE; } msgConfirm("OK. First, we're going to go to the disk label editor. In this editor\n" "you will be expected to Mount any partitions you're interested in\n" "upgrading. DO NOT set the Newfs flag to Y on anything in the label editor\n" "unless you're absolutely sure you know what you're doing! In this\n" "instance, you'll be using the label editor as little more than a fancy\n" "screen-oriented partition mounting tool.\n\n" "Once you're done in the label editor, press Q to return here for the next\n" "step."); if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE) { msgConfirm("The disk label editor returned an error status. Upgrade operation\n" "aborted."); return DITEM_FAILURE | DITEM_RESTORE; } /* Don't write out MBR info */ variable_set2(DISK_PARTITIONED, "written", 0); if (DITEM_STATUS(diskLabelCommit(self)) == DITEM_FAILURE) { msgConfirm("Not all file systems were properly mounted. Upgrade operation\n" "aborted."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE | DITEM_RESTORE; } msgNotify("Updating /stand on root filesystem"); (void)vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity()); if (DITEM_STATUS(chroot("/mnt")) == DITEM_FAILURE) { msgConfirm("Unable to chroot to /mnt - something is wrong with the\n" "root partition or the way it's mounted if this doesn't work."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE | DITEM_RESTORE; } chdir("/"); installEnvironment(); systemCreateHoloshell(); } saved_etc[0] = '\0'; /* Don't allow sources to be upgraded unless if we have src already */ if (directory_exists("/usr/src/") && (Dists & DIST_SRC)) { Dists &= ~DIST_SRC; msgConfirm("Warning: /usr/src exists and sources were selected as upgrade\n" "targets. Unfortunately, this is not the way to upgrade your\n" "sources - please use CTM or CVSup or some other method which\n" "handles ``deletion events'', unlike this particular feature.\n\n" "Your existing /usr/src will not be affected by this upgrade.\n"); } if (extractingBin) { while (!*saved_etc) { char *cp = msgGetInput("/usr/tmp/etc", "Under which directory do you wish to save your current /etc?"); if (!cp || !*cp || Mkdir(cp)) { if (msgYesNo("Directory was not specified, was invalid or user selected Cancel.\n\n" "Doing an upgrade without first backing up your /etc directory is a very\n" "bad idea! Do you want to go back and specify the save directory again?") != 0) break; } else { SAFE_STRCPY(saved_etc, cp); } } if (saved_etc[0]) { msgNotify("Preserving /etc directory.."); if (vsystem("tar -cBpf - -C /etc . | tar --unlink -xBpf - -C %s", saved_etc)) if (msgYesNo("Unable to backup your /etc into %s.\n" "Do you want to continue anyway?", saved_etc) != 0) return DITEM_FAILURE; msgNotify("Preserving /root directory.."); vsystem("tar -cBpf - -C / root | tar --unlink -xBpf - -C %s", saved_etc); } msgNotify("chflags'ing old binaries - please wait."); (void)vsystem("chflags -R noschg /bin /sbin /usr/sbin /usr/bin /usr/lib /usr/libexec /kernel*"); if (file_readable("/kernel")) { msgNotify("Moving old kernel to /kernel.prev"); if (system("mv /kernel /kernel.prev")) { if (!msgYesNo("Hmmm! I couldn't move the old kernel over! Do you want to\n" "treat this as a big problem and abort the upgrade? Due to the\n" "way that this upgrade process works, you will have to reboot\n" "and start over from the beginning. Select Yes to reboot now")) systemShutdown(1); } else msgConfirm("NOTICE: Your old kernel is in /kernel.prev should this upgrade\n" "fail for any reason and you need to boot your old kernel"); } } media: /* We do this very late, but we unfortunately need to back up /etc first */ if (!mediaVerify()) return DITEM_FAILURE; if (!mediaDevice->init(mediaDevice)) { if (!msgYesNo("Couldn't initialize the media. Would you like\n" "to adjust your media selection and try again?")) { mediaDevice = NULL; goto media; } else return DITEM_FAILURE | DITEM_REDRAW | DITEM_RESTORE; } msgNotify("Beginning extraction of distributions.."); if (DITEM_STATUS(distExtractAll(self)) == DITEM_FAILURE) { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } else if (Dists) { if (!extractingBin || !(Dists & DIST_BIN)) { msgNotify("The extraction process seems to have had some problems, but we got most\n" "of the essentials. We'll treat this as a warning since it may have been\n" "only non-essential distributions which failed to load."); } else { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } } if (extractingBin) vsystem("disklabel -B `awk '$2~/\\/$/ {print substr($1, 6, 3)}' /etc/fstab`"); msgNotify("First stage of upgrade completed successfully!\n\n" "Next comes stage 2, where we attempt to resurrect your /etc\n" "directory!"); if (saved_etc && chdir(saved_etc)) { msgConfirm("Unable to go to your saved /etc directory in %s?! Argh!\n" "Something went seriously wrong! It's quite possible that\n" "your former /etc is toast. I hope you didn't have any\n" "important customizations you wanted to keep in there.. :(", saved_etc); } else { /* Now try to resurrect the /etc files */ traverseHitlist(etc_files); /* Resurrect the root dotfiles */ vsystem("tar -cBpf - root | tar -xBpf - -C / && rm -rf root"); } msgConfirm("Upgrade completed! All of your old /etc files have been restored.\n" "For your reference, the new /etc files are in /etc/upgrade/ in case\n" "you wish to upgrade these files by hand (though that should not be\n" "strictly necessary). If your root partition is specified in /etc/fstab\n" "using the old \"compatibility\" slice, you may also wish to update it to\n" "use a fully qualified slice name in order to avoid warnings on startup.\n\n" "When you're ready to reboot into the new system, simply exit the installation."); return DITEM_SUCCESS | DITEM_REDRAW | DITEM_RESTORE; } static int installUpgradeNonInteractive(dialogMenuItem *self) { char *saved_etc; Boolean extractingBin = TRUE; variable_set2(SYSTEM_STATE, "upgrade", 0); /* Make sure at least BIN is selected */ Dists |= DIST_BIN; if (RunningAsInit) { Device **devs; int i, cnt; char *cp; cp = variable_get(VAR_DISK); devs = deviceFind(cp, DEVICE_TYPE_DISK); cnt = deviceCount(devs); if (!cnt) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE; } else { /* Enable all the drives befor we start */ for (i = 0; i < cnt; i++) devs[i]->enabled = TRUE; } msgConfirm("OK. First, we're going to go to the disk label editor. In this editor\n" "you will be expected to Mount any partitions you're interested in\n" "upgrading. DO NOT set the Newfs flag to Y on anything in the label editor\n" "unless you're absolutely sure you know what you're doing! In this\n" "instance, you'll be using the label editor as little more than a fancy\n" "screen-oriented partition mounting tool.\n\n" "Once you're done in the label editor, press Q to return here for the next\n" "step."); if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE) { msgConfirm("The disk label editor returned an error status. Upgrade operation\n" "aborted."); return DITEM_FAILURE; } /* Don't write out MBR info */ variable_set2(DISK_PARTITIONED, "written", 0); if (DITEM_STATUS(diskLabelCommit(self)) == DITEM_FAILURE) { msgConfirm("Not all file systems were properly mounted. Upgrade operation\n" "aborted."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE; } if (extractingBin) { msgNotify("chflags'ing old binaries - please wait."); (void)vsystem("chflags -R noschg /mnt/"); } msgNotify("Updating /stand on root filesystem"); (void)vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity()); if (DITEM_STATUS(chroot("/mnt")) == DITEM_FAILURE) { msgConfirm("Unable to chroot to /mnt - something is wrong with the\n" "root partition or the way it's mounted if this doesn't work."); variable_unset(DISK_PARTITIONED); return DITEM_FAILURE; } chdir("/"); systemCreateHoloshell(); } if (!mediaVerify() || !mediaDevice->init(mediaDevice)) { msgNotify("Upgrade: Couldn't initialize media."); return DITEM_FAILURE; } saved_etc = "/usr/tmp/etc"; Mkdir(saved_etc); msgNotify("Preserving /etc directory.."); if (vsystem("tar -cpBf - -C /etc . | tar -xpBf - -C %s", saved_etc)) { msgNotify("Unable to backup your /etc into %s.", saved_etc); return DITEM_FAILURE; } if (file_readable("/kernel")) { msgNotify("Moving old kernel to /kernel.prev"); if (!system("chflags noschg /kernel && mv /kernel /kernel.prev")) { /* Give us a working kernel in case we crash and reboot */ system("cp /kernel.prev /kernel"); } } msgNotify("Beginning extraction of distributions.."); if (DITEM_STATUS(distExtractAll(self)) == DITEM_FAILURE) { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } else if (Dists) { if (!(Dists & DIST_BIN)) { msgNotify("The extraction process seems to have had some problems, but we got most\n" "of the essentials. We'll treat this as a warning since it may have been\n" "only non-essential distributions which failed to upgrade."); } else { msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n" "should be considered a failure and started from the beginning, sorry!\n" "The system will reboot now."); dialog_clear(); systemShutdown(1); } } msgNotify("First stage of upgrade completed successfully."); if (vsystem("tar -cpBf - -C %s . | tar --unlink -xpBf - -C /etc", saved_etc)) { msgNotify("Unable to resurrect your old /etc!"); return DITEM_FAILURE; } return DITEM_SUCCESS | DITEM_REDRAW; } Index: head/usr.sbin/ypserv/ypserv.8 =================================================================== --- head/usr.sbin/ypserv/ypserv.8 (revision 65531) +++ head/usr.sbin/ypserv/ypserv.8 (revision 65532) @@ -1,458 +1,458 @@ .\" Copyright (c) 1995 .\" Bill Paul . 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by Bill Paul. .\" 4. Neither the name of the author nor the names of any co-contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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$ .\" .Dd February 4, 1995 .Dt YPSERV 8 .Os .Sh NAME .Nm ypserv .Nd NIS database server .Sh SYNOPSIS .Nm .Op Fl n .Op Fl d .Op Fl p Ar path .Sh DESCRIPTION .Tn NIS is an RPC-based service designed to allow a number of UNIX-based machines to share a common set of configuration files. Rather than requiring a system administrator to update several copies of files such as .Pa /etc/hosts , .Pa /etc/passwd and .Pa /etc/group , which tend to require frequent changes in most environments, .Tn NIS allows groups of computers to share one set of data which can be updated from a single location. .Pp The .Nm program is the server that distributes .Tn NIS databases to client systems within an .Tn NIS .Em domain . Each client in an .Tn NIS domain must have its domainname set to one of the domains served by .Nm using the .Xr domainname 1 command. The clients must also run .Xr ypbind 8 in order to attach to a particular server, since it is possible to have several servers within a single .Tn NIS domain. .Pp The databases distributed by .Nm are stored in .Pa /var/yp/[domainname] where .Pa domainname is the name of the domain being served. There can be several such directories with different domainnames, and you need only one .Nm daemon to handle them all. .Pp The databases, or .Pa maps as they are often called, are created by .Pa /var/yp/Makefile using several system files as source. The database files are in .Xr db 3 format to help speed retrieval when there are many records involved. In .Fx , the maps are always readable and writable only by root for security reasons. Technically this is only necessary for the password maps, but since the data in the other maps can be found in other world-readable files anyway, it doesn't hurt and it's considered good general practice. .Pp The .Nm program is started by .Pa /etc/rc.network if it has been enabled in .Pa /etc/rc.conf . .Sh SPECIAL FEATURES There are some problems associated with distributing a .Fx password database via .Tn NIS Ns : .Fx normally only stores encrypted passwords in .Pa /etc/master.passwd , which is readable and writable only by root. By turning this file into an .Tn NIS map, this security feature would be completely defeated. .Pp To make up for this, the .Fx version of .Nm handles the .Pa master.passwd.byname and .Pa master.passwd.byuid maps in a special way. When the server receives a request to access either of these two maps, it will check the TCP port from which the request originated and return an error if the port number is greater than 1023. Since only the superuser is allowed to bind to TCP ports with values less than 1024, the server can use this test to determine whether or not the access request came from a privileged user. Any requests made by non-privileged users are therefore rejected. .Pp Furthermore, the .Xr getpwent 3 routines in the .Fx standard C library will only attempt to retrieve data from the .Pa master.passwd.byname and .Pa master.passwd.byuid maps for the superuser: if a normal user calls any of these functions, the standard .Pa passwd.byname and .Pa passwd.byuid maps will be accessed instead. The latter two maps are constructed by .Pa /var/yp/Makefile by parsing the .Pa master.passwd file and stripping out the password fields, and are therefore safe to pass on to unprivileged users. In this way, the shadow password aspect of the protected .Pa master.passwd database is maintained through .Tn NIS . .Pp .Sh NOTES .Ss Setting Up Master and Slave Servers .Xr ypinit 8 is a convenient script that will help setup master and slave .Tn NIS servers. .Ss Limitations There are two problems inherent with password shadowing in .Tn NIS that users should be aware of: .Bl -enum -offset indent .It The .Sq TCP port less than 1024 test is trivial to defeat for users with unrestricted access to machines on your network (even those machines which do not run UNIX-based operating systems). .It If you plan to use a .Fx system to serve .No non- Ns Tn FreeBSD clients that have no support for password shadowing (which is most of them), you will have to disable the password shadowing entirely by uncommenting the .Em UNSECURE=True entry in .Pa /var/yp/Makefile . This will cause the standard .Pa passwd.byname and .Pa passwd.byuid maps to be generated with valid encrypted password fields, which is necessary in order for .No non- Ns Tn FreeBSD clients to perform user authentication through .Tn NIS . .El .Pp .Ss Security In general, any remote user can issue an RPC to .Nm and retrieve the contents of your .Tn NIS maps, provided the remote user knows your domain name. To prevent such unauthorized transactions, .Nm supports a feature called .Pa securenets which can be used to restrict access to a given set of hosts. At startup, .Nm will attempt to load the securenets information from a file called .Pa /var/yp/securenets . (Note that this path varies depending on the path specified with the .Fl p option, which is explained below.) This file contains entries that consist of a network specification and a network mask separated by white space. Lines starting with .Dq \&# are considered to be comments. A sample securenets file might look like this: .Bd -unfilled -offset indent # allow connections from local host -- mandatory 127.0.0.1 255.255.255.255 # allow connections from any host # on the 192.168.128.0 network 192.168.128.0 255.255.255.0 # allow connections from any host # between 10.0.0.0 to 10.0.15.255 10.0.0.0 255.255.240.0 .Ed .Pp If .Nm receives a request from an address that matches one of these rules, it will process the request normally. If the address fails to match a rule, the request will be ignored and a warning message will be logged. If the .Pa /var/yp/securenets file does not exist, .Nm will allow connections from any host. .Pp The .Nm program also has support for Wietse Venema's .Em tcpwrapper package, though it is not compiled in by default since the .Em tcpwrapper package is not distributed with .Fx . However, if you have .Pa libwrap.a and .Pa tcpd.h , you can easily recompile .Nm with them. This allows the administrator to use the tcpwrapper configuration files ( .Pa /etc/hosts.allow and .Pa /etc/hosts.deny ) for access control instead of .Pa /var/yp/securenets . .Pp Note: while both of these access control mechanisms provide some security, they, like the privileged port test, are both vulnerable to .Dq IP spoofing attacks. .Pp .Ss NIS v1 compatibility This version of .Nm has some support for serving .Tn NIS v1 clients. The .Fx .Tn NIS implementation only uses the .Tn NIS v2 protocol, however other implementations include support for the v1 protocol for backwards compatibility with older systems. The .Xr ypbind 8 daemons supplied with these systems will try to establish a binding to an .Tn NIS v1 server even though they may never actually need it (and they may persist in broadcasting in search of one even after they receive a response from a v2 server). Note that while support for normal client calls is provided, this version of .Nm does not handle v1 map transfer requests; consequently, it can not be used as a master or slave in conjunction with older .Tn NIS servers that only support the v1 protocol. Fortunately, there probably aren't any such servers still in use today. .Ss NIS servers that are also NIS clients Care must be taken when running .Nm in a multi-server domain where the server machines are also .Tn NIS clients. It is generally a good idea to force the servers to bind to themselves rather than allowing them to broadcast bind requests and possibly become bound to each other: strange failure modes can result if one server goes down and others are dependent upon on it. (Eventually all the clients will time out and attempt to bind to other servers, but the delay involved can be considerable and the failure mode is still present since the servers might bind to each other all over again). .Pp Refer to the .Xr ypbind 8 man page for details on how to force it to bind to a particular server. .Sh OPTIONS The following options are supported by .Nm Ns : .Bl -tag -width flag .It Fl n This option affects the way .Nm handles yp_match requests for the .Pa hosts.byname and .Pa hosts.byaddress maps. By default, if .Nm can't find an entry for a given host in its hosts maps, it will return an error and perform no further processing. With the .Fl n flag, .Nm will go one step further: rather than giving up immediately, it will try to resolve the hostname or address using a DNS nameserver query. If the query is successful, .Nm will construct a fake database record and return it to the client, thereby making it seem as though the client's yp_match request succeeded. .Pp This feature is provided for compatiblity with SunOS 4.1.x, which has brain-damaged resolver functions in its standard C library that depend on .Tn NIS for hostname and address resolution. The .Fx resolver can be configured to do DNS queries directly, therefore it is not necessary to enable this option when serving only .Fx .Tn NIS clients. .It Fl d Cause the server to run in debugging mode. Normally, .Nm reports only unusual errors (access violations, file access failures) using the .Xr syslog 3 facility. In debug mode, the server does not background itself and prints extra status messages to stderr for each request that it receives. Also, while running in debug mode, .Nm will not spawn any additional subprocesses as it normally does when handling yp_all requests or doing DNS lookups. (These actions often take a fair amount of time to complete and are therefore handled in subprocesses, allowing the parent server process to go on handling other requests.) This makes it easier to trace the server with a debugging tool. .It Fl p Ar path Normally, .Nm assumes that all .Tn NIS maps are stored under .Pa /var/yp . The .Fl p flag may be used to specify an alternate .Tn NIS root path, allowing the system administrator to move the map files to a different place within the filesystem. .El .Sh FILES .Bl -tag -width Pa -compact .It Pa /var/yp/[domainname]/[maps] the .Tn NIS maps -.It Pa /etc/host.conf -resolver configuration file +.It Pa /etc/nsswitch.conf +name switch configuration file .It Pa /var/yp/securenets host access control file .El .Sh SEE ALSO .Xr ypcat 1 , .Xr db 3 , .Xr yp 4 , .Xr rpc.yppasswdd 8 , .Xr ypbind 8 , .Xr ypinit 8 , .Xr yppush 8 , .Xr ypxfr 8 .Sh AUTHORS .An Bill Paul Aq wpaul@ctr.columbia.edu .Sh HISTORY This version of .Nm first appeared in .Fx 2.2 .